From fe9187117561205f27301bf72fb5f7399ae396d7 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 16:44:12 -0700 Subject: [PATCH 01/67] bump release version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 31e32e57e..0ccc8659a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "badc" -version = "0.1.1" +version = "0.1.2" dependencies = [ "hashbrown", "libm", diff --git a/Cargo.toml b/Cargo.toml index 64a7ddb52..46aa8a094 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "badc" -version = "0.1.1" +version = "0.1.2" edition = "2024" license = "MIT" description = "A quick, slim cross-platform C compiler (also a compiler-as-library) (C99, C11, and more) with a JIT and native ELF / PE / Mach-O backends." From 76bf6fb43fe7172fc590cd6e79d8f7c5b580d66d Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 18:11:46 -0700 Subject: [PATCH 02/67] mach-o: route an executable's dynamic exports through the export trie dyld resolves an image carrying LC_DYLD_INFO exclusively through the export trie; the executable's dynamic exports (the every-global set a dlopen'd module binds against) only reached the classic symtab, so a flat-namespace lookup from a plugin failed despite the nlist entry. Append each dynamic export (text and data) to the trie at its image-base-relative address, matching the shared-library export path. Co-Authored-By: Claude Fable 5 --- src/c5/object/mach_o.rs | 5 +- src/c5/tests/linker.rs | 145 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 1 deletion(-) diff --git a/src/c5/object/mach_o.rs b/src/c5/object/mach_o.rs index d823b1a54..23ad7b31e 100644 --- a/src/c5/object/mach_o.rs +++ b/src/c5/object/mach_o.rs @@ -2226,7 +2226,9 @@ pub(super) fn write(program: &Program, build: &Build) -> Result, C5Error // global symbols, so a dlopen'd module binds against them. A text // symbol's value is the code base plus its byte offset within // `build.text`; a data symbol's value is the `__data` section - // vmaddr plus its byte offset within `build.data`. + // vmaddr plus its byte offset within `build.data`. dyld resolves + // an image carrying LC_DYLD_INFO through the export trie only, so + // each dynamic export joins the trie alongside its symtab entry. let dyn_export_str_base = n_locals + export_disk_names.len(); for (i, d) in dyn_exports_emit.iter().enumerate() { let n_strx = str_indices[dyn_export_str_base + i]; @@ -2243,6 +2245,7 @@ pub(super) fn write(program: &Program, build: &Build) -> Result, C5Error } }; symtab.extend_from_slice(&nlist_defined(n_strx, n_value, n_sect)); + export_trie_entries.push((dyn_export_disk_names[i].clone(), n_value - TEXT_VMADDR_BASE)); } // [Undefined imports] (N_EXT | N_UNDF). Indices in // `str_indices` are shifted past the locals + exports. diff --git a/src/c5/tests/linker.rs b/src/c5/tests/linker.rs index 3aacace98..0063ab510 100644 --- a/src/c5/tests/linker.rs +++ b/src/c5/tests/linker.rs @@ -944,6 +944,151 @@ fn export_data_exposes_data_globals_in_dynsym() { ); } +#[test] +fn macho_executable_exports_globals_through_dyld_info_trie() { + // macOS publishes every global of an executable so a dlopen'd module + // resolves them against the host. dyld resolves an image carrying + // LC_DYLD_INFO exclusively through the export trie -- a symtab-only + // entry is invisible to it -- so a text and a data global must both + // resolve through the trie at their symtab addresses. + use crate::c5::linker::{ + emit_aarch64_plt, link_native_objects, parse_native_elf, write_native_image_from_merged, + }; + use crate::c5::{CompileOptions, NativeOptions, OutputKind, Target, emit_native_with_options}; + let program = Compiler::with_options( + alloc::format!( + "{TEST_PRELUDE}\ + int host_data = 7;\n\ + int host_api(int x) {{ return x + host_data; }}\n\ + int main(void) {{ return host_api(0); }}\n" + ), + Target::MacOSAarch64, + CompileOptions::default(), + ) + .compile() + .expect("compile"); + let opts = NativeOptions { + output_kind: OutputKind::Relocatable, + ..Default::default() + }; + let bytes = emit_native_with_options(&program, Target::MacOSAarch64, opts).expect("emit"); + let obj = parse_native_elf(&bytes).expect("parse ET_REL"); + let mut merged = link_native_objects(&[obj]).expect("link"); + let plt = emit_aarch64_plt(&mut merged).expect("plt"); + let exe = write_native_image_from_merged( + &merged, + &plt, + "main", + None, + OutputKind::Executable, + Target::MacOSAarch64, + None, + ) + .expect("write executable"); + + fn uleb(buf: &[u8], p: &mut usize) -> u64 { + let (mut v, mut shift) = (0u64, 0); + loop { + let b = buf[*p]; + *p += 1; + v |= ((b & 0x7F) as u64) << shift; + if b & 0x80 == 0 { + return v; + } + shift += 7; + } + } + fn trie_lookup(trie: &[u8], name: &str) -> Option { + let bytes = name.as_bytes(); + let (mut node, mut pos) = (0usize, 0usize); + loop { + let mut p = node; + let term_size = uleb(trie, &mut p) as usize; + if pos == bytes.len() { + if term_size == 0 { + return None; + } + let _flags = uleb(trie, &mut p); + return Some(uleb(trie, &mut p)); + } + p += term_size; + let child_count = trie[p]; + p += 1; + let mut next = None; + for _ in 0..child_count { + let start = p; + while trie[p] != 0 { + p += 1; + } + let label = &trie[start..p]; + p += 1; + let child = uleb(trie, &mut p) as usize; + if bytes[pos..].starts_with(label) { + next = Some((label.len(), child)); + break; + } + } + match next { + Some((len, child)) => { + pos += len; + node = child; + } + None => return None, + } + } + } + + let read_u32 = |off: usize| u32::from_le_bytes(exe[off..off + 4].try_into().unwrap()); + let read_u64 = |off: usize| u64::from_le_bytes(exe[off..off + 8].try_into().unwrap()); + assert_eq!(read_u32(0), 0xfeed_facf, "executable must be MH_MAGIC_64"); + // Walk the load commands for LC_DYLD_INFO_ONLY (export_off/size at + // +40/+44), LC_SYMTAB (symoff/nsyms/stroff at +8/+12/+16), and the + // __TEXT segment vmaddr (image base; trie addresses are relative to it). + let sizeofcmds = read_u32(20) as usize; + let (mut export_range, mut symtab_loc, mut image_base) = (None, None, None); + let mut p = 32usize; + while p < 32 + sizeofcmds { + match read_u32(p) { + 0x8000_0022 => { + export_range = Some((read_u32(p + 40) as usize, read_u32(p + 44) as usize)); + } + 0x2 => { + symtab_loc = Some(( + read_u32(p + 8) as usize, + read_u32(p + 12) as usize, + read_u32(p + 16) as usize, + )); + } + 0x19 if exe[p + 8..p + 15] == *b"__TEXT\0" => { + image_base = Some(read_u64(p + 24)); + } + _ => {} + } + p += read_u32(p + 4) as usize; + } + let (export_off, export_size) = export_range.expect("LC_DYLD_INFO_ONLY must be present"); + let trie = &exe[export_off..export_off + export_size]; + let (symoff, nsyms, stroff) = symtab_loc.expect("LC_SYMTAB must be present"); + let image_base = image_base.expect("__TEXT segment must be present"); + let n_value_of = |name: &str| -> u64 { + (0..nsyms) + .find_map(|i| { + let base = symoff + i * 16; + let s = &exe[stroff + read_u32(base) as usize..]; + let end = s.iter().position(|&b| b == 0).unwrap(); + (&s[..end] == name.as_bytes()).then(|| read_u64(base + 8)) + }) + .unwrap_or_else(|| panic!("symtab must carry {name}")) + }; + for name in ["_host_api", "_host_data"] { + assert_eq!( + trie_lookup(trie, name), + Some(n_value_of(name) - image_base), + "{name} must resolve through the export trie at its symtab address" + ); + } +} + #[test] fn shared_object_relocates_internal_data_pointers() { // A function / data pointer baked into a shared object's static data From fd8b75576280663126099dc7f8d99c72e9675ff6 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 18:12:09 -0700 Subject: [PATCH 03/67] elf: reject _Thread_local data in shared-library output Both backends lower _Thread_local access with the local-exec TLS model, whose TP-relative offsets are valid only in the executable's static TLS block; baked into ET_DYN they silently address another module's TLS. Fail the link until the general-dynamic model lands (TODO in the writer). Mach-O (TLV descriptors) and PE (TLS directory) resolve per-module and stay unaffected. fmt_link_err moves to the native-emit gate so the final-image writer can use it. Co-Authored-By: Claude Fable 5 --- src/c5/error.rs | 6 +++--- src/c5/object/elf.rs | 11 ++++++++++ src/c5/tests/linker.rs | 49 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/c5/error.rs b/src/c5/error.rs index 7f3e3f915..02b165e97 100644 --- a/src/c5/error.rs +++ b/src/c5/error.rs @@ -63,11 +63,11 @@ pub(crate) fn fmt_internal_err(message: &str) -> String { /// malformed archives). These describe a problem with the user's /// command line or sources -- not a c5 bug -- so they MUST NOT /// carry the `internal compiler error:` marker. Mirrors ld / -/// gold's "error:" prefix. Gated to the `full` feature -- the -/// only caller lives in the linker module, so under +/// gold's "error:" prefix. Gated to `native-emit` -- the callers +/// live in the linker module and the final-image writers, so under /// `--no-default-features --lib` this helper would otherwise /// trip the dead-code lint. -#[cfg(feature = "full")] +#[cfg(feature = "native-emit")] pub(crate) fn fmt_link_err(message: &str) -> String { use alloc::format; format!("error: {message}") diff --git a/src/c5/object/elf.rs b/src/c5/object/elf.rs index 909cc500f..60c5713cd 100644 --- a/src/c5/object/elf.rs +++ b/src/c5/object/elf.rs @@ -1311,6 +1311,17 @@ pub(super) fn write( machine: Machine, ) -> Result, C5Error> { let is_shared = build.output_kind == super::OutputKind::SharedLibrary; + // Both backends lower `_Thread_local` access with the local-exec + // model, whose TP-relative offsets are valid only in the + // executable's static TLS block; baked into ET_DYN they address + // another module's TLS. TODO: implement the general-dynamic TLS + // model for ELF shared-library output. + if is_shared && !build.tls_data.is_empty() { + return Err(C5Error::Compile(crate::c5::error::fmt_link_err( + "_Thread_local data is not supported in ELF shared-library output: \ + only the executable-model (local-exec) TLS sequence is implemented", + ))); + } let n_imports = build.imports.imports.len(); // Pick the libc-exit tail when the user has any // libc `exit` import (typically through ``), diff --git a/src/c5/tests/linker.rs b/src/c5/tests/linker.rs index 0063ab510..5b8adbba9 100644 --- a/src/c5/tests/linker.rs +++ b/src/c5/tests/linker.rs @@ -1089,6 +1089,55 @@ fn macho_executable_exports_globals_through_dyld_info_trie() { } } +#[test] +fn thread_local_in_elf_shared_library_is_a_link_error() { + // The emitted `_Thread_local` sequences use the local-exec TLS + // model, whose TP-relative offsets are valid only in the + // executable's static TLS block; baked into ET_DYN they address + // another module's TLS. The writer must reject the combination + // until the general-dynamic model is implemented. + use crate::c5::linker::{ + emit_x86_64_plt, link_native_objects, parse_native_elf, write_native_image_from_merged, + }; + use crate::c5::{CompileOptions, NativeOptions, OutputKind, Target, emit_native_with_options}; + let program = Compiler::with_options( + "_Thread_local int counter = 7;\n\ + int bump(void) { counter += 1; return counter; }\n" + .to_string(), + Target::LinuxX64, + CompileOptions::default().with_no_entry_point(true), + ) + .compile() + .expect("compile"); + let opts = NativeOptions { + output_kind: OutputKind::Relocatable, + ..Default::default() + }; + let bytes = emit_native_with_options(&program, Target::LinuxX64, opts).expect("emit"); + let obj = parse_native_elf(&bytes).expect("parse ET_REL"); + let mut merged = link_native_objects(&[obj]).expect("link"); + assert!( + !merged.tls_data.is_empty(), + "the merged unit must carry TLS data" + ); + let plt = emit_x86_64_plt(&mut merged).expect("plt"); + let err = write_native_image_from_merged( + &merged, + &plt, + "", + None, + OutputKind::SharedLibrary, + Target::LinuxX64, + None, + ) + .expect_err("a _Thread_local shared library must be rejected"); + assert!( + err.to_string() + .contains("_Thread_local data is not supported in ELF shared-library output"), + "unexpected diagnostic: {err}" + ); +} + #[test] fn shared_object_relocates_internal_data_pointers() { // A function / data pointer baked into a shared object's static data From 7130eeb81a5d4ad0b71d5633e720bddda6aa46bd Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 18:12:15 -0700 Subject: [PATCH 04/67] preprocessor: literal-aware comment handling, missing #include is fatal Directive parsing truncated #define bodies at the first // even inside a string literal ("http://x.com" recorded as "http:), and the #if expression pre-pass had the same literal-unaware truncation. Comments are removed once in translation phase 3 (C99 5.1.1.2) by the literal-aware strip_c_comments; the redundant naive strips in parse_directive and expand_for_if are removed, and the post-substitution strip on #if expressions (which covers driver-predefined macro bodies that never pass phase 3) now uses strip_c_comments as well. The literal-unaware strip_comments helper is deleted. A missing #include emitted a warning and continued with an empty body, so the compile exited 0 on a miscompiled unit. It is now a hard error naming the header and the search outcome, matching gcc/clang; the -H trace still records the '! name (missing)' line first. Regression tests: define_body_keeps_slashes_inside_string_literal, if_string_comparison_keeps_slashes_inside_literal, unknown_include_is_a_hard_error; quoted_include_form_is_recognised and show_includes_records_resolution_trace adapted to the fatal behavior. Co-Authored-By: Claude Fable 5 --- src/c5/preprocessor.rs | 164 ++++++++++++++++++----------------------- 1 file changed, 73 insertions(+), 91 deletions(-) diff --git a/src/c5/preprocessor.rs b/src/c5/preprocessor.rs index 38ffbe594..26e36bb13 100644 --- a/src/c5/preprocessor.rs +++ b/src/c5/preprocessor.rs @@ -1919,21 +1919,8 @@ impl Preprocessor { i += 1; continue; } - // Strip `/* ... */` block comments and `// ...` line - // comments. They show up routinely on `#if` lines. - if bytes[i] == b'/' && bytes.get(i + 1) == Some(&b'*') { - i += 2; - while i + 1 < bytes.len() && !(bytes[i] == b'*' && bytes[i + 1] == b'/') { - i += 1; - } - i = (i + 2).min(bytes.len()); - out.push(' '); - continue; - } - if bytes[i] == b'/' && bytes.get(i + 1) == Some(&b'/') { - i = bytes.len(); - continue; - } + // Comments were removed in phase 3; the literal-aware + // strip after substitution covers macro-introduced ones. // Match `defined` keyword (must be a complete word). if bytes[i..].starts_with(b"defined") { let after = i + b"defined".len(); @@ -1987,11 +1974,12 @@ impl Preprocessor { } // Now expand all remaining identifiers (object + function- // like) via the standard substitute pass. Then strip block - // and line comments from the result -- macro bodies can - // carry inline `/* ... */` comments that survive expansion - // and would otherwise confuse the expression tokenizer. + // and line comments from the result -- driver-predefined + // macro bodies never went through phase 3 and can carry + // comments that would confuse the expression tokenizer. + // `strip_c_comments` keeps string and char literals intact. let substituted = self.substitute(&out, "<#if>", line_no); - strip_comments(&substituted) + strip_c_comments(&substituted) } fn eval_condition(&self, expr: &str, line_no: usize) -> Result { @@ -2710,8 +2698,8 @@ impl Preprocessor { self.finish_include(resolved, name, line_no, filename) } - /// Shared tail of `process_include` / `process_include_next`: warn on a - /// miss, honour `#pragma once`, bound the include depth, and process + /// Shared tail of `process_include` / `process_include_next`: error on + /// a miss, honour `#pragma once`, bound the include depth, and process /// the resolved body. fn finish_include( &mut self, @@ -2721,19 +2709,22 @@ impl Preprocessor { filename: &str, ) -> Result { let Some((content, resolved_path)) = resolved else { - // Missing header. Push a warning into the same list - // the parser uses; the caller drains it through to - // `Program::warnings` after the compile finishes. - self.warnings.push(format!( - "{filename}:{line_no}: warning: include `{name}` not found, \ - dropping (no header search path or embedded header matched)" - )); + // Missing header is a hard error, as in gcc/clang: the + // directive cannot perform the replacement C99 6.10.2 + // requires, and continuing with an empty body miscompiles. if self.show_includes { let depth = self.include_stack.len() + 1; self.include_trace .push(format!("{} {} (missing)", "!".repeat(depth), name)); } - return Ok(String::new()); + return Err(C5Error::Compile(super::error::fmt_compile_err( + filename, + line_no, + &format!( + "include `{name}` not found \ + (no header search path or embedded header matched)" + ), + ))); }; // `#pragma once` dedups by the resolved path (file identity), // not the include spelling, so two different spellings that @@ -2985,33 +2976,6 @@ impl Blocklist<'_> { } } -/// Strip C-style `/* ... */` block comments and `// ...` line -/// comments from a single-line buffer. Used on the post-macro- -/// expansion `#if` expression where inlined comments would -/// otherwise confuse the expression tokenizer. -fn strip_comments(s: &str) -> String { - let mut out = String::with_capacity(s.len()); - let bytes = s.as_bytes(); - let mut i = 0; - while i < bytes.len() { - if bytes[i] == b'/' && bytes.get(i + 1) == Some(&b'*') { - i += 2; - while i + 1 < bytes.len() && !(bytes[i] == b'*' && bytes[i + 1] == b'/') { - i += 1; - } - i = (i + 2).min(bytes.len()); - out.push(' '); - continue; - } - if bytes[i] == b'/' && bytes.get(i + 1) == Some(&b'/') { - break; - } - out.push(bytes[i] as char); - i += 1; - } - out -} - /// Phase-3 comment removal: strip `/* ... */` block comments and /// `// ...` line comments from the entire source. Each comment is /// replaced by a single space so token boundaries are preserved @@ -3549,18 +3513,9 @@ fn parse_directive(rest: &str) -> Directive<'_> { if let Some(after) = rest.strip_prefix("define") { let after = after.trim_start(); let (name, rest_after_name) = split_ident(after); - // Strip `//` line comments from the macro body. Otherwise - // `#define X 42 // a constant` would expand to "42 // a - // constant", and the comment text would either swallow the - // rest of the substitution line (lexer treats `//` as - // line-comment) or land in the token stream and break - // parsing. C `/* ... */` comments inside macro bodies - // aren't supported elsewhere in this dialect, so we don't - // try to strip those. - let stripped = match rest_after_name.find("//") { - Some(i) => &rest_after_name[..i], - None => rest_after_name, - }; + // Comments were removed in translation phase 3 (C99 5.1.1.2) + // before directives execute, so `//` or `/*` remaining here + // can only be string- or char-literal content and must stay. // Function-like form: name immediately followed by `(`. The // C standard requires no whitespace between the name and the // open paren -- a space turns it into an object-like macro @@ -3568,7 +3523,7 @@ fn parse_directive(rest: &str) -> Directive<'_> { // to the object-like branch with the whole tail as the body, // matching how the lexer would see a syntactically broken // `#define`. - if let Some(after_paren) = stripped.strip_prefix('(') + if let Some(after_paren) = rest_after_name.strip_prefix('(') && let Some(close) = after_paren.find(')') { let params_str = &after_paren[..close]; @@ -3580,7 +3535,7 @@ fn parse_directive(rest: &str) -> Directive<'_> { }; return Directive::DefineFn(name, params, body); } - return Directive::Define(name, stripped.trim()); + return Directive::Define(name, rest_after_name.trim()); } if let Some(after) = rest.strip_prefix("undef") { return Directive::Undef(after.trim()); @@ -5398,6 +5353,31 @@ mod tests { assert!(!out.contains("// a constant")); } + #[test] + fn define_body_keeps_slashes_inside_string_literal() { + // Comment removal happens in translation phase 3 (C99 + // 5.1.1.2), where a quoted string is opaque; `//` and `/*` + // inside one are literal content, not comment openers. + let out = process( + "#define URL \"http://x.com/*y*/\"\n#define P 'a' // note\nconst char *u = URL;\nchar c = P;\n", + ); + assert!( + out.contains("const char *u = \"http://x.com/*y*/\";"), + "string body truncated:\n{out}" + ); + assert!(out.contains("char c = 'a';"), "{out}"); + } + + #[test] + fn if_string_comparison_keeps_slashes_inside_literal() { + // The `#if` expression strip must also treat literals as + // opaque; `//` inside a compared string is not a comment. + let src = "#define U \"a//b\"\n#if U == \"a//b\"\nint yes;\n#else\nint no;\n#endif\n"; + let out = process(src); + assert!(out.contains("int yes;"), "{out:?}"); + assert!(!out.contains("int no;"), "{out:?}"); + } + #[test] fn ifdef_keeps_active_branch() { let src = "#define FOO 1\n#ifdef FOO\nint a;\n#else\nint b;\n#endif\n"; @@ -5618,23 +5598,18 @@ mod tests { } #[test] - fn unknown_include_is_silently_dropped() { - // Headers not in the embedded registry no-op so legacy - // sources sprinkled with `#include ` keep building - // until a real header takes that slot. The compile keeps - // going; the warning surfaces separately via - // `pp.warnings`. + fn unknown_include_is_a_hard_error() { + // A header that resolves nowhere aborts the compile, as in + // gcc/clang; continuing with an empty body would miscompile. let mut pp = Preprocessor::new("macos-aarch64", Target::MacOSAarch64, "0.1.0"); - let out = pp + let err = pp .process("#include \nint main() { return 0; }\n") - .expect("preprocessor failed"); - assert!(out.contains("int main()")); - assert_eq!(pp.warnings.len(), 1); - assert!( - pp.warnings[0].contains("not found"), - "missing-include warning shape: {}", - pp.warnings[0] - ); + .expect_err("missing include must fail"); + let C5Error::Compile(msg) = err else { + panic!("expected a compile error"); + }; + assert!(msg.contains("not-a-real-header.h"), "{msg}"); + assert!(msg.contains("not found"), "{msg}"); } #[test] @@ -5846,7 +5821,7 @@ int x_2 = __COUNTER__; pp.set_show_includes(true); let _ = pp .process("#include \nint main() { return 0; }\n") - .expect("preprocessor failed"); + .expect_err("missing include must fail"); assert!( pp.include_trace .iter() @@ -5858,11 +5833,18 @@ int x_2 = __COUNTER__; #[test] fn quoted_include_form_is_recognised() { - // `"foo.h"` and `` go through the same registry today. - // The quoted form is still parsed -- we'd just look it up the - // same way -- so an unknown name no-ops cleanly. - let out = process("#include \"not-a-real-header.h\"\nint main() {}\n"); - assert!(out.contains("int main()")); + // `"foo.h"` resolves through the same search chain as + // `` (C99 6.10.2p2/p3), so a search-path hit works + // for both spellings. + let base = std::env::temp_dir().join(format!("badc-quoted-inc-{}", std::process::id())); + std::fs::create_dir_all(&base).unwrap(); + std::fs::write(base.join("foo.h"), "int from_quoted;\n").unwrap(); + let mut pp = Preprocessor::new("macos-aarch64", Target::MacOSAarch64, "0.1.0"); + pp.add_search_path(base.to_str().unwrap()); + let out = pp.process("#include \"foo.h\"\nint main() {}\n").unwrap(); + std::fs::remove_dir_all(&base).ok(); + assert!(out.contains("from_quoted"), "{out}"); + assert!(out.contains("int main()"), "{out}"); } #[test] From 293f58c81b9fbb2ddfd0071316573277cc5eeade Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 18:16:52 -0700 Subject: [PATCH 05/67] pe: sort the export name pointer table lexically PE/COFF orders the export name pointer table by name so the loader's import binding and GetProcAddress can binary-search it; the writer emitted declaration order, so a DLL whose exports were not declared alphabetically resolved names data-dependently (a miss surfaces as STATUS_ENTRYPOINT_NOT_FOUND). Emit the name pointers, the ordinal table, and the name strings in lexical order; AddressOfFunctions stays in declaration order and each name maps back through its ordinal. Co-Authored-By: Claude Fable 5 --- src/c5/object/pe.rs | 22 ++++--- src/c5/tests/codegen.rs | 128 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 7 deletions(-) diff --git a/src/c5/object/pe.rs b/src/c5/object/pe.rs index 6d2842791..285d3b985 100644 --- a/src/c5/object/pe.rs +++ b/src/c5/object/pe.rs @@ -1371,23 +1371,31 @@ fn build_export_directory( out.extend_from_slice(&rva.to_le_bytes()); } + // The name pointer table must be lexically ordered (the loader + // and GetProcAddress binary-search it); the parallel ordinal + // table maps each name back to its declaration-order + // AddressOfFunctions slot. + let mut by_name: Vec = (0..exports.len()).collect(); + by_name.sort_by(|&a, &b| exports[a].name.as_bytes().cmp(exports[b].name.as_bytes())); + // AddressOfNames -- RVA of each export's name string. let mut cur = strings_rva + dll_name.len() as u32 + 1; - for exp in exports { + for &i in &by_name { out.extend_from_slice(&cur.to_le_bytes()); - cur += exp.name.len() as u32 + 1; + cur += exports[i].name.len() as u32 + 1; } - // AddressOfNameOrdinals -- u16 ordinal per export. - for i in 0..n { + // AddressOfNameOrdinals -- u16 unbiased ordinal per name. + for &i in &by_name { out.extend_from_slice(&(i as u16).to_le_bytes()); } - // String blob: DLL name first, then each export name. + // String blob: DLL name first, then each export name in + // name-pointer-table order. out.extend_from_slice(dll_name.as_bytes()); out.push(0); - for exp in exports { - out.extend_from_slice(exp.name.as_bytes()); + for &i in &by_name { + out.extend_from_slice(exports[i].name.as_bytes()); out.push(0); } diff --git a/src/c5/tests/codegen.rs b/src/c5/tests/codegen.rs index 12104e193..74cd29e8d 100644 --- a/src/c5/tests/codegen.rs +++ b/src/c5/tests/codegen.rs @@ -1494,3 +1494,131 @@ fn debug_info_does_not_change_codegen() { ); } } + +/// PE/COFF orders the export name pointer table lexically: the loader's +/// import binding and GetProcAddress binary-search it, so a table in +/// declaration order resolves names data-dependently (a miss surfaces as +/// STATUS_ENTRYPOINT_NOT_FOUND). Export in non-alphabetical declaration +/// order and byte-walk the emitted directory: the name table must come +/// out sorted with each name's ordinal still selecting its own +/// function's AddressOfFunctions slot. +#[test] +fn pe_export_name_table_is_lexically_sorted() { + use crate::c5::linker::{ + emit_x86_64_plt, link_native_objects, parse_native_elf, write_native_image_from_merged, + }; + use crate::{ + CompileOptions, Compiler, NativeOptions, OutputKind, Target, emit_native_with_options, + }; + // Each function carries a unique imm32 marker so the export's + // resolved address can be tied back to the right body. + let program = Compiler::with_options( + "#pragma export(zeta)\n\ + #pragma export(mike)\n\ + #pragma export(alpha)\n\ + int zeta(void) { return 0x5a17aa01; }\n\ + int mike(void) { return 0x5a17aa02; }\n\ + int alpha(void) { return 0x5a17aa03; }\n" + .to_string(), + Target::WindowsX64, + CompileOptions::default().with_no_entry_point(true), + ) + .compile() + .expect("compile export TU"); + let opts = NativeOptions { + output_kind: OutputKind::Relocatable, + ..Default::default() + }; + let bytes = emit_native_with_options(&program, Target::WindowsX64, opts).expect("emit"); + let obj = parse_native_elf(&bytes).expect("parse ET_REL"); + let mut merged = link_native_objects(&[obj]).expect("link"); + let plt = emit_x86_64_plt(&mut merged).expect("plt"); + let dll = write_native_image_from_merged( + &merged, + &plt, + "", + None, + OutputKind::SharedLibrary, + Target::WindowsX64, + Some("exp.dll"), + ) + .expect("write DLL"); + + let u16a = |o: usize| u16::from_le_bytes(dll[o..o + 2].try_into().unwrap()); + let u32a = |o: usize| u32::from_le_bytes(dll[o..o + 4].try_into().unwrap()); + let pe = u32a(0x3c) as usize; + let opt = pe + 24; + // Section table maps RVAs to file offsets. + let num_sections = u16a(pe + 6) as usize; + let opt_size = u16a(pe + 20) as usize; + let sec_table = pe + 24 + opt_size; + let rva_to_off = |rva: u32| -> usize { + for s in 0..num_sections { + let sh = sec_table + s * 40; + let va = u32a(sh + 12); + let vsize = u32a(sh + 8); + let raw_off = u32a(sh + 20); + if rva >= va && rva < va + vsize { + return (raw_off + (rva - va)) as usize; + } + } + panic!("rva {rva:#x} outside every section"); + }; + let cstr_at = |off: usize| -> alloc::string::String { + let end = dll[off..] + .iter() + .position(|&c| c == 0) + .map_or(off, |n| off + n); + alloc::string::String::from_utf8_lossy(&dll[off..end]).into_owned() + }; + // Data directory 0 is the Export Directory (PE32+: opt + 112). + let edata_rva = u32a(opt + 112); + assert_ne!(edata_rva, 0, "DLL must carry an export directory"); + let ed = rva_to_off(edata_rva); + let n_names = u32a(ed + 24) as usize; + assert_eq!(n_names, 3); + let funcs_off = rva_to_off(u32a(ed + 28)); + let names_off = rva_to_off(u32a(ed + 32)); + let ords_off = rva_to_off(u32a(ed + 36)); + + let names: alloc::vec::Vec = (0..n_names) + .map(|i| cstr_at(rva_to_off(u32a(names_off + 4 * i)))) + .collect(); + assert_eq!( + names, + ["alpha", "mike", "zeta"], + "name pointer table must be lexically sorted" + ); + // Ground truth per function: the file offset of its unique marker. + let marker_off = |imm: u32| -> usize { + let needle = imm.to_le_bytes(); + let hits: alloc::vec::Vec = dll + .windows(4) + .enumerate() + .filter(|(_, w)| *w == needle) + .map(|(i, _)| i) + .collect(); + assert_eq!(hits.len(), 1, "marker {imm:#x} must be unique"); + hits[0] + }; + let markers = [ + ("zeta", marker_off(0x5a17aa01)), + ("mike", marker_off(0x5a17aa02)), + ("alpha", marker_off(0x5a17aa03)), + ]; + for (i, name) in names.iter().enumerate() { + let ordinal = u16a(ords_off + 2 * i) as usize; + let fn_off = rva_to_off(u32a(funcs_off + 4 * ordinal)); + // The nearest marker at or past the function's entry must be + // this export's own -- the ordinal table maps name -> body. + let (owner, _) = markers + .iter() + .filter(|&&(_, m)| m >= fn_off) + .min_by_key(|&&(_, m)| m) + .expect("a marker must follow the entry"); + assert_eq!( + owner, name, + "export `{name}` (ordinal {ordinal}) must resolve to its own body" + ); + } +} From 58bf282a94e0972dc14648aab6956286cb5ae792 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 18:17:22 -0700 Subject: [PATCH 06/67] link: honor sh_addralign through data concat and image placement Data-family sections were byte-concatenated with sh_addralign ignored and the merged stream placed at an 8-aligned base, so a foreign object's 16-byte constant pool (clang/gcc -O2 `.rodata.cst16`) could land misaligned and legacy-SSE aligned loads fault at runtime. Pad the family blob to each section's alignment when parsing, carry the maximum through NativeObject / MergedNative / Build, align each unit's base in the merged `.data`, and place the data section at that alignment in the writers: ELF rounds `data_off` past `.got` (p_vaddr tracks p_offset), Mach-O rounds `__data`'s in-segment offset and records the section alignment; PE's `.data` RVA is already page-aligned. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/aarch64/encode.rs | 1 + src/c5/codegen/mod.rs | 5 + src/c5/codegen/x86_64/encode.rs | 1 + src/c5/linker/image.rs | 1 + src/c5/linker/link.rs | 16 ++- src/c5/linker/object.rs | 17 ++++ src/c5/linker/synth_build.rs | 2 + src/c5/object/elf.rs | 13 ++- src/c5/object/elf_reloc.rs | 1 + src/c5/object/mach_o.rs | 14 ++- src/c5/tests/codegen.rs | 162 +++++++++++++++++++++++++++++++ 11 files changed, 226 insertions(+), 7 deletions(-) diff --git a/src/c5/codegen/aarch64/encode.rs b/src/c5/codegen/aarch64/encode.rs index 3c6e5ab05..b4b12be1e 100644 --- a/src/c5/codegen/aarch64/encode.rs +++ b/src/c5/codegen/aarch64/encode.rs @@ -1866,6 +1866,7 @@ pub(crate) fn lower( copy_relocs: Vec::new(), text: code, data: program.data.clone(), + data_align: 8, bss_size: 0, entry_offset, got_fixups, diff --git a/src/c5/codegen/mod.rs b/src/c5/codegen/mod.rs index dd02e3704..d7c27e3b4 100644 --- a/src/c5/codegen/mod.rs +++ b/src/c5/codegen/mod.rs @@ -1175,6 +1175,11 @@ pub(crate) struct Build { /// segment, so a `DataFixup { data_offset: K }` resolves to /// byte K of this `Vec`. pub data: Vec, + /// Base alignment `data` requires in the image, at least 8. + /// Raised past 8 only by linked foreign sections with a larger + /// sh_addralign (e.g. `.rodata.cst16`); the writers place the + /// data section at a multiple of it. + pub data_align: usize, /// Bytes of zero-initialised data placed past the file image, in the /// `[data.len(), data.len() + bss_size)` offset range. Carries no file /// storage: the loader zero-fills it (ELF `p_memsz > p_filesz`, PE diff --git a/src/c5/codegen/x86_64/encode.rs b/src/c5/codegen/x86_64/encode.rs index fb1d44a6d..218ee4a6a 100644 --- a/src/c5/codegen/x86_64/encode.rs +++ b/src/c5/codegen/x86_64/encode.rs @@ -2303,6 +2303,7 @@ pub(crate) fn lower( copy_relocs: Vec::new(), text: code, data: program.data.clone(), + data_align: 8, bss_size: 0, entry_offset, got_fixups, diff --git a/src/c5/linker/image.rs b/src/c5/linker/image.rs index 580eb39d6..eed2d7912 100644 --- a/src/c5/linker/image.rs +++ b/src/c5/linker/image.rs @@ -1033,6 +1033,7 @@ mod tests { // x86_64: `mov eax, 42; ret` -- minimal main body. text: alloc::vec![0xb8, 0x2a, 0x00, 0x00, 0x00, 0xc3], data: alloc::vec![], + data_align: 8, bss_size: 0, defined, imports: alloc::vec![], diff --git a/src/c5/linker/link.rs b/src/c5/linker/link.rs index 62e015c36..17c632139 100644 --- a/src/c5/linker/link.rs +++ b/src/c5/linker/link.rs @@ -49,6 +49,10 @@ pub struct MergedNative { pub text: Vec, /// Concatenated `.data` bytes. pub data: Vec, + /// Base alignment the merged `.data` requires: the largest input + /// section alignment, at least 8. The image writers place the + /// data stream at a multiple of this. + pub data_align: usize, /// Sum of every unit's `.bss` size. The final-image writer /// emits a single `.bss` of this size; no file bytes. pub bss_size: usize, @@ -357,18 +361,21 @@ pub fn link_native_objects_with_options( // Pass 1 -- layout. Compute each unit's `.text` / `.data` / // `.bss` base in the merged image. 16-byte alignment for // `.text` (matches the writer's section header) and 8-byte - // for `.data` / `.bss`. + // for `.data` / `.bss`, raised to a unit's own data alignment + // (a foreign object's high-align sections, e.g. `.rodata.cst16`). let mut text_bases: Vec = Vec::with_capacity(objs.len()); let mut data_bases: Vec = Vec::with_capacity(objs.len()); let mut bss_bases: Vec = Vec::with_capacity(objs.len()); let mut text: Vec = Vec::new(); let mut data: Vec = Vec::new(); let mut bss_size: usize = 0; + let mut data_align: usize = 8; for obj in objs { align_up(&mut text, 16); text_bases.push(text.len()); text.extend_from_slice(&obj.text); - align_up(&mut data, 8); + align_up(&mut data, obj.data_align.max(8)); + data_align = data_align.max(obj.data_align); data_bases.push(data.len()); data.extend_from_slice(&obj.data); bss_size = align_usize(bss_size, 8); @@ -1172,6 +1179,7 @@ pub fn link_native_objects_with_options( Ok(MergedNative { text, data, + data_align, bss_size, defined, imports, @@ -2099,6 +2107,7 @@ mod tests { machine: NativeMachine::X86_64, text: alloc::vec::Vec::new(), data: alloc::vec::Vec::new(), + data_align: 1, bss_size: 0, tls_data: alloc::vec::Vec::new(), tls_bss_size: 0, @@ -2168,6 +2177,7 @@ mod tests { machine: NativeMachine::X86_64, text: alloc::vec::Vec::new(), data: alloc::vec::Vec::new(), + data_align: 1, bss_size: 0, tls_data: alloc::vec::Vec::new(), tls_bss_size: 0, @@ -2212,6 +2222,7 @@ mod tests { machine: NativeMachine::X86_64, text: alloc::vec::Vec::new(), data: alloc::vec![0u8; 4], + data_align: 1, bss_size: 0, tls_data: alloc::vec::Vec::new(), tls_bss_size: 0, @@ -2286,6 +2297,7 @@ mod tests { machine: NativeMachine::X86_64, text, data, + data_align: 1, bss_size: 0, tls_data: alloc::vec::Vec::new(), tls_bss_size: 0, diff --git a/src/c5/linker/object.rs b/src/c5/linker/object.rs index 7ab488c9d..eb5eb531c 100644 --- a/src/c5/linker/object.rs +++ b/src/c5/linker/object.rs @@ -340,6 +340,10 @@ pub struct NativeObject { pub machine: NativeMachine, pub text: Vec, pub data: Vec, + /// Largest sh_addralign among the data-family sections. The linker + /// aligns this object's base in the merged `.data` to it and the + /// image writers keep the merged stream's base alignment. + pub data_align: usize, /// Size of the `.bss` section in bytes. The reader doesn't /// allocate bytes for it (the writer doesn't either -- /// `SHT_NOBITS` records size but no file content). @@ -620,6 +624,7 @@ pub fn parse_native_elf(bytes: &[u8]) -> Result { text_bytes.extend_from_slice(section_slice(bytes, sh)?); } let mut data_bytes: Vec = Vec::new(); + let mut data_align: usize = 1; let mut data_base_per_shndx: Vec<(usize, u64)> = Vec::with_capacity(data_section_indices.len()); for &sh_i in &data_section_indices { let sh = &shdrs[sh_i]; @@ -628,6 +633,17 @@ pub fn parse_native_elf(bytes: &[u8]) -> Result { "data-family section at index {sh_i} has sh_type SHT_NOBITS (must hold file bytes)", ))); } + // Honor the section's sh_addralign (e.g. `.rodata.cst16` carries + // 16 for SSE constants): pad the merged blob before appending and + // carry the maximum outward so the image placement keeps it. + let align = sh.sh_addralign.max(1) as usize; + if !align.is_power_of_two() { + return Err(err(&format!( + "data-family section at index {sh_i} has non-power-of-two sh_addralign {align}", + ))); + } + data_align = data_align.max(align); + data_bytes.resize(data_bytes.len().next_multiple_of(align), 0); let base = data_bytes.len() as u64; data_base_per_shndx.push((sh_i, base)); data_bytes.extend_from_slice(section_slice(bytes, sh)?); @@ -1025,6 +1041,7 @@ pub fn parse_native_elf(bytes: &[u8]) -> Result { machine, text: text_bytes, data: data_bytes, + data_align, bss_size, tls_data: tls_data_bytes, tls_bss_size, diff --git a/src/c5/linker/synth_build.rs b/src/c5/linker/synth_build.rs index 5a98dab1d..fad8cdc9b 100644 --- a/src/c5/linker/synth_build.rs +++ b/src/c5/linker/synth_build.rs @@ -339,6 +339,7 @@ fn synth_program_and_build( dynamic_exports, text: merged.text.clone(), data: merged.data.clone(), + data_align: merged.data_align, bss_size: merged.bss_size as i64, entry_offset, got_fixups, @@ -953,6 +954,7 @@ mod tests { // aarch64: `mov w0, #42; ret`. text: alloc::vec![0x40, 0x05, 0x80, 0x52, 0xc0, 0x03, 0x5f, 0xd6], data: alloc::vec![], + data_align: 8, bss_size: 0, defined, imports: alloc::vec![], diff --git a/src/c5/object/elf.rs b/src/c5/object/elf.rs index 60c5713cd..ab02c8e0b 100644 --- a/src/c5/object/elf.rs +++ b/src/c5/object/elf.rs @@ -1627,7 +1627,10 @@ pub(super) fn write( let dynamic_size = (build.imports.dylibs.len() as u64 + 11 + version_dyn_tags) * ELF64_DYN_SIZE; let got_off = dynamic_off + dynamic_size; let got_size = (n_imports as u64) * 8; - let data_off = got_off + got_size; + // `.data`'s base alignment: p_vaddr == p_offset within the RW + // segment, so aligning the file offset aligns the vaddr. + let data_align = build.data_align.max(8) as u64; + let data_off = round_up(got_off + got_size, data_align); let data_size = build.data.len() as u64; // PT_TLS requires `p_vaddr % p_align == 0` (ELF gABI), and glibc // computes a `_Thread_local`'s address as `tp - roundup(p_memsz, @@ -2216,6 +2219,11 @@ pub(super) fn write( // .got -- one zero-filled u64 per import. Loader fills these in // via .rela.dyn / R_AARCH64_GLOB_DAT before _start runs. out.extend(vec![0u8; got_size as usize]); + // Pad to the aligned `data_off` (see the layout). + while (out.len() as u64) < data_off { + out.push(0); + } + debug_assert_eq!(out.len() as u64, data_off); // build.data -- the program's static data segment, with // pointer-to-global initializers resolved to absolute VAs. @@ -2568,7 +2576,7 @@ pub(super) fn write( sh_size: data_size, sh_link: 0, sh_info: 0, - sh_addralign: 8, + sh_addralign: data_align, sh_entsize: 0, }, ); @@ -2906,6 +2914,7 @@ mod tests { copy_relocs: Default::default(), text: vec![0x40, 0x05, 0x80, 0xD2, 0xC0, 0x03, 0x5F, 0xD6], data: Vec::new(), + data_align: 8, bss_size: 0, entry_offset: 0, got_fixups: Vec::new(), diff --git a/src/c5/object/elf_reloc.rs b/src/c5/object/elf_reloc.rs index d0c40872a..74c9a0d91 100644 --- a/src/c5/object/elf_reloc.rs +++ b/src/c5/object/elf_reloc.rs @@ -1776,6 +1776,7 @@ mod tests { copy_relocs: Default::default(), text: Vec::new(), data: Vec::new(), + data_align: 8, bss_size: 0, entry_offset: 0, got_fixups: Vec::new(), diff --git a/src/c5/object/mach_o.rs b/src/c5/object/mach_o.rs index 23ad7b31e..7a49e69cc 100644 --- a/src/c5/object/mach_o.rs +++ b/src/c5/object/mach_o.rs @@ -753,6 +753,7 @@ fn segment_data_with_tlv( data_addr: u64, data_size: u64, data_offset: u32, + data_align_log2: u32, thread_vars_addr: u64, thread_vars_size: u64, thread_vars_offset: u32, @@ -809,7 +810,7 @@ fn segment_data_with_tlv( addr: data_addr, size: data_size, offset: data_offset, - align: 3, + align: data_align_log2, reloff: 0, nreloc: 0, flags: 0, @@ -924,6 +925,7 @@ fn segment_data( data_addr: u64, data_size: u64, data_offset: u32, + data_align_log2: u32, bss_addr: u64, bss_size: u64, ) -> Vec { @@ -979,7 +981,7 @@ fn segment_data( addr: data_addr, size: data_size, offset: data_offset, - align: 3, // log2 -- 8 bytes + align: data_align_log2, reloff: 0, nreloc: 0, flags: 0, // S_REGULAR @@ -1994,7 +1996,10 @@ pub(super) fn write(program: &Program, build: &Build) -> Result, C5Error let data_vmaddr = TEXT_VMADDR_BASE + text_vmsize; let got_size = (build.imports.imports.len() * 8) as u64; let got_section_offset_in_segment: u64 = 0; - let data_section_offset_in_segment: u64 = round_up(got_size, 8); + // __data's base alignment: the segment base is page-aligned, so + // aligning the in-segment offset aligns both fileoff and vmaddr. + let data_align = build.data_align.max(8) as u64; + let data_section_offset_in_segment: u64 = round_up(got_size, data_align); let program_data_size = build.data.len() as u64; let post_data_offset_in_segment: u64 = round_up(data_section_offset_in_segment + program_data_size, 8); @@ -2438,6 +2443,7 @@ pub(super) fn write(program: &Program, build: &Build) -> Result, C5Error data_section_vmaddr, program_data_size, data_section_fileoff as u32, + data_align.trailing_zeros(), thread_vars_vmaddr, thread_vars_size, thread_vars_fileoff as u32, @@ -2460,6 +2466,7 @@ pub(super) fn write(program: &Program, build: &Build) -> Result, C5Error data_section_vmaddr, program_data_size, data_section_fileoff as u32, + data_align.trailing_zeros(), bss_base_vmaddr, build.bss_size as u64, ) @@ -2831,6 +2838,7 @@ mod tests { // movz x0, #42 ; ret text: vec![0x40, 0x05, 0x80, 0xD2, 0xC0, 0x03, 0x5F, 0xD6], data: Vec::new(), + data_align: 8, bss_size: 0, entry_offset: 0, got_fixups: Vec::new(), diff --git a/src/c5/tests/codegen.rs b/src/c5/tests/codegen.rs index 74cd29e8d..7d6cb22ad 100644 --- a/src/c5/tests/codegen.rs +++ b/src/c5/tests/codegen.rs @@ -1622,3 +1622,165 @@ fn pe_export_name_table_is_lexically_sorted() { ); } } + +/// Minimal foreign ET_REL mirroring clang -O2's SSE constant pool: a +/// 4-byte `.rodata` (align 4) followed by `.rodata.cst16` (align 16) +/// holding `mask`, with a global object symbol `c16_mask` on it. +fn foreign_et_rel_with_cst16(mask: &[u8; 16]) -> alloc::vec::Vec { + let rodata: [u8; 4] = [1, 2, 3, 4]; + let strtab = b"\0c16_mask\0"; + let shstrtab = b"\0.rodata\0.rodata.cst16\0.symtab\0.strtab\0.shstrtab\0"; + let rodata_off = 64usize; + let cst16_off = rodata_off + rodata.len(); + let symtab_off = cst16_off + mask.len(); + // Elf64Sym pair: the null symbol, then GLOBAL OBJECT `c16_mask` + // at offset 0 of section 2 (`.rodata.cst16`). + let mut symtab = alloc::vec![0u8; 24]; + symtab.extend_from_slice(&1u32.to_le_bytes()); + symtab.push(0x11); // (STB_GLOBAL << 4) | STT_OBJECT + symtab.push(0); + symtab.extend_from_slice(&2u16.to_le_bytes()); + symtab.extend_from_slice(&0u64.to_le_bytes()); + symtab.extend_from_slice(&16u64.to_le_bytes()); + let strtab_off = symtab_off + symtab.len(); + let shstr_off = strtab_off + strtab.len(); + let shoff = (shstr_off + shstrtab.len()).next_multiple_of(8); + + let mut out = alloc::vec![0u8; 64]; + out[0..4].copy_from_slice(b"\x7fELF"); + out[4] = 2; // ELFCLASS64 + out[5] = 1; // ELFDATA2LSB + out[6] = 1; // EV_CURRENT + out[16..18].copy_from_slice(&1u16.to_le_bytes()); // ET_REL + out[18..20].copy_from_slice(&62u16.to_le_bytes()); // EM_X86_64 + out[20..24].copy_from_slice(&1u32.to_le_bytes()); // e_version + out[40..48].copy_from_slice(&(shoff as u64).to_le_bytes()); + out[52..54].copy_from_slice(&64u16.to_le_bytes()); // e_ehsize + out[58..60].copy_from_slice(&64u16.to_le_bytes()); // e_shentsize + out[60..62].copy_from_slice(&6u16.to_le_bytes()); // e_shnum + out[62..64].copy_from_slice(&5u16.to_le_bytes()); // e_shstrndx + out.extend_from_slice(&rodata); + out.extend_from_slice(mask); + out.extend_from_slice(&symtab); + out.extend_from_slice(strtab); + out.extend_from_slice(shstrtab); + out.resize(shoff, 0); + let mut shdr = |name: u32, + ty: u32, + flags: u64, + off: usize, + size: usize, + link: u32, + info: u32, + align: u64, + entsize: u64| { + out.extend_from_slice(&name.to_le_bytes()); + out.extend_from_slice(&ty.to_le_bytes()); + out.extend_from_slice(&flags.to_le_bytes()); + out.extend_from_slice(&0u64.to_le_bytes()); // sh_addr + out.extend_from_slice(&(off as u64).to_le_bytes()); + out.extend_from_slice(&(size as u64).to_le_bytes()); + out.extend_from_slice(&link.to_le_bytes()); + out.extend_from_slice(&info.to_le_bytes()); + out.extend_from_slice(&align.to_le_bytes()); + out.extend_from_slice(&entsize.to_le_bytes()); + }; + shdr(0, 0, 0, 0, 0, 0, 0, 0, 0); + shdr(1, 1, 2, rodata_off, rodata.len(), 0, 0, 4, 0); // .rodata + shdr(9, 1, 2, cst16_off, mask.len(), 0, 0, 16, 0); // .rodata.cst16 + shdr(23, 2, 0, symtab_off, symtab.len(), 4, 1, 8, 24); // .symtab + shdr(31, 3, 0, strtab_off, strtab.len(), 0, 0, 1, 0); // .strtab + shdr(39, 3, 0, shstr_off, shstrtab.len(), 0, 0, 1, 0); // .shstrtab + out +} + +/// `(sh_addr, sh_offset)` of the named section in an ELF64 image. +fn elf64_shdr_addr_off(b: &[u8], want: &str) -> Option<(u64, u64)> { + let u16a = |o: usize| u16::from_le_bytes(b[o..o + 2].try_into().unwrap()); + let u32a = |o: usize| u32::from_le_bytes(b[o..o + 4].try_into().unwrap()); + let u64a = |o: usize| u64::from_le_bytes(b[o..o + 8].try_into().unwrap()); + let shoff = u64a(0x28) as usize; + let shentsize = u16a(0x3a) as usize; + let shnum = u16a(0x3c) as usize; + let shstrndx = u16a(0x3e) as usize; + let str_off = u64a(shoff + shstrndx * shentsize + 0x18) as usize; + for i in 0..shnum { + let sh = shoff + i * shentsize; + let name_off = str_off + u32a(sh) as usize; + let end = b[name_off..] + .iter() + .position(|&c| c == 0) + .map_or(name_off, |n| name_off + n); + if &b[name_off..end] == want.as_bytes() { + return Some((u64a(sh + 0x10), u64a(sh + 0x18))); + } + } + None +} + +/// A foreign object's `.rodata.cst16`-style section (sh_addralign 16 -- +/// clang/gcc -O2 SSE constant pools) must keep its alignment through the +/// family concatenation, the unit merge, and the final image placement: +/// legacy-SSE aligned loads (`xorps`/`movaps`) fault on a misaligned +/// operand. Link the foreign object after a badc unit and check the +/// constant's final vaddr. +#[test] +fn foreign_cst16_section_lands_sixteen_aligned_in_image() { + use crate::c5::linker::{ + emit_x86_64_plt, link_native_objects, parse_native_elf, write_native_image_from_merged, + }; + use crate::{NativeOptions, OutputKind, Target, emit_native_with_options}; + let mask: [u8; 16] = [ + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, + 0xaf, + ]; + let foreign = parse_native_elf(&foreign_et_rel_with_cst16(&mask)).expect("parse foreign"); + assert_eq!(foreign.data_align, 16, "sh_addralign must be recorded"); + // Intra-object: the 4-byte `.rodata` ahead forces 12 bytes of pad. + assert_eq!(&foreign.data[16..32], &mask); + + // A badc unit with an import so the image carries `.dynamic` and a + // non-empty `.got` ahead of `.data` (the placement the alignment + // rounding must correct). + let program = super::compile_str_bare( + "int puts(const char *s); \ + int main(void) { return puts(\"x\"); }", + ); + let opts = NativeOptions { + output_kind: OutputKind::Relocatable, + ..Default::default() + }; + let bytes = emit_native_with_options(&program, Target::LinuxX64, opts).expect("emit"); + let tu = parse_native_elf(&bytes).expect("parse TU"); + let mut merged = link_native_objects(&[tu, foreign]).expect("link"); + assert_eq!(merged.data_align, 16, "merge must carry the max alignment"); + let sym_value = merged + .defined + .get("c16_mask") + .expect("foreign data symbol must survive the merge") + .value; + assert_eq!(sym_value % 16, 0, "merged .data offset must stay aligned"); + let plt = emit_x86_64_plt(&mut merged).expect("plt"); + let exe = write_native_image_from_merged( + &merged, + &plt, + "main", + None, + OutputKind::Executable, + Target::LinuxX64, + None, + ) + .expect("write executable"); + let (data_addr, data_off) = elf64_shdr_addr_off(&exe, ".data").expect(".data section header"); + assert_eq!( + (data_addr + sym_value) % 16, + 0, + "the 16-byte constant's runtime address must be 16-aligned" + ); + let at = (data_off + sym_value) as usize; + assert_eq!( + &exe[at..at + 16], + &mask, + "the constant's bytes must land at the placed offset" + ); +} From e4a9840c0c20bdbe3dd4ed70030ff51c6389fdba Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 18:27:56 -0700 Subject: [PATCH 07/67] aggregate: allocate packed bitfield storage in the trailing repack repack_struct skipped bitfield members without reserving their storage, so `struct { int flags:8; char c; } __attribute__((packed))` got sizeof 1 with both members at offset 0 and a store to `c` corrupted `flags`. The repack now lays bitfields out at the bit level with no storage-unit padding -- the gcc/clang packed layout; C99 6.7.2.1p11 leaves the unit implementation-defined -- places the next non-bitfield member at the following byte boundary, and re-derives each bitfield's addressable unit as the smallest 1/2/4/8-byte window covering its bits, slid back from the struct's tail so the read-modify-write span stays in bounds. Co-Authored-By: Claude Fable 5 --- src/c5/compiler/aggregate.rs | 40 +++++++++++++--- src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + tests/fixtures/c/packed_bitfield_repack.c | 57 +++++++++++++++++++++++ 8 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 tests/fixtures/c/packed_bitfield_repack.c diff --git a/src/c5/compiler/aggregate.rs b/src/c5/compiler/aggregate.rs index dbce15ded..2f743c33b 100644 --- a/src/c5/compiler/aggregate.rs +++ b/src/c5/compiler/aggregate.rs @@ -742,24 +742,35 @@ impl Compiler { /// semantics: no inter-member padding and an alignment of 1. Used /// when the attribute marker follows the body, after the fields were /// placed at their natural alignment. A union only loses its tail - /// padding (members already sit at offset 0). Bitfield members are - /// left at their computed offsets; the packed bit-layout rules are - /// not modeled here. + /// padding (members already sit at offset 0). Bitfields pack at the + /// bit level with no storage-unit padding (the GCC/clang packed + /// layout; C99 6.7.2.1p11 leaves the unit implementation-defined); + /// a non-bitfield member starts at the next byte boundary. pub(super) fn repack_struct(&mut self, struct_id: usize) { self.structs[struct_id].align = 1; if self.structs[struct_id].is_union { return; } let n = self.structs[struct_id].fields.len(); - let mut offset = 0usize; + let mut bit_cursor = 0usize; + let mut bitfields: Vec<(usize, usize)> = Vec::new(); for i in 0..n { let (ty, array_size, bit_width) = { let f = &self.structs[struct_id].fields[i]; (f.ty, f.array_size, f.bit_width) }; if bit_width > 0 { + // TODO: a field whose bits would span more than an + // 8-byte load window (start % 8 + width > 64) is bumped + // to the next byte; gcc packs it contiguously. + if bit_cursor % 8 + bit_width as usize > 64 { + bit_cursor = round_up(bit_cursor, 8); + } + bitfields.push((i, bit_cursor)); + bit_cursor += bit_width as usize; continue; } + let offset = bit_cursor.div_ceil(8); self.structs[struct_id].fields[i].offset = offset; let storage = if array_size > 0 { self.size_of_type(ty) * array_size as usize @@ -768,9 +779,26 @@ impl Compiler { } else { self.size_of_type(ty) }; - offset += storage; + bit_cursor = (offset + storage) * 8; + } + let size = bit_cursor.div_ceil(8).max(1); + // Each bitfield's addressable unit is the smallest 1/2/4/8-byte + // window covering its bits, slid back when it would extend past + // the struct's tail (a packed struct has no tail padding to + // absorb the read-modify-write span). + for (i, bit_start) in bitfields { + let width = self.structs[struct_id].fields[i].bit_width as usize; + let unit = (bit_start % 8 + width).div_ceil(8).next_power_of_two(); + let mut off = bit_start / 8; + if off + unit > size && unit <= size { + off = size - unit; + } + let f = &mut self.structs[struct_id].fields[i]; + f.offset = off; + f.bit_offset = (bit_start - off * 8) as u32; + f.bit_unit_size = unit as u8; } - self.structs[struct_id].size = offset.max(1); + self.structs[struct_id].size = size; } } diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index 0866e754d..3ef2f6fc5 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1539,6 +1539,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ // __tlv_bootstrap is future work). The native_elf and // native_elf_x64 runners validate the Linux paths once the // built ELF lands on the orb VMs. + ("packed_bitfield_repack.c", 0), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index c2a10683a..9fa68bb51 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -910,6 +910,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ // retry. Exits 0 when the auto-include path is wired up; // a `BuildError` on this entry means the retry regressed. ("auto_include_undeclared_libc.c", 0), + ("packed_bitfield_repack.c", 0), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index 18828fa52..5bfffbe98 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -700,6 +700,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ // Without that, `strtold` would land at 0.0 for any power-of- // two value (mantissa = 0, exponent only in v0's high half). ("strtold_aapcs_return.c", 0), + ("packed_bitfield_repack.c", 0), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 792a9e450..9408192e4 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -649,6 +649,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ // glibc's old @GLIBC_2.2.5 stub and 0 under the @@GLIBC_2.3.2 // default. ("elf_symbol_version_default.c", 0), + ("packed_bitfield_repack.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index 6b7ab2e70..f27fefb03 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -909,6 +909,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("setjmp_basic_stack.c", 0), ("setjmp_misaligned.c", 0), ("setjmp_longjmp_roundtrip.c", 0), + ("packed_bitfield_repack.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index 0c6780b98..beb7babe1 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -927,6 +927,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ // `setjmp_longjmp.c` can join this list. ("setjmp_basic_stack.c", 0), ("setjmp_misaligned.c", 0), + ("packed_bitfield_repack.c", 0), ]; #[test] diff --git a/tests/fixtures/c/packed_bitfield_repack.c b/tests/fixtures/c/packed_bitfield_repack.c new file mode 100644 index 000000000..363acbccb --- /dev/null +++ b/tests/fixtures/c/packed_bitfield_repack.c @@ -0,0 +1,57 @@ +// A struct with a trailing `__attribute__((packed))` re-lays its +// fields with no inter-member padding. Bitfield members must keep +// their storage: C99 6.7.2.1p11 leaves the addressable unit +// implementation-defined, and the packed layout (matching gcc and +// clang) allocates bitfields at the bit level, placing the next +// non-bitfield member at the following byte boundary. Sizes, +// offsets, and read-back values are checked against clang output. +// +// Returns 0 only when every check passes; each failure path +// returns a distinct nonzero code. + +#include + +struct A { int flags:8; char c; } __attribute__((packed)); +struct B { int a:17; int b:10; char c; } __attribute__((packed)); +struct C { char a:3; char b:7; char c; } __attribute__((packed)); +struct E { char c; int b:16; } __attribute__((packed)); + +struct A ga = { 85, 7 }; + +int main(void) { + if (sizeof(struct A) != 2 || offsetof(struct A, c) != 1) return 1; + if (sizeof(struct B) != 5 || offsetof(struct B, c) != 4) return 2; + if (sizeof(struct C) != 3 || offsetof(struct C, c) != 2) return 3; + if (sizeof(struct E) != 3) return 4; + + // Writing the plain member must not clobber the bitfield's + // storage unit (they overlapped when the repack dropped the + // bitfield's byte). + struct A a; + a.flags = 85; + a.c = 7; + if (a.flags != 85 || a.c != 7) return 5; + + // A run straddling byte boundaries packs contiguously. + struct B b; + b.a = 65000; + b.b = 500; + b.c = 9; + if (b.a != 65000 || b.b != 500 || b.c != 9) return 6; + + struct C c; + c.a = 3; + c.b = 60; + c.c = 4; + if (c.a != 3 || c.b != 60 || c.c != 4) return 7; + + // Trailing bitfield: the access window stays inside the struct. + struct E e; + e.c = 11; + e.b = 30000; + if (e.c != 11 || e.b != 30000) return 8; + + // Static initializer merges into the packed unit. + if (ga.flags != 85 || ga.c != 7) return 9; + return 0; +} From d7d3c0e68eb7698777418f37f9b946f96e4963e0 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 18:28:48 -0700 Subject: [PATCH 08/67] initializer: nested-designator member dispatch, unbraced union conversion Two constant-initializer fixes sharing one member-dispatch path: A designator chain naming a char-array member (`.outer.inner = "s"`) stored the literal's address bytes with a mis-sized relocation instead of copying the array (C99 6.7.8p14). The per-member dispatch of fill_struct_fields is factored into fill_member_value and the chain now resolves to the final member's StructField, so a chain takes the same string / array / aggregate / bitfield shapes as a directly named member; the runtime local path gains the matching string-copy branch. An unbraced union member of a struct fell into the scalar path, which wrote the raw integer bits over the whole union with no conversion to the first named member's type (C99 6.7.8p17), and write_init_bytes wrapped the byte shift past 8 bytes, repeating the pattern at offset 8 (a debug build panicked on the shift). The unbraced union now routes through fill_struct_fields, which converts and stores one value into the first named member and stops; struct_flat_init_slots counts a union as its first member's slots; write_init_bytes zero-fills past the value's 8 significant bytes. Co-Authored-By: Claude Fable 5 --- src/c5/compiler/initializer.rs | 617 +++++++++--------- src/c5/compiler/locals.rs | 45 +- src/c5/tests/jit.rs | 2 + src/c5/tests/native.rs | 2 + src/c5/tests/native_elf.rs | 2 + src/c5/tests/native_elf_x64.rs | 2 + src/c5/tests/native_pe_arm64.rs | 2 + src/c5/tests/native_pe_x64.rs | 2 + .../c/nested_designator_string_member.c | 31 + tests/fixtures/c/union_member_unbraced_init.c | 43 ++ 10 files changed, 448 insertions(+), 300 deletions(-) create mode 100644 tests/fixtures/c/nested_designator_string_member.c create mode 100644 tests/fixtures/c/union_member_unbraced_init.c diff --git a/src/c5/compiler/initializer.rs b/src/c5/compiler/initializer.rs index 6cb9e3b80..d6fab27a9 100644 --- a/src/c5/compiler/initializer.rs +++ b/src/c5/compiler/initializer.rs @@ -208,12 +208,10 @@ impl Compiler { /// `self.data` at byte offset `here`. Caller has already /// grown `self.data` to at least `here + n_bytes`. fn write_init_bytes(&mut self, here: usize, value: i64, n_bytes: usize) { - if n_bytes == 1 { - self.data[here] = value as u8; - } else { - for i in 0..n_bytes { - self.data[here + i] = ((value >> (i * 8)) & 0xFF) as u8; - } + // `value` carries at most 8 significant bytes; zero a wider + // destination's tail rather than wrapping the shift count. + for i in 0..n_bytes { + self.data[here + i] = if i < 8 { (value >> (i * 8)) as u8 } else { 0 }; } } @@ -1405,17 +1403,19 @@ impl Compiler { } /// Walk a C99 6.7.8p7 designator-chain tail (the part after the - /// first `.field` has already been consumed) and resolve it - /// down to a concrete `(byte_offset, type)` pair for the value - /// site. Accepts further `.member` steps; `[index]` sub-array - /// designators surface as a parse error until they are wired - /// up. The current type must be a value-typed struct or union - /// for any `.` step. + /// first `.field` has already been consumed) and resolve it down + /// to the final member: its absolute byte offset and its + /// `StructField` record (so the caller sees array / bitfield + /// shape, not just the element type). Accepts further `.member` + /// steps; `[index]` sub-array designators surface as a parse + /// error until they are wired up. The current type must be a + /// value-typed struct or union for any `.` step. pub(super) fn resolve_nested_designator_chain( &mut self, mut cur_offset: i64, mut cur_ty: i64, - ) -> Result<(i64, i64), C5Error> { + ) -> Result<(i64, super::StructField), C5Error> { + let mut last: Option = None; while self.lex.tk == Token::Dot || self.lex.tk == Token::Brak { if self.lex.tk == Token::Dot { if !is_struct_ty(cur_ty) || struct_ptr_depth(cur_ty) != 0 { @@ -1443,13 +1443,16 @@ impl Compiler { let sub = self.structs[sid].fields[sub_idx].clone(); cur_offset += sub.offset as i64; cur_ty = sub.ty; + last = Some(sub); } else { return Err(self.compile_err( "`[N]` sub-designator inside a struct chain is not yet supported", )); } } - Ok((cur_offset, cur_ty)) + let field = + last.ok_or_else(|| self.compile_err("empty designator chain after `.field`"))?; + Ok((cur_offset, field)) } /// Collect a `{ ... }` struct initializer. Each entry can be @@ -1460,14 +1463,15 @@ impl Compiler { /// Number of scalar initializer positions a struct consumes in a /// brace-elided (flat) list (C99 6.7.8p20). A scalar / pointer / /// bitfield field is one; an array of N elements is N times the - /// element type's count; a nested struct recurses; an anonymous - /// union contributes its first member's count only (its - /// alternatives share one positional slot). + /// element type's count; a nested struct recurses; a union -- + /// named or anonymous -- contributes its first member's count + /// only (6.7.8p17: one initializer, for the first named member). pub(super) fn struct_flat_init_slots(&self, struct_id: usize) -> usize { let fields = self.structs[struct_id].fields.clone(); + let is_union = self.structs[struct_id].is_union; let mut total = 0usize; let mut i = 0; - while i < fields.len() { + while i < fields.len() && (!is_union || i == 0) { let f = &fields[i]; let elem = if is_struct_ty(f.ty) && struct_ptr_depth(f.ty) == 0 { self.struct_flat_init_slots(struct_id_of(f.ty)) @@ -1695,22 +1699,27 @@ impl Compiler { // C99 6.7.8p7: a designator list may be a chain of // `.member` and `[index]` steps. `.outer.inner = v` // is equivalent to `.outer = { .inner = v }`. Walk - // the chain to compute the cumulative byte offset - // and the final field's type, then store the value - // there directly. Falls through to the existing + // the chain to the final member, then initialize it + // through the shared member dispatch so a char-array + // member takes a string literal (6.7.8p14) and a + // bitfield merges into its unit, exactly as when the + // member is named directly. Falls through to the // single-level path when no extra steps follow. if self.lex.tk == Token::Dot || self.lex.tk == Token::Brak { let outer = self.structs[struct_id].fields[outer_idx].clone(); let chain_base = (var_offset as usize) + outer.offset; - let (final_offset, final_ty) = + let (final_offset, final_field) = self.resolve_nested_designator_chain(chain_base as i64, outer.ty)?; if self.lex.tk != Token::Assign { return Err(self.compile_err("`=` expected after nested-designator chain")); } self.next()?; - let (value, reloc) = self.parse_constant_init_value()?; - let size = self.size_of_type(final_ty); - self.write_init_value(final_offset as usize, size, value, reloc, final_ty); + self.skip_opt_compound_literal_cast()?; + let chain_parens = core::mem::take(&mut self.pending.compound_lit_close_parens); + self.fill_member_value(struct_id, &final_field, final_offset as usize)?; + for _ in 0..chain_parens { + self.accept(')')?; + } pos = outer_idx + 1; self.accept(',')?; continue; @@ -1856,303 +1865,315 @@ impl Compiler { self.accept(',')?; continue; } - // Three field shapes get nested `{ ... }` initializers: - // * array field (`T xs[N]`) - // * value-typed nested struct - // * value-typed nested union - // Pointer / scalar / bitfield fields read a single - // constant-expression value via parse_constant_init_value. - // C99 6.7.9p14: a char-array member may be initialized by a - // string literal optionally enclosed in braces - // (`struct S { char a[N]; } x = { {"..."} };`). Unwrap a - // single `{ "..." }` so the string-copy path handles it; a - // multi-dimensional char array (`char c[2][6] = {"a","b"}`, - // one string per row) keeps the brace as a per-row list. - let mut char_array_brace_string = false; - if field.array_size > 0 - && field.inner_array_size == 0 - && (field.ty & !UNSIGNED_BIT) == Ty::Char as i64 - && self.lex.tk == '{' - { - let snap = self.lex.snapshot(); - // Peeking the inner string token appends its bytes to the - // data segment; restore the length too if it is not a - // brace-wrapped string after all. - let data_snap = self.data.len(); - self.next()?; - if self.lex.tk == '"' { - char_array_brace_string = true; - } else { - self.lex.restore(snap); - self.data.truncate(data_snap); - } + self.fill_member_value(struct_id, &field, field_base)?; + // Consume the grouping `)` that wrapped a parenthesized + // compound literal element (`((T){...})`), counted while the + // cast was stripped above. + for _ in 0..close_parens { + self.accept(')')?; } - // A string literal initializing a char array may be enclosed - // in parentheses (C99 6.5.1 -- a parenthesized expression has - // the same value; `._data = ("str")` is the form a macro - // produces). Skip the leading `(` so the string-copy path - // below sees the literal; the matching `)`s are consumed after - // the copy. Without this the parenthesized leaf falls into the - // single-value path and stores the string's pointer. - let mut char_array_paren_depth = 0usize; - if field.array_size > 0 - && field.inner_array_size == 0 - && (field.ty & !UNSIGNED_BIT) == Ty::Char as i64 - && self.lex.tk == '(' - { - let snap = self.lex.snapshot(); - let data_snap = self.data.len(); - let mut depth = 0usize; - while self.lex.tk == '(' { - depth += 1; - self.next()?; + // A positional initializer fills the first member of an + // anonymous union (C99 6.7.8); the remaining members share + // its storage, so advance past the whole group rather than + // landing on the next alternative. + pos = field_idx + 1; + let group = field.anon_union_group; + if group != 0 { + let fields = &self.structs[struct_id].fields; + while pos < fields.len() && fields[pos].anon_union_group == group { + pos += 1; } - if self.lex.tk == '"' { - char_array_paren_depth = depth; + } + self.accept(',')?; + // C99 6.7.8p17: without designators a union takes a single + // initializer, for its first named member; in a brace-elided + // context stop there rather than consuming values meant for + // the surrounding aggregate's next members. + if !braced && self.structs[struct_id].is_union { + break; + } + } + Ok(()) + } + + /// Initialize one member at `field_base` from the current token + /// position, dispatching on the member's shape: + /// * char-array member from a string literal (C99 6.7.8p14), + /// optionally brace- or paren-wrapped + /// * array member from a brace list or a brace-elided flat list + /// (6.7.8p20) + /// * nested struct / union member, braced or brace-elided + /// * bitfield member (read-modify-write of its storage unit) + /// * scalar / pointer member from a single constant expression + /// Shared by the positional walk in `fill_struct_fields` and the + /// nested-designator path, so `.outer.inner = value` takes the + /// same shapes as a directly named member. `struct_id` is the + /// containing aggregate (error text only). + fn fill_member_value( + &mut self, + struct_id: usize, + field: &super::StructField, + field_base: usize, + ) -> Result<(), C5Error> { + let mut char_array_brace_string = false; + if field.array_size > 0 + && field.inner_array_size == 0 + && (field.ty & !UNSIGNED_BIT) == Ty::Char as i64 + && self.lex.tk == '{' + { + let snap = self.lex.snapshot(); + // Peeking the inner string token appends its bytes to the + // data segment; restore the length too if it is not a + // brace-wrapped string after all. + let data_snap = self.data.len(); + self.next()?; + if self.lex.tk == '"' { + char_array_brace_string = true; + } else { + self.lex.restore(snap); + self.data.truncate(data_snap); + } + } + // A string literal initializing a char array may be enclosed + // in parentheses (C99 6.5.1 -- a parenthesized expression has + // the same value; `._data = ("str")` is the form a macro + // produces). Skip the leading `(` so the string-copy path + // below sees the literal; the matching `)`s are consumed after + // the copy. Without this the parenthesized leaf falls into the + // single-value path and stores the string's pointer. + let mut char_array_paren_depth = 0usize; + if field.array_size > 0 + && field.inner_array_size == 0 + && (field.ty & !UNSIGNED_BIT) == Ty::Char as i64 + && self.lex.tk == '(' + { + let snap = self.lex.snapshot(); + let data_snap = self.data.len(); + let mut depth = 0usize; + while self.lex.tk == '(' { + depth += 1; + self.next()?; + } + if self.lex.tk == '"' { + char_array_paren_depth = depth; + } else { + self.lex.restore(snap); + self.data.truncate(data_snap); + } + } + if field.array_size > 0 + && self.lex.tk == '"' + && (field.ty & !UNSIGNED_BIT) == Ty::Char as i64 + { + // `struct S { char a[N]; } x = { "..." };` -- copy the + // string bytes (including the trailing NUL) into the + // char-array field, padding the remainder with zeroes. + // Without this branch the parser falls into the + // single-value path and writes the *pointer* to the + // string's data-segment slot into the field's first + // 8 bytes, which produces garbage at read time. + let start_addr = self.take_concat_string_literal()?; + self.data.push(0); // ensure NUL terminator + let max = field.array_size as usize; + let mut idx = 0usize; + while idx < max { + let b = if start_addr + idx < self.data.len() { + self.data[start_addr + idx] } else { - self.lex.restore(snap); - self.data.truncate(data_snap); + 0 + }; + self.write_init_value( + field_base + idx, + 1, + b as i64, + super::initializer::InitElemReloc::None, + field.ty, + ); + idx += 1; + if start_addr + idx >= self.data.len() { + // Past the string; remainder stays zero. + // Still walk the loop so all `max` bytes are + // explicitly written (zeroed above by + // write_init_value when source byte is 0). } } - if field.array_size > 0 - && self.lex.tk == '"' - && (field.ty & !UNSIGNED_BIT) == Ty::Char as i64 - { - // `struct S { char a[N]; } x = { "..." };` -- copy the - // string bytes (including the trailing NUL) into the - // char-array field, padding the remainder with zeroes. - // Without this branch the parser falls into the - // single-value path and writes the *pointer* to the - // string's data-segment slot into the field's first - // 8 bytes, which produces garbage at read time. - let start_addr = self.take_concat_string_literal()?; - self.data.push(0); // ensure NUL terminator - let max = field.array_size as usize; - let mut idx = 0usize; - while idx < max { - let b = if start_addr + idx < self.data.len() { - self.data[start_addr + idx] - } else { - 0 - }; - self.write_init_value( - field_base + idx, - 1, - b as i64, - super::initializer::InitElemReloc::None, - field.ty, - ); - idx += 1; - if start_addr + idx >= self.data.len() { - // Past the string; remainder stays zero. - // Still walk the loop so all `max` bytes are - // explicitly written (zeroed above by - // write_init_value when source byte is 0). - } - } - if char_array_brace_string { - self.expect_close_brace_after_wrapped_string()?; - } - for _ in 0..char_array_paren_depth { - if self.lex.tk != ')' { - return Err(self.compile_err( - "`)` expected to close a parenthesized string initializer", - )); - } - self.next()?; + if char_array_brace_string { + self.expect_close_brace_after_wrapped_string()?; + } + for _ in 0..char_array_paren_depth { + if self.lex.tk != ')' { + return Err(self + .compile_err("`)` expected to close a parenthesized string initializer")); } - } else if field.array_size > 0 && self.lex.tk == '{' { self.next()?; - let elem_size = self.size_of_type(field.ty); - // C99 6.7.8p21: a brace-enclosed initializer for the - // array member initializes every element; positions not - // named by a designator -- and any value left by an - // overridden duplicate initializer (6.7.8p19) -- are set - // to zero. Clear the member's region before applying the - // listed values. - let region = elem_size * field.array_size as usize; - for b in &mut self.data[field_base..field_base + region] { - *b = 0; - } - let elem_is_struct = is_struct_ty(field.ty) && struct_ptr_depth(field.ty) == 0; - let elem_sid = if elem_is_struct { - Some(struct_id_of(field.ty)) - } else { - None - }; - let mut idx: usize = 0; - while self.lex.tk != '}' { - // C99 6.7.8p7 array designator inside an array - // field's nested initializer. `[N] = value` - // jumps the write cursor to N; subsequent - // positional entries (or further `[K] = ...` - // clauses) continue from there. Mirrors the - // top-level array-init path in - // `collect_array_initializer`. - if self.lex.tk == Token::Brak { - self.next()?; - let n = self.parse_constant_int()?; - if n < 0 { - return Err(self.compile_err(format!( - "array designator index must be non-negative (got {n})" - ))); - } - if self.lex.tk != ']' { - return Err( - self.compile_err("`]` expected after array designator index") - ); - } - self.next()?; - if self.lex.tk != Token::Assign { - return Err(self.compile_err("`=` expected after `[N]` designator")); - } - self.next()?; - idx = n as usize; - } - if idx as i64 >= field.array_size { + } + } else if field.array_size > 0 && self.lex.tk == '{' { + self.next()?; + let elem_size = self.size_of_type(field.ty); + // C99 6.7.8p21: a brace-enclosed initializer for the + // array member initializes every element; positions not + // named by a designator -- and any value left by an + // overridden duplicate initializer (6.7.8p19) -- are set + // to zero. Clear the member's region before applying the + // listed values. + let region = elem_size * field.array_size as usize; + for b in &mut self.data[field_base..field_base + region] { + *b = 0; + } + let elem_is_struct = is_struct_ty(field.ty) && struct_ptr_depth(field.ty) == 0; + let elem_sid = if elem_is_struct { + Some(struct_id_of(field.ty)) + } else { + None + }; + let mut idx: usize = 0; + while self.lex.tk != '}' { + // C99 6.7.8p7 array designator inside an array + // field's nested initializer. `[N] = value` + // jumps the write cursor to N; subsequent + // positional entries (or further `[K] = ...` + // clauses) continue from there. Mirrors the + // top-level array-init path in + // `collect_array_initializer`. + if self.lex.tk == Token::Brak { + self.next()?; + let n = self.parse_constant_int()?; + if n < 0 { return Err(self.compile_err(format!( - "too many initializers for `{}.{}`", - self.structs[struct_id].name, field.name + "array designator index must be non-negative (got {n})" ))); } - let here = field_base + idx * elem_size; - // C99 6.7.8p20: an array-of-struct field accepts a - // nested brace-enclosed initializer for each element, - // and the element's braces may be elided. A `{ ... }` - // element routes through the struct collector; a - // brace-elided element consumes exactly that element's - // fields from the flat list via `fill_struct_fields`. - // Scalar element types fall through to the constant- - // value path. (Without the elided-element branch a - // flat list wrote a single scalar with the struct's - // byte width, overflowing `write_init_bytes`.) - if let Some(sid) = elem_sid { - if self.lex.tk == '{' { - self.collect_struct_initializer(sid, here as i64)?; - } else { - self.fill_struct_fields(sid, here as i64, false)?; - } - } else { - let (value, reloc) = self.parse_constant_init_value()?; - self.write_init_value(here, elem_size, value, reloc, field.ty); + if self.lex.tk != ']' { + return Err(self.compile_err("`]` expected after array designator index")); } - idx += 1; - self.accept(',')?; - } - self.next()?; // consume `}` - } else if field.array_size > 0 { - // C99 6.7.8p20 "implicit braces removed": a flat - // value list inside a struct initializer can fill - // an array field directly, without nested braces. - // Absorb up to `array_size` values from the - // surrounding brace list; the outer struct loop - // then advances to the next field on the - // following `,`. A canonical instance is - // struct { unsigned char c[4]; } v = { 1,2,3,4 }; - // where the inner array's brace pair is elided. - let elem_size = self.size_of_type(field.ty); - let mut idx: usize = 0; - while (idx as i64) < field.array_size && self.lex.tk != '}' { - let (value, reloc) = self.parse_constant_init_value()?; - let here = field_base + idx * elem_size; - self.write_init_value(here, elem_size, value, reloc, field.ty); - idx += 1; - if idx as i64 >= field.array_size { - break; + self.next()?; + if self.lex.tk != Token::Assign { + return Err(self.compile_err("`=` expected after `[N]` designator")); } - if self.lex.tk == ',' { - self.next()?; + self.next()?; + idx = n as usize; + } + if idx as i64 >= field.array_size { + return Err(self.compile_err(format!( + "too many initializers for `{}.{}`", + self.structs[struct_id].name, field.name + ))); + } + let here = field_base + idx * elem_size; + // C99 6.7.8p20: an array-of-struct field accepts a + // nested brace-enclosed initializer for each element, + // and the element's braces may be elided. A `{ ... }` + // element routes through the struct collector; a + // brace-elided element consumes exactly that element's + // fields from the flat list via `fill_struct_fields`. + // Scalar element types fall through to the constant- + // value path. (Without the elided-element branch a + // flat list wrote a single scalar with the struct's + // byte width, overflowing `write_init_bytes`.) + if let Some(sid) = elem_sid { + if self.lex.tk == '{' { + self.collect_struct_initializer(sid, here as i64)?; } else { - break; + self.fill_struct_fields(sid, here as i64, false)?; } - } - } else if is_struct_ty(field.ty) - && struct_ptr_depth(field.ty) == 0 - && (self.lex.tk == '{' || !self.structs[struct_id_of(field.ty)].is_union) - { - let nested_sid = struct_id_of(field.ty); - if self.lex.tk == '{' { - self.collect_struct_initializer(nested_sid, field_base as i64)?; } else { - // C99 6.7.8p20: a nested struct field's braces may be - // elided, filling its members from the surrounding flat - // list. Mirrors the array-of-struct element path. An - // unbraced union takes only its first member, handled by - // the single-value path below. - self.fill_struct_fields(nested_sid, field_base as i64, false)?; + let (value, reloc) = self.parse_constant_init_value()?; + self.write_init_value(here, elem_size, value, reloc, field.ty); } - } else if field.bit_width > 0 { - // Bitfield brace-initializer entry. C99 6.7.8 says - // the initializer's value is converted to the - // bitfield's type as if assigned. A naive - // `write_init_value(field_base, sizeof(base), value)` - // would clobber every other bitfield sharing the - // same storage unit -- adjacent fields in the same - // brace list each rewrite the entire unit. Merge - // the bitfield's bits into the existing storage - // unit instead. - let (value, _reloc) = self.parse_constant_init_value()?; - // C99 6.7.2.1p11: the bitfield's addressable storage - // unit width is determined by the declared base type; - // the RMW span must match `bit_unit_size` so it does - // not read or write outside the unit. - let unit_bytes = field.bit_unit_size as usize; - let mut unit_value: i64 = 0; - for i in 0..unit_bytes { - unit_value |= (self.data[field_base + i] as i64) << (i * 8); + idx += 1; + self.accept(',')?; + } + self.next()?; // consume `}` + } else if field.array_size > 0 { + // C99 6.7.8p20 "implicit braces removed": a flat + // value list inside a struct initializer can fill + // an array field directly, without nested braces. + // Absorb up to `array_size` values from the + // surrounding brace list; the outer struct loop + // then advances to the next field on the + // following `,`. A canonical instance is + // struct { unsigned char c[4]; } v = { 1,2,3,4 }; + // where the inner array's brace pair is elided. + let elem_size = self.size_of_type(field.ty); + let mut idx: usize = 0; + while (idx as i64) < field.array_size && self.lex.tk != '}' { + let (value, reloc) = self.parse_constant_init_value()?; + let here = field_base + idx * elem_size; + self.write_init_value(here, elem_size, value, reloc, field.ty); + idx += 1; + if idx as i64 >= field.array_size { + break; } - let bit_width = field.bit_width; - let bit_offset = field.bit_offset; - let mask: i64 = if bit_width >= 64 { - -1 + if self.lex.tk == ',' { + self.next()?; } else { - (1i64 << bit_width) - 1 - }; - let cleared = unit_value & !(mask << bit_offset); - let merged = cleared | ((value & mask) << bit_offset); - for i in 0..unit_bytes { - self.data[field_base + i] = ((merged >> (i * 8)) & 0xFF) as u8; + break; } + } + } else if is_struct_ty(field.ty) && struct_ptr_depth(field.ty) == 0 { + let nested_sid = struct_id_of(field.ty); + if self.lex.tk == '{' { + self.collect_struct_initializer(nested_sid, field_base as i64)?; } else { - // C99 6.7.9p11: a scalar member's initializer may be - // enclosed in braces (`{ .field = { expr } }`); strip a - // single wrapper, matching the runtime scalar path. - let braced_scalar = self.lex.tk == '{'; - if braced_scalar { - self.next()?; - } - let (value, reloc) = self.parse_constant_init_value()?; - let field_size = self.size_of_type(field.ty); - self.write_init_value(field_base, field_size, value, reloc, field.ty); - if braced_scalar { - self.accept(',')?; - if self.lex.tk != '}' { - return Err(self.compile_err( - "scalar initializer wrapped in `{ ... }` must hold a single value", - )); - } - self.next()?; // consume `}` - } + // C99 6.7.8p20: a nested aggregate field's braces may be + // elided, filling its members from the surrounding flat + // list. Mirrors the array-of-struct element path. For a + // union the recursion converts and stores one value into + // the first named member (6.7.8p17) and returns. + self.fill_struct_fields(nested_sid, field_base as i64, false)?; + } + } else if field.bit_width > 0 { + // Bitfield brace-initializer entry. C99 6.7.8 says + // the initializer's value is converted to the + // bitfield's type as if assigned. A naive + // `write_init_value(field_base, sizeof(base), value)` + // would clobber every other bitfield sharing the + // same storage unit -- adjacent fields in the same + // brace list each rewrite the entire unit. Merge + // the bitfield's bits into the existing storage + // unit instead. + let (value, _reloc) = self.parse_constant_init_value()?; + // C99 6.7.2.1p11: the bitfield's addressable storage + // unit width is determined by the declared base type; + // the RMW span must match `bit_unit_size` so it does + // not read or write outside the unit. + let unit_bytes = field.bit_unit_size as usize; + let mut unit_value: i64 = 0; + for i in 0..unit_bytes { + unit_value |= (self.data[field_base + i] as i64) << (i * 8); + } + let bit_width = field.bit_width; + let bit_offset = field.bit_offset; + let mask: i64 = if bit_width >= 64 { + -1 + } else { + (1i64 << bit_width) - 1 + }; + let cleared = unit_value & !(mask << bit_offset); + let merged = cleared | ((value & mask) << bit_offset); + for i in 0..unit_bytes { + self.data[field_base + i] = ((merged >> (i * 8)) & 0xFF) as u8; } - // Consume the grouping `)` that wrapped a parenthesized - // compound literal element (`((T){...})`), counted while the - // cast was stripped above. - for _ in 0..close_parens { - self.accept(')')?; + } else { + // C99 6.7.9p11: a scalar member's initializer may be + // enclosed in braces (`{ .field = { expr } }`); strip a + // single wrapper, matching the runtime scalar path. + let braced_scalar = self.lex.tk == '{'; + if braced_scalar { + self.next()?; } - // A positional initializer fills the first member of an - // anonymous union (C99 6.7.8); the remaining members share - // its storage, so advance past the whole group rather than - // landing on the next alternative. - pos = field_idx + 1; - let group = field.anon_union_group; - if group != 0 { - let fields = &self.structs[struct_id].fields; - while pos < fields.len() && fields[pos].anon_union_group == group { - pos += 1; + let (value, reloc) = self.parse_constant_init_value()?; + let field_size = self.size_of_type(field.ty); + self.write_init_value(field_base, field_size, value, reloc, field.ty); + if braced_scalar { + self.accept(',')?; + if self.lex.tk != '}' { + return Err(self.compile_err( + "scalar initializer wrapped in `{ ... }` must hold a single value", + )); } + self.next()?; // consume `}` } - self.accept(',')?; } Ok(()) } diff --git a/src/c5/compiler/locals.rs b/src/c5/compiler/locals.rs index 48993a1bc..a476805e7 100644 --- a/src/c5/compiler/locals.rs +++ b/src/c5/compiler/locals.rs @@ -1468,17 +1468,58 @@ impl Compiler { // C99 6.7.8p7 nested designator chain. See the // matching branch in `collect_struct_initializer` // for the constant-staging variant. Computes the - // cumulative offset / final type, then emits one + // cumulative offset / final member, then emits one // store at `&local + extra_offset + final_offset`. if self.lex.tk == Token::Dot || self.lex.tk == Token::Brak { let outer = self.structs[sid].fields[outer_idx].clone(); let chain_base = extra_offset + outer.offset as i64; - let (final_offset, final_ty) = + let (final_offset, final_field) = self.resolve_nested_designator_chain(chain_base, outer.ty)?; if self.lex.tk != Token::Assign { return Err(self.compile_err("`=` expected after nested-designator chain")); } self.next()?; + // A char-array final member takes a string literal + // (C99 6.7.8p14): per-byte constant stores, zero + // fill; mirrors the positional branch below. Other + // array or bitfield finals are rejected the same + // way the positional walk rejects them. + if final_field.array_size > 0 { + if self.lex.tk == '"' + && !self.lex.str_is_wide + && (final_field.ty & !UNSIGNED_BIT) == Ty::Char as i64 + { + let start_addr = self.take_concat_string_literal()?; + self.data.push(0); // ensure NUL terminator + for k in 0..final_field.array_size as usize { + let b = if start_addr + k < self.data.len() { + self.data[start_addr + k] as i64 + } else { + 0 + }; + let value = self.ast_emit_int_lit(b, Ty::Char as i64); + self.pending_local_runtime_elements.push( + super::super::ast::RuntimeInitElement { + offset: final_offset + k as i64, + value, + ty: Ty::Char as i64, + }, + ); + } + pos = outer_idx + 1; + self.accept(',')?; + continue; + } + return Err(self.compile_err( + "non-constant array-field initializer not yet supported", + )); + } + if final_field.bit_width > 0 { + return Err( + self.compile_err("non-constant bitfield initializer not yet supported") + ); + } + let final_ty = final_field.ty; self.emit_lea(local_val); if final_offset > 0 { self.ast_psh(); diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index 3ef2f6fc5..9d1b732e7 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1540,6 +1540,8 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ // native_elf_x64 runners validate the Linux paths once the // built ELF lands on the orb VMs. ("packed_bitfield_repack.c", 0), + ("nested_designator_string_member.c", 0), + ("union_member_unbraced_init.c", 0), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index 9fa68bb51..62419a76b 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -911,6 +911,8 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ // a `BuildError` on this entry means the retry regressed. ("auto_include_undeclared_libc.c", 0), ("packed_bitfield_repack.c", 0), + ("nested_designator_string_member.c", 0), + ("union_member_unbraced_init.c", 0), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index 5bfffbe98..e66c90228 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -701,6 +701,8 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ // two value (mantissa = 0, exponent only in v0's high half). ("strtold_aapcs_return.c", 0), ("packed_bitfield_repack.c", 0), + ("nested_designator_string_member.c", 0), + ("union_member_unbraced_init.c", 0), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 9408192e4..c690465c2 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -650,6 +650,8 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ // default. ("elf_symbol_version_default.c", 0), ("packed_bitfield_repack.c", 0), + ("nested_designator_string_member.c", 0), + ("union_member_unbraced_init.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index f27fefb03..a4a985c09 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -910,6 +910,8 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("setjmp_misaligned.c", 0), ("setjmp_longjmp_roundtrip.c", 0), ("packed_bitfield_repack.c", 0), + ("nested_designator_string_member.c", 0), + ("union_member_unbraced_init.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index beb7babe1..06e6f6c83 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -928,6 +928,8 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("setjmp_basic_stack.c", 0), ("setjmp_misaligned.c", 0), ("packed_bitfield_repack.c", 0), + ("nested_designator_string_member.c", 0), + ("union_member_unbraced_init.c", 0), ]; #[test] diff --git a/tests/fixtures/c/nested_designator_string_member.c b/tests/fixtures/c/nested_designator_string_member.c new file mode 100644 index 000000000..2903dd83e --- /dev/null +++ b/tests/fixtures/c/nested_designator_string_member.c @@ -0,0 +1,31 @@ +// C99 6.7.8p7/p14: a designator chain `.outer.inner = "str"` naming a +// char-array member copies the string's bytes (with zero fill), the +// same as naming the member directly; it must not store the literal's +// address. Checked for a static object (constant staging) and for an +// automatic object whose sibling values force the runtime store path. +// +// Returns 0 only when every check passes; each failure path +// returns a distinct nonzero code. + +struct In { int x; char name[8]; }; +struct Out { struct In in; int y; }; + +struct Out g = { .in.name = "abc", .y = 7, .in.x = 5 }; + +static int str_eq(const char *a, const char *b) { + while (*a && *a == *b) { a++; b++; } + return *a == *b; +} + +int main(int argc, char **argv) { + (void)argv; + if (!str_eq(g.in.name, "abc")) return 1; + if (g.in.name[3] != 0 || g.in.name[7] != 0) return 2; + if (g.y != 7 || g.in.x != 5) return 3; + + struct Out l = { .in.name = "wxyz", .y = argc + 6, .in.x = argc + 4 }; + if (!str_eq(l.in.name, "wxyz")) return 4; + if (l.in.name[4] != 0 || l.in.name[7] != 0) return 5; + if (l.y != argc + 6 || l.in.x != argc + 4) return 6; + return 0; +} diff --git a/tests/fixtures/c/union_member_unbraced_init.c b/tests/fixtures/c/union_member_unbraced_init.c new file mode 100644 index 000000000..0d35a0c57 --- /dev/null +++ b/tests/fixtures/c/union_member_unbraced_init.c @@ -0,0 +1,43 @@ +// C99 6.7.8p17: with its braces elided, a union member of a struct +// takes a single initializer for its first named member, converted as +// if by assignment. The integer 3 must land as the double 3.0, the +// following value goes to the next struct member, and a union wider +// than 8 bytes must not wrap the stored bytes at offset 8. +// +// Returns 0 only when every check passes; each failure path +// returns a distinct nonzero code. + +union U { double d; char pad[16]; }; +struct S { union U u; int tag; }; +struct S gs = { 3, 42 }; + +union U8 { double d; long l; }; +struct S8 { union U8 u; int tag; } gs8 = { 5, 43 }; + +// The first member may itself be an aggregate; elision continues +// into it (6.7.8p20). +union V { struct { int a; int b; } s; double d; }; +struct W { union V v; int t; } gw = { 1, 2, 9 }; + +struct S garr[2] = { 3, 42, 4, 43 }; + +int main(void) { + if (gs.u.d != 3.0 || gs.tag != 42) return 1; + // Bytes past offset 8 of the 16-byte union stay zero. + for (int i = 8; i < 16; i++) { + if (gs.u.pad[i] != 0) return 2; + } + if (gs8.u.d != 5.0 || gs8.tag != 43) return 3; + if (gw.v.s.a != 1 || gw.v.s.b != 2 || gw.t != 9) return 4; + if (garr[0].u.d != 3.0 || garr[0].tag != 42) return 5; + if (garr[1].u.d != 4.0 || garr[1].tag != 43) return 6; + + // Automatic storage with constant values follows the same path. + struct S l = { 3, 42 }; + if (l.u.d != 3.0 || l.tag != 42) return 7; + + // A braced union member is unaffected. + struct S lb = { { 6 }, 44 }; + if (lb.u.d != 6.0 || lb.tag != 44) return 8; + return 0; +} From 7a7f45facf824bca0ff50f269960e871e72931d4 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 18:33:46 -0700 Subject: [PATCH 09/67] headers: fix strtof/ioctl/shm_open bindings; runtime: C99 snprintf on Windows Four libc-surface fixes: * stdlib.h declares strtof as returning double (c5 aliases float to double), but Linux bound it to libc's float-returning strtof and Windows to a strtof msvcrt does not export. Bind to strtod on every OS, matching the prototype and the existing macOS binding. * Darwin's ioctl and shm_open are variadic and read the third argument via va_arg -- from the stack on arm64 -- so the fixed-arity prototypes passed it in x2 where the callee never looks (EFAULT for FIONREAD, garbage permission bits for shm_open). Declare ioctl variadic (POSIX XSH; glibc agrees) and shm_open variadic on Darwin only (glibc uses the fixed POSIX shape). Add the Linux FIO* request codes. * msvcrt's _snprintf/_vsnprintf return -1 and omit the NUL on truncation; C99 7.19.6.5p3 / 7.19.6.12p3 require the untruncated length and a NUL for size > 0. The runtime now defines conforming snprintf/vsnprintf over _vsnprintf + _vscprintf, gated on the new __BADC_C5_CRT__ (set for hosted executables and shared libraries; native/EFI and freestanding images stay CRT-import-free), and stdio.h drops the msvcrt bindings for the standard spellings so they resolve against the runtime. The underscored _snprintf and _vsnprintf spellings keep msvcrt semantics. Regression fixtures: strtof_parses_float, ioctl_fionread_pipe, shm_open_mode_arg (all pass on macOS arm64; fixed-arity ioctl counter-check returns 3), snprintf_truncation_c99 (Windows lanes run the runtime shim; POSIX lanes lock the libc contract), plus PE-level tests for the import shape and the CRT-only gate. Co-Authored-By: Claude Fable 5 --- headers/include/stdio.h | 45 +++-- headers/include/stdlib.h | 9 +- headers/include/sys/ioctl.h | 16 +- headers/include/sys/mman.h | 9 +- lib/runtime.c | 66 ++++++- src/c5/runtime.rs | 18 +- src/c5/tests/codegen.rs | 76 ++++++++ src/c5/tests/jit.rs | 2 + src/c5/tests/mod.rs | 14 +- src/c5/tests/native.rs | 4 + src/c5/tests/native_elf.rs | 4 + src/c5/tests/native_elf_x64.rs | 4 + src/c5/tests/native_pe_arm64.rs | 2 + src/c5/tests/native_pe_x64.rs | 2 + src/main.rs | 33 ++-- tests/fixtures/c/ioctl_fionread_pipe.c | 28 +++ tests/fixtures/c/shm_open_mode_arg.c | 31 ++++ tests/fixtures/c/snprintf_truncation_c99.c | 44 +++++ tests/fixtures/c/strtof_parses_float.c | 22 +++ .../asm/ioctl_fionread_pipe.aarch64.asm | 83 +++++++++ .../snapshots/asm/ioctl_fionread_pipe.x64.asm | 84 +++++++++ tests/snapshots/asm/posix_os_headers.x64.asm | 2 +- .../asm/shm_open_mode_arg.aarch64.asm | 80 ++++++++ tests/snapshots/asm/shm_open_mode_arg.x64.asm | 84 +++++++++ .../asm/snprintf_truncation_c99.aarch64.asm | 175 ++++++++++++++++++ .../asm/snprintf_truncation_c99.x64.asm | 158 ++++++++++++++++ .../asm/strtof_parses_float.aarch64.asm | 62 +++++++ .../snapshots/asm/strtof_parses_float.x64.asm | 67 +++++++ tests/snapshots/ssa/ioctl_fionread_pipe.ssa | 105 +++++++++++ tests/snapshots/ssa/shm_open_mode_arg.ssa | 107 +++++++++++ .../snapshots/ssa/snprintf_truncation_c99.ssa | 157 ++++++++++++++++ tests/snapshots/ssa/strtof_parses_float.ssa | 86 +++++++++ 32 files changed, 1622 insertions(+), 57 deletions(-) create mode 100644 tests/fixtures/c/ioctl_fionread_pipe.c create mode 100644 tests/fixtures/c/shm_open_mode_arg.c create mode 100644 tests/fixtures/c/snprintf_truncation_c99.c create mode 100644 tests/fixtures/c/strtof_parses_float.c create mode 100644 tests/snapshots/asm/ioctl_fionread_pipe.aarch64.asm create mode 100644 tests/snapshots/asm/ioctl_fionread_pipe.x64.asm create mode 100644 tests/snapshots/asm/shm_open_mode_arg.aarch64.asm create mode 100644 tests/snapshots/asm/shm_open_mode_arg.x64.asm create mode 100644 tests/snapshots/asm/snprintf_truncation_c99.aarch64.asm create mode 100644 tests/snapshots/asm/snprintf_truncation_c99.x64.asm create mode 100644 tests/snapshots/asm/strtof_parses_float.aarch64.asm create mode 100644 tests/snapshots/asm/strtof_parses_float.x64.asm create mode 100644 tests/snapshots/ssa/ioctl_fionread_pipe.ssa create mode 100644 tests/snapshots/ssa/shm_open_mode_arg.ssa create mode 100644 tests/snapshots/ssa/snprintf_truncation_c99.ssa create mode 100644 tests/snapshots/ssa/strtof_parses_float.ssa diff --git a/headers/include/stdio.h b/headers/include/stdio.h index c15e99e3a..dfa62c721 100644 --- a/headers/include/stdio.h +++ b/headers/include/stdio.h @@ -243,29 +243,31 @@ typedef struct __c5_fpos_t fpos_t; #pragma binding(msvcrt::wprintf, "wprintf") #pragma binding(msvcrt::fprintf, "fprintf") #pragma binding(msvcrt::sprintf, "sprintf") -// MSVC renamed the safe forms; the original `snprintf` only landed -// in msvcrt circa VS2015. `_snprintf` is the universally available -// spelling and behaves the same way for our usage (no NUL guarantee -// on overflow, but neither does our other targets' `snprintf` once -// the buffer fills). Note that msvcrt's printf family prints -// infinity / NaN as `1.#INF` / `1.#IND` / `1.#QNAN` rather than -// C99 `inf` / `nan`; programs that classify formatted output -// by a digit-prefix regex misclassify the msvcrt output as -// numeric. -// Routing through `ucrtbase._snprintf` would emit the C99 -// spelling but that entry point fails with -// STATUS_ENTRYPOINT_NOT_FOUND at PE load time on the GitHub -// Windows runners -- the documented UCRT import path is via the -// `api-ms-win-crt-stdio-l1-1-0.dll` proxy set, not ucrtbase -// directly. Tracked under the TODO marker until c5 grows +// The original `snprintf` only landed in msvcrt circa VS2015, and +// `_snprintf` deviates from C99 7.19.6.5 (returns -1 and omits the +// NUL on truncation). The standard `snprintf` / `vsnprintf` +// spellings carry no binding here: they resolve at link time against +// the conforming definitions in the auto-linked runtime, which wrap +// `_vsnprintf` + `_vscprintf`. The underscored spellings keep the +// msvcrt entry points for source written against msvcrt semantics. +// Note that msvcrt's printf family prints infinity / NaN as +// `1.#INF` / `1.#IND` / `1.#QNAN` rather than C99 `inf` / `nan`; +// programs that classify formatted output by a digit-prefix regex +// misclassify the msvcrt output as numeric. +// Routing through `ucrtbase` would emit the C99 spelling but its +// entry points fail with STATUS_ENTRYPOINT_NOT_FOUND at PE load +// time on the GitHub Windows runners -- the documented UCRT import +// path is via the `api-ms-win-crt-stdio-l1-1-0.dll` proxy set, not +// ucrtbase directly. Tracked under the TODO marker until c5 grows // support for the UCRT proxy DLLs. -#pragma binding(msvcrt::snprintf, "_snprintf") #pragma binding(msvcrt::_snprintf, "_snprintf") +#pragma binding(msvcrt::_vsnprintf,"_vsnprintf") #pragma binding(msvcrt::vprintf, "vprintf") #pragma binding(msvcrt::vfprintf, "vfprintf") #pragma binding(msvcrt::vsprintf, "vsprintf") -#pragma binding(msvcrt::vsnprintf, "_vsnprintf") -#pragma binding(msvcrt::_vsnprintf,"_vsnprintf") +// The runtime's `vsnprintf` needs a prototype on Windows; every +// other target binds the name straight to libc. +int vsnprintf(char *buf, int size, char *fmt, char *ap); #pragma binding(msvcrt::scanf, "scanf") #pragma binding(msvcrt::fscanf, "fscanf") #pragma binding(msvcrt::sscanf, "sscanf") @@ -797,9 +799,12 @@ static char *__c5_lazy_stream(int idx) { // Windows-flavoured sources spell the v* names with a leading underscore // (`#define vsnprintf _vsnprintf` is a common MSVC idiom). Alias the // underscored spellings to the canonical names so they resolve through the -// same per-target bindings -- on Windows the canonical names already bind -// to the underscored CRT entry points. +// same per-target bindings. On Windows `_vsnprintf` stays a direct msvcrt +// binding with msvcrt semantics; the canonical `vsnprintf` is the C99 +// definition in the auto-linked runtime. #define _vfprintf vfprintf #define _vprintf vprintf #define _vsprintf vsprintf +#ifndef _WIN32 #define _vsnprintf vsnprintf +#endif diff --git a/headers/include/stdlib.h b/headers/include/stdlib.h index f7a56aa68..d9f685f00 100644 --- a/headers/include/stdlib.h +++ b/headers/include/stdlib.h @@ -90,7 +90,10 @@ #pragma binding(libc::strtol, "strtol") #pragma binding(libc::strtoll, "strtoll") #pragma binding(libc::strtod, "strtod") -#pragma binding(libc::strtof, "strtof") +// The prototype below declares `strtof` as returning double (c5 +// aliases `float` to `double`), so the binding must target the +// double-returning entry point; libc's own `strtof` returns `float`. +#pragma binding(libc::strtof, "strtod") #pragma binding(libc::strtold, "strtold") #pragma binding(libc::abs, "abs") #pragma binding(libc::abort, "abort") @@ -155,7 +158,9 @@ #pragma binding(msvcrt::strtoull, "_strtoui64") #pragma binding(msvcrt::_strtoui64, "_strtoui64") #pragma binding(msvcrt::strtod, "strtod") -#pragma binding(msvcrt::strtof, "strtof") +// msvcrt.dll exports no `strtof` (a UCRT addition); `strtof` routes +// through `strtod`, matching the double-returning prototype below. +#pragma binding(msvcrt::strtof, "strtod") // msvcrt.dll has no `strtold`; UCRT exports it but the // universally-available CRT here does not. Programs that // need `long double` parsing on Windows pin to UCRT. diff --git a/headers/include/sys/ioctl.h b/headers/include/sys/ioctl.h index 7e2f63271..8f3c32585 100644 --- a/headers/include/sys/ioctl.h +++ b/headers/include/sys/ioctl.h @@ -32,32 +32,46 @@ struct winsize { #define TIOCGWINSZ 0x5413 #endif -int ioctl(int fd, unsigned long request, void *argp); +// POSIX (XSH) and both target libcs declare ioctl variadic; Darwin's +// wrapper reads the argument via va_arg, so a fixed-arity prototype +// passes it where the callee does not look (Darwin arm64 takes +// variadic arguments from the stack). +int ioctl(int fd, unsigned long request, ...); // ioctl request codes referenced by terminal/file modules. Per-target codes. #ifndef FIOASYNC #if defined(__APPLE__) #define FIOASYNC 2147772029 +#elif defined(__linux__) +#define FIOASYNC 0x5452 #endif #endif #ifndef FIOCLEX #if defined(__APPLE__) #define FIOCLEX 536897025 +#elif defined(__linux__) +#define FIOCLEX 0x5451 #endif #endif #ifndef FIONBIO #if defined(__APPLE__) #define FIONBIO 2147772030 +#elif defined(__linux__) +#define FIONBIO 0x5421 #endif #endif #ifndef FIONCLEX #if defined(__APPLE__) #define FIONCLEX 536897026 +#elif defined(__linux__) +#define FIONCLEX 0x5450 #endif #endif #ifndef FIONREAD #if defined(__APPLE__) #define FIONREAD 1074030207 +#elif defined(__linux__) +#define FIONREAD 0x541b #endif #endif #ifdef __APPLE__ diff --git a/headers/include/sys/mman.h b/headers/include/sys/mman.h index 795004982..8d22a0a70 100644 --- a/headers/include/sys/mman.h +++ b/headers/include/sys/mman.h @@ -83,6 +83,13 @@ char *mremap(char *old, unsigned long old_size, unsigned long new_size, int flag int msync(char *addr, unsigned long len, int flags); int mprotect(char *addr, unsigned long len, int prot); int madvise(char *addr, unsigned long len, int advice); -// POSIX shared memory objects; mode is mode_t (an unsigned int on the targets). +// POSIX shared memory objects; mode is mode_t (an unsigned int on the +// targets). Darwin declares shm_open variadic and reads the mode via +// va_arg (from the stack on arm64), so the prototype must match; glibc +// declares the fixed three-argument POSIX shape. +#ifdef __APPLE__ +int shm_open(const char *name, int oflag, ...); +#else int shm_open(const char *name, int oflag, int mode); +#endif int shm_unlink(const char *name); diff --git a/lib/runtime.c b/lib/runtime.c index 21d2ab387..5d756b968 100644 --- a/lib/runtime.c +++ b/lib/runtime.c @@ -5,13 +5,65 @@ // `embedded_headers` registry) and compiled + linked alongside the // user's translation units. // -// Everything here is gated on `__BADC_C5_START__`, which the driver -// defines only when the image writer emits an entry stub -- i.e. for -// a hosted executable. Shared libraries and passthrough-entry -// subsystems (native / EFI) leave it undefined and link none of it: -// they carry no user-mode CRT import (a kernel-mode driver cannot -// resolve `msvcrt!exit`), and `environ` belongs to the host process, -// not a library that imports it. +// Two gates, both defined by the driver: +// +// * `__BADC_C5_CRT__` -- the image may import the user-mode C +// library (hosted executables and shared libraries; native / EFI +// subsystems and freestanding images leave it undefined -- a +// kernel-mode driver cannot resolve `msvcrt!exit`). +// * `__BADC_C5_START__` -- the image writer emits an entry stub +// (hosted executables only). Shared libraries link the CRT section +// but not the startup section: `environ` belongs to the host +// process, not a library that imports it. + +#ifdef __BADC_C5_CRT__ +#ifdef _WIN32 + +// C99 7.19.6.5p3 / 7.19.6.12p3: snprintf / vsnprintf return the +// length the output would have had without truncation and always +// NUL-terminate a nonempty buffer. msvcrt's `_vsnprintf` returns -1 +// on truncation and omits the NUL, so the standard spellings resolve +// to these definitions (`` declares them without a binding +// on Windows); `_vscprintf` supplies the untruncated length. +#pragma dylib(libc, "msvcrt.dll") +#pragma binding(libc::_vsnprintf, "_vsnprintf") +#pragma binding(libc::_vscprintf, "_vscprintf") + +extern int _vsnprintf(char *buf, unsigned long long count, char *fmt, void *ap); +extern int _vscprintf(char *fmt, void *ap); + +int vsnprintf(char *buf, int size, char *fmt, void *ap) { + int len = _vscprintf(fmt, ap); + if (len < 0) { + return len; + } + if (size > 0) { + _vsnprintf(buf, size, fmt, ap); + if (len >= size) { + buf[size - 1] = 0; + } + } + return len; +} + +// Windows `va_list` is a byte cursor over the home area / stack +// (see ``); the intrinsics take the cursor's address. +#pragma intrinsic("__builtin_va_start") +#pragma intrinsic("__builtin_va_end") +void __builtin_va_start(void **ap, void *last_addr); +void __builtin_va_end(void **ap); + +int snprintf(char *buf, int size, char *fmt, ...) { + void *ap; + int len; + __builtin_va_start(&ap, (void *)&fmt); + len = vsnprintf(buf, size, fmt, ap); + __builtin_va_end(&ap); + return len; +} + +#endif +#endif #ifdef __BADC_C5_START__ diff --git a/src/c5/runtime.rs b/src/c5/runtime.rs index b8abf1468..a351fd920 100644 --- a/src/c5/runtime.rs +++ b/src/c5/runtime.rs @@ -8,14 +8,16 @@ //! native ELF ET_REL alongside the user's translation units. //! //! Single registry [`EMBEDDED_RUNTIME`]. Its one source -//! (`runtime.c`) gates everything -- the `environ` / `_environ` data -//! and the `__c5_exit` / `__c5_entry` startup -- on -//! `__BADC_C5_START__`, which the driver defines only when the image -//! writer emits an entry stub. Shared libraries and passthrough-entry -//! subsystems (native / EFI) leave it undefined, so the source -//! compiles to nothing for them: no user-mode CRT import, and no -//! `environ` definition (a library inherits it from the host -//! process). +//! (`runtime.c`) gates its sections on driver-defined macros: +//! `__BADC_C5_CRT__` (the image may import the user-mode C library -- +//! hosted executables and shared libraries) selects the Windows C99 +//! snprintf / vsnprintf definitions, and `__BADC_C5_START__` (an +//! entry stub is emitted -- hosted executables only) selects the +//! `environ` / `tzname` data and the `__c5_exit` / `__c5_entry` +//! startup. Passthrough-entry subsystems (native / EFI) and +//! freestanding images leave both undefined, so the source compiles +//! to nothing for them: no user-mode CRT import, and no `environ` +//! definition (a library inherits it from the host process). /// Runtime sources compiled + linked alongside the user's /// translation units on the native-link path. diff --git a/src/c5/tests/codegen.rs b/src/c5/tests/codegen.rs index 7d6cb22ad..4e5ec4ec0 100644 --- a/src/c5/tests/codegen.rs +++ b/src/c5/tests/codegen.rs @@ -496,6 +496,82 @@ fn data_import_routes_to_declaring_dylib_on_windows_x64() { ); } +/// C99 7.19.6.5p3 / 7.19.6.12p3: snprintf / vsnprintf return the +/// untruncated length and NUL-terminate a nonempty buffer; msvcrt's +/// `_snprintf` / `_vsnprintf` return -1 and omit the NUL. The standard +/// spellings therefore carry no msvcrt binding on Windows: they resolve +/// against the runtime's conforming definitions, which wrap +/// `_vsnprintf` + `_vscprintf`. +#[test] +fn windows_snprintf_resolves_to_the_runtime_definition() { + use crate::{CompileOptions, Compiler, NativeOptions, Target}; + for target in [Target::WindowsX64, Target::WindowsAarch64] { + let program = Compiler::with_options( + "#include \n\ + int main(void){char b[4]; return snprintf(b, 4, \"%d\", 123456);}\n" + .to_string(), + target, + CompileOptions::default().with_no_entry_point(true), + ) + .compile() + .expect("compile snprintf TU"); + let image = super::link_executable_with_runtime(&program, target, NativeOptions::default()) + .expect("link Windows executable"); + for imported in ["_vscprintf", "_vsnprintf"] { + assert_eq!( + pe_import_dll_of(&image, imported).as_deref(), + Some("msvcrt.dll"), + "{target:?}: the runtime definition must import `{imported}`" + ); + } + for absent in ["_snprintf", "snprintf", "vsnprintf"] { + assert!( + pe_iat_slot_rva(&image, absent).is_none(), + "{target:?}: `{absent}` must not appear in the import table" + ); + } + } +} + +/// A shared library compiles the runtime with `__BADC_C5_CRT__` but +/// without the startup gate; the CRT section alone must still define +/// the C99 snprintf / vsnprintf so a DLL's calls resolve locally. +#[test] +fn windows_runtime_crt_section_defines_snprintf_without_start_gate() { + use crate::{ + CompileOptions, Compiler, NativeOptions, OutputKind, Target, embedded_runtime, + link_native_objects, parse_native_elf, + }; + let target = Target::WindowsX64; + let reloc = NativeOptions { + output_kind: OutputKind::Relocatable, + ..Default::default() + }; + let mut objs = Vec::new(); + for (name, body) in embedded_runtime() { + let copts = CompileOptions::default() + .with_no_entry_point(true) + .with_defines(vec![("__BADC_C5_CRT__".to_string(), "1".to_string())]); + let rt = Compiler::with_options(body.to_string(), target, copts) + .compile() + .unwrap_or_else(|e| panic!("compile runtime {name}: {e}")); + let bytes = crate::emit_native_with_options(&rt, target, reloc) + .unwrap_or_else(|e| panic!("emit runtime {name}: {e}")); + objs.push(parse_native_elf(&bytes).expect("parse runtime object")); + } + let merged = link_native_objects(&objs).expect("link CRT-only runtime"); + for def in ["snprintf", "vsnprintf"] { + assert!( + merged.defined.contains_key(def), + "the CRT section must define `{def}`" + ); + } + assert!( + !merged.defined.contains_key("__c5_entry"), + "the startup section must stay gated out" + ); +} + /// Return the `(VirtualAddress, raw bytes)` of the PE `.text` /// section. RVA-relative byte scans use the VirtualAddress; the raw /// bytes are the section's file image. diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index 9d1b732e7..1b20f5bf8 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1087,6 +1087,8 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("variadic_struct_arg.c", 18), ("variadic_struct_arg_16b.c", 51), ("libc_div.c", 0), + ("strtof_parses_float.c", 0), + ("snprintf_truncation_c99.c", 0), ("strength_reduce_pow2_divmod.c", 0), ("return_callee_saved_value.c", 0), ("spill_slot_reuse_disjoint_calls.c", 0), diff --git a/src/c5/tests/mod.rs b/src/c5/tests/mod.rs index 0ace32560..139803667 100644 --- a/src/c5/tests/mod.rs +++ b/src/c5/tests/mod.rs @@ -140,12 +140,14 @@ pub fn link_executable_with_runtime( objs.push(parse_native_elf(&prog_bytes).map_err(|e| format!("parse program object: {e}"))?); // This helper always builds a hosted executable, so the runtime's - // startup section is compiled in (`__BADC_C5_START__`). + // CRT and startup sections are both compiled in. // The entry shape follows the entry symbol: `__BADC_WIN_WINMAIN__` // for a `WinMain` entry, `__BADC_WIN_WIDE__` for `wmain`, else `main` // with argc/argv -- independent of the PE subsystem. - let mut rt_defines: Vec<(String, String)> = - vec![("__BADC_C5_START__".to_string(), "1".to_string())]; + let mut rt_defines: Vec<(String, String)> = vec![ + ("__BADC_C5_CRT__".to_string(), "1".to_string()), + ("__BADC_C5_START__".to_string(), "1".to_string()), + ]; rt_defines.push(( "__BADC_ENTRY__".to_string(), program @@ -218,8 +220,10 @@ pub fn link_executable_with_runtime_multi( // PLT pass numbers trampolines in object order, so the order must be // stable across linkers. let mut objs = Vec::new(); - let mut rt_defines: Vec<(String, String)> = - vec![("__BADC_C5_START__".to_string(), "1".to_string())]; + let mut rt_defines: Vec<(String, String)> = vec![ + ("__BADC_C5_CRT__".to_string(), "1".to_string()), + ("__BADC_C5_START__".to_string(), "1".to_string()), + ]; rt_defines.push(( "__BADC_ENTRY__".to_string(), entry diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index 62419a76b..b1f0265b1 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -378,6 +378,10 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("variadic_struct_arg.c", 18), ("variadic_struct_arg_16b.c", 51), ("libc_div.c", 0), + ("strtof_parses_float.c", 0), + ("snprintf_truncation_c99.c", 0), + ("ioctl_fionread_pipe.c", 0), + ("shm_open_mode_arg.c", 0), ("wide_string_literal_alignment.c", 0), ("va_arg_through_pointer.c", 0), ("pthread_key_once_width.c", 0), diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index e66c90228..4ed036712 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -324,6 +324,10 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("variadic_struct_arg.c", 18), ("variadic_struct_arg_16b.c", 51), ("libc_div.c", 0), + ("strtof_parses_float.c", 0), + ("snprintf_truncation_c99.c", 0), + ("ioctl_fionread_pipe.c", 0), + ("shm_open_mode_arg.c", 0), ("strength_reduce_pow2_divmod.c", 0), ("return_callee_saved_value.c", 0), ("spill_slot_reuse_disjoint_calls.c", 0), diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index c690465c2..32b0565f2 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -284,6 +284,10 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("variadic_struct_arg.c", 18), ("variadic_struct_arg_16b.c", 51), ("libc_div.c", 0), + ("strtof_parses_float.c", 0), + ("snprintf_truncation_c99.c", 0), + ("ioctl_fionread_pipe.c", 0), + ("shm_open_mode_arg.c", 0), ("wide_string_literal_alignment.c", 0), ("va_arg_through_pointer.c", 0), ("pthread_key_once_width.c", 0), diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index a4a985c09..21c9e5115 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -620,6 +620,8 @@ fn build_and_run_fixture_with_options(name: &str, opts: NativeOptions, suffix: & /// are arch-independent. const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("arithmetic.c", 60), + ("strtof_parses_float.c", 0), + ("snprintf_truncation_c99.c", 0), ("control_flow.c", 1), ("do_while.c", 5), ("break_continue.c", 4), diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index 06e6f6c83..e8f08fdc5 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -633,6 +633,8 @@ fn build_and_run_fixture_with_options(name: &str, opts: NativeOptions, suffix: & /// POSIX-only semantics. const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("arithmetic.c", 60), + ("strtof_parses_float.c", 0), + ("snprintf_truncation_c99.c", 0), ("control_flow.c", 1), ("do_while.c", 5), ("break_continue.c", 4), diff --git a/src/main.rs b/src/main.rs index 272c6124b..9d529a1da 100644 --- a/src/main.rs +++ b/src/main.rs @@ -933,9 +933,11 @@ fn main() { // below: same compile + emit chain, no filesystem read. let compile_in_memory = |label: &str, src: String, extra: &[(&str, &str)]| -> Vec { // The embedded runtime gates its sections on macros the - // driver sets per image: `__BADC_C5_START__` (an entry - // stub is emitted), `__BADC_WIN_WINMAIN__` (WinMain-shaped - // entry), `__BADC_WIN_WIDE__` (wide `wmain` / `wWinMain` entry). + // driver sets per image: `__BADC_C5_CRT__` (the image may + // import the user-mode C library), `__BADC_C5_START__` + // (an entry stub is emitted), `__BADC_WIN_WINMAIN__` + // (WinMain-shaped entry), `__BADC_WIN_WIDE__` (wide + // `wmain` / `wWinMain` entry). let mut copts_defines = defines.clone(); for (k, v) in extra { copts_defines.push((k.to_string(), v.to_string())); @@ -1025,12 +1027,12 @@ fn main() { std::process::exit(1); } } - // The embedded runtime's startup (`__c5_entry`, `__c5_exit`, - // `environ`) links only when the writer emits an entry stub -- - // not into shared libraries, passthrough-entry subsystems - // (native / EFI), or freestanding images. - let emits_start_stub = mode != Mode::SharedLibrary - && !freestanding + // The runtime's CRT section (the C99 snprintf / vsnprintf + // definitions on Windows) links into any image that may + // import the user-mode C library -- hosted executables and + // shared libraries, but not passthrough-entry subsystems + // (native / EFI) or freestanding images. + let links_crt = !freestanding && !matches!( subsystem_override, Some( @@ -1041,10 +1043,17 @@ fn main() { | badc::Subsystem::EfiRom ) ); - // The single runtime source compiles to nothing unless - // `__BADC_C5_START__` is set; the GUI / wide-entry macros - // select the matching `__c5_entry` body on Windows. + // The startup section (`__c5_entry`, `__c5_exit`, `environ`) + // links only when the writer emits an entry stub -- not into + // shared libraries. + let emits_start_stub = mode != Mode::SharedLibrary && links_crt; + // The single runtime source compiles to nothing unless a gate + // macro is set; the GUI / wide-entry macros select the + // matching `__c5_entry` body on Windows. let mut runtime_defines: Vec<(&str, &str)> = Vec::new(); + if links_crt { + runtime_defines.push(("__BADC_C5_CRT__", "1")); + } if emits_start_stub { runtime_defines.push(("__BADC_C5_START__", "1")); // `__c5_entry` calls this symbol; default `main`, diff --git a/tests/fixtures/c/ioctl_fionread_pipe.c b/tests/fixtures/c/ioctl_fionread_pipe.c new file mode 100644 index 000000000..a7a13070b --- /dev/null +++ b/tests/fixtures/c/ioctl_fionread_pipe.c @@ -0,0 +1,28 @@ +// POSIX (XSH) declares ioctl variadic and both target libcs read the +// argument via va_arg -- on Darwin arm64 from the stack, so a caller +// compiled against a fixed-arity prototype passes the pointer where +// the callee does not look and FIONREAD faults with EFAULT. A pipe +// holding 5 unread bytes must report 5. + +#include +#include + +int main(void) { + int fds[2]; + int n = 0; + if (pipe(fds) != 0) { + return 1; + } + if (write(fds[1], "hello", 5) != 5) { + return 2; + } + if (ioctl(fds[0], FIONREAD, &n) != 0) { + return 3; + } + if (n != 5) { + return 4; + } + close(fds[0]); + close(fds[1]); + return 0; +} diff --git a/tests/fixtures/c/shm_open_mode_arg.c b/tests/fixtures/c/shm_open_mode_arg.c new file mode 100644 index 000000000..edc7b28ce --- /dev/null +++ b/tests/fixtures/c/shm_open_mode_arg.c @@ -0,0 +1,31 @@ +// Darwin declares shm_open variadic and fetches the mode via va_arg +// (from the stack on arm64); a caller compiled against a fixed-arity +// prototype leaves that slot unwritten and the object is created with +// garbage permission bits. Create with 0600 and read the mode back. + +#include +#include +#include +#include +#include + +int main(void) { + char name[64]; + struct stat st; + int fd; + int rc = 0; + sprintf(name, "/badc_shm_%d", getpid()); + shm_unlink(name); + fd = shm_open(name, O_CREAT | O_EXCL | O_RDWR, 0600); + if (fd < 0) { + return 1; + } + if (fstat(fd, (char *)&st) != 0) { + rc = 2; + } else if ((st.st_mode & 0777) != 0600) { + rc = 3; + } + close(fd); + shm_unlink(name); + return rc; +} diff --git a/tests/fixtures/c/snprintf_truncation_c99.c b/tests/fixtures/c/snprintf_truncation_c99.c new file mode 100644 index 000000000..e97f85b8a --- /dev/null +++ b/tests/fixtures/c/snprintf_truncation_c99.c @@ -0,0 +1,44 @@ +// C99 7.19.6.5p3: on truncation snprintf returns the length the +// output would have had and NUL-terminates what fits (size > 0); +// with size 0 nothing is written. 7.19.6.12p3 gives vsnprintf the +// same contract. msvcrt's _snprintf / _vsnprintf return -1 and omit +// the NUL, so on Windows the standard spellings resolve to the +// conforming wrappers in the auto-linked runtime. + +#include +#include +#include + +static int wrap(char *buf, int size, char *fmt, ...) { + va_list ap; + int n; + va_start(ap, fmt); + n = vsnprintf(buf, size, fmt, ap); + va_end(ap); + return n; +} + +int main(void) { + char buf[8]; + memset(buf, 'A', sizeof(buf)); + if (snprintf(buf, 4, "%d", 123456) != 6) { + return 1; + } + if (strcmp(buf, "123") != 0) { + return 2; + } + if (snprintf(0, 0, "%s", "hello") != 5) { + return 3; + } + memset(buf, 'A', sizeof(buf)); + if (wrap(buf, 4, "%d", 987654) != 6) { + return 4; + } + if (strcmp(buf, "987") != 0) { + return 5; + } + if (snprintf(buf, 8, "%d", 42) != 2 || strcmp(buf, "42") != 0) { + return 6; + } + return 0; +} diff --git a/tests/fixtures/c/strtof_parses_float.c b/tests/fixtures/c/strtof_parses_float.c new file mode 100644 index 000000000..c726fc365 --- /dev/null +++ b/tests/fixtures/c/strtof_parses_float.c @@ -0,0 +1,22 @@ +// C99 7.20.1.3: strtof converts the initial portion of the string and +// sets *endp past the consumed prefix. c5 aliases `float` to `double`, +// so the header binds strtof to the target's double-returning strtod; +// a binding to libc's float-returning strtof leaves the wrong register +// width behind the double-typed prototype. + +#include + +int main(void) { + char *end; + double v = strtof("3.5xyz", &end); + if (v != 3.5) { + return 1; + } + if (*end != 'x') { + return 2; + } + if (strtof("-0.25", 0) != -0.25) { + return 3; + } + return 0; +} diff --git a/tests/snapshots/asm/ioctl_fionread_pipe.aarch64.asm b/tests/snapshots/asm/ioctl_fionread_pipe.aarch64.asm new file mode 100644 index 000000000..f207bd9d4 --- /dev/null +++ b/tests/snapshots/asm/ioctl_fionread_pipe.aarch64.asm @@ -0,0 +1,83 @@ + +ioctl_fionread_pipe.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x420 // =1056 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x50 + str x20, [sp] + str x19, [sp, #0x10] + mov x0, #0x0 // =0 + stur w0, [x29, #-0x10] + sub x0, x29, #0x8 + bl + sxtw x0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x1 // =1 + ldr x20, [sp] + ldr x19, [sp, #0x10] + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x8 + ldrsw x0, [x0, #0x4] + adrp x1, + add x1, x1, + mov x2, #0x5 // =5 + bl + sxtw x0, w0 + cmp x0, #0x5 + b.eq + mov x0, #0x2 // =2 + ldr x20, [sp] + ldr x19, [sp, #0x10] + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x8 + ldrsw x0, [x0] + mov x1, #0x541b // =21531 + sub x2, x29, #0x10 + bl + sxtw x0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x3 // =3 + ldr x20, [sp] + ldr x19, [sp, #0x10] + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + ret + ldursw x0, [x29, #-0x10] + cmp x0, #0x5 + b.eq + mov x0, #0x4 // =4 + ldr x20, [sp] + ldr x19, [sp, #0x10] + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x8 + mov x20, #0x0 // =0 + ldrsw x0, [x0] + bl + sxtw x0, w0 + sub x0, x29, #0x8 + ldrsw x0, [x0, #0x4] + bl + sxtw x0, w0 + mov x0, x20 + ldr x20, [sp] + ldr x19, [sp, #0x10] + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/ioctl_fionread_pipe.x64.asm b/tests/snapshots/asm/ioctl_fionread_pipe.x64.asm new file mode 100644 index 000000000..d84c4b011 --- /dev/null +++ b/tests/snapshots/asm/ioctl_fionread_pipe.x64.asm @@ -0,0 +1,84 @@ + +ioctl_fionread_pipe.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x40, %rsp + movq %rbx, (%rsp) + xorq %rax, %rax + movl %eax, -0x10(%rbp) + leaq -0x8(%rbp), %rdi + xorl %eax, %eax + callq + movslq %eax, %rax + testq %rax, %rax + je + movl $0x1, %eax + movq (%rsp), %rbx + addq $0x40, %rsp + popq %rbp + retq + leaq -0x8(%rbp), %rax + movslq 0x4(%rax), %rdi + leaq , %rsi + movl $0x5, %edx + xorl %eax, %eax + callq + movslq %eax, %rax + cmpq $0x5, %rax + je + movl $0x2, %eax + movq (%rsp), %rbx + addq $0x40, %rsp + popq %rbp + retq + leaq -0x8(%rbp), %rax + movslq (%rax), %rdi + movl $0x541b, %esi # imm = 0x541B + leaq -0x10(%rbp), %rdx + movb $0x0, %al + callq + movslq %eax, %rax + testq %rax, %rax + je + movl $0x3, %eax + movq (%rsp), %rbx + addq $0x40, %rsp + popq %rbp + retq + movslq -0x10(%rbp), %rax + cmpq $0x5, %rax + je + movl $0x4, %eax + movq (%rsp), %rbx + addq $0x40, %rsp + popq %rbp + retq + leaq -0x8(%rbp), %rax + xorq %rbx, %rbx + movslq (%rax), %rdi + xorl %eax, %eax + callq + movslq %eax, %rax + leaq -0x8(%rbp), %rax + movslq 0x4(%rax), %rdi + xorl %eax, %eax + callq + movslq %eax, %rax + movq %rbx, %rax + movq (%rsp), %rbx + addq $0x40, %rsp + popq %rbp + retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/posix_os_headers.x64.asm b/tests/snapshots/asm/posix_os_headers.x64.asm index 95a08b574..b49372de3 100644 --- a/tests/snapshots/asm/posix_os_headers.x64.asm +++ b/tests/snapshots/asm/posix_os_headers.x64.asm @@ -113,7 +113,7 @@ Disassembly of section .text: movl $0x5413, %esi # imm = 0x5413 leaq -0x70(%rbp), %rdx movq %rbx, %rdi - xorl %eax, %eax + movb $0x0, %al callq movslq %eax, %rax movq %rbx, %rax diff --git a/tests/snapshots/asm/shm_open_mode_arg.aarch64.asm b/tests/snapshots/asm/shm_open_mode_arg.aarch64.asm new file mode 100644 index 000000000..cc6cd1fdf --- /dev/null +++ b/tests/snapshots/asm/shm_open_mode_arg.aarch64.asm @@ -0,0 +1,80 @@ + +shm_open_mode_arg.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x4a0 // =1184 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x120 + str x20, [sp] + str x21, [sp, #0x8] + str x22, [sp, #0x10] + str x19, [sp, #0x20] + mov x22, #0x0 // =0 + sub x20, x29, #0x40 + adrp x21, + add x21, x21, + bl + sxtw x0, w0 + mov x2, x0 + mov x0, x20 + mov x1, x21 + bl + sxtw x0, w0 + sub x0, x29, #0x40 + bl + sxtw x0, w0 + sub x0, x29, #0x40 + mov x1, #0xc2 // =194 + mov x2, #0x180 // =384 + bl + sxtw x0, w0 + mov x20, x0 + sxtw x0, w20 + cmp x0, #0x0 + b.ge + mov x0, #0x1 // =1 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + ldr x19, [sp, #0x20] + add sp, sp, #0x120 + ldp x29, x30, [sp], #0x10 + ret + sxtw x0, w20 + sub x1, x29, #0xc0 + bl + sxtw x0, w0 + cmp x0, #0x0 + b.eq + mov x22, #0x2 // =2 + sxtw x0, w20 + bl + sxtw x0, w0 + sub x0, x29, #0x40 + bl + sxtw x0, w0 + sxtw x0, w22 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + ldr x19, [sp, #0x20] + add sp, sp, #0x120 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0xc0 + ldrsw x0, [x0, #0x10] + mov x17, #0x1ff // =511 + and x0, x0, x17 + cmp x0, #0x180 + b.eq + mov x22, #0x3 // =3 + b + b diff --git a/tests/snapshots/asm/shm_open_mode_arg.x64.asm b/tests/snapshots/asm/shm_open_mode_arg.x64.asm new file mode 100644 index 000000000..b5caa9d1e --- /dev/null +++ b/tests/snapshots/asm/shm_open_mode_arg.x64.asm @@ -0,0 +1,84 @@ + +shm_open_mode_arg.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x120, %rsp # imm = 0x120 + movq %rbx, (%rsp) + movq %r12, 0x8(%rsp) + movq %r13, 0x10(%rsp) + xorq %r13, %r13 + leaq -0x40(%rbp), %rbx + leaq , %r12 + xorl %eax, %eax + callq + movslq %eax, %rax + movq %rax, %rdx + movq %rbx, %rdi + movq %r12, %rsi + movb $0x0, %al + callq + movslq %eax, %rax + leaq -0x40(%rbp), %rdi + xorl %eax, %eax + callq + movslq %eax, %rax + leaq -0x40(%rbp), %rdi + movl $0xc2, %esi + movl $0x180, %edx # imm = 0x180 + xorl %eax, %eax + callq + movslq %eax, %rax + movq %rax, %rbx + movslq %ebx, %rax + testq %rax, %rax + jge + movl $0x1, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x120, %rsp # imm = 0x120 + popq %rbp + retq + movslq %ebx, %rdi + leaq -0xd0(%rbp), %rsi + xorl %eax, %eax + callq + movslq %eax, %rax + testq %rax, %rax + je + movl $0x2, %r13d + movslq %ebx, %rdi + xorl %eax, %eax + callq + movslq %eax, %rax + leaq -0x40(%rbp), %rdi + xorl %eax, %eax + callq + movslq %eax, %rax + movslq %r13d, %rax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x120, %rsp # imm = 0x120 + popq %rbp + retq + leaq -0xd0(%rbp), %rax + movslq 0x18(%rax), %rax + andq $0x1ff, %rax # imm = 0x1FF + cmpq $0x180, %rax # imm = 0x180 + je + movl $0x3, %r13d + jmp + jmp + addb %al, (%rax) diff --git a/tests/snapshots/asm/snprintf_truncation_c99.aarch64.asm b/tests/snapshots/asm/snprintf_truncation_c99.aarch64.asm new file mode 100644 index 000000000..6a76506f0 --- /dev/null +++ b/tests/snapshots/asm/snprintf_truncation_c99.aarch64.asm @@ -0,0 +1,175 @@ + +snprintf_truncation_c99.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x330 // =816 + movk x1, #0x0, lsl #16 + b + brk #: + sub sp, sp, #0xc0 + str x0, [sp] + str x1, [sp, #0x8] + str x2, [sp, #0x10] + str x3, [sp, #0x18] + str x4, [sp, #0x20] + str x5, [sp, #0x28] + str x6, [sp, #0x30] + str x7, [sp, #0x38] + str d0, [sp, #0x40] + str d1, [sp, #0x50] + str d2, [sp, #0x60] + str d3, [sp, #0x70] + str d4, [sp, #0x80] + str d5, [sp, #0x90] + str d6, [sp, #0xa0] + str d7, [sp, #0xb0] + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x60 + str x19, [sp] + sub x0, x29, #0x20 + add x1, x29, #0x20 + mov x16, x0 + add x17, x29, #0xd0 + str x17, [x16] + add x17, x29, #0x50 + str x17, [x16, #0x8] + add x17, x29, #0xd0 + str x17, [x16, #0x10] + mov x17, #0xffd8 // =65496 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + str w17, [x16, #0x18] + mov x17, #0xff80 // =65408 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + str w17, [x16, #0x1c] + ldur x0, [x29, #0x10] + ldursw x1, [x29, #0x18] + ldur x2, [x29, #0x20] + sub x3, x29, #0x20 + bl + sub x1, x29, #0x20 + sxtw x0, w0 + ldr x19, [sp] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0xc0 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x40 + str x19, [sp] + sub x0, x29, #0x8 + mov x1, #0x41 // =65 + mov x2, #0x8 // =8 + bl + sub x0, x29, #0x8 + mov x1, #0x4 // =4 + adrp x2, + add x2, x2, + mov x3, #0xe240 // =57920 + movk x3, #0x1, lsl #16 + bl + sxtw x0, w0 + cmp x0, #0x6 + b.eq + mov x0, #0x1 // =1 + ldr x19, [sp] + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x8 + adrp x1, + add x1, x1, + bl + sxtw x0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x2 // =2 + ldr x19, [sp] + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + adrp x2, + add x2, x2, + adrp x3, + add x3, x3, + mov x1, x0 + bl + sxtw x0, w0 + cmp x0, #0x5 + b.eq + mov x0, #0x3 // =3 + ldr x19, [sp] + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x8 + mov x1, #0x41 // =65 + mov x2, #0x8 // =8 + bl + sub x0, x29, #0x8 + mov x1, #0x4 // =4 + adrp x2, + add x2, x2, + mov x3, #0x1206 // =4614 + movk x3, #0xf, lsl #16 + bl + cmp x0, #0x6 + b.eq + mov x0, #0x4 // =4 + ldr x19, [sp] + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x8 + adrp x1, + add x1, x1, + bl + sxtw x0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x5 // =5 + ldr x19, [sp] + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x8 + mov x1, #0x8 // =8 + adrp x2, + add x2, x2, + mov x3, #0x2a // =42 + bl + sxtw x0, w0 + cmp x0, #0x2 + cset x1, ne + cbnz x1, + sub x0, x29, #0x8 + adrp x1, + add x1, x1, + bl + sxtw x0, w0 + cmp x0, #0x0 + cset x1, ne + cbz x1, + mov x0, #0x6 // =6 + ldr x19, [sp] + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldr x19, [sp] + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret + b diff --git a/tests/snapshots/asm/snprintf_truncation_c99.x64.asm b/tests/snapshots/asm/snprintf_truncation_c99.x64.asm new file mode 100644 index 000000000..9b9cd96a9 --- /dev/null +++ b/tests/snapshots/asm/snprintf_truncation_c99.x64.asm @@ -0,0 +1,158 @@ + +snprintf_truncation_c99.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + pushq %rbp + movq %rsp, %rbp + subq $0xf0, %rsp + movq %rdi, -0xf0(%rbp) + movq %rsi, -0xe8(%rbp) + movq %rdx, -0xe0(%rbp) + movq %rcx, -0xd8(%rbp) + movq %r8, -0xd0(%rbp) + movq %r9, -0xc8(%rbp) + testb %al, %al + je + movsd %xmm0, -0xc0(%rbp,%riz) + movsd %xmm1, -0xb0(%rbp,%riz) + movsd %xmm2, -0xa0(%rbp,%riz) + movsd %xmm3, -0x90(%rbp,%riz) + movsd %xmm4, -0x80(%rbp,%riz) + movsd %xmm5, -0x70(%rbp,%riz) + movsd %xmm6, -0x60(%rbp,%riz) + movsd %xmm7, -0x50(%rbp,%riz) + leaq -0x18(%rbp), %rax + leaq -0xe0(%rbp), %rcx + movl $0x18, (%rax) + movl $0x30, 0x4(%rax) + leaq 0x10(%rbp), %r10 + movq %r10, 0x8(%rax) + leaq -0xf0(%rbp), %r10 + movq %r10, 0x10(%rax) + movq -0xf0(%rbp), %rdi + movslq -0xe8(%rbp), %rsi + movq -0xe0(%rbp), %rdx + leaq -0x18(%rbp), %rcx + xorl %eax, %eax + callq + leaq -0x18(%rbp), %rcx + movslq %eax, %rax + addq $0xf0, %rsp + popq %rbp + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x30, %rsp + leaq -0x8(%rbp), %rdi + movl $0x41, %esi + movl $0x8, %edx + xorl %eax, %eax + callq + leaq -0x8(%rbp), %rdi + movl $0x4, %esi + leaq , %rdx + movl $0x1e240, %ecx # imm = 0x1E240 + movb $0x0, %al + callq + movslq %eax, %rax + cmpq $0x6, %rax + je + movl $0x1, %eax + addq $0x30, %rsp + popq %rbp + retq + leaq -0x8(%rbp), %rdi + leaq , %rsi + xorl %eax, %eax + callq + movslq %eax, %rax + testq %rax, %rax + je + movl $0x2, %eax + addq $0x30, %rsp + popq %rbp + retq + xorq %rdi, %rdi + leaq , %rdx + leaq , %rcx + movq %rdi, %rsi + movb $0x0, %al + callq + movslq %eax, %rax + cmpq $0x5, %rax + je + movl $0x3, %eax + addq $0x30, %rsp + popq %rbp + retq + leaq -0x8(%rbp), %rdi + movl $0x41, %esi + movl $0x8, %edx + xorl %eax, %eax + callq + leaq -0x8(%rbp), %rdi + movl $0x4, %esi + leaq , %rdx + movl $0xf1206, %ecx # imm = 0xF1206 + movb $0x0, %al + callq + cmpq $0x6, %rax + je + movl $0x4, %eax + addq $0x30, %rsp + popq %rbp + retq + leaq -0x8(%rbp), %rdi + leaq , %rsi + xorl %eax, %eax + callq + movslq %eax, %rax + testq %rax, %rax + je + movl $0x5, %eax + addq $0x30, %rsp + popq %rbp + retq + leaq -0x8(%rbp), %rdi + movl $0x8, %esi + leaq , %rdx + movl $0x2a, %ecx + movb $0x0, %al + callq + movslq %eax, %rax + cmpq $0x2, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + jne + leaq -0x8(%rbp), %rdi + leaq , %rsi + xorl %eax, %eax + callq + movslq %eax, %rax + testq %rax, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x6, %eax + addq $0x30, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x30, %rsp + popq %rbp + retq + jmp + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/strtof_parses_float.aarch64.asm b/tests/snapshots/asm/strtof_parses_float.aarch64.asm new file mode 100644 index 000000000..e30344a8e --- /dev/null +++ b/tests/snapshots/asm/strtof_parses_float.aarch64.asm @@ -0,0 +1,62 @@ + +strtof_parses_float.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x270 // =624 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x30 + str x19, [sp] + adrp x0, + add x0, x0, + sub x1, x29, #0x8 + bl + mov x0, #0x400c000000000000 // =4615063718147915776 + fmov d17, x0 + fcmp d0, d17 + cset x0, ne + cbz x0, + mov x0, #0x1 // =1 + ldr x19, [sp] + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + ldur x0, [x29, #-0x8] + ldrb w0, [x0] + mov x17, #0x78 // =120 + eor x0, x0, x17 + mov w0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x2 // =2 + ldr x19, [sp] + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + adrp x0, + add x0, x0, + mov x1, #0x0 // =0 + bl + mov x0, #0x3fd0000000000000 // =4598175219545276416 + fmov d16, x0 + fneg d1, d16 + fcmp d0, d1 + cset x0, ne + cbz x0, + mov x0, #0x3 // =3 + ldr x19, [sp] + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldr x19, [sp] + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/strtof_parses_float.x64.asm b/tests/snapshots/asm/strtof_parses_float.x64.asm new file mode 100644 index 000000000..ff657bc78 --- /dev/null +++ b/tests/snapshots/asm/strtof_parses_float.x64.asm @@ -0,0 +1,67 @@ + +strtof_parses_float.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x20, %rsp + leaq , %rdi + leaq -0x8(%rbp), %rsi + xorl %eax, %eax + callq + movabsq $0x400c000000000000, %rax # imm = 0x400C000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %al + movzbq %al, %rax + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rax + testq %rax, %rax + je + movl $0x1, %eax + addq $0x20, %rsp + popq %rbp + retq + movq -0x8(%rbp), %rax + movsbq (%rax), %rax + cmpq $0x78, %rax + je + movl $0x2, %eax + addq $0x20, %rsp + popq %rbp + retq + leaq , %rdi + xorq %rsi, %rsi + xorl %eax, %eax + callq + movabsq $0x3fd0000000000000, %rax # imm = 0x3FD0000000000000 + movq %rax, %xmm1 + movabsq $-0x8000000000000000, %r10 # imm = 0x8000000000000000 + movq %r10, %xmm15 + xorpd %xmm15, %xmm1 + ucomisd %xmm1, %xmm0 + setne %al + movzbq %al, %rax + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rax + testq %rax, %rax + je + movl $0x3, %eax + addq $0x20, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x20, %rsp + popq %rbp + retq diff --git a/tests/snapshots/ssa/ioctl_fionread_pipe.ssa b/tests/snapshots/ssa/ioctl_fionread_pipe.ssa new file mode 100644 index 000000000..98940c89a --- /dev/null +++ b/tests/snapshots/ssa/ioctl_fionread_pipe.ssa @@ -0,0 +1,105 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=5 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(0) -> x0 + v2 StoreLocal { off=-2, value=v1, kind=I32 } -> - + v3 LocalAddr(-1) -> x7 + v4 CallExt { binding_idx=64, args=[v3], fp_arg_mask=0x0 } -> x0 + v5 BinopI { op=ne, lhs=v4, rhs_imm=0 } -> x0 + terminator Bz { cond=v5, target=b2, fall=b1 } (exit_acc=v5) + block 1 start_pc=0 + v6 Imm(1) -> x0 + terminator Return(v6) (exit_acc=v6) + block 2 start_pc=0 + v7 LocalAddr(-1) -> x0 + v8 Imm(4) -> x1 + v9 BinopI { op=add, lhs=v7, rhs_imm=4 } -> x1 + v10 Load { addr=v7, disp=4, kind=I32 } -> x7 + v11 ImmData(48) -> x6 + v12 Imm(5) -> x2 + v13 CallExt { binding_idx=28, args=[v10, v11, v12], fp_arg_mask=0x0 } -> x0 + v14 BinopI { op=ne, lhs=v13, rhs_imm=5 } -> x0 + terminator Bz { cond=v14, target=b4, fall=b3 } (exit_acc=v14) + block 3 start_pc=0 + v15 Imm(2) -> x0 + terminator Return(v15) (exit_acc=v15) + block 4 start_pc=0 + v16 LocalAddr(-1) -> x0 + v17 Imm(0) -> x1 + v18 Load { addr=v16, disp=0, kind=I32 } -> x7 + v19 Imm(21531) -> x6 + v20 LocalAddr(-2) -> x2 + v21 CallExt { binding_idx=0, args=[v18, v19, v20], fp_arg_mask=0x0 } -> x0 + v22 BinopI { op=ne, lhs=v21, rhs_imm=0 } -> x0 + terminator Bz { cond=v22, target=b6, fall=b5 } (exit_acc=v22) + block 5 start_pc=0 + v23 Imm(3) -> x0 + terminator Return(v23) (exit_acc=v23) + block 6 start_pc=0 + v24 LoadLocal { off=-2, kind=I32 } -> x0 + v25 BinopI { op=ne, lhs=v24, rhs_imm=5 } -> x0 + terminator Bz { cond=v25, target=b8, fall=b7 } (exit_acc=v25) + block 7 start_pc=0 + v26 Imm(4) -> x0 + terminator Return(v26) (exit_acc=v26) + block 8 start_pc=0 + v27 LocalAddr(-1) -> x0 + v28 Imm(0) -> x3 + v29 Load { addr=v27, disp=0, kind=I32 } -> x7 + v30 CallExt { binding_idx=25, args=[v29], fp_arg_mask=0x0 } -> x0 + v31 LocalAddr(-1) -> x0 + v32 Imm(4) -> x1 + v33 BinopI { op=add, lhs=v31, rhs_imm=4 } -> x1 + v34 Load { addr=v31, disp=4, kind=I32 } -> x7 + v35 CallExt { binding_idx=25, args=[v34], fp_arg_mask=0x0 } -> x0 + terminator Return(v28) (exit_acc=v28) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/shm_open_mode_arg.ssa b/tests/snapshots/ssa/shm_open_mode_arg.ssa new file mode 100644 index 000000000..dae7507dc --- /dev/null +++ b/tests/snapshots/ssa/shm_open_mode_arg.ssa @@ -0,0 +1,107 @@ +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=31 + spill_count=0 gpr_used=[3, 12, 13] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(0) -> x13 + v2 Imm(0) -> x0 + v3 LocalAddr(-8) -> x3 + v4 ImmData(76) -> x12 + v5 CallExt { binding_idx=64, args=[], fp_arg_mask=0x0 } -> x2 + v6 CallExt { binding_idx=168, args=[v3, v4, v5], fp_arg_mask=0x0 } -> x0 + v7 LocalAddr(-8) -> x7 + v8 CallExt { binding_idx=7, args=[v7], fp_arg_mask=0x0 } -> x0 + v9 LocalAddr(-8) -> x7 + v10 Imm(192) -> x0 + v11 Imm(194) -> x6 + v12 Imm(384) -> x2 + v13 CallExt { binding_idx=6, args=[v9, v11, v12], fp_arg_mask=0x0 } -> x3 + v14 Imm(0) -> x0 + v15 Extend { value=v13, kind=I32 } -> x0 + v16 BinopI { op=lt, lhs=v15, rhs_imm=0 } -> x0 + terminator Bz { cond=v16, target=b2, fall=b1 } (exit_acc=v16) + block 1 start_pc=0 + v17 Imm(1) -> x0 + terminator Return(v17) (exit_acc=v17) + block 2 start_pc=0 + v18 Extend { value=v13, kind=I32 } -> x7 + v19 LocalAddr(-26) -> x6 + v20 CallExt { binding_idx=53, args=[v18, v19], fp_arg_mask=0x0 } -> x0 + v21 BinopI { op=ne, lhs=v20, rhs_imm=0 } -> x0 + terminator Bz { cond=v21, target=b5, fall=b3 } (exit_acc=v21) + block 3 start_pc=0 + v22 Imm(2) -> x13 + v23 Imm(0) -> x0 + terminator Jmp(b4) (exit_acc=v22) + block 4 start_pc=0 + v24 Phi { incoming=[b3:v22, b7:v37], kind=I64 } -> x13 + v25 Extend { value=v13, kind=I32 } -> x7 + v26 CallExt { binding_idx=40, args=[v25], fp_arg_mask=0x0 } -> x0 + v27 LocalAddr(-8) -> x7 + v28 CallExt { binding_idx=7, args=[v27], fp_arg_mask=0x0 } -> x0 + v29 Extend { value=v24, kind=I32 } -> x0 + terminator Return(v29) (exit_acc=v29) + block 5 start_pc=0 + v30 LocalAddr(-26) -> x0 + v31 BinopI { op=add, lhs=v30, rhs_imm=24 } -> x1 + v32 Load { addr=v30, disp=24, kind=I32 } -> x0 + v33 BinopI { op=and, lhs=v32, rhs_imm=511 } -> x0 + v34 BinopI { op=ne, lhs=v33, rhs_imm=384 } -> x0 + terminator Bz { cond=v34, target=b8, fall=b6 } (exit_acc=v34) + block 6 start_pc=0 + v35 Imm(3) -> x13 + v36 Imm(0) -> x0 + terminator Jmp(b7) (exit_acc=v35) + block 7 start_pc=0 + v37 Phi { incoming=[b8:v1, b6:v35], kind=I64 } -> x13 + terminator Jmp(b4) + block 8 start_pc=0 + terminator Jmp(b7) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/snprintf_truncation_c99.ssa b/tests/snapshots/ssa/snprintf_truncation_c99.ssa new file mode 100644 index 000000000..38300acc4 --- /dev/null +++ b/tests/snapshots/ssa/snprintf_truncation_c99.ssa @@ -0,0 +1,157 @@ +; --- SSA dump (ok=true) ent_pc=1 --- +; name=wrap +fn ent_pc=1 n_params=3 variadic=true locals=8 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-3) -> x0 + v2 LocalAddr(4) -> x1 + v3 Intrinsic { kind=4, args=[v1, v2] } -> x0 + v4 LoadLocal { off=2, kind=I64 } -> x7 + v5 LoadLocal { off=3, kind=I32 } -> x6 + v6 LoadLocal { off=4, kind=I64 } -> x2 + v7 LocalAddr(-3) -> x1 + v8 CallExt { binding_idx=7, args=[v4, v5, v6, v7], fp_arg_mask=0x0 } -> x0 + v9 Imm(0) -> x1 + v10 LocalAddr(-3) -> x1 + v11 Intrinsic { kind=6, args=[v10] } -> x1 + v12 Extend { value=v8, kind=I32 } -> x0 + terminator Return(v12) (exit_acc=v12) +; --- SSA dump (ok=true) ent_pc=2 --- +; name=main +fn ent_pc=2 n_params=0 variadic=false locals=6 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-1) -> x7 + v2 Imm(65) -> x6 + v3 Imm(8) -> x2 + v4 CallExt { binding_idx=54, args=[v1, v2, v3], fp_arg_mask=0x0 } -> x0 + v5 LocalAddr(-1) -> x7 + v6 Imm(4) -> x6 + v7 ImmData(36) -> x2 + v8 Imm(123456) -> x1 + v9 CallExt { binding_idx=3, args=[v5, v6, v7, v8], fp_arg_mask=0x0 } -> x0 + v10 BinopI { op=ne, lhs=v9, rhs_imm=6 } -> x0 + terminator Bz { cond=v10, target=b2, fall=b1 } (exit_acc=v10) + block 1 start_pc=0 + v11 Imm(1) -> x0 + terminator Return(v11) (exit_acc=v11) + block 2 start_pc=0 + v12 LocalAddr(-1) -> x7 + v13 ImmData(39) -> x6 + v14 CallExt { binding_idx=62, args=[v12, v13], fp_arg_mask=0x0 } -> x0 + v15 BinopI { op=ne, lhs=v14, rhs_imm=0 } -> x0 + terminator Bz { cond=v15, target=b4, fall=b3 } (exit_acc=v15) + block 3 start_pc=0 + v16 Imm(2) -> x0 + terminator Return(v16) (exit_acc=v16) + block 4 start_pc=0 + v17 Imm(0) -> x7 + v18 ImmData(43) -> x2 + v19 ImmData(46) -> x1 + v20 CallExt { binding_idx=3, args=[v17, v17, v18, v19], fp_arg_mask=0x0 } -> x0 + v21 BinopI { op=ne, lhs=v20, rhs_imm=5 } -> x0 + terminator Bz { cond=v21, target=b6, fall=b5 } (exit_acc=v21) + block 5 start_pc=0 + v22 Imm(3) -> x0 + terminator Return(v22) (exit_acc=v22) + block 6 start_pc=0 + v23 LocalAddr(-1) -> x7 + v24 Imm(65) -> x6 + v25 Imm(8) -> x2 + v26 CallExt { binding_idx=54, args=[v23, v24, v25], fp_arg_mask=0x0 } -> x0 + v27 LocalAddr(-1) -> x7 + v28 Imm(4) -> x6 + v29 ImmData(52) -> x2 + v30 Imm(987654) -> x1 + v31 Call { target_pc=1, args=[v27, v28, v29, v30], fixed_args=3, fp_return=false, fp_arg_mask=0x0 } -> x0 + v32 BinopI { op=ne, lhs=v31, rhs_imm=6 } -> x0 + terminator Bz { cond=v32, target=b8, fall=b7 } (exit_acc=v32) + block 7 start_pc=0 + v33 Imm(4) -> x0 + terminator Return(v33) (exit_acc=v33) + block 8 start_pc=0 + v34 LocalAddr(-1) -> x7 + v35 ImmData(55) -> x6 + v36 CallExt { binding_idx=62, args=[v34, v35], fp_arg_mask=0x0 } -> x0 + v37 BinopI { op=ne, lhs=v36, rhs_imm=0 } -> x0 + terminator Bz { cond=v37, target=b10, fall=b9 } (exit_acc=v37) + block 9 start_pc=0 + v38 Imm(5) -> x0 + terminator Return(v38) (exit_acc=v38) + block 10 start_pc=0 + v39 LocalAddr(-1) -> x7 + v40 Imm(8) -> x6 + v41 ImmData(59) -> x2 + v42 Imm(42) -> x1 + v43 CallExt { binding_idx=3, args=[v39, v40, v41, v42], fp_arg_mask=0x0 } -> x0 + v44 BinopI { op=ne, lhs=v43, rhs_imm=2 } -> x1 + v45 Imm(0) -> x0 + terminator Bnz { cond=v44, target=b15, fall=b11 } (exit_acc=v44) + block 11 start_pc=0 + v46 LocalAddr(-1) -> x7 + v47 ImmData(62) -> x6 + v48 CallExt { binding_idx=62, args=[v46, v47], fp_arg_mask=0x0 } -> x0 + v49 BinopI { op=ne, lhs=v48, rhs_imm=0 } -> x1 + v50 Imm(0) -> x0 + terminator Jmp(b12) (exit_acc=v49) + block 12 start_pc=0 + v51 Phi { incoming=[b15:v44, b11:v49], kind=I64 } -> x1 + v52 LoadLocal { off=-6, kind=I64 } -> x0 + terminator Bz { cond=v51, target=b14, fall=b13 } (exit_acc=v51) + block 13 start_pc=0 + v53 Imm(6) -> x0 + terminator Return(v53) (exit_acc=v53) + block 14 start_pc=0 + v54 Imm(0) -> x0 + terminator Return(v54) (exit_acc=v54) + block 15 start_pc=0 + terminator Jmp(b12) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/strtof_parses_float.ssa b/tests/snapshots/ssa/strtof_parses_float.ssa new file mode 100644 index 000000000..94bd2359a --- /dev/null +++ b/tests/snapshots/ssa/strtof_parses_float.ssa @@ -0,0 +1,86 @@ +; --- SSA dump (ok=true) ent_pc=5 --- +; name=main +fn ent_pc=5 n_params=0 variadic=false locals=4 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ImmData(8) -> x7 + v2 LocalAddr(-1) -> x6 + v3 CallExt { binding_idx=11, args=[v1, v2], fp_arg_mask=0x0, fp_return=true } -> d0 + v4 Imm(0) -> x0 + v5 LoadLocal { off=-2, kind=F64 } -> d1 + v6 Imm(4615063718147915776) -> x0 + v7 Binop { op=fne, lhs=v3, rhs=v6 } -> x0 + terminator Bz { cond=v7, target=b2, fall=b1 } (exit_acc=v7) + block 1 start_pc=0 + v8 Imm(1) -> x0 + terminator Return(v8) (exit_acc=v8) + block 2 start_pc=0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Load { addr=v9, disp=0, kind=I8 } -> x0 + v11 BinopI { op=ne, lhs=v10, rhs_imm=120 } -> x0 + terminator Bz { cond=v11, target=b4, fall=b3 } (exit_acc=v11) + block 3 start_pc=0 + v12 Imm(2) -> x0 + terminator Return(v12) (exit_acc=v12) + block 4 start_pc=0 + v13 ImmData(15) -> x7 + v14 Imm(0) -> x6 + v15 CallExt { binding_idx=11, args=[v13, v14], fp_arg_mask=0x0, fp_return=true } -> d0 + v16 Imm(4598175219545276416) -> x0 + v17 Fneg(v16) -> d1 + v18 Binop { op=fne, lhs=v15, rhs=v17 } -> x0 + terminator Bz { cond=v18, target=b6, fall=b5 } (exit_acc=v18) + block 5 start_pc=0 + v19 Imm(3) -> x0 + terminator Return(v19) (exit_acc=v19) + block 6 start_pc=0 + v20 Imm(0) -> x0 + terminator Return(v20) (exit_acc=v20) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) From c49a75d5ba48158ede251b2d2dbc06c479aaf764 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 18:43:14 -0700 Subject: [PATCH 10/67] c5: track integer type facts through literals, constants, and operators One family of front-end fixes where a width/signedness/rank fact was dropped instead of tracked: * lexer: octal and binary literals route through the shared u/U/l/L suffix scanner instead of silently dropping the suffix. * expr: integer-literal typing at the 2^31 / 2^63 boundaries (C99 6.4.4.1p5); the signed range test was off by one, so 2147483648 stayed int and -2147483648 - 1 wrapped at 32 bits. * const_expr: ConstVal carries the value's C type; one fold (const_int_binop) applies the 6.3.1.8 conversions to every operator, so unsigned 64-bit /, %, >>, and relationals fold unsigned. Division by zero in an evaluated constant expression is diagnosed (6.6p4) instead of folding to 0, unevaluated ?: arms and short-circuited operands stay accepted, and LLONG_MIN / -1 wraps instead of aborting the compiler. * expr: signed >> takes the promoted left-operand type (6.5.7p3), not int, so a 64-bit shift result is not re-narrowed. * expr: a ternary with differing arithmetic integer arms converts both arms to the usual-arithmetic-conversions common type (6.5.15p5) instead of taking the else arm's type. * expr + walk: compound /= and %= select signedness from the common type of both operands (6.5.16.2p3) and mask narrow unsigned operands like the plain-binary lowering. * walk: switch case labels convert to the promoted controlling type (6.8.4.2p5), so case 0x80000000: matches an int INT_MIN. * decl_base + aggregate: base-first specifier orders (int long, int unsigned, char unsigned, double long) fold the trailing modifiers into the base type (6.7.2p2) instead of discarding them; trailing inline / _Noreturn set their pending flags. Regression fixtures (compiled, executed, parity-checked) plus lexer suffix and const-expr diagnostic unit tests. Co-Authored-By: Claude Fable 5 --- src/c5/ast/walk.rs | 30 +- src/c5/compiler/aggregate.rs | 17 +- src/c5/compiler/const_expr.rs | 401 +++++++++++++----- src/c5/compiler/decl_base.rs | 48 ++- src/c5/compiler/expr.rs | 60 ++- src/c5/compiler/mod.rs | 8 + src/c5/lexer.rs | 73 +--- src/c5/tests/jit.rs | 7 + src/c5/tests/lexer.rs | 23 + src/c5/tests/mod.rs | 5 + src/c5/tests/native.rs | 7 + src/c5/tests/parser.rs | 40 ++ .../fixtures/c/compound_assign_unsigned_div.c | 40 ++ tests/fixtures/c/const_expr_unsigned_fold.c | 44 ++ tests/fixtures/c/decl_specifier_any_order.c | 42 ++ tests/fixtures/c/int_literal_boundary_types.c | 42 ++ tests/fixtures/c/shift_result_promoted_type.c | 29 ++ tests/fixtures/c/switch_case_label_promoted.c | 48 +++ tests/fixtures/c/ternary_arith_common_type.c | 26 ++ 19 files changed, 809 insertions(+), 181 deletions(-) create mode 100644 tests/fixtures/c/compound_assign_unsigned_div.c create mode 100644 tests/fixtures/c/const_expr_unsigned_fold.c create mode 100644 tests/fixtures/c/decl_specifier_any_order.c create mode 100644 tests/fixtures/c/int_literal_boundary_types.c create mode 100644 tests/fixtures/c/shift_result_promoted_type.c create mode 100644 tests/fixtures/c/switch_case_label_promoted.c create mode 100644 tests/fixtures/c/ternary_arith_common_type.c diff --git a/src/c5/ast/walk.rs b/src/c5/ast/walk.rs index 33e3e4f1c..b306770ea 100644 --- a/src/c5/ast/walk.rs +++ b/src/c5/ast/walk.rs @@ -1074,6 +1074,17 @@ impl<'a> Walker<'a> { } sorted.sort_by_key(|p| p.0 as u64); } else { + // Signed controlling type: a 4-byte type promotes to + // itself and a sub-int type to signed `int`, so the + // label converts by sign-truncation to 32 bits -- + // `case 0x80000000:` on an `int` switch must match + // the sign-extended INT_MIN discriminant. An 8-byte + // type keeps the full-width label. + if type_size_bytes(disc_ty, self.target) <= 4 { + for c in sorted.iter_mut() { + c.0 = (c.0 as i32) as i64; + } + } sorted.sort_by_key(|p| p.0); } let lt_op = if disc_unsigned { BinOp::Ult } else { BinOp::Lt }; @@ -2992,7 +3003,7 @@ impl<'a> Walker<'a> { } else if imm_safe && let Expr::IntLit { val, .. } = self.ast.expr(*rhs) { b.binop_imm(*op, old, *val) } else { - let rhs_val = self.walk_expr_rvalue(b, *rhs)?; + let mut rhs_val = self.walk_expr_rvalue(b, *rhs)?; // The walked rhs may have constant-folded to // an `Imm` even when the AST shape isn't an // `IntLit`; route through `binop_imm` in that @@ -3001,7 +3012,22 @@ impl<'a> Walker<'a> { if imm_safe && let Some(rk) = b.peek_imm(rhs_val) { b.binop_imm(*op, old, rk) } else { - b.binop(*op, old, rhs_val) + let mut lv = old; + // C99 6.3.1.3 + 6.3.1.8: unsigned divide / + // modulo at a narrower-than-register common + // type masks each operand first, mirroring + // the `Expr::Binary` lowering. Both operand + // types <= 4 bytes means the common type is + // 4 bytes (integer promotion floors at int). + if matches!(*op, BinOp::Divu | BinOp::Modu) { + let rhs_sz = expr_ty(self.ast.expr(*rhs)) + .map_or(8, |t| type_size_bytes(t, self.target)); + if type_size_bytes(*ty, self.target) <= 4 && rhs_sz <= 4 { + lv = b.binop_imm(BinOp::And, lv, 0xffff_ffff); + rhs_val = b.binop_imm(BinOp::And, rhs_val, 0xffff_ffff); + } + } + b.binop(*op, lv, rhs_val) } }; place.store(b, new_val, store_kind); diff --git a/src/c5/compiler/aggregate.rs b/src/c5/compiler/aggregate.rs index 2f743c33b..26de8dfac 100644 --- a/src/c5/compiler/aggregate.rs +++ b/src/c5/compiler/aggregate.rs @@ -168,7 +168,8 @@ impl Compiler { // unsigned, so a value with the field's high bit set // zero-extends rather than sign-extends. let mut field_base_is_enum = false; - let field_base = if let Some(inner) = atomic_field_base { + let field_base_tok = self.lex.tk; + let mut field_base = if let Some(inner) = atomic_field_base { inner } else if self.lex.tk == Token::Typeof { // `typeof ( ... ) member;` (C23 6.7.2.5): the operand's @@ -310,13 +311,15 @@ impl Compiler { return Err(self.compile_err("type expected in struct field")); }; - // Trailing modifiers: `int long`, `unsigned long long`, etc. - while is_decl_modifier(self.lex.tk) { - if self.lex.tk == Token::Attribute { - self.skip_attribute_specifiers()?; - continue; + // Trailing specifiers: C99 6.7.2p2 admits any order, so + // `int long` / `char unsigned` fields re-derive the base + // tag from the folded modifiers. + if self.consume_trailing_decl_modifiers(&mut mods)? { + if field_base_tok == Token::Int { + field_base = mods.int_base(); + } else if field_base_tok == Token::Char { + field_base = mods.char_tag(self.target.plain_char_signed()); } - self.next()?; } // Anonymous struct/union member (C11 6.7.2.1p13). The diff --git a/src/c5/compiler/const_expr.rs b/src/c5/compiler/const_expr.rs index cf4b111fb..3a8e7589c 100644 --- a/src/c5/compiler/const_expr.rs +++ b/src/c5/compiler/const_expr.rs @@ -33,8 +33,8 @@ use super::super::error::C5Error; use super::super::token::{Token, Ty}; use super::Compiler; use super::types::{ - is_floating_ty, is_struct_ty, is_unsigned_ty, narrow_const_int, strip_unsigned, struct_id_of, - struct_ptr_depth, + UNSIGNED_BIT, integer_promote, is_floating_ty, is_pointer_ty, is_struct_ty, is_unsigned_ty, + narrow_const_int, strip_unsigned, struct_id_of, struct_ptr_depth, usual_arith_common_ty, }; /// Compile-time arithmetic value of a constant expression. Integer @@ -45,29 +45,78 @@ use super::types::{ /// conversions"). The integer-typed callers (array sizes, enums, /// bitfield widths, integer global inits) truncate via /// [`ConstVal::as_int`] at the boundary. +/// +/// An integer value carries its C type tag so every operator can +/// apply the 6.3.1.8 conversions at the right width and signedness +/// (`0xFFFFFFFFFFFFFFFFULL / 3` divides unsigned; `-1 < 1u` +/// compares at `unsigned int`). Invariant: `val` holds the value +/// in `ty`'s representation -- sign-extended for a signed type, +/// zero-extended for an unsigned type narrower than 8 bytes, raw +/// bits for an unsigned 8-byte type. #[derive(Copy, Clone, Debug)] pub(super) enum ConstVal { - Int(i64), + Int { val: i64, ty: i64 }, Float(f64), } +/// Operator selector for [`Compiler::const_int_binop`], the single +/// integer fold shared by every binary operator in the +/// constant-expression grammar. +#[derive(Copy, Clone, PartialEq)] +enum ConstBinOp { + Or, + Xor, + And, + Add, + Sub, + Mul, + Div, + Rem, + Shl, + Shr, + Lt, + Le, + Gt, + Ge, + Eq, + Ne, +} + impl ConstVal { + /// An `int`-typed value: comparison and logical results, and + /// the other places C99 mandates `int`. + fn int(v: i64) -> ConstVal { + ConstVal::Int { + val: v, + ty: Ty::Int as i64, + } + } + /// Coerce to an `i64`. Float values truncate toward zero, matching /// C's "cast to integer" semantics for the destination integer /// constant expression. pub(super) fn as_int(self) -> i64 { match self { - ConstVal::Int(v) => v, + ConstVal::Int { val, .. } => val, ConstVal::Float(v) => v as i64, } } + /// The C type tag of an integer value (`int` for a float a + /// caller coerces through [`Self::as_int`]). + fn int_ty(self) -> i64 { + match self { + ConstVal::Int { ty, .. } => ty, + ConstVal::Float(_) => Ty::Int as i64, + } + } + /// Coerce to an `f64`. Integer values widen exactly for any value /// within `f64`'s 53-bit mantissa range (which is every integer /// constant c5 currently lexes). pub(super) fn as_float(self) -> f64 { match self { - ConstVal::Int(v) => v as f64, + ConstVal::Int { val, .. } => val as f64, ConstVal::Float(v) => v, } } @@ -79,13 +128,114 @@ impl ConstVal { /// True if the value is non-zero. Used by `&&`, `||`, `?:`, `!`. fn is_truthy(self) -> bool { match self { - ConstVal::Int(v) => v != 0, + ConstVal::Int { val, .. } => val != 0, ConstVal::Float(v) => v != 0.0, } } } impl Compiler { + /// Fold one integer binary operator per C99 6.3.1.8: both + /// operands convert to their common type and the operation runs + /// in that type's signedness, renormalized to its width. Shifts + /// take the promoted left-operand type instead (6.5.7p3). + /// Pointer-typed operands (string addresses, offsetof chains) + /// fold at full 64-bit width with no conversion. A zero divisor + /// in an evaluated operand is a compile error (6.6p4); signed + /// overflow wraps, matching the runtime lowering. + fn const_int_binop( + &self, + op: ConstBinOp, + l: ConstVal, + r: ConstVal, + ) -> Result { + use ConstBinOp as B; + let (a_ty, b_ty) = (l.int_ty(), r.int_ty()); + let ptr = is_pointer_ty(a_ty) || is_pointer_ty(b_ty); + if matches!(op, B::Shl | B::Shr) { + let pty = if ptr { + Ty::LongLong as i64 + } else { + integer_promote(a_ty) + }; + let bytes = self.size_of_type(pty); + let uns = is_unsigned_ty(pty); + let lv = narrow_const_int(bytes, uns, false, l.as_int()); + let sh = (r.as_int() & 63) as u32; + let v = if op == B::Shl { + (lv as u64).wrapping_shl(sh) as i64 + } else if uns { + ((lv as u64) >> sh) as i64 + } else { + lv.wrapping_shr(sh) + }; + return Ok(ConstVal::Int { + val: narrow_const_int(bytes, uns, false, v), + ty: pty, + }); + } + let common = if ptr { + Ty::LongLong as i64 + } else { + usual_arith_common_ty(a_ty, b_ty, self.target) + }; + let bytes = self.size_of_type(common); + let uns = is_unsigned_ty(common); + let lv = narrow_const_int(bytes, uns, false, l.as_int()); + let rv = narrow_const_int(bytes, uns, false, r.as_int()); + let val = match op { + B::Or => lv | rv, + B::Xor => lv ^ rv, + B::And => lv & rv, + B::Add => lv.wrapping_add(rv), + B::Sub => lv.wrapping_sub(rv), + B::Mul => lv.wrapping_mul(rv), + B::Div | B::Rem => { + if rv == 0 { + if self.const_unevaluated == 0 { + return Err(self.compile_err("division by zero in a constant expression")); + } + 0 + } else if uns { + let (a, b) = (lv as u64, rv as u64); + (if op == B::Rem { a % b } else { a / b }) as i64 + } else if op == B::Rem { + lv.wrapping_rem(rv) + } else { + lv.wrapping_div(rv) + } + } + B::Lt | B::Le | B::Gt | B::Ge | B::Eq | B::Ne => { + let hold = if uns { + let (a, b) = (lv as u64, rv as u64); + match op { + B::Lt => a < b, + B::Le => a <= b, + B::Gt => a > b, + B::Ge => a >= b, + B::Eq => a == b, + _ => a != b, + } + } else { + match op { + B::Lt => lv < rv, + B::Le => lv <= rv, + B::Gt => lv > rv, + B::Ge => lv >= rv, + B::Eq => lv == rv, + _ => lv != rv, + } + }; + return Ok(ConstVal::int(hold as i64)); + } + B::Shl | B::Shr => unreachable!(), + }; + Ok(ConstVal::Int { + val: narrow_const_int(bytes, uns, false, val), + ty: common, + }) + } + /// Parse a constant integer expression at parse time. Used /// during declarator parsing where the value has to be known /// before any IR-building emit (array dimensions, bitfield @@ -183,33 +333,54 @@ impl Compiler { let cond = self.parse_const_expr_or_val()?; if self.lex.tk == Token::Cond { self.next()?; - let then_val = self.parse_const_expr_or_val()?; + // Both arms are parsed (their tokens must be consumed) + // but the not-taken arm is unevaluated per C99 6.5.15, + // so a zero divisor there must not diagnose. + let taken = cond.is_truthy(); + let then_val = self.parse_const_unevaluated(!taken, Self::parse_const_expr_or_val)?; if self.lex.tk != ':' { return Err(self.compile_err("`:` expected in conditional constant expression")); } self.next()?; - let else_val = self.parse_const_expr_cond_val()?; - Ok(if cond.is_truthy() { then_val } else { else_val }) + let else_val = self.parse_const_unevaluated(taken, Self::parse_const_expr_cond_val)?; + Ok(if taken { then_val } else { else_val }) } else { Ok(cond) } } + /// Run `rule` with the unevaluated-operand depth raised when + /// `unevaluated` holds, so C99 6.6p4 zero-divisor diagnostics + /// stay scoped to evaluated operands. + fn parse_const_unevaluated( + &mut self, + unevaluated: bool, + rule: fn(&mut Self) -> Result, + ) -> Result { + if unevaluated { + self.const_unevaluated += 1; + } + let r = rule(self); + if unevaluated { + self.const_unevaluated -= 1; + } + r + } + pub(super) fn parse_const_expr_or_val(&mut self) -> Result { let mut left = self.parse_const_expr_and_val()?; while self.lex.tk == Token::Lor { self.next()?; - let right = self.parse_const_expr_and_val()?; - // Short-circuit semantics aren't observable at parse - // time -- the right operand was already consumed by - // the recursive call -- but the result still has C99's - // `int 0 | 1` shape. + // The right operand's tokens are always consumed, but a + // short-circuited operand is unevaluated (C99 6.5.14). + let right = + self.parse_const_unevaluated(left.is_truthy(), Self::parse_const_expr_and_val)?; let r = if left.is_truthy() || right.is_truthy() { 1 } else { 0 }; - left = ConstVal::Int(r); + left = ConstVal::int(r); } Ok(left) } @@ -218,13 +389,14 @@ impl Compiler { let mut left = self.parse_const_expr_bitor_val()?; while self.lex.tk == Token::Lan { self.next()?; - let right = self.parse_const_expr_bitor_val()?; + let right = + self.parse_const_unevaluated(!left.is_truthy(), Self::parse_const_expr_bitor_val)?; let r = if left.is_truthy() && right.is_truthy() { 1 } else { 0 }; - left = ConstVal::Int(r); + left = ConstVal::int(r); } Ok(left) } @@ -234,7 +406,7 @@ impl Compiler { while self.lex.tk == Token::OrOp { self.next()?; let right = self.parse_const_expr_xor_val()?; - left = ConstVal::Int(left.as_int() | right.as_int()); + left = self.const_int_binop(ConstBinOp::Or, left, right)?; } Ok(left) } @@ -244,7 +416,7 @@ impl Compiler { while self.lex.tk == Token::XorOp { self.next()?; let right = self.parse_const_expr_bitand_val()?; - left = ConstVal::Int(left.as_int() ^ right.as_int()); + left = self.const_int_binop(ConstBinOp::Xor, left, right)?; } Ok(left) } @@ -254,7 +426,7 @@ impl Compiler { while self.lex.tk == Token::AndOp { self.next()?; let right = self.parse_const_expr_eq_val()?; - left = ConstVal::Int(left.as_int() & right.as_int()); + left = self.const_int_binop(ConstBinOp::And, left, right)?; } Ok(left) } @@ -262,27 +434,21 @@ impl Compiler { fn parse_const_expr_eq_val(&mut self) -> Result { let mut left = self.parse_const_expr_rel_val()?; loop { - if self.lex.tk == Token::EqOp { - self.next()?; - let r = self.parse_const_expr_rel_val()?; - let eq = if left.is_float() || r.is_float() { - left.as_float() == r.as_float() - } else { - left.as_int() == r.as_int() - }; - left = ConstVal::Int(eq as i64); + let op = if self.lex.tk == Token::EqOp { + ConstBinOp::Eq } else if self.lex.tk == Token::NeOp { - self.next()?; - let r = self.parse_const_expr_rel_val()?; - let ne = if left.is_float() || r.is_float() { - left.as_float() != r.as_float() - } else { - left.as_int() != r.as_int() - }; - left = ConstVal::Int(ne as i64); + ConstBinOp::Ne } else { break; - } + }; + self.next()?; + let r = self.parse_const_expr_rel_val()?; + left = if left.is_float() || r.is_float() { + let eq = left.as_float() == r.as_float(); + ConstVal::int((if op == ConstBinOp::Eq { eq } else { !eq }) as i64) + } else { + self.const_int_binop(op, left, r)? + }; } Ok(left) } @@ -291,39 +457,31 @@ impl Compiler { let mut left = self.parse_const_expr_shift_val()?; loop { let op = if self.lex.tk == Token::LtOp { - Some('<') + ConstBinOp::Lt } else if self.lex.tk == Token::LeOp { - Some('l') + ConstBinOp::Le } else if self.lex.tk == Token::GtOp { - Some('>') + ConstBinOp::Gt } else if self.lex.tk == Token::GeOp { - Some('g') + ConstBinOp::Ge } else { - None + break; }; - let Some(op) = op else { break }; self.next()?; let r = self.parse_const_expr_shift_val()?; - let b = if left.is_float() || r.is_float() { + left = if left.is_float() || r.is_float() { let lf = left.as_float(); let rf = r.as_float(); - match op { - '<' => lf < rf, - 'l' => lf <= rf, - '>' => lf > rf, + let b = match op { + ConstBinOp::Lt => lf < rf, + ConstBinOp::Le => lf <= rf, + ConstBinOp::Gt => lf > rf, _ => lf >= rf, - } + }; + ConstVal::int(b as i64) } else { - let li = left.as_int(); - let ri = r.as_int(); - match op { - '<' => li < ri, - 'l' => li <= ri, - '>' => li > ri, - _ => li >= ri, - } + self.const_int_binop(op, left, r)? }; - left = ConstVal::Int(b as i64); } Ok(left) } @@ -331,17 +489,16 @@ impl Compiler { fn parse_const_expr_shift_val(&mut self) -> Result { let mut left = self.parse_const_expr_add_val()?; loop { - if self.lex.tk == Token::ShlOp { - self.next()?; - let r = self.parse_const_expr_add_val()?; - left = ConstVal::Int(left.as_int() << r.as_int()); + let op = if self.lex.tk == Token::ShlOp { + ConstBinOp::Shl } else if self.lex.tk == Token::ShrOp { - self.next()?; - let r = self.parse_const_expr_add_val()?; - left = ConstVal::Int(left.as_int() >> r.as_int()); + ConstBinOp::Shr } else { break; - } + }; + self.next()?; + let r = self.parse_const_expr_add_val()?; + left = self.const_int_binop(op, left, r)?; } Ok(left) } @@ -367,7 +524,7 @@ impl Compiler { left = if left.is_float() || r.is_float() { ConstVal::Float(left.as_float() + r.as_float()) } else { - ConstVal::Int(left.as_int().wrapping_add(r.as_int())) + self.const_int_binop(ConstBinOp::Add, left, r)? }; } else if self.lex.tk == Token::SubOp { self.next()?; @@ -375,7 +532,7 @@ impl Compiler { left = if left.is_float() || r.is_float() { ConstVal::Float(left.as_float() - r.as_float()) } else { - ConstVal::Int(left.as_int().wrapping_sub(r.as_int())) + self.const_int_binop(ConstBinOp::Sub, left, r)? }; } else { break; @@ -397,7 +554,7 @@ impl Compiler { left = if left.is_float() || r.is_float() { ConstVal::Float(left.as_float() * r.as_float()) } else { - ConstVal::Int(left.as_int().wrapping_mul(r.as_int())) + self.const_int_binop(ConstBinOp::Mul, left, r)? }; } else if self.lex.tk == Token::DivOp { self.next()?; @@ -408,18 +565,14 @@ impl Compiler { // for 0.0/0.0, not a fold to zero. ConstVal::Float(left.as_float() / r.as_float()) } else { - let ri = r.as_int(); - let v = if ri == 0 { 0 } else { left.as_int() / ri }; - ConstVal::Int(v) + self.const_int_binop(ConstBinOp::Div, left, r)? }; } else if self.lex.tk == Token::ModOp { // C99 6.5.5: `%` requires integer operands. Coerce - // both sides through `as_int` and operate on i64. + // both sides through `as_int` and fold as integers. self.next()?; let r = self.parse_const_expr_unary_val()?; - let ri = r.as_int(); - let v = if ri == 0 { 0 } else { left.as_int() % ri }; - left = ConstVal::Int(v); + left = self.const_int_binop(ConstBinOp::Rem, left, r)?; } else { break; } @@ -427,11 +580,29 @@ impl Compiler { Ok(left) } + /// Renormalize a unary integer result to the operand's promoted + /// type (C99 6.5.3.3: `-` and `~` apply the integer promotions + /// and yield the promoted type). Pointer-typed operands keep + /// their full-width value. + fn const_unary_promoted(&self, v: i64, operand_ty: i64) -> ConstVal { + if is_pointer_ty(operand_ty) { + return ConstVal::Int { + val: v, + ty: operand_ty, + }; + } + let pty = integer_promote(operand_ty); + ConstVal::Int { + val: narrow_const_int(self.size_of_type(pty), is_unsigned_ty(pty), false, v), + ty: pty, + } + } + pub(super) fn parse_const_expr_unary_val(&mut self) -> Result { if self.lex.tk == Token::SubOp { self.next()?; return Ok(match self.parse_const_expr_unary_val()? { - ConstVal::Int(v) => ConstVal::Int(v.wrapping_neg()), + ConstVal::Int { val, ty } => self.const_unary_promoted(val.wrapping_neg(), ty), ConstVal::Float(v) => ConstVal::Float(-v), }); } @@ -442,33 +613,56 @@ impl Compiler { if self.lex.tk == '!' { self.next()?; let v = self.parse_const_expr_unary_val()?; - return Ok(ConstVal::Int(if v.is_truthy() { 0 } else { 1 })); + return Ok(ConstVal::int(if v.is_truthy() { 0 } else { 1 })); } if self.lex.tk == '~' { self.next()?; - let v = self.parse_const_expr_unary_val()?.as_int(); - return Ok(ConstVal::Int(!v)); + let v = self.parse_const_expr_unary_val()?; + return Ok(self.const_unary_promoted(!v.as_int(), v.int_ty())); } if self.lex.tk == Token::AndOp { - return Ok(ConstVal::Int(self.parse_const_offsetof()?)); + // Address constant: full-width, no arithmetic conversion. + let v = self.parse_const_offsetof()?; + return Ok(ConstVal::Int { + val: v, + ty: Ty::Ptr as i64, + }); } if self.lex.tk == Token::Sizeof { // Shared sizeof operand parser handles all three // shapes (type-name, bare identifier, general // expression). Constant-expression context just - // returns the byte count directly. + // returns the byte count, typed `size_t` (C99 6.5.3.4p4). self.next()?; - return Ok(ConstVal::Int(self.sizeof_operand_bytes()?)); + let v = self.sizeof_operand_bytes()?; + return Ok(ConstVal::Int { + val: v, + ty: self.size_t_ty(), + }); } if self.lex.tk == Token::Alignof { // C11 6.5.3.4: `_Alignof ( type-name )` is a constant - // expression; return the alignment directly. + // expression; the result is `size_t`. self.next()?; - return Ok(ConstVal::Int(self.alignof_operand_bytes()?)); + let v = self.alignof_operand_bytes()?; + return Ok(ConstVal::Int { + val: v, + ty: self.size_t_ty(), + }); } self.parse_const_expr_primary_val() } + /// The `size_t` type tag: `unsigned long` on LP64, + /// `unsigned long long` on LLP64. + fn size_t_ty(&self) -> i64 { + if self.target.is_windows() { + Ty::LongLong as i64 | UNSIGNED_BIT + } else { + Ty::Long as i64 | UNSIGNED_BIT + } + } + /// Recognise the GCC-style `offsetof` expansion in a constant /// expression -- `&((T*))->field[.field]*[[N]]`. The /// macro typically expands to @@ -668,12 +862,15 @@ impl Compiler { // targets are 8 bytes and keep the full value. let bytes = self.size_of_type(target_ty); let is_bool = strip_unsigned(target_ty) == Ty::Bool as i64; - ConstVal::Int(narrow_const_int( - bytes, - is_unsigned_ty(target_ty), - is_bool, - v.as_int(), - )) + ConstVal::Int { + val: narrow_const_int( + bytes, + is_unsigned_ty(target_ty), + is_bool, + v.as_int(), + ), + ty: target_ty, + } }); } let v = self.parse_const_expr_cond_val()?; @@ -684,9 +881,12 @@ impl Compiler { return Ok(v); } if self.lex.tk == Token::Num { + // Type the literal per C99 6.4.4.1p5 (suffix + magnitude) + // before `next()` resets the lexer's suffix fields. let v = self.lex.ival; + let ty = self.literal_auto_promoted_type(v); self.next()?; - return Ok(ConstVal::Int(v)); + return Ok(ConstVal::Int { val: v, ty }); } if self.lex.tk == '"' { // String literal in a constant expression -- evaluates @@ -701,7 +901,10 @@ impl Compiler { self.next()?; } self.data.push(0); - return Ok(ConstVal::Int(addr)); + return Ok(ConstVal::Int { + val: addr, + ty: Ty::Ptr as i64, + }); } if self.lex.tk == Token::FloatNum { // Floating literal -- the lexer staged the f64 bit @@ -718,9 +921,17 @@ impl Compiler { } if self.lex.tk == Token::Id && self.symbols[self.lex.curr_id_idx].class == Token::Num as i64 { + // Enumeration constants have type `int` (C99 6.7.2.2p3); + // a value past `int`'s range (accepted as an extension) + // keeps 64-bit rank so arithmetic doesn't truncate it. let v = self.symbols[self.lex.curr_id_idx].val; self.next()?; - return Ok(ConstVal::Int(v)); + let ty = if v as i32 as i64 == v { + Ty::Int as i64 + } else { + Ty::LongLong as i64 + }; + return Ok(ConstVal::Int { val: v, ty }); } let id_suffix = if self.lex.tk == Token::Id { format!(" `{}`", self.symbols[self.lex.curr_id_idx].name) diff --git a/src/c5/compiler/decl_base.rs b/src/c5/compiler/decl_base.rs index 13f033028..c65823382 100644 --- a/src/c5/compiler/decl_base.rs +++ b/src/c5/compiler/decl_base.rs @@ -528,7 +528,8 @@ impl Compiler { return self.parse_typeof_specifier(); } - let bt = if let Some(scalar) = self.parse_scalar_base_specifier(&m)? { + let base_tok = self.lex.tk; + let mut bt = if let Some(scalar) = self.parse_scalar_base_specifier(&m)? { scalar } else if self.lex.tk == Token::Enum { // `enum [Tag] [{ ... }]` collapses to `int`; the shared @@ -590,17 +591,52 @@ impl Compiler { return Err(self.compile_err("type expected")); }; - // Trailing qualifiers / modifiers: `int const`, `int long`, - // `unsigned int long long`, etc. all collapse to the base type - // already chosen. + // Trailing specifiers: C99 6.7.2p2 admits the specifier + // multiset in any order, so `int long`, `int unsigned`, + // `char unsigned`, `double long` re-derive the base tag from + // the folded modifiers. A non-scalar base (typedef, struct, + // enum) has no valid int-modifier combination; the tokens are + // consumed as before. + if self.consume_trailing_decl_modifiers(&mut m)? { + if base_tok == Token::Int { + bt = m.int_base(); + } else if base_tok == Token::Char { + bt = m.char_tag(self.target.plain_char_signed()); + } else if base_tok == Token::Double && m.saw_long() { + self.pending.base_was_long_double = true; + } + } + + Ok(bt) + } + + /// Consume the specifiers that may trail the base-type keyword: + /// int modifiers fold into `m` (the caller re-derives the base + /// tag), qualifiers are no-ops, and `inline` / `_Noreturn` set + /// the same pending flags as in leading position. Returns true + /// when an int modifier was consumed. + pub(super) fn consume_trailing_decl_modifiers( + &mut self, + m: &mut IntModifiers, + ) -> Result { + let mut saw_int_mod = false; while is_decl_modifier(self.lex.tk) { if self.lex.tk == Token::Attribute { self.skip_attribute_specifiers()?; continue; } + if self.lex.tk == Token::Inline { + self.pending_is_inline = true; + } + if self.lex.tk == Token::Noreturn { + self.pending_noreturn = true; + } + if self.try_consume_int_modifier(m)? { + saw_int_mod = true; + continue; + } self.next()?; } - - Ok(bt) + Ok(saw_int_mod) } } diff --git a/src/c5/compiler/expr.rs b/src/c5/compiler/expr.rs index 3cfa7dfd1..4aed51089 100644 --- a/src/c5/compiler/expr.rs +++ b/src/c5/compiler/expr.rs @@ -109,7 +109,7 @@ impl Compiler { /// With `u`/`U`: same hierarchy in the unsigned variants. /// With `l`/`L` / `ll`/`LL`: floor at the named width and let /// the magnitude bump further as needed. - fn literal_auto_promoted_type(&self, ival: i64) -> i64 { + pub(super) fn literal_auto_promoted_type(&self, ival: i64) -> i64 { let suffix_long = self.lex.int_suffix_long; let mut is_unsigned = self.lex.int_suffix_unsigned; // C99 6.4.4.1: a hexadecimal, octal, or binary constant may take @@ -133,7 +133,9 @@ impl Compiler { if bits >= 128 { true } else { - mag <= (1u128 << (bits - 1)) + // Signed max is 2^(bits-1) - 1; 2^31 / 2^63 exactly + // must move to the next rank (or unsigned type). + mag < (1u128 << (bits - 1)) } } else if bits >= 128 { true @@ -2450,7 +2452,8 @@ impl Compiler { // below when the lvalue is integer but the rhs is // floating (C99 6.5.16.2 performs the operation in the // common type). - let rhs_is_fp = is_floating_scalar(self.ty); + let rhs_ty = self.ty; + let rhs_is_fp = is_floating_scalar(rhs_ty); if (binop == Token::AddOp as i64 || binop == Token::SubOp as i64) && is_pointer_ty(lhs_ty) && !is_floating_scalar(lhs_ty) @@ -2503,6 +2506,16 @@ impl Compiler { // converts the result back to the lvalue's integer // type (C99 6.5.16.2). let op_is_fp = lhs_is_fp || rhs_is_fp; + // C99 6.5.16.2p3: `E1 op= E2` computes `E1 op E2`, so + // divide / modulo signedness follows the 6.3.1.8 common + // type of both operands, not the lvalue alone (`int x; + // x /= 2u` divides unsigned). Pointer operands keep the + // lvalue's signedness (no arithmetic common type). + let div_unsigned = if op_is_fp || is_pointer_ty(lhs_ty) || is_pointer_ty(rhs_ty) { + is_unsigned_ty(lhs_ty) + } else { + is_unsigned_ty(usual_arith_common_ty(lhs_ty, rhs_ty, self.target)) + }; use super::super::ir::BinOp as B; let bop = match binop { x if x == Token::AddOp as i64 => { @@ -2529,14 +2542,14 @@ impl Compiler { x if x == Token::DivOp as i64 => { if op_is_fp { B::Fdiv - } else if is_unsigned_ty(lhs_ty) { + } else if div_unsigned { B::Divu } else { B::Div } } x if x == Token::ModOp as i64 => { - if is_unsigned_ty(lhs_ty) { + if div_unsigned { B::Modu } else { B::Mod @@ -2615,18 +2628,21 @@ impl Compiler { let else_ty = self.ty; // C99 6.5.15p5: when both arms have arithmetic type the // conditional's type is their usual-arithmetic-conversions - // common type and each arm converts to it. Without the cast a - // mixed int / floating ternary stores one arm through the - // other arm's store kind (integer bits read as a double). Pure - // integer arms already lower correctly on the I64 path, so - // only the floating-involved case needs the conversion here. + // common type and each arm converts to it. Without the cast + // a mixed int / floating ternary stores one arm through the + // other arm's store kind, and mixed-signedness integer arms + // take the wrong signedness (`c ? 1u : -1` must be the + // zero-extended unsigned value, not sign-extended int). + // Same-typed integer arms need no conversion. let mut result_ty = self.ty; let arith = |t: i64| !is_pointer_ty(t) && !is_struct_ty(t); - if (is_floating_scalar(then_ty) || is_floating_scalar(else_ty)) - && arith(then_ty) - && arith(else_ty) - { - let common = fp_result_ty(then_ty, else_ty); + let arms_fp = is_floating_scalar(then_ty) || is_floating_scalar(else_ty); + if (arms_fp || then_ty != else_ty) && arith(then_ty) && arith(else_ty) { + let common = if arms_fp { + fp_result_ty(then_ty, else_ty) + } else { + usual_arith_common_ty(then_ty, else_ty, self.target) + }; result_ty = common; if then_ty != common && then_ast.is_some() { let pos = self.ast_src_pos(); @@ -2798,16 +2814,18 @@ impl Compiler { self.next()?; self.ast_psh(); self.expr(Token::AddOp as i64)?; - // Pick logical (Shru) for unsigned LHS, arithmetic (Shr) otherwise. - // The RHS is the shift count; only the LHS sign matters. - + // Pick logical (Shru) for unsigned LHS, arithmetic (Shr) + // otherwise; the RHS is the shift count and does not + // participate. C99 6.5.7p3: the result has the promoted + // LHS type, so a 64-bit LHS keeps its width. Set the + // type before building the AST node so the node carries + // the result type, mirroring the `<<` path. + let lhs_size = self.size_of_type(t); + self.ty = if lhs_size <= 2 { Ty::Int as i64 } else { t }; if is_unsigned_ty(t) { self.ast_binop(crate::c5::ir::BinOp::Shru); - // Preserve LHS unsigned-ness so chained shifts/compares stay unsigned. - self.ty = t; } else { self.ast_binop(crate::c5::ir::BinOp::Shr); - self.ty = Ty::Int as i64; } } else if self.lex.tk == Token::AddOp { self.next()?; diff --git a/src/c5/compiler/mod.rs b/src/c5/compiler/mod.rs index 165a98c1b..19d25c9a4 100644 --- a/src/c5/compiler/mod.rs +++ b/src/c5/compiler/mod.rs @@ -695,6 +695,13 @@ pub struct Compiler { /// scopes to the immediately following declarator only. pending_noreturn: bool, + /// Nesting depth of unevaluated constant-expression operands + /// (short-circuited `&&` / `||` right sides and not-taken `?:` + /// arms). C99 6.6p4 forbids a zero divisor in a constant + /// expression, but an unevaluated operand must not trigger the + /// diagnostic (`1 ? 2 : 1/0` is accepted by gcc / clang). + const_unevaluated: u32, + /// Per-function AST. The arena is reset at every function /// entry; the SSA walker reads from these snapshots at codegen /// entry. @@ -1274,6 +1281,7 @@ impl Compiler { uses_alloca_in_current_fn: false, pending_is_inline: false, pending_noreturn: false, + const_unevaluated: 0, ast: super::ast::Ast::new(), ast_acc: None, ast_vstack: Vec::new(), diff --git a/src/c5/lexer.rs b/src/c5/lexer.rs index 47f97a6d2..95878dc4b 100644 --- a/src/c5/lexer.rs +++ b/src/c5/lexer.rs @@ -943,6 +943,24 @@ impl Lexer { items } + /// Consume the C99 6.4.4.1 integer suffix (`u`/`U` and one or two + /// `l`/`L` in any combination) and record it in the suffix fields + /// the expression parser types the literal from. Shared by every + /// integer base so no base drops the suffix. + fn lex_int_suffix(&mut self) { + let mut l_count: u8 = 0; + let mut u_seen = false; + while self.pos < self.src.len() && matches!(self.src[self.pos], b'u' | b'U' | b'l' | b'L') { + match self.src[self.pos] { + b'l' | b'L' => l_count = l_count.saturating_add(1), + _ => u_seen = true, + } + self.pos += 1; + } + self.int_suffix_long = l_count.min(2); + self.int_suffix_unsigned = u_seen; + } + /// Finalise a numeric constant: a digit/suffix run must not be /// immediately followed by an identifier character. `1_000`, /// `0x1_0000`, `1.0q` are invalid preprocessing numbers (C99 6.4.8) @@ -1075,11 +1093,7 @@ impl Lexer { val = val * 8 + (self.src[self.pos] - b'0') as i64; self.pos += 1; } - while self.pos < self.src.len() - && matches!(self.src[self.pos], b'u' | b'U' | b'l' | b'L') - { - self.pos += 1; - } + self.lex_int_suffix(); self.ival = val; self.tk = Tok(Token::Num as i64); self.int_is_decimal = false; @@ -1116,11 +1130,7 @@ impl Lexer { ), ))); } - while self.pos < self.src.len() - && matches!(self.src[self.pos], b'u' | b'U' | b'l' | b'L') - { - self.pos += 1; - } + self.lex_int_suffix(); self.ival = val; self.tk = Tok(Token::Num as i64); self.int_is_decimal = false; @@ -1176,30 +1186,9 @@ impl Lexer { &format!("{}: hex literal `0x` has no digits", self.line), ))); } - // Hex literals can carry the standard integer suffix - // letters (u/U/l/L plus ll/LL combinations such as - // 0xFFFFULL). Per C99 6.4.4.1 record the longness - // (one or two `l`/`L`) and the unsigned modifier - // so the expression parser can type the literal - // accordingly; without that the literal would - // default to `int` and any arithmetic that - // assumes 64-bit width truncates to 32. - let mut l_count: u8 = 0; - let mut u_seen = false; - while self.pos < self.src.len() - && matches!(self.src[self.pos], b'u' | b'U' | b'l' | b'L') - { - match self.src[self.pos] { - b'l' | b'L' => l_count = l_count.saturating_add(1), - b'u' | b'U' => u_seen = true, - _ => {} - } - self.pos += 1; - } + self.lex_int_suffix(); self.ival = val; self.tk = Tok(Token::Num as i64); - self.int_suffix_long = l_count.min(2); - self.int_suffix_unsigned = u_seen; self.int_is_decimal = false; return self.end_number(); } @@ -1225,29 +1214,13 @@ impl Lexer { // (1u, 1L, 1ULL, 1lu, ...). When any suffix letter is // present, the literal is unambiguously an integer -- // no float-suffix `f`/`F` can follow because the - // standard doesn't allow it on integer literals. Per - // C99 6.4.4.1, count consecutive `l`/`L` characters - // (one => long, two => long long) and note any - // `u`/`U` for the unsigned modifier. + // standard doesn't allow it on integer literals. if self.pos < self.src.len() && matches!(self.src[self.pos], b'u' | b'U' | b'l' | b'L') { - let mut l_count: u8 = 0; - let mut u_seen = false; - while self.pos < self.src.len() - && matches!(self.src[self.pos], b'u' | b'U' | b'l' | b'L') - { - match self.src[self.pos] { - b'l' | b'L' => l_count = l_count.saturating_add(1), - b'u' | b'U' => u_seen = true, - _ => {} - } - self.pos += 1; - } + self.lex_int_suffix(); self.ival = val; self.tk = Tok(Token::Num as i64); - self.int_suffix_long = l_count.min(2); - self.int_suffix_unsigned = u_seen; return self.end_number(); } diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index 1b20f5bf8..6cdb64c5a 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1082,6 +1082,13 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("goto.c", 5), ("switch_statement.c", 25), ("switch_binary_search.c", 0), + ("switch_case_label_promoted.c", 0), + ("int_literal_boundary_types.c", 0), + ("const_expr_unsigned_fold.c", 0), + ("shift_result_promoted_type.c", 0), + ("ternary_arith_common_type.c", 0), + ("compound_assign_unsigned_div.c", 0), + ("decl_specifier_any_order.c", 0), ("branch_relaxation.c", 21), ("float_register_resident.c", 45), ("variadic_struct_arg.c", 18), diff --git a/src/c5/tests/lexer.rs b/src/c5/tests/lexer.rs index dce9cf61e..0abf21ef7 100644 --- a/src/c5/tests/lexer.rs +++ b/src/c5/tests/lexer.rs @@ -31,6 +31,29 @@ fn hex_literal_lower_and_upper() { assert_eq!(h.ival(), 0xABCD); } +// C99 6.4.4.1: every integer base carries the same u/U/l/L suffix; +// octal and binary literals must record it like decimal and hex do. +#[test] +fn integer_suffix_recorded_for_every_base() { + let cases: &[(&str, i64, u8, bool)] = &[ + ("010u", 8, 0, true), + ("0777UL", 511, 1, true), + ("01ll", 1, 2, false), + ("0b101u", 5, 0, true), + ("0b1LL", 1, 2, false), + ("0xFFull", 255, 2, true), + ("42lu", 42, 1, true), + ("7", 7, 0, false), + ]; + for &(src, val, l_count, unsigned) in cases { + let mut h = LexHarness::new(src); + assert_eq!(h.next(), Token::Num, "{src}"); + assert_eq!(h.ival(), val, "{src}"); + assert_eq!(h.int_suffix(), (l_count, unsigned), "{src}"); + assert_eq!(h.next(), Tok::EOF, "{src}"); + } +} + #[test] fn keywords_resolve_to_their_tokens() { let mut h = LexHarness::new("int char if else while return sizeof"); diff --git a/src/c5/tests/mod.rs b/src/c5/tests/mod.rs index 139803667..cac735b5f 100644 --- a/src/c5/tests/mod.rs +++ b/src/c5/tests/mod.rs @@ -402,6 +402,11 @@ impl LexHarness { pub fn ival(&self) -> i64 { self.lex.ival } + /// `(l_count, unsigned)` suffix record of the most recently lexed + /// integer literal. + pub fn int_suffix(&self) -> (u8, bool) { + (self.lex.int_suffix_long, self.lex.int_suffix_unsigned) + } pub fn line(&self) -> usize { self.lex.line } diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index b1f0265b1..f4f6dadbf 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -373,6 +373,13 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("goto.c", 5), ("switch_statement.c", 25), ("switch_binary_search.c", 0), + ("switch_case_label_promoted.c", 0), + ("int_literal_boundary_types.c", 0), + ("const_expr_unsigned_fold.c", 0), + ("shift_result_promoted_type.c", 0), + ("ternary_arith_common_type.c", 0), + ("compound_assign_unsigned_div.c", 0), + ("decl_specifier_any_order.c", 0), ("branch_relaxation.c", 21), ("float_register_resident.c", 45), ("variadic_struct_arg.c", 18), diff --git a/src/c5/tests/parser.rs b/src/c5/tests/parser.rs index 9904a62fd..589676f9c 100644 --- a/src/c5/tests/parser.rs +++ b/src/c5/tests/parser.rs @@ -761,3 +761,43 @@ fn deeply_nested_macro_expansion_does_not_overflow_the_stack() { // Must return (Ok or Err), not crash the test process. let _ = crate::c5::Compiler::new(src).compile(); } + +// C99 6.6p4: a zero divisor in an evaluated constant expression is a +// compile error, not a silent fold to 0; a short-circuited or +// not-taken operand stays unevaluated and must compile. +#[test] +fn constant_expression_division_by_zero_is_diagnosed() { + expect_compile_error( + "int x[1/0];\nint main(void){ return 0; }", + "division by zero in a constant expression", + ); + expect_compile_error( + "enum { A = 1 % 0 };\nint main(void){ return 0; }", + "division by zero in a constant expression", + ); + expect_compile_error( + "static int g = 8 / (4 - 4);\nint main(void){ return 0; }", + "division by zero in a constant expression", + ); + crate::c5::Compiler::new( + "int a[1 ? 2 : 1/0];\nint b[0 || 1 ? 2 : 5/0];\nenum { K = 0 && 1/0 };\n\ + int main(void){ return 0; }" + .to_string(), + ) + .compile() + .expect("unevaluated zero divisors must compile"); +} + +// C99 6.5.5 with the both-operands-wrap model: LLONG_MIN / -1 and +// LLONG_MIN % -1 fold (wrapping) instead of aborting the compiler. +#[test] +fn constant_expression_llong_min_div_neg_one_folds() { + crate::c5::Compiler::new( + "static long long k = (-9223372036854775807LL - 1) / -1;\n\ + static long long r = (-9223372036854775807LL - 1) % -1;\n\ + int main(void){ return r == 0 && k != 0 ? 0 : 1; }" + .to_string(), + ) + .compile() + .expect("LLONG_MIN / -1 must fold, not panic"); +} diff --git a/tests/fixtures/c/compound_assign_unsigned_div.c b/tests/fixtures/c/compound_assign_unsigned_div.c new file mode 100644 index 000000000..e1d1da13f --- /dev/null +++ b/tests/fixtures/c/compound_assign_unsigned_div.c @@ -0,0 +1,40 @@ +/* C99 6.5.16.2p3: `E1 op= E2` computes `E1 op E2`, so divide and + remainder run in the 6.3.1.8 common type of both operands -- at + its width and signedness -- and the result converts back to E1's + type. `unsigned x /= -2` divides 0xFFFFFFFF by 0xFFFFFFFE at 32 + bits; `int x /= 2u` divides unsigned. */ +int main(void) { + unsigned q = 0xffffffffu; + q /= -2; + if (q != 1) { + return 1; + } + unsigned q2 = 0xffffffffu; + q2 %= -2; + if (q2 != 1) { + return 2; + } + int d = -2; + d /= 2u; + if (d != 2147483647) { + return 3; + } + int e = -7; + e %= 3; + if (e != -1) { + return 4; + } + /* 64-bit unsigned lvalue: full-width divide, no masking. */ + unsigned long long big = 0xFFFFFFFFFFFFFFFFULL; + big /= 3; + if (big != 6148914691236517205ULL) { + return 5; + } + /* Sub-int unsigned lvalue promotes to signed int: 255 / -2. */ + unsigned char uc = 255; + uc /= -2; + if (uc != 129) { + return 6; + } + return 0; +} diff --git a/tests/fixtures/c/const_expr_unsigned_fold.c b/tests/fixtures/c/const_expr_unsigned_fold.c new file mode 100644 index 000000000..6f0ba6f61 --- /dev/null +++ b/tests/fixtures/c/const_expr_unsigned_fold.c @@ -0,0 +1,44 @@ +/* C99 6.6 + 6.3.1.8: constant expressions fold with the operands' + signedness -- unsigned division, remainder, right shift, and + relational compares on 64-bit unsigned values, and unsigned-int + compares for mixed narrow operands. INT64_MIN / -1 wraps instead + of aborting the compiler; a zero divisor in a not-taken `?:` arm + or short-circuited operand is unevaluated (6.6p4 scopes to the + evaluated expression). */ +static unsigned long long g_div = 0xFFFFFFFFFFFFFFFFULL / 3; +static unsigned long long g_shr = 0xFFFFFFFFFFFFFFFFULL >> 4; +static unsigned long long g_rem = 0xFFFFFFFFFFFFFFFFULL % 7; +static int g_gt = 0xFFFFFFFFFFFFFFFFULL > 2; +static int g_mixed = -1 < 1u; +static long long g_wrap = (-9223372036854775807LL - 1) / -1; +static int arr[0xFFFFFFFFu / 1000000000u]; +static int live[1 ? 3 : 1 / 0]; +static int shortcut = 0 && 1 / 0; + +int main(void) { + if (g_div != 6148914691236517205ULL) { + return 1; + } + if (g_shr != 1152921504606846975ULL) { + return 2; + } + if (g_rem != 1) { + return 3; + } + if (g_gt != 1) { + return 4; + } + if (g_mixed != 0) { + return 5; + } + if (g_wrap != -9223372036854775807LL - 1) { + return 6; + } + if (sizeof(arr) / sizeof(arr[0]) != 4) { + return 7; + } + if (sizeof(live) / sizeof(live[0]) != 3 || shortcut != 0) { + return 8; + } + return 0; +} diff --git a/tests/fixtures/c/decl_specifier_any_order.c b/tests/fixtures/c/decl_specifier_any_order.c new file mode 100644 index 000000000..43ea61c30 --- /dev/null +++ b/tests/fixtures/c/decl_specifier_any_order.c @@ -0,0 +1,42 @@ +/* C99 6.7.2p2: type specifiers may appear in any order, so the + modifier may follow the base keyword: `int long` is `long int`, + `int unsigned` is `unsigned int`, `char unsigned` is `unsigned + char`, `int long long` is `long long int`. */ +struct pair { + long a; + int long b; /* same layout as `long b` */ +}; + +int main(void) { + if (sizeof(int long) != sizeof(long)) { + return 1; + } + if (sizeof(int long long) != sizeof(long long)) { + return 2; + } + int long long big = 0x100000000LL; + if (big >> 32 != 1) { + return 3; + } + int unsigned u = -1; + if (!(u > 0)) { + return 4; + } + char unsigned c = -1; + if (c != 255) { + return 5; + } + long int long llv = -1; /* `long int long` is long long */ + if (sizeof(llv) != 8) { + return 6; + } + if (sizeof(struct pair) != 2 * sizeof(long)) { + return 7; + } + struct pair p; + p.b = -5; + if (p.b >= 0) { + return 8; + } + return 0; +} diff --git a/tests/fixtures/c/int_literal_boundary_types.c b/tests/fixtures/c/int_literal_boundary_types.c new file mode 100644 index 000000000..5e7f5b05f --- /dev/null +++ b/tests/fixtures/c/int_literal_boundary_types.c @@ -0,0 +1,42 @@ +/* C99 6.4.4.1p5 at the signed-max boundaries: an unsuffixed decimal + constant takes the first of int, long, long long that represents + it, so 2147483648 (2^31) is long, not a wrapped int; a decimal + constant past LLONG_MAX takes unsigned long long (existing gcc / + clang practice). Hex constants at 2^31 / 2^63 take the unsigned + type at the same rank. Octal and binary literals carry the same + u/U/l/L suffixes as decimal and hex. */ +int main(void) { + /* 2147483648 is long (or long long): the negation and subtraction + run at 64 bits instead of wrapping at int width. */ + long long a = -2147483648 - 1; + if (a != -2147483649LL) { + return 1; + } + if (sizeof(2147483648) != sizeof(long long) && sizeof(2147483648) != 8) { + return 2; + } + /* 0x80000000 is unsigned int: -1 converts to 0xFFFFFFFF and + compares above it. */ + if (-1 < 0x80000000) { + return 3; + } + if (sizeof(0x80000000) != 4) { + return 4; + } + /* 2^63: hex and decimal both land at unsigned long long. */ + if (!(0x8000000000000000 > 0x7FFFFFFFFFFFFFFF)) { + return 5; + } + if (9223372036854775808 / 2 != 4611686018427387904) { + return 6; + } + /* Octal / binary suffixes are recorded, not dropped. */ + if (sizeof(01ll) != 8 || sizeof(0777LL) != 8 || sizeof(0b1ull) != 8) { + return 7; + } + /* 010u is unsigned int: the mixed compare runs unsigned. */ + if (-1 < 010u) { + return 8; + } + return 0; +} diff --git a/tests/fixtures/c/shift_result_promoted_type.c b/tests/fixtures/c/shift_result_promoted_type.c new file mode 100644 index 000000000..1baa254c9 --- /dev/null +++ b/tests/fixtures/c/shift_result_promoted_type.c @@ -0,0 +1,29 @@ +/* C99 6.5.7p3: the result of a shift has the promoted type of the + left operand; the count operand does not participate. A signed + 64-bit `>>` must not narrow to int in a surrounding expression. */ +int main(void) { + long long x = -8589934592LL; /* -0x2_0000_0000 */ + long long y = (x >> 1) + 0; + if (y != -4294967296LL) { + return 1; + } + unsigned long long b = 0x8000000000000000ULL; + if ((b >> 63) != 1) { + return 2; + } + unsigned int u = 0x80000000u; + if ((u >> 31) != 1) { + return 3; + } + int neg = -16; + if ((neg >> 2) != -4) { + return 4; + } + /* Promoted sub-int LHS: unsigned char shifts as (zero-extended) + int. */ + unsigned char c = 0x80; + if ((c >> 3) != 0x10) { + return 5; + } + return 0; +} diff --git a/tests/fixtures/c/switch_case_label_promoted.c b/tests/fixtures/c/switch_case_label_promoted.c new file mode 100644 index 000000000..fc1df47fa --- /dev/null +++ b/tests/fixtures/c/switch_case_label_promoted.c @@ -0,0 +1,48 @@ +/* C99 6.8.4.2p5: each case constant converts to the promoted type of + the controlling expression. On an int switch `case 0x80000000:` + (unsigned int constant) converts to INT_MIN and must match. */ +int main(void) { + int v = -2147483647 - 1; + int hit = 0; + switch (v) { + case 0x80000000: + hit = 1; + break; + default: + hit = 2; + break; + } + if (hit != 1) { + return 1; + } + /* Unsigned controlling type: a negative label wraps modulo 2^32. */ + unsigned u = 0xfffffffeu; + switch (u) { + case -2: + hit = 3; + break; + default: + hit = 4; + break; + } + if (hit != 3) { + return 2; + } + /* 8-byte controlling type keeps full-width labels. */ + long long w = -4294967296LL; + switch (w) { + case -4294967296LL: + hit = 5; + break; + case 0x80000000: + hit = 6; + break; + default: + hit = 7; + break; + } + if (hit != 5) { + return 3; + } + return 0; +} diff --git a/tests/fixtures/c/ternary_arith_common_type.c b/tests/fixtures/c/ternary_arith_common_type.c new file mode 100644 index 000000000..1b5807d9e --- /dev/null +++ b/tests/fixtures/c/ternary_arith_common_type.c @@ -0,0 +1,26 @@ +/* C99 6.5.15p5: with two arithmetic arms the conditional's type is + the usual-arithmetic-conversions common type and each arm converts + to it, whichever arm is selected. `c ? 1u : -1` is unsigned int in + both directions, not the else-arm's int. */ +int main(void) { + unsigned r = 0; + long z = (r == 0) ? 1u : -1; + if (z != 1) { + return 1; + } + long w = (r != 0) ? 1u : -1; + if (w != 4294967295L) { + return 2; + } + /* Then-arm conversion: -1 selected against an unsigned else. */ + long v = (r == 0) ? -1 : 1u; + if (v != 4294967295L) { + return 3; + } + /* Rank widening: the int arm widens to long long. */ + long long p = (r == 0) ? -1 : 0LL; + if (p != -1LL) { + return 4; + } + return 0; +} From 48d8304f6ed416593771a82f1ffa5c42fe14c070 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 18:50:30 -0700 Subject: [PATCH 11/67] tests: re-pin the relocatable golden table, add fixture snapshots The release-version bump changes OUTPUT_MARKER in every emitted object, so the byte+reloc golden table pins to the new version (the mismatch reproduces at the bump commit with no compiler change). New snapshots cover the ten fixtures added with the front-end and initializer fixes; math_classify / libc_fp_classify pick up the return-narrowing the promoted shift type now requires. Co-Authored-By: Claude Fable 5 --- src/c5/tests/reloc_golden.rs | 80 ++--- .../compound_assign_unsigned_div.aarch64.asm | 117 ++++++ .../asm/compound_assign_unsigned_div.x64.asm | 109 ++++++ .../asm/const_expr_unsigned_fold.aarch64.asm | 110 ++++++ .../asm/const_expr_unsigned_fold.x64.asm | 103 ++++++ .../asm/decl_specifier_any_order.aarch64.asm | 89 +++++ .../asm/decl_specifier_any_order.x64.asm | 80 +++++ .../int_literal_boundary_types.aarch64.asm | 84 +++++ .../asm/int_literal_boundary_types.x64.asm | 80 +++++ .../asm/libc_fp_classify.aarch64.asm | 1 + tests/snapshots/asm/libc_fp_classify.x64.asm | 2 + tests/snapshots/asm/math_classify.aarch64.asm | 1 + tests/snapshots/asm/math_classify.x64.asm | 2 + ...ested_designator_string_member.aarch64.asm | 189 ++++++++++ .../nested_designator_string_member.x64.asm | 206 +++++++++++ .../asm/packed_bitfield_repack.aarch64.asm | 247 +++++++++++++ .../asm/packed_bitfield_repack.x64.asm | 237 +++++++++++++ .../shift_result_promoted_type.aarch64.asm | 72 ++++ .../asm/shift_result_promoted_type.x64.asm | 65 ++++ .../switch_case_label_promoted.aarch64.asm | 91 +++++ .../asm/switch_case_label_promoted.x64.asm | 86 +++++ .../asm/ternary_arith_common_type.aarch64.asm | 78 ++++ .../asm/ternary_arith_common_type.x64.asm | 70 ++++ .../union_member_unbraced_init.aarch64.asm | 197 ++++++++++ .../asm/union_member_unbraced_init.x64.asm | 237 +++++++++++++ .../ssa/compound_assign_unsigned_div.ssa | 142 ++++++++ .../ssa/const_expr_unsigned_fold.ssa | 139 ++++++++ .../ssa/decl_specifier_any_order.ssa | 128 +++++++ .../ssa/int_literal_boundary_types.ssa | 146 ++++++++ tests/snapshots/ssa/libc_fp_classify.ssa | 4 +- tests/snapshots/ssa/math_classify.ssa | 4 +- .../ssa/nested_designator_string_member.ssa | 279 +++++++++++++++ .../snapshots/ssa/packed_bitfield_repack.ssa | 335 ++++++++++++++++++ .../ssa/shift_result_promoted_type.ssa | 109 ++++++ .../ssa/switch_case_label_promoted.ssa | 140 ++++++++ .../ssa/ternary_arith_common_type.ssa | 148 ++++++++ .../ssa/union_member_unbraced_init.ssa | 269 ++++++++++++++ 37 files changed, 4434 insertions(+), 42 deletions(-) create mode 100644 tests/snapshots/asm/compound_assign_unsigned_div.aarch64.asm create mode 100644 tests/snapshots/asm/compound_assign_unsigned_div.x64.asm create mode 100644 tests/snapshots/asm/const_expr_unsigned_fold.aarch64.asm create mode 100644 tests/snapshots/asm/const_expr_unsigned_fold.x64.asm create mode 100644 tests/snapshots/asm/decl_specifier_any_order.aarch64.asm create mode 100644 tests/snapshots/asm/decl_specifier_any_order.x64.asm create mode 100644 tests/snapshots/asm/int_literal_boundary_types.aarch64.asm create mode 100644 tests/snapshots/asm/int_literal_boundary_types.x64.asm create mode 100644 tests/snapshots/asm/nested_designator_string_member.aarch64.asm create mode 100644 tests/snapshots/asm/nested_designator_string_member.x64.asm create mode 100644 tests/snapshots/asm/packed_bitfield_repack.aarch64.asm create mode 100644 tests/snapshots/asm/packed_bitfield_repack.x64.asm create mode 100644 tests/snapshots/asm/shift_result_promoted_type.aarch64.asm create mode 100644 tests/snapshots/asm/shift_result_promoted_type.x64.asm create mode 100644 tests/snapshots/asm/switch_case_label_promoted.aarch64.asm create mode 100644 tests/snapshots/asm/switch_case_label_promoted.x64.asm create mode 100644 tests/snapshots/asm/ternary_arith_common_type.aarch64.asm create mode 100644 tests/snapshots/asm/ternary_arith_common_type.x64.asm create mode 100644 tests/snapshots/asm/union_member_unbraced_init.aarch64.asm create mode 100644 tests/snapshots/asm/union_member_unbraced_init.x64.asm create mode 100644 tests/snapshots/ssa/compound_assign_unsigned_div.ssa create mode 100644 tests/snapshots/ssa/const_expr_unsigned_fold.ssa create mode 100644 tests/snapshots/ssa/decl_specifier_any_order.ssa create mode 100644 tests/snapshots/ssa/int_literal_boundary_types.ssa create mode 100644 tests/snapshots/ssa/nested_designator_string_member.ssa create mode 100644 tests/snapshots/ssa/packed_bitfield_repack.ssa create mode 100644 tests/snapshots/ssa/shift_result_promoted_type.ssa create mode 100644 tests/snapshots/ssa/switch_case_label_promoted.ssa create mode 100644 tests/snapshots/ssa/ternary_arith_common_type.ssa create mode 100644 tests/snapshots/ssa/union_member_unbraced_init.ssa diff --git a/src/c5/tests/reloc_golden.rs b/src/c5/tests/reloc_golden.rs index 2cd83a142..bde2396b2 100644 --- a/src/c5/tests/reloc_golden.rs +++ b/src/c5/tests/reloc_golden.rs @@ -108,74 +108,74 @@ fn reloc_bytes(src: &str, target: Target) -> alloc::vec::Vec { /// of (source, target, options) only. Regenerate by running /// `reloc_object_bytes_match_golden` -- it panics with the current table. const GOLDEN: &[(&str, &str, u64, usize)] = &[ - ("ret42", "linux-x64", 0x19e783356189ee32, 1472), - ("ret42", "linux-arm64", 0x07fc9f07b272d045, 1472), - ("ret42", "macos-arm64", 0x07fc9f07b272d045, 1472), - ("ret42", "win-x64", 0x19e783356189ee32, 1472), - ("ret42", "win-arm64", 0x07fc9f07b272d045, 1472), - ("intarith", "linux-x64", 0x32e7f9a8a23d2879, 1776), - ("intarith", "linux-arm64", 0x3680fddfc8f85338, 1744), - ("intarith", "macos-arm64", 0x3680fddfc8f85338, 1744), - ("intarith", "win-x64", 0xf005b58ff0e2f9d2, 1800), - ("intarith", "win-arm64", 0x862165d8b7d20f14, 1784), - ("fparith", "linux-x64", 0x6dd6a94a4ceb8f5e, 1752), - ("fparith", "linux-arm64", 0x4bc00602138d1458, 1688), - ("fparith", "macos-arm64", 0x4bc00602138d1458, 1688), - ("fparith", "win-x64", 0x0daf626ffa7c9b1a, 1840), - ("fparith", "win-arm64", 0x4bc00602138d1458, 1688), - ("fpunary", "linux-x64", 0xd6da793aba57f99a, 1848), - ("fpunary", "linux-arm64", 0xf4b5b3f74419f790, 1752), - ("fpunary", "macos-arm64", 0xf4b5b3f74419f790, 1752), - ("fpunary", "win-x64", 0x4c3544b7d7598186, 1984), - ("fpunary", "win-arm64", 0xf4b5b3f74419f790, 1752), - ("mem", "linux-x64", 0xa0f7e9b7194eaa86, 1600), - ("mem", "linux-arm64", 0x44394734000af3f7, 1608), - ("mem", "macos-arm64", 0x44394734000af3f7, 1608), - ("mem", "win-x64", 0x9d9c12dbe29b0a26, 1600), - ("mem", "win-arm64", 0x44394734000af3f7, 1608), - ("data_calls", "linux-x64", 0x021bff3d4de3acec, 1664), - ("data_calls", "linux-arm64", 0x2eaa6b7fcabb0b37, 1688), - ("data_calls", "macos-arm64", 0x2eaa6b7fcabb0b37, 1688), - ("data_calls", "win-x64", 0x8701619c09b78c22, 1680), - ("data_calls", "win-arm64", 0x2eaa6b7fcabb0b37, 1688), - ("struct_param_spill", "linux-x64", 0x4c486c8df4456e10, 1680), + ("ret42", "linux-x64", 0x2fab302afe7d051f, 1472), + ("ret42", "linux-arm64", 0xa1f9fbf7bb9cbb2c, 1472), + ("ret42", "macos-arm64", 0xa1f9fbf7bb9cbb2c, 1472), + ("ret42", "win-x64", 0x2fab302afe7d051f, 1472), + ("ret42", "win-arm64", 0xa1f9fbf7bb9cbb2c, 1472), + ("intarith", "linux-x64", 0x23f78314c1cff274, 1776), + ("intarith", "linux-arm64", 0xfe88c2dcdf472389, 1744), + ("intarith", "macos-arm64", 0xfe88c2dcdf472389, 1744), + ("intarith", "win-x64", 0x996e3098a493f373, 1800), + ("intarith", "win-arm64", 0xd65c6cec47efdad5, 1784), + ("fparith", "linux-x64", 0xaed28d15dbe12f9f, 1752), + ("fparith", "linux-arm64", 0x10b5c40cae1c98b9, 1688), + ("fparith", "macos-arm64", 0x10b5c40cae1c98b9, 1688), + ("fparith", "win-x64", 0xbc441586c78cb6ab, 1840), + ("fparith", "win-arm64", 0x10b5c40cae1c98b9, 1688), + ("fpunary", "linux-x64", 0xa7c6296710fb7597, 1848), + ("fpunary", "linux-arm64", 0x23cf0e4149bb3595, 1752), + ("fpunary", "macos-arm64", 0x23cf0e4149bb3595, 1752), + ("fpunary", "win-x64", 0xbc02ab7882ec515f, 1984), + ("fpunary", "win-arm64", 0x23cf0e4149bb3595, 1752), + ("mem", "linux-x64", 0xb5e67861feca0b63, 1600), + ("mem", "linux-arm64", 0x30acdb6f0e6ff6be, 1608), + ("mem", "macos-arm64", 0x30acdb6f0e6ff6be, 1608), + ("mem", "win-x64", 0x445055ce1605ec83, 1600), + ("mem", "win-arm64", 0x30acdb6f0e6ff6be, 1608), + ("data_calls", "linux-x64", 0xe8c2b32035325e81, 1664), + ("data_calls", "linux-arm64", 0x6f46939d6a2a0046, 1688), + ("data_calls", "macos-arm64", 0x6f46939d6a2a0046, 1688), + ("data_calls", "win-x64", 0xc3ebc6db69470097, 1680), + ("data_calls", "win-arm64", 0x6f46939d6a2a0046, 1688), + ("struct_param_spill", "linux-x64", 0x46151b2f7769d061, 1680), ( "struct_param_spill", "linux-arm64", - 0x57d897a30a6971ba, + 0xff95238ed7250147, 1664, ), ( "struct_param_spill", "macos-arm64", - 0x57d897a30a6971ba, + 0xff95238ed7250147, 1664, ), - ("struct_param_spill", "win-x64", 0xc8b021ee3b3b7577, 1720), - ("struct_param_spill", "win-arm64", 0x0bcb20a73947ed86, 1696), + ("struct_param_spill", "win-x64", 0x3fef0b9e920a5ec2, 1720), + ("struct_param_spill", "win-arm64", 0xb9721374270c6243, 1696), ( "fp_across_struct_call", "linux-x64", - 0x9e3edfe0dc19dbdb, + 0x2ff371699761f6ca, 1744, ), ( "fp_across_struct_call", "linux-arm64", - 0x728818c3ad0a7bc6, + 0x8bfeabe2701aede3, 1688, ), ( "fp_across_struct_call", "macos-arm64", - 0x728818c3ad0a7bc6, + 0x8bfeabe2701aede3, 1688, ), - ("fp_across_struct_call", "win-x64", 0xefdbefe433ac8e18, 1816), + ("fp_across_struct_call", "win-x64", 0x87d8fca72654ef11, 1816), ( "fp_across_struct_call", "win-arm64", - 0x728818c3ad0a7bc6, + 0x8bfeabe2701aede3, 1688, ), ]; diff --git a/tests/snapshots/asm/compound_assign_unsigned_div.aarch64.asm b/tests/snapshots/asm/compound_assign_unsigned_div.aarch64.asm new file mode 100644 index 000000000..b22201f68 --- /dev/null +++ b/tests/snapshots/asm/compound_assign_unsigned_div.aarch64.asm @@ -0,0 +1,117 @@ + +compound_assign_unsigned_div.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x30 + mov x0, #0xffff // =65535 + movk x0, #0xffff, lsl #16 + mov x1, #0xfffe // =65534 + movk x1, #0xffff, lsl #16 + udiv x0, x0, x1 + mov w0, w0 + mov x17, #0x1 // =1 + eor x0, x0, x17 + mov w0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x1 // =1 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0xffff // =65535 + movk x0, #0xffff, lsl #16 + mov x1, #0xfffe // =65534 + movk x1, #0xffff, lsl #16 + udiv x17, x0, x1 + msub x0, x17, x1, x0 + mov w0, w0 + mov x17, #0x1 // =1 + eor x0, x0, x17 + mov w0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x2 // =2 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0xfffe // =65534 + movk x0, #0xffff, lsl #16 + movk x0, #0xffff, lsl #32 + movk x0, #0xffff, lsl #48 + mov x1, #0x2 // =2 + mov w0, w0 + udiv x0, x0, x1 + sxtw x0, w0 + mov x17, #0xffff // =65535 + movk x17, #0x7fff, lsl #16 + cmp x0, x17 + b.eq + mov x0, #0x3 // =3 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0xfff9 // =65529 + movk x0, #0xffff, lsl #16 + movk x0, #0xffff, lsl #32 + movk x0, #0xffff, lsl #48 + mov x1, #0x3 // =3 + sdiv x17, x0, x1 + msub x0, x17, x1, x0 + sxtw x0, w0 + mov x17, #0xffff // =65535 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + cmp x0, x17 + b.eq + mov x0, #0x4 // =4 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0xffff // =65535 + movk x0, #0xffff, lsl #16 + movk x0, #0xffff, lsl #32 + movk x0, #0xffff, lsl #48 + mov x1, #0x3 // =3 + udiv x0, x0, x1 + mov x17, #0x5555 // =21845 + movk x17, #0x5555, lsl #16 + movk x17, #0x5555, lsl #32 + movk x17, #0x5555, lsl #48 + cmp x0, x17 + b.eq + mov x0, #0x5 // =5 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0xff // =255 + mov x1, #0xfffe // =65534 + movk x1, #0xffff, lsl #16 + movk x1, #0xffff, lsl #32 + movk x1, #0xffff, lsl #48 + sdiv x0, x0, x1 + mov x17, #0xff // =255 + and x0, x0, x17 + mov x17, #0x81 // =129 + eor x0, x0, x17 + mov w0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x6 // =6 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/compound_assign_unsigned_div.x64.asm b/tests/snapshots/asm/compound_assign_unsigned_div.x64.asm new file mode 100644 index 000000000..34cbd9cf6 --- /dev/null +++ b/tests/snapshots/asm/compound_assign_unsigned_div.x64.asm @@ -0,0 +1,109 @@ + +compound_assign_unsigned_div.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x30, %rsp + movl $0xffffffff, %eax # imm = 0xFFFFFFFF + movl $0xfffffffe, %ecx # imm = 0xFFFFFFFE + pushq %rdx + xorq %rdx, %rdx + divq %rcx + popq %rdx + movl %eax, %eax + xorq $0x1, %rax + movl %eax, %eax + testq %rax, %rax + je + movl $0x1, %eax + addq $0x30, %rsp + popq %rbp + retq + movl $0xffffffff, %eax # imm = 0xFFFFFFFF + movl $0xfffffffe, %ecx # imm = 0xFFFFFFFE + pushq %rdx + xorq %rdx, %rdx + divq %rcx + movq %rdx, %rax + popq %rdx + movl %eax, %eax + xorq $0x1, %rax + movl %eax, %eax + testq %rax, %rax + je + movl $0x2, %eax + addq $0x30, %rsp + popq %rbp + retq + movabsq $-0x2, %rax + movl $0x2, %ecx + movl %eax, %eax + pushq %rdx + xorq %rdx, %rdx + divq %rcx + popq %rdx + movslq %eax, %rax + cmpq $0x7fffffff, %rax # imm = 0x7FFFFFFF + je + movl $0x3, %eax + addq $0x30, %rsp + popq %rbp + retq + movabsq $-0x7, %rax + movl $0x3, %ecx + pushq %rdx + cqto + idivq %rcx + movq %rdx, %rax + popq %rdx + movslq %eax, %rax + cmpq $-0x1, %rax + je + movl $0x4, %eax + addq $0x30, %rsp + popq %rbp + retq + movabsq $-0x1, %rax + movl $0x3, %ecx + pushq %rdx + xorq %rdx, %rdx + divq %rcx + popq %rdx + movabsq $0x5555555555555555, %r11 # imm = 0x5555555555555555 + cmpq %r11, %rax + je + movl $0x5, %eax + addq $0x30, %rsp + popq %rbp + retq + movl $0xff, %eax + movabsq $-0x2, %rcx + pushq %rdx + cqto + idivq %rcx + popq %rdx + andq $0xff, %rax + xorq $0x81, %rax + movl %eax, %eax + testq %rax, %rax + je + movl $0x6, %eax + addq $0x30, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x30, %rsp + popq %rbp + retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/const_expr_unsigned_fold.aarch64.asm b/tests/snapshots/asm/const_expr_unsigned_fold.aarch64.asm new file mode 100644 index 000000000..d60d73ebd --- /dev/null +++ b/tests/snapshots/asm/const_expr_unsigned_fold.aarch64.asm @@ -0,0 +1,110 @@ + +const_expr_unsigned_fold.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x10 + adrp x0, + add x0, x0, + ldr x0, [x0] + mov x17, #0x5555 // =21845 + movk x17, #0x5555, lsl #16 + movk x17, #0x5555, lsl #32 + movk x17, #0x5555, lsl #48 + cmp x0, x17 + b.eq + mov x0, #0x1 // =1 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + adrp x0, + add x0, x0, + ldr x0, [x0] + mov x17, #0xffff // =65535 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xfff, lsl #48 + cmp x0, x17 + b.eq + mov x0, #0x2 // =2 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + adrp x0, + add x0, x0, + ldr x0, [x0] + cmp x0, #0x1 + b.eq + mov x0, #0x3 // =3 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + adrp x0, + add x0, x0, + ldrsw x0, [x0] + cmp x0, #0x1 + b.eq + mov x0, #0x4 // =4 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + adrp x0, + add x0, x0, + ldrsw x0, [x0] + cmp x0, #0x0 + b.eq + mov x0, #0x5 // =5 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + adrp x0, + add x0, x0, + ldr x0, [x0] + mov x17, #-0x8000000000000000 // =-9223372036854775808 + cmp x0, x17 + b.eq + mov x0, #0x6 // =6 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x10 // =16 + mov x1, #0x0 // =0 + add x0, x0, x1 + asr x0, x0, #2 + cmp x0, #0x4 + b.eq + mov x0, #0x7 // =7 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0xc // =12 + mov x1, #0x0 // =0 + add x0, x0, x1 + asr x0, x0, #2 + cmp x0, #0x3 + cset x1, ne + cbnz x1, + adrp x0, + add x0, x0, + ldrsw x0, [x0] + cmp x0, #0x0 + cset x1, ne + cbz x1, + mov x0, #0x8 // =8 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + b diff --git a/tests/snapshots/asm/const_expr_unsigned_fold.x64.asm b/tests/snapshots/asm/const_expr_unsigned_fold.x64.asm new file mode 100644 index 000000000..94f7d29d4 --- /dev/null +++ b/tests/snapshots/asm/const_expr_unsigned_fold.x64.asm @@ -0,0 +1,103 @@ + +const_expr_unsigned_fold.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x10, %rsp + leaq , %rax + movq (%rax), %rax + movabsq $0x5555555555555555, %r11 # imm = 0x5555555555555555 + cmpq %r11, %rax + je + movl $0x1, %eax + addq $0x10, %rsp + popq %rbp + retq + leaq , %rax + movq (%rax), %rax + movabsq $0xfffffffffffffff, %r11 # imm = 0xFFFFFFFFFFFFFFF + cmpq %r11, %rax + je + movl $0x2, %eax + addq $0x10, %rsp + popq %rbp + retq + leaq , %rax + movq (%rax), %rax + cmpq $0x1, %rax + je + movl $0x3, %eax + addq $0x10, %rsp + popq %rbp + retq + leaq , %rax + movslq (%rax), %rax + cmpq $0x1, %rax + je + movl $0x4, %eax + addq $0x10, %rsp + popq %rbp + retq + leaq , %rax + movslq (%rax), %rax + testq %rax, %rax + je + movl $0x5, %eax + addq $0x10, %rsp + popq %rbp + retq + leaq , %rax + movq (%rax), %rax + movabsq $-0x8000000000000000, %r11 # imm = 0x8000000000000000 + cmpq %r11, %rax + je + movl $0x6, %eax + addq $0x10, %rsp + popq %rbp + retq + movl $0x10, %eax + xorq %rcx, %rcx + addq %rcx, %rax + sarq $0x2, %rax + cmpq $0x4, %rax + je + movl $0x7, %eax + addq $0x10, %rsp + popq %rbp + retq + movl $0xc, %eax + xorq %rcx, %rcx + addq %rcx, %rax + sarq $0x2, %rax + cmpq $0x3, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + jne + leaq , %rax + movslq (%rax), %rax + testq %rax, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x8, %eax + addq $0x10, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x10, %rsp + popq %rbp + retq + jmp + addb %al, (%rax) diff --git a/tests/snapshots/asm/decl_specifier_any_order.aarch64.asm b/tests/snapshots/asm/decl_specifier_any_order.aarch64.asm new file mode 100644 index 000000000..926afb583 --- /dev/null +++ b/tests/snapshots/asm/decl_specifier_any_order.aarch64.asm @@ -0,0 +1,89 @@ + +decl_specifier_any_order.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x30 + b + mov x0, #0x1 // =1 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + b + mov x0, #0x2 // =2 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x100000000 // =4294967296 + asr x0, x0, #32 + cmp x0, #0x1 + b.eq + mov x0, #0x3 // =3 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0xffff // =65535 + movk x0, #0xffff, lsl #16 + movk x0, #0xffff, lsl #32 + movk x0, #0xffff, lsl #48 + mov w0, w0 + cmp x0, #0x0 + cset x0, hi + cmp x0, #0x0 + b.ne + mov x0, #0x4 // =4 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0xffff // =65535 + movk x0, #0xffff, lsl #16 + movk x0, #0xffff, lsl #32 + movk x0, #0xffff, lsl #48 + mov x17, #0xff // =255 + and x0, x0, x17 + mov x17, #0xff // =255 + eor x0, x0, x17 + mov w0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x5 // =5 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + b + mov x0, #0x6 // =6 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + b + mov x0, #0x7 // =7 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x30 + mov x1, #0xfffb // =65531 + movk x1, #0xffff, lsl #16 + movk x1, #0xffff, lsl #32 + movk x1, #0xffff, lsl #48 + str x1, [x0, #0x8] + sub x0, x29, #0x30 + ldr x0, [x0, #0x8] + cmp x0, #0x0 + b.lt + mov x0, #0x8 // =8 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/decl_specifier_any_order.x64.asm b/tests/snapshots/asm/decl_specifier_any_order.x64.asm new file mode 100644 index 000000000..ff8048b3c --- /dev/null +++ b/tests/snapshots/asm/decl_specifier_any_order.x64.asm @@ -0,0 +1,80 @@ + +decl_specifier_any_order.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x30, %rsp + jmp + movl $0x1, %eax + addq $0x30, %rsp + popq %rbp + retq + jmp + movl $0x2, %eax + addq $0x30, %rsp + popq %rbp + retq + movabsq $0x100000000, %rax # imm = 0x100000000 + sarq $0x20, %rax + cmpq $0x1, %rax + je + movl $0x3, %eax + addq $0x30, %rsp + popq %rbp + retq + movabsq $-0x1, %rax + movl %eax, %eax + testq %rax, %rax + seta %al + movzbq %al, %rax + testq %rax, %rax + jne + movl $0x4, %eax + addq $0x30, %rsp + popq %rbp + retq + movabsq $-0x1, %rax + andq $0xff, %rax + xorq $0xff, %rax + movl %eax, %eax + testq %rax, %rax + je + movl $0x5, %eax + addq $0x30, %rsp + popq %rbp + retq + jmp + movl $0x6, %eax + addq $0x30, %rsp + popq %rbp + retq + jmp + movl $0x7, %eax + addq $0x30, %rsp + popq %rbp + retq + leaq -0x30(%rbp), %rax + movabsq $-0x5, %rcx + movq %rcx, 0x8(%rax) + leaq -0x30(%rbp), %rax + movq 0x8(%rax), %rax + testq %rax, %rax + jl + movl $0x8, %eax + addq $0x30, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x30, %rsp + popq %rbp + retq diff --git a/tests/snapshots/asm/int_literal_boundary_types.aarch64.asm b/tests/snapshots/asm/int_literal_boundary_types.aarch64.asm new file mode 100644 index 000000000..9aae0b7f2 --- /dev/null +++ b/tests/snapshots/asm/int_literal_boundary_types.aarch64.asm @@ -0,0 +1,84 @@ + +int_literal_boundary_types.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x20 + mov x0, #0xffff // =65535 + movk x0, #0x7fff, lsl #16 + movk x0, #0xffff, lsl #32 + movk x0, #0xffff, lsl #48 + mov x17, #0xffff // =65535 + movk x17, #0x7fff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + cmp x0, x17 + b.eq + mov x0, #0x1 // =1 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + mov x1, #0x0 // =0 + b + mov x1, #0x0 // =0 + cbz x1, + mov x0, #0x2 // =2 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x80000000 // =2147483648 + mov x1, #0xffff // =65535 + movk x1, #0xffff, lsl #16 + cmp x1, x0 + b.hs + mov x0, #0x3 // =3 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + b + mov x0, #0x4 // =4 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + b + mov x0, #0x5 // =5 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + b + mov x0, #0x6 // =6 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + mov x2, #0x1 // =1 + mov x2, #0x0 // =0 + cbnz x2, + mov x2, #0x0 // =0 + cbz x2, + mov x0, #0x7 // =7 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x8 // =8 + mov x1, #0xffff // =65535 + movk x1, #0xffff, lsl #16 + cmp x1, x0 + b.hs + mov x0, #0x8 // =8 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + b diff --git a/tests/snapshots/asm/int_literal_boundary_types.x64.asm b/tests/snapshots/asm/int_literal_boundary_types.x64.asm new file mode 100644 index 000000000..512073ab5 --- /dev/null +++ b/tests/snapshots/asm/int_literal_boundary_types.x64.asm @@ -0,0 +1,80 @@ + +int_literal_boundary_types.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x20, %rsp + movabsq $-0x80000001, %rax # imm = 0xFFFFFFFF7FFFFFFF + movabsq $-0x80000001, %r11 # imm = 0xFFFFFFFF7FFFFFFF + cmpq %r11, %rax + je + movl $0x1, %eax + addq $0x20, %rsp + popq %rbp + retq + xorq %rcx, %rcx + jmp + xorq %rcx, %rcx + testq %rcx, %rcx + je + movl $0x2, %eax + addq $0x20, %rsp + popq %rbp + retq + movl $0x80000000, %eax # imm = 0x80000000 + movl $0xffffffff, %ecx # imm = 0xFFFFFFFF + cmpq %rax, %rcx + jae + movl $0x3, %eax + addq $0x20, %rsp + popq %rbp + retq + jmp + movl $0x4, %eax + addq $0x20, %rsp + popq %rbp + retq + jmp + movl $0x5, %eax + addq $0x20, %rsp + popq %rbp + retq + jmp + movl $0x6, %eax + addq $0x20, %rsp + popq %rbp + retq + movl $0x1, %edx + xorq %rdx, %rdx + testq %rdx, %rdx + jne + xorq %rdx, %rdx + testq %rdx, %rdx + je + movl $0x7, %eax + addq $0x20, %rsp + popq %rbp + retq + movl $0x8, %eax + movl $0xffffffff, %ecx # imm = 0xFFFFFFFF + cmpq %rax, %rcx + jae + movl $0x8, %eax + addq $0x20, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x20, %rsp + popq %rbp + retq + jmp diff --git a/tests/snapshots/asm/libc_fp_classify.aarch64.asm b/tests/snapshots/asm/libc_fp_classify.aarch64.asm index 8cde21431..c71127733 100644 --- a/tests/snapshots/asm/libc_fp_classify.aarch64.asm +++ b/tests/snapshots/asm/libc_fp_classify.aarch64.asm @@ -66,6 +66,7 @@ Disassembly of section .text: sub x0, x29, #0x8 ldr x0, [x0] lsr x0, x0, #63 + sxtw x0, w0 add sp, sp, #0x10 ldp x29, x30, [sp], #0x10 ret diff --git a/tests/snapshots/asm/libc_fp_classify.x64.asm b/tests/snapshots/asm/libc_fp_classify.x64.asm index ca372184d..fdc7cc245 100644 --- a/tests/snapshots/asm/libc_fp_classify.x64.asm +++ b/tests/snapshots/asm/libc_fp_classify.x64.asm @@ -63,6 +63,7 @@ Disassembly of section .text: leaq -0x8(%rbp), %rax movq (%rax), %rax shrq $0x3f, %rax + movslq %eax, %rax addq $0x10, %rsp popq %rbp retq @@ -282,3 +283,4 @@ Disassembly of section .text: popq %rbp retq addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/math_classify.aarch64.asm b/tests/snapshots/asm/math_classify.aarch64.asm index a8b075fa9..14768c97c 100644 --- a/tests/snapshots/asm/math_classify.aarch64.asm +++ b/tests/snapshots/asm/math_classify.aarch64.asm @@ -93,6 +93,7 @@ Disassembly of section .text: sub x0, x29, #0x8 ldr x0, [x0] lsr x0, x0, #63 + sxtw x0, w0 add sp, sp, #0x10 ldp x29, x30, [sp], #0x10 ret diff --git a/tests/snapshots/asm/math_classify.x64.asm b/tests/snapshots/asm/math_classify.x64.asm index 032a0e01c..260477607 100644 --- a/tests/snapshots/asm/math_classify.x64.asm +++ b/tests/snapshots/asm/math_classify.x64.asm @@ -93,6 +93,7 @@ Disassembly of section .text: leaq -0x8(%rbp), %rax movq (%rax), %rax shrq $0x3f, %rax + movslq %eax, %rax addq $0x10, %rsp popq %rbp retq @@ -257,3 +258,4 @@ Disassembly of section .text: addq $0x50, %rsp popq %rbp retq + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/nested_designator_string_member.aarch64.asm b/tests/snapshots/asm/nested_designator_string_member.aarch64.asm new file mode 100644 index 000000000..37c037376 --- /dev/null +++ b/tests/snapshots/asm/nested_designator_string_member.aarch64.asm @@ -0,0 +1,189 @@ + +nested_designator_string_member.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x10 + mov x2, x0 + ldrb w3, [x2] + cbz x3, + b + add x2, x2, #0x1 + add x1, x1, #0x1 + b + ldrb w0, [x2] + ldrb w1, [x1] + cmp x0, x1 + cset x0, eq + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + ldrb w0, [x2] + ldrb w3, [x1] + cmp x0, x3 + cset x3, eq + cbz x3, + b + b + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x60 + str x20, [sp] + str x21, [sp, #0x8] + str x22, [sp, #0x10] + mov x20, x0 + adrp x21, + add x21, x21, + add x0, x21, #0x4 + adrp x1, + add x1, x1, + bl + cmp x0, #0x0 + b.ne + mov x0, #0x1 // =1 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret + ldrb w0, [x21, #0x7] + cmp x0, #0x0 + cset x22, ne + cbnz x22, + ldrb w0, [x21, #0xb] + cmp x0, #0x0 + cset x22, ne + cbz x22, + mov x0, #0x2 // =2 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret + ldrsw x0, [x21, #0xc] + cmp x0, #0x7 + cset x22, ne + cbnz x22, + ldrsw x0, [x21] + cmp x0, #0x5 + cset x22, ne + cbz x22, + mov x0, #0x3 // =3 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x10 + adrp x1, + add x1, x1, + str x10, [sp, #-0x10]! + ldr x10, [x1] + str x10, [x0] + ldr x10, [x1, #0x8] + str x10, [x0, #0x8] + ldr x10, [sp], #0x10 + mov x0, #0x77 // =119 + sub x1, x29, #0x10 + strb w0, [x1, #0x4] + mov x0, #0x78 // =120 + sub x1, x29, #0x10 + strb w0, [x1, #0x5] + mov x0, #0x79 // =121 + sub x1, x29, #0x10 + strb w0, [x1, #0x6] + mov x0, #0x7a // =122 + sub x1, x29, #0x10 + strb w0, [x1, #0x7] + mov x0, #0x0 // =0 + sub x1, x29, #0x10 + strb w0, [x1, #0x8] + sub x1, x29, #0x10 + strb w0, [x1, #0x9] + sub x1, x29, #0x10 + strb w0, [x1, #0xa] + sub x1, x29, #0x10 + strb w0, [x1, #0xb] + add x0, x20, #0x6 + sub x1, x29, #0x10 + str w0, [x1, #0xc] + add x0, x20, #0x4 + sub x1, x29, #0x10 + str w0, [x1] + sub x0, x29, #0x10 + add x0, x0, #0x4 + adrp x1, + add x1, x1, + bl + cmp x0, #0x0 + b.ne + mov x0, #0x4 // =4 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x10 + ldrb w0, [x0, #0x8] + cmp x0, #0x0 + cset x1, ne + cbnz x1, + sub x0, x29, #0x10 + ldrb w0, [x0, #0xb] + cmp x0, #0x0 + cset x1, ne + cbz x1, + mov x0, #0x5 // =5 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x10 + ldrsw x0, [x0, #0xc] + add x1, x20, #0x6 + sxtw x1, w1 + cmp x0, x1 + cset x1, ne + cbnz x1, + sub x0, x29, #0x10 + ldrsw x0, [x0] + add x1, x20, #0x4 + sxtw x1, w1 + cmp x0, x1 + cset x1, ne + cbz x1, + mov x0, #0x6 // =6 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret + b + b + b + b diff --git a/tests/snapshots/asm/nested_designator_string_member.x64.asm b/tests/snapshots/asm/nested_designator_string_member.x64.asm new file mode 100644 index 000000000..afa5f07da --- /dev/null +++ b/tests/snapshots/asm/nested_designator_string_member.x64.asm @@ -0,0 +1,206 @@ + +nested_designator_string_member.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + pushq %rbp + movq %rsp, %rbp + subq $0x10, %rsp + movsbq (%rdi), %rcx + testq %rcx, %rcx + je + jmp + incq %rdi + incq %rsi + jmp + movsbq (%rdi), %rax + movsbq (%rsi), %rcx + cmpq %rcx, %rax + sete %al + movzbq %al, %rax + addq $0x10, %rsp + popq %rbp + retq + movsbq (%rdi), %rax + movsbq (%rsi), %rcx + cmpq %rcx, %rax + sete %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + jmp + jmp + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x60, %rsp + movq %rbx, (%rsp) + movq %r12, 0x8(%rsp) + movq %r13, 0x10(%rsp) + movq %rdi, %rbx + leaq , %r12 + leaq 0x4(%r12), %rdi + leaq , %rsi + callq + testq %rax, %rax + jne + movl $0x1, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x60, %rsp + popq %rbp + retq + movsbq 0x7(%r12), %rax + testq %rax, %rax + setne %r13b + movzbq %r13b, %r13 + testq %r13, %r13 + jne + movsbq 0xb(%r12), %rax + testq %rax, %rax + setne %r13b + movzbq %r13b, %r13 + testq %r13, %r13 + je + movl $0x2, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x60, %rsp + popq %rbp + retq + movslq 0xc(%r12), %rax + cmpq $0x7, %rax + setne %r13b + movzbq %r13b, %r13 + testq %r13, %r13 + jne + movslq (%r12), %rax + cmpq $0x5, %rax + setne %r13b + movzbq %r13b, %r13 + testq %r13, %r13 + je + movl $0x3, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x60, %rsp + popq %rbp + retq + leaq -0x10(%rbp), %rax + leaq , %rcx + pushq %rdx + movq (%rcx), %rdx + movq %rdx, (%rax) + movq 0x8(%rcx), %rdx + movq %rdx, 0x8(%rax) + popq %rdx + movl $0x77, %eax + leaq -0x10(%rbp), %rcx + movb %al, 0x4(%rcx) + movl $0x78, %eax + leaq -0x10(%rbp), %rcx + movb %al, 0x5(%rcx) + movl $0x79, %eax + leaq -0x10(%rbp), %rcx + movb %al, 0x6(%rcx) + movl $0x7a, %eax + leaq -0x10(%rbp), %rcx + movb %al, 0x7(%rcx) + xorq %rax, %rax + leaq -0x10(%rbp), %rcx + movb %al, 0x8(%rcx) + leaq -0x10(%rbp), %rcx + movb %al, 0x9(%rcx) + leaq -0x10(%rbp), %rcx + movb %al, 0xa(%rcx) + leaq -0x10(%rbp), %rcx + movb %al, 0xb(%rcx) + leaq 0x6(%rbx), %rax + leaq -0x10(%rbp), %rcx + movl %eax, 0xc(%rcx) + leaq 0x4(%rbx), %rax + leaq -0x10(%rbp), %rcx + movl %eax, (%rcx) + leaq -0x10(%rbp), %rax + leaq 0x4(%rax), %rdi + leaq , %rsi + callq + testq %rax, %rax + jne + movl $0x4, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x60, %rsp + popq %rbp + retq + leaq -0x10(%rbp), %rax + movsbq 0x8(%rax), %rax + testq %rax, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + jne + leaq -0x10(%rbp), %rax + movsbq 0xb(%rax), %rax + testq %rax, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x5, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x60, %rsp + popq %rbp + retq + leaq -0x10(%rbp), %rax + movslq 0xc(%rax), %rax + leaq 0x6(%rbx), %rcx + movslq %ecx, %rcx + cmpq %rcx, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + jne + leaq -0x10(%rbp), %rax + movslq (%rax), %rax + leaq 0x4(%rbx), %rcx + movslq %ecx, %rcx + cmpq %rcx, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x6, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x60, %rsp + popq %rbp + retq + xorq %rax, %rax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x60, %rsp + popq %rbp + retq + jmp + jmp + jmp + jmp + addb %al, (%rax) diff --git a/tests/snapshots/asm/packed_bitfield_repack.aarch64.asm b/tests/snapshots/asm/packed_bitfield_repack.aarch64.asm new file mode 100644 index 000000000..51f763818 --- /dev/null +++ b/tests/snapshots/asm/packed_bitfield_repack.aarch64.asm @@ -0,0 +1,247 @@ + +packed_bitfield_repack.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x70 + mov x1, #0x0 // =0 + mov x1, #0x0 // =0 + cbz x1, + mov x0, #0x1 // =1 + add sp, sp, #0x70 + ldp x29, x30, [sp], #0x10 + ret + mov x1, #0x0 // =0 + mov x1, #0x0 // =0 + cbz x1, + mov x0, #0x2 // =2 + add sp, sp, #0x70 + ldp x29, x30, [sp], #0x10 + ret + mov x1, #0x0 // =0 + mov x1, #0x0 // =0 + cbz x1, + mov x0, #0x3 // =3 + add sp, sp, #0x70 + ldp x29, x30, [sp], #0x10 + ret + b + mov x0, #0x4 // =4 + add sp, sp, #0x70 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x8 + mov x1, #0x55 // =85 + ldrb w2, [x0] + mov x17, #0xff00 // =65280 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + and x2, x2, x17 + orr x1, x2, x1 + strb w1, [x0] + sub x0, x29, #0x8 + mov x1, #0x7 // =7 + strb w1, [x0, #0x1] + sub x0, x29, #0x8 + ldrb w0, [x0] + sxtb x0, w0 + cmp x0, #0x55 + cset x1, ne + cbnz x1, + sub x0, x29, #0x8 + ldrb w0, [x0, #0x1] + mov x17, #0x7 // =7 + eor x0, x0, x17 + mov w0, w0 + cmp x0, #0x0 + cset x1, ne + cbz x1, + mov x0, #0x5 // =5 + add sp, sp, #0x70 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x10 + mov x1, #0xfde8 // =65000 + ldr w2, [x0] + mov x17, #0xfffe0000 // =4294836224 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + and x2, x2, x17 + orr x1, x2, x1 + str w1, [x0] + sub x0, x29, #0x10 + ldrh w1, [x0, #0x2] + mov x17, #0xf801 // =63489 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + and x1, x1, x17 + mov x2, #0x3e8 // =1000 + orr x1, x1, x2 + strh w1, [x0, #0x2] + sub x0, x29, #0x10 + mov x1, #0x9 // =9 + strb w1, [x0, #0x4] + sub x0, x29, #0x10 + ldr w0, [x0] + mov x17, #0xffff // =65535 + movk x17, #0x1, lsl #16 + and x0, x0, x17 + lsl x0, x0, #47 + asr x0, x0, #47 + mov x17, #0xfde8 // =65000 + cmp x0, x17 + cset x0, ne + mov x2, #0x1 // =1 + cbnz x0, + sub x0, x29, #0x10 + ldrh w0, [x0, #0x2] + asr x0, x0, #1 + mov x17, #0x3ff // =1023 + and x0, x0, x17 + lsl x0, x0, #54 + asr x0, x0, #54 + cmp x0, #0x1f4 + cset x0, ne + cmp x0, #0x0 + cset x2, ne + cbnz x2, + sub x0, x29, #0x10 + ldrb w0, [x0, #0x4] + mov x17, #0x9 // =9 + eor x0, x0, x17 + mov w0, w0 + cmp x0, #0x0 + cset x2, ne + cbz x2, + mov x0, #0x6 // =6 + add sp, sp, #0x70 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x18 + mov x1, #0x3 // =3 + ldrb w2, [x0] + mov x17, #0xfff8 // =65528 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + and x2, x2, x17 + orr x1, x2, x1 + strb w1, [x0] + sub x0, x29, #0x18 + ldrh w1, [x0] + mov x17, #0xfc07 // =64519 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + and x1, x1, x17 + mov x2, #0x1e0 // =480 + orr x1, x1, x2 + strh w1, [x0] + sub x0, x29, #0x18 + mov x1, #0x4 // =4 + strb w1, [x0, #0x2] + sub x0, x29, #0x18 + ldrb w0, [x0] + mov x17, #0x7 // =7 + and x0, x0, x17 + cmp x0, #0x3 + cset x0, ne + mov x2, #0x1 // =1 + cbnz x0, + sub x0, x29, #0x18 + ldrh w0, [x0] + asr x0, x0, #3 + mov x17, #0x7f // =127 + and x0, x0, x17 + cmp x0, #0x3c + cset x0, ne + cmp x0, #0x0 + cset x2, ne + cbnz x2, + sub x0, x29, #0x18 + ldrb w0, [x0, #0x2] + mov x17, #0x4 // =4 + eor x0, x0, x17 + mov w0, w0 + cmp x0, #0x0 + cset x2, ne + cbz x2, + mov x0, #0x7 // =7 + add sp, sp, #0x70 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x20 + mov x1, #0xb // =11 + strb w1, [x0] + sub x0, x29, #0x20 + add x0, x0, #0x1 + mov x1, #0x7530 // =30000 + ldrh w2, [x0] + mov x17, #0xffff0000 // =4294901760 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + and x2, x2, x17 + orr x1, x2, x1 + strh w1, [x0] + sub x0, x29, #0x20 + ldrb w0, [x0] + mov x17, #0xb // =11 + eor x0, x0, x17 + mov w0, w0 + cmp x0, #0x0 + cset x1, ne + cbnz x1, + sub x0, x29, #0x20 + add x0, x0, #0x1 + ldrh w0, [x0] + sxth x0, w0 + mov x17, #0x7530 // =30000 + cmp x0, x17 + cset x1, ne + cbz x1, + mov x0, #0x8 // =8 + add sp, sp, #0x70 + ldp x29, x30, [sp], #0x10 + ret + adrp x0, + add x0, x0, + ldrb w0, [x0] + sxtb x0, w0 + cmp x0, #0x55 + cset x1, ne + cbnz x1, + adrp x0, + add x0, x0, + ldrb w0, [x0, #0x1] + mov x17, #0x7 // =7 + eor x0, x0, x17 + mov w0, w0 + cmp x0, #0x0 + cset x1, ne + cbz x1, + mov x0, #0x9 // =9 + add sp, sp, #0x70 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + add sp, sp, #0x70 + ldp x29, x30, [sp], #0x10 + ret + b + b + b + b + b + b + b diff --git a/tests/snapshots/asm/packed_bitfield_repack.x64.asm b/tests/snapshots/asm/packed_bitfield_repack.x64.asm new file mode 100644 index 000000000..12b6325e0 --- /dev/null +++ b/tests/snapshots/asm/packed_bitfield_repack.x64.asm @@ -0,0 +1,237 @@ + +packed_bitfield_repack.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x70, %rsp + xorq %rcx, %rcx + xorq %rcx, %rcx + testq %rcx, %rcx + je + movl $0x1, %eax + addq $0x70, %rsp + popq %rbp + retq + xorq %rcx, %rcx + xorq %rcx, %rcx + testq %rcx, %rcx + je + movl $0x2, %eax + addq $0x70, %rsp + popq %rbp + retq + xorq %rcx, %rcx + xorq %rcx, %rcx + testq %rcx, %rcx + je + movl $0x3, %eax + addq $0x70, %rsp + popq %rbp + retq + jmp + movl $0x4, %eax + addq $0x70, %rsp + popq %rbp + retq + leaq -0x8(%rbp), %rax + movl $0x55, %ecx + movzbq (%rax), %rdx + andq $-0x100, %rdx + orq %rdx, %rcx + movb %cl, (%rax) + leaq -0x8(%rbp), %rax + movl $0x7, %ecx + movb %cl, 0x1(%rax) + leaq -0x8(%rbp), %rax + movzbq (%rax), %rax + movsbq %al, %rax + cmpq $0x55, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + jne + leaq -0x8(%rbp), %rax + movsbq 0x1(%rax), %rax + cmpq $0x7, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x5, %eax + addq $0x70, %rsp + popq %rbp + retq + leaq -0x10(%rbp), %rax + movl $0xfde8, %ecx # imm = 0xFDE8 + movl (%rax), %edx + andq $-0x20000, %rdx # imm = 0xFFFE0000 + orq %rdx, %rcx + movl %ecx, (%rax) + leaq -0x10(%rbp), %rax + movzwq 0x2(%rax), %rcx + andq $-0x7ff, %rcx # imm = 0xF801 + movl $0x3e8, %edx # imm = 0x3E8 + orq %rdx, %rcx + movw %cx, 0x2(%rax) + leaq -0x10(%rbp), %rax + movl $0x9, %ecx + movb %cl, 0x4(%rax) + leaq -0x10(%rbp), %rax + movl (%rax), %eax + andq $0x1ffff, %rax # imm = 0x1FFFF + shlq $0x2f, %rax + sarq $0x2f, %rax + cmpq $0xfde8, %rax # imm = 0xFDE8 + setne %al + movzbq %al, %rax + movl $0x1, %edx + testq %rax, %rax + jne + leaq -0x10(%rbp), %rax + movzwq 0x2(%rax), %rax + sarq $0x1, %rax + andq $0x3ff, %rax # imm = 0x3FF + shlq $0x36, %rax + sarq $0x36, %rax + cmpq $0x1f4, %rax # imm = 0x1F4 + setne %al + movzbq %al, %rax + testq %rax, %rax + setne %dl + movzbq %dl, %rdx + testq %rdx, %rdx + jne + leaq -0x10(%rbp), %rax + movsbq 0x4(%rax), %rax + cmpq $0x9, %rax + setne %dl + movzbq %dl, %rdx + testq %rdx, %rdx + je + movl $0x6, %eax + addq $0x70, %rsp + popq %rbp + retq + leaq -0x18(%rbp), %rax + movl $0x3, %ecx + movzbq (%rax), %rdx + andq $-0x8, %rdx + orq %rdx, %rcx + movb %cl, (%rax) + leaq -0x18(%rbp), %rax + movzwq (%rax), %rcx + andq $-0x3f9, %rcx # imm = 0xFC07 + movl $0x1e0, %edx # imm = 0x1E0 + orq %rdx, %rcx + movw %cx, (%rax) + leaq -0x18(%rbp), %rax + movl $0x4, %ecx + movb %cl, 0x2(%rax) + leaq -0x18(%rbp), %rax + movzbq (%rax), %rax + andq $0x7, %rax + shlq $0x3d, %rax + sarq $0x3d, %rax + cmpq $0x3, %rax + setne %al + movzbq %al, %rax + movl $0x1, %edx + testq %rax, %rax + jne + leaq -0x18(%rbp), %rax + movzwq (%rax), %rax + sarq $0x3, %rax + andq $0x7f, %rax + shlq $0x39, %rax + sarq $0x39, %rax + cmpq $0x3c, %rax + setne %al + movzbq %al, %rax + testq %rax, %rax + setne %dl + movzbq %dl, %rdx + testq %rdx, %rdx + jne + leaq -0x18(%rbp), %rax + movsbq 0x2(%rax), %rax + cmpq $0x4, %rax + setne %dl + movzbq %dl, %rdx + testq %rdx, %rdx + je + movl $0x7, %eax + addq $0x70, %rsp + popq %rbp + retq + leaq -0x20(%rbp), %rax + movl $0xb, %ecx + movb %cl, (%rax) + leaq -0x20(%rbp), %rax + incq %rax + movl $0x7530, %ecx # imm = 0x7530 + movzwq (%rax), %rdx + andq $-0x10000, %rdx # imm = 0xFFFF0000 + orq %rdx, %rcx + movw %cx, (%rax) + leaq -0x20(%rbp), %rax + movsbq (%rax), %rax + cmpq $0xb, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + jne + leaq -0x20(%rbp), %rax + incq %rax + movzwq (%rax), %rax + movswq %ax, %rax + cmpq $0x7530, %rax # imm = 0x7530 + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x8, %eax + addq $0x70, %rsp + popq %rbp + retq + leaq , %rax + movzbq (%rax), %rax + movsbq %al, %rax + cmpq $0x55, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + jne + leaq , %rax + movsbq 0x1(%rax), %rax + cmpq $0x7, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x9, %eax + addq $0x70, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x70, %rsp + popq %rbp + retq + jmp + jmp + jmp + jmp + jmp + jmp + jmp + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/shift_result_promoted_type.aarch64.asm b/tests/snapshots/asm/shift_result_promoted_type.aarch64.asm new file mode 100644 index 000000000..d8369d8bc --- /dev/null +++ b/tests/snapshots/asm/shift_result_promoted_type.aarch64.asm @@ -0,0 +1,72 @@ + +shift_result_promoted_type.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x30 + mov x0, #0xfffe00000000 // =281466386776064 + movk x0, #0xffff, lsl #48 + asr x0, x0, #1 + mov x17, #0xffff00000000 // =281470681743360 + movk x17, #0xffff, lsl #48 + cmp x0, x17 + b.eq + mov x0, #0x1 // =1 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #-0x8000000000000000 // =-9223372036854775808 + lsr x0, x0, #63 + cmp x0, #0x1 + b.eq + mov x0, #0x2 // =2 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x80000000 // =2147483648 + lsr x0, x0, #31 + mov x17, #0x1 // =1 + eor x0, x0, x17 + mov w0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x3 // =3 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0xfff0 // =65520 + movk x0, #0xffff, lsl #16 + movk x0, #0xffff, lsl #32 + movk x0, #0xffff, lsl #48 + asr x0, x0, #2 + mov x17, #0xfffc // =65532 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + cmp x0, x17 + b.eq + mov x0, #0x4 // =4 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x80 // =128 + lsr x0, x0, #3 + cmp x0, #0x10 + b.eq + mov x0, #0x5 // =5 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/shift_result_promoted_type.x64.asm b/tests/snapshots/asm/shift_result_promoted_type.x64.asm new file mode 100644 index 000000000..4630c329f --- /dev/null +++ b/tests/snapshots/asm/shift_result_promoted_type.x64.asm @@ -0,0 +1,65 @@ + +shift_result_promoted_type.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x30, %rsp + movabsq $-0x200000000, %rax # imm = 0xFFFFFFFE00000000 + sarq $0x1, %rax + movabsq $-0x100000000, %r11 # imm = 0xFFFFFFFF00000000 + cmpq %r11, %rax + je + movl $0x1, %eax + addq $0x30, %rsp + popq %rbp + retq + movabsq $-0x8000000000000000, %rax # imm = 0x8000000000000000 + shrq $0x3f, %rax + cmpq $0x1, %rax + je + movl $0x2, %eax + addq $0x30, %rsp + popq %rbp + retq + movl $0x80000000, %eax # imm = 0x80000000 + shrq $0x1f, %rax + xorq $0x1, %rax + movl %eax, %eax + testq %rax, %rax + je + movl $0x3, %eax + addq $0x30, %rsp + popq %rbp + retq + movabsq $-0x10, %rax + sarq $0x2, %rax + cmpq $-0x4, %rax + je + movl $0x4, %eax + addq $0x30, %rsp + popq %rbp + retq + movl $0x80, %eax + shrq $0x3, %rax + cmpq $0x10, %rax + je + movl $0x5, %eax + addq $0x30, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x30, %rsp + popq %rbp + retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/switch_case_label_promoted.aarch64.asm b/tests/snapshots/asm/switch_case_label_promoted.aarch64.asm new file mode 100644 index 000000000..f0babd65b --- /dev/null +++ b/tests/snapshots/asm/switch_case_label_promoted.aarch64.asm @@ -0,0 +1,91 @@ + +switch_case_label_promoted.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x20 + mov x0, #0x80000000 // =2147483648 + movk x0, #0xffff, lsl #32 + movk x0, #0xffff, lsl #48 + mov x17, #0x80000000 // =2147483648 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + cmp x0, x17 + b.eq + b + sxtw x0, w0 + cmp x0, #0x1 + b.eq + b + mov x0, #0x1 // =1 + b + mov x0, #0x2 // =2 + b + b + mov x0, #0x1 // =1 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0xfffe // =65534 + movk x0, #0xffff, lsl #16 + mov x17, #0xfffe // =65534 + movk x17, #0xffff, lsl #16 + cmp x0, x17 + b.eq + b + sxtw x0, w0 + cmp x0, #0x3 + b.eq + b + mov x0, #0x3 // =3 + b + mov x0, #0x4 // =4 + b + b + mov x0, #0x2 // =2 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0xffff00000000 // =281470681743360 + movk x0, #0xffff, lsl #48 + mov x17, #0x80000000 // =2147483648 + cmp x0, x17 + b.lt + b + sxtw x0, w0 + cmp x0, #0x5 + b.eq + b + mov x0, #0x5 // =5 + b + mov x0, #0x6 // =6 + b + mov x0, #0x7 // =7 + b + mov x17, #0xffff00000000 // =281470681743360 + movk x17, #0xffff, lsl #48 + cmp x0, x17 + b.eq + b + mov x17, #0x80000000 // =2147483648 + cmp x0, x17 + b.eq + b + b + mov x0, #0x3 // =3 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/switch_case_label_promoted.x64.asm b/tests/snapshots/asm/switch_case_label_promoted.x64.asm new file mode 100644 index 000000000..159dd2d1f --- /dev/null +++ b/tests/snapshots/asm/switch_case_label_promoted.x64.asm @@ -0,0 +1,86 @@ + +switch_case_label_promoted.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x20, %rsp + movabsq $-0x80000000, %rax # imm = 0x80000000 + cmpq $-0x80000000, %rax # imm = 0x80000000 + je + jmp + movslq %eax, %rax + cmpq $0x1, %rax + je + jmp + movl $0x1, %eax + jmp + movl $0x2, %eax + jmp + jmp + movl $0x1, %eax + addq $0x20, %rsp + popq %rbp + retq + movl $0xfffffffe, %eax # imm = 0xFFFFFFFE + movl $0xfffffffe, %r11d # imm = 0xFFFFFFFE + cmpq %r11, %rax + je + jmp + movslq %eax, %rax + cmpq $0x3, %rax + je + jmp + movl $0x3, %eax + jmp + movl $0x4, %eax + jmp + jmp + movl $0x2, %eax + addq $0x20, %rsp + popq %rbp + retq + movabsq $-0x100000000, %rax # imm = 0xFFFFFFFF00000000 + movl $0x80000000, %r11d # imm = 0x80000000 + movq %rax, %rcx + cmpq %r11, %rax + jl + jmp + movslq %eax, %rax + cmpq $0x5, %rax + je + jmp + movl $0x5, %eax + jmp + movl $0x6, %eax + jmp + movl $0x7, %eax + jmp + movabsq $-0x100000000, %r11 # imm = 0xFFFFFFFF00000000 + cmpq %r11, %rax + je + jmp + movl $0x80000000, %r11d # imm = 0x80000000 + cmpq %r11, %rax + je + jmp + jmp + movl $0x3, %eax + addq $0x20, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x20, %rsp + popq %rbp + retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/ternary_arith_common_type.aarch64.asm b/tests/snapshots/asm/ternary_arith_common_type.aarch64.asm new file mode 100644 index 000000000..770b56d7e --- /dev/null +++ b/tests/snapshots/asm/ternary_arith_common_type.aarch64.asm @@ -0,0 +1,78 @@ + +ternary_arith_common_type.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x50 + mov x0, #0x0 // =0 + cmp x0, #0x0 + b.ne + mov x2, #0x1 // =1 + b + mov x2, #0xffff // =65535 + movk x2, #0xffff, lsl #16 + cmp x2, #0x1 + b.eq + mov x0, #0x1 // =1 + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + ret + cmp x0, #0x0 + b.eq + mov x2, #0x1 // =1 + b + mov x2, #0xffff // =65535 + movk x2, #0xffff, lsl #16 + mov x17, #0xffff // =65535 + movk x17, #0xffff, lsl #16 + cmp x2, x17 + b.eq + mov x0, #0x2 // =2 + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + ret + cmp x0, #0x0 + b.ne + mov x2, #0xffff // =65535 + movk x2, #0xffff, lsl #16 + b + mov x2, #0x1 // =1 + mov x17, #0xffff // =65535 + movk x17, #0xffff, lsl #16 + cmp x2, x17 + b.eq + mov x0, #0x3 // =3 + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + ret + cmp x0, #0x0 + b.ne + mov x1, #0xffff // =65535 + movk x1, #0xffff, lsl #16 + movk x1, #0xffff, lsl #32 + movk x1, #0xffff, lsl #48 + b + mov x1, #0x0 // =0 + mov x17, #0xffff // =65535 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + cmp x1, x17 + b.eq + mov x0, #0x4 // =4 + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/ternary_arith_common_type.x64.asm b/tests/snapshots/asm/ternary_arith_common_type.x64.asm new file mode 100644 index 000000000..8c92a0e0f --- /dev/null +++ b/tests/snapshots/asm/ternary_arith_common_type.x64.asm @@ -0,0 +1,70 @@ + +ternary_arith_common_type.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x50, %rsp + xorq %rax, %rax + testq %rax, %rax + jne + movl $0x1, %edx + jmp + movl $0xffffffff, %edx # imm = 0xFFFFFFFF + cmpq $0x1, %rdx + je + movl $0x1, %eax + addq $0x50, %rsp + popq %rbp + retq + testq %rax, %rax + je + movl $0x1, %edx + jmp + movl $0xffffffff, %edx # imm = 0xFFFFFFFF + movl $0xffffffff, %r11d # imm = 0xFFFFFFFF + movq %rdx, %rcx + cmpq %r11, %rdx + je + movl $0x2, %eax + addq $0x50, %rsp + popq %rbp + retq + testq %rax, %rax + jne + movl $0xffffffff, %edx # imm = 0xFFFFFFFF + jmp + movl $0x1, %edx + movl $0xffffffff, %r11d # imm = 0xFFFFFFFF + movq %rdx, %rcx + cmpq %r11, %rdx + je + movl $0x3, %eax + addq $0x50, %rsp + popq %rbp + retq + testq %rax, %rax + jne + movabsq $-0x1, %rcx + jmp + xorq %rcx, %rcx + cmpq $-0x1, %rcx + je + movl $0x4, %eax + addq $0x50, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x50, %rsp + popq %rbp + retq + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/union_member_unbraced_init.aarch64.asm b/tests/snapshots/asm/union_member_unbraced_init.aarch64.asm new file mode 100644 index 000000000..b41394ee6 --- /dev/null +++ b/tests/snapshots/asm/union_member_unbraced_init.aarch64.asm @@ -0,0 +1,197 @@ + +union_member_unbraced_init.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x80 + adrp x0, + add x0, x0, + ldr d0, [x0] + mov x1, #0x4008000000000000 // =4613937818241073152 + fmov d17, x1 + fcmp d0, d17 + cset x2, ne + cbnz x2, + ldrsw x1, [x0, #0x10] + cmp x1, #0x2a + cset x2, ne + cbz x2, + mov x0, #0x1 // =1 + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + mov x2, #0x8 // =8 + sxtw x1, w2 + cmp x1, #0x10 + b.ge + b + sxtw x1, w2 + add x2, x1, #0x1 + b + sxtw x1, w2 + add x1, x0, x1 + ldrb w1, [x1] + cmp x1, #0x0 + b.eq + b + adrp x0, + add x0, x0, + ldr d0, [x0] + mov x0, #0x4014000000000000 // =4617315517961601024 + fmov d17, x0 + fcmp d0, d17 + cset x1, ne + cbnz x1, + b + mov x0, #0x2 // =2 + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + b + adrp x0, + add x0, x0, + ldrsw x0, [x0, #0x8] + cmp x0, #0x2b + cset x1, ne + cbz x1, + mov x0, #0x3 // =3 + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + adrp x0, + add x0, x0, + ldrsw x0, [x0] + cmp x0, #0x1 + cset x0, ne + mov x2, #0x1 // =1 + cbnz x0, + adrp x0, + add x0, x0, + ldrsw x0, [x0, #0x4] + cmp x0, #0x2 + cset x0, ne + cmp x0, #0x0 + cset x2, ne + cbnz x2, + adrp x0, + add x0, x0, + ldrsw x0, [x0, #0x8] + cmp x0, #0x9 + cset x2, ne + cbz x2, + mov x0, #0x4 // =4 + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + adrp x0, + add x0, x0, + ldr d0, [x0] + mov x0, #0x4008000000000000 // =4613937818241073152 + fmov d17, x0 + fcmp d0, d17 + cset x1, ne + cbnz x1, + adrp x0, + add x0, x0, + ldrsw x0, [x0, #0x10] + cmp x0, #0x2a + cset x1, ne + cbz x1, + mov x0, #0x5 // =5 + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + adrp x0, + add x0, x0, + add x0, x0, #0x18 + ldr d0, [x0] + mov x0, #0x4010000000000000 // =4616189618054758400 + fmov d17, x0 + fcmp d0, d17 + cset x1, ne + cbnz x1, + adrp x0, + add x0, x0, + ldrsw x0, [x0, #0x28] + cmp x0, #0x2b + cset x1, ne + cbz x1, + mov x0, #0x6 // =6 + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x20 + adrp x1, + add x1, x1, + str x10, [sp, #-0x10]! + ldr x10, [x1] + str x10, [x0] + ldr x10, [x1, #0x8] + str x10, [x0, #0x8] + ldr x10, [x1, #0x10] + str x10, [x0, #0x10] + ldr x10, [sp], #0x10 + sub x0, x29, #0x20 + ldr d0, [x0] + mov x0, #0x4008000000000000 // =4613937818241073152 + fmov d17, x0 + fcmp d0, d17 + cset x1, ne + cbnz x1, + sub x0, x29, #0x20 + ldrsw x0, [x0, #0x10] + cmp x0, #0x2a + cset x1, ne + cbz x1, + mov x0, #0x7 // =7 + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x38 + adrp x1, + add x1, x1, + str x10, [sp, #-0x10]! + ldr x10, [x1] + str x10, [x0] + ldr x10, [x1, #0x8] + str x10, [x0, #0x8] + ldr x10, [x1, #0x10] + str x10, [x0, #0x10] + ldr x10, [sp], #0x10 + sub x0, x29, #0x38 + ldr d0, [x0] + mov x0, #0x4018000000000000 // =4618441417868443648 + fmov d17, x0 + fcmp d0, d17 + cset x1, ne + cbnz x1, + sub x0, x29, #0x38 + ldrsw x0, [x0, #0x10] + cmp x0, #0x2c + cset x1, ne + cbz x1, + mov x0, #0x8 // =8 + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + b + b + b + b + b + b + b + b diff --git a/tests/snapshots/asm/union_member_unbraced_init.x64.asm b/tests/snapshots/asm/union_member_unbraced_init.x64.asm new file mode 100644 index 000000000..dc52e1dac --- /dev/null +++ b/tests/snapshots/asm/union_member_unbraced_init.x64.asm @@ -0,0 +1,237 @@ + +union_member_unbraced_init.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x80, %rsp + leaq , %rax + movsd (%rax,%riz), %xmm0 + movabsq $0x4008000000000000, %rcx # imm = 0x4008000000000000 + movq %rcx, %xmm15 + ucomisd %xmm15, %xmm0 + setne %dl + movzbq %dl, %rdx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rdx + testq %rdx, %rdx + jne + movslq 0x10(%rax), %rcx + cmpq $0x2a, %rcx + setne %dl + movzbq %dl, %rdx + testq %rdx, %rdx + je + movl $0x1, %eax + addq $0x80, %rsp + popq %rbp + retq + movl $0x8, %edx + movslq %edx, %rcx + cmpq $0x10, %rcx + jge + jmp + movslq %edx, %rcx + leaq 0x1(%rcx), %rdx + jmp + movslq %edx, %rcx + addq %rax, %rcx + movsbq (%rcx), %rcx + testq %rcx, %rcx + je + jmp + leaq , %rax + movsd (%rax,%riz), %xmm0 + movabsq $0x4014000000000000, %rax # imm = 0x4014000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %cl + movzbq %cl, %rcx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rcx + testq %rcx, %rcx + jne + jmp + movl $0x2, %eax + addq $0x80, %rsp + popq %rbp + retq + jmp + leaq , %rax + movslq 0x8(%rax), %rax + cmpq $0x2b, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x3, %eax + addq $0x80, %rsp + popq %rbp + retq + leaq , %rax + movslq (%rax), %rax + cmpq $0x1, %rax + setne %al + movzbq %al, %rax + movl $0x1, %edx + testq %rax, %rax + jne + leaq , %rax + movslq 0x4(%rax), %rax + cmpq $0x2, %rax + setne %al + movzbq %al, %rax + testq %rax, %rax + setne %dl + movzbq %dl, %rdx + testq %rdx, %rdx + jne + leaq , %rax + movslq 0x8(%rax), %rax + cmpq $0x9, %rax + setne %dl + movzbq %dl, %rdx + testq %rdx, %rdx + je + movl $0x4, %eax + addq $0x80, %rsp + popq %rbp + retq + leaq , %rax + movsd (%rax,%riz), %xmm0 + movabsq $0x4008000000000000, %rax # imm = 0x4008000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %cl + movzbq %cl, %rcx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rcx + testq %rcx, %rcx + jne + leaq , %rax + movslq 0x10(%rax), %rax + cmpq $0x2a, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x5, %eax + addq $0x80, %rsp + popq %rbp + retq + leaq , %rax + addq $0x18, %rax + movsd (%rax,%riz), %xmm0 + movabsq $0x4010000000000000, %rax # imm = 0x4010000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %cl + movzbq %cl, %rcx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rcx + testq %rcx, %rcx + jne + leaq , %rax + movslq 0x28(%rax), %rax + cmpq $0x2b, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x6, %eax + addq $0x80, %rsp + popq %rbp + retq + leaq -0x20(%rbp), %rax + leaq , %rcx + pushq %rdx + movq (%rcx), %rdx + movq %rdx, (%rax) + movq 0x8(%rcx), %rdx + movq %rdx, 0x8(%rax) + movq 0x10(%rcx), %rdx + movq %rdx, 0x10(%rax) + popq %rdx + leaq -0x20(%rbp), %rax + movsd (%rax,%riz), %xmm0 + movabsq $0x4008000000000000, %rax # imm = 0x4008000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %cl + movzbq %cl, %rcx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rcx + testq %rcx, %rcx + jne + leaq -0x20(%rbp), %rax + movslq 0x10(%rax), %rax + cmpq $0x2a, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x7, %eax + addq $0x80, %rsp + popq %rbp + retq + leaq -0x38(%rbp), %rax + leaq , %rcx + pushq %rdx + movq (%rcx), %rdx + movq %rdx, (%rax) + movq 0x8(%rcx), %rdx + movq %rdx, 0x8(%rax) + movq 0x10(%rcx), %rdx + movq %rdx, 0x10(%rax) + popq %rdx + leaq -0x38(%rbp), %rax + movsd (%rax,%riz), %xmm0 + movabsq $0x4018000000000000, %rax # imm = 0x4018000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %cl + movzbq %cl, %rcx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rcx + testq %rcx, %rcx + jne + leaq -0x38(%rbp), %rax + movslq 0x10(%rax), %rax + cmpq $0x2c, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x8, %eax + addq $0x80, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x80, %rsp + popq %rbp + retq + jmp + jmp + jmp + jmp + jmp + jmp + jmp + jmp + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/ssa/compound_assign_unsigned_div.ssa b/tests/snapshots/ssa/compound_assign_unsigned_div.ssa new file mode 100644 index 000000000..c57e699fb --- /dev/null +++ b/tests/snapshots/ssa/compound_assign_unsigned_div.ssa @@ -0,0 +1,142 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=6 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(4294967295) -> x0 + v2 Imm(0) -> x1 + v3 LoadLocal { off=-1, kind=U32 } -> x1 + v4 Imm(-2) -> x1 + v5 Imm(4294967294) -> x1 + v6 Binop { op=divu, lhs=v1, rhs=v5 } -> x0 + v7 Imm(0) -> x1 + v8 BinopI { op=and, lhs=v6, rhs_imm=4294967295 } -> x0 + v9 BinopI { op=xor, lhs=v8, rhs_imm=1 } -> x0 + v10 BinopI { op=and, lhs=v9, rhs_imm=4294967295 } -> x0 + v11 BinopI { op=ne, lhs=v10, rhs_imm=0 } -> x0 + terminator Bz { cond=v11, target=b2, fall=b1 } (exit_acc=v11) + block 1 start_pc=0 + v12 Imm(1) -> x0 + terminator Return(v12) (exit_acc=v12) + block 2 start_pc=0 + v13 Imm(4294967295) -> x0 + v14 Imm(0) -> x1 + v15 LoadLocal { off=-2, kind=U32 } -> x1 + v16 Imm(-2) -> x1 + v17 Imm(4294967294) -> x1 + v18 Binop { op=modu, lhs=v13, rhs=v17 } -> x0 + v19 Imm(0) -> x1 + v20 BinopI { op=and, lhs=v18, rhs_imm=4294967295 } -> x0 + v21 BinopI { op=xor, lhs=v20, rhs_imm=1 } -> x0 + v22 BinopI { op=and, lhs=v21, rhs_imm=4294967295 } -> x0 + v23 BinopI { op=ne, lhs=v22, rhs_imm=0 } -> x0 + terminator Bz { cond=v23, target=b4, fall=b3 } (exit_acc=v23) + block 3 start_pc=0 + v24 Imm(2) -> x0 + terminator Return(v24) (exit_acc=v24) + block 4 start_pc=0 + v25 Imm(-2) -> x0 + v26 Imm(0) -> x1 + v27 LoadLocal { off=-3, kind=I32 } -> x1 + v28 Imm(2) -> x1 + v29 BinopI { op=and, lhs=v25, rhs_imm=4294967295 } -> x0 + v30 Binop { op=divu, lhs=v29, rhs=v28 } -> x0 + v31 Imm(0) -> x1 + v32 Extend { value=v30, kind=I32 } -> x0 + v33 BinopI { op=ne, lhs=v32, rhs_imm=2147483647 } -> x0 + terminator Bz { cond=v33, target=b6, fall=b5 } (exit_acc=v33) + block 5 start_pc=0 + v34 Imm(3) -> x0 + terminator Return(v34) (exit_acc=v34) + block 6 start_pc=0 + v35 Imm(-7) -> x0 + v36 Imm(0) -> x1 + v37 LoadLocal { off=-4, kind=I32 } -> x1 + v38 Imm(3) -> x1 + v39 Binop { op=mod, lhs=v35, rhs=v38 } -> x0 + v40 Imm(0) -> x1 + v41 Extend { value=v39, kind=I32 } -> x0 + v42 BinopI { op=ne, lhs=v41, rhs_imm=-1 } -> x0 + terminator Bz { cond=v42, target=b8, fall=b7 } (exit_acc=v42) + block 7 start_pc=0 + v43 Imm(4) -> x0 + terminator Return(v43) (exit_acc=v43) + block 8 start_pc=0 + v44 Imm(-1) -> x0 + v45 Imm(0) -> x1 + v46 LoadLocal { off=-5, kind=I64 } -> x1 + v47 Imm(3) -> x1 + v48 Binop { op=divu, lhs=v44, rhs=v47 } -> x0 + v49 Imm(0) -> x1 + v50 LoadLocal { off=-5, kind=I64 } -> x1 + v51 BinopI { op=ne, lhs=v48, rhs_imm=6148914691236517205 } -> x0 + terminator Bz { cond=v51, target=b10, fall=b9 } (exit_acc=v51) + block 9 start_pc=0 + v52 Imm(5) -> x0 + terminator Return(v52) (exit_acc=v52) + block 10 start_pc=0 + v53 Imm(255) -> x0 + v54 Imm(0) -> x1 + v55 LoadLocal { off=-6, kind=U8 } -> x1 + v56 Imm(-2) -> x1 + v57 Binop { op=div, lhs=v53, rhs=v56 } -> x0 + v58 Imm(0) -> x1 + v59 BinopI { op=and, lhs=v57, rhs_imm=255 } -> x0 + v60 BinopI { op=xor, lhs=v59, rhs_imm=129 } -> x0 + v61 BinopI { op=and, lhs=v60, rhs_imm=4294967295 } -> x0 + v62 BinopI { op=ne, lhs=v61, rhs_imm=0 } -> x0 + terminator Bz { cond=v62, target=b12, fall=b11 } (exit_acc=v62) + block 11 start_pc=0 + v63 Imm(6) -> x0 + terminator Return(v63) (exit_acc=v63) + block 12 start_pc=0 + v64 Imm(0) -> x0 + terminator Return(v64) (exit_acc=v64) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/const_expr_unsigned_fold.ssa b/tests/snapshots/ssa/const_expr_unsigned_fold.ssa new file mode 100644 index 000000000..f21f6019a --- /dev/null +++ b/tests/snapshots/ssa/const_expr_unsigned_fold.ssa @@ -0,0 +1,139 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ImmData(8) -> x0 + v2 Load { addr=v1, disp=0, kind=I64 } -> x0 + v3 BinopI { op=ne, lhs=v2, rhs_imm=6148914691236517205 } -> x0 + terminator Bz { cond=v3, target=b2, fall=b1 } (exit_acc=v3) + block 1 start_pc=0 + v4 Imm(1) -> x0 + terminator Return(v4) (exit_acc=v4) + block 2 start_pc=0 + v5 ImmData(16) -> x0 + v6 Load { addr=v5, disp=0, kind=I64 } -> x0 + v7 BinopI { op=ne, lhs=v6, rhs_imm=1152921504606846975 } -> x0 + terminator Bz { cond=v7, target=b4, fall=b3 } (exit_acc=v7) + block 3 start_pc=0 + v8 Imm(2) -> x0 + terminator Return(v8) (exit_acc=v8) + block 4 start_pc=0 + v9 ImmData(24) -> x0 + v10 Load { addr=v9, disp=0, kind=I64 } -> x0 + v11 BinopI { op=ne, lhs=v10, rhs_imm=1 } -> x0 + terminator Bz { cond=v11, target=b6, fall=b5 } (exit_acc=v11) + block 5 start_pc=0 + v12 Imm(3) -> x0 + terminator Return(v12) (exit_acc=v12) + block 6 start_pc=0 + v13 ImmData(32) -> x0 + v14 Load { addr=v13, disp=0, kind=I32 } -> x0 + v15 BinopI { op=ne, lhs=v14, rhs_imm=1 } -> x0 + terminator Bz { cond=v15, target=b8, fall=b7 } (exit_acc=v15) + block 7 start_pc=0 + v16 Imm(4) -> x0 + terminator Return(v16) (exit_acc=v16) + block 8 start_pc=0 + v17 ImmData(72) -> x0 + v18 Load { addr=v17, disp=0, kind=I32 } -> x0 + v19 BinopI { op=ne, lhs=v18, rhs_imm=0 } -> x0 + terminator Bz { cond=v19, target=b10, fall=b9 } (exit_acc=v19) + block 9 start_pc=0 + v20 Imm(5) -> x0 + terminator Return(v20) (exit_acc=v20) + block 10 start_pc=0 + v21 ImmData(48) -> x0 + v22 Load { addr=v21, disp=0, kind=I64 } -> x0 + v23 Imm(-9223372036854775808) -> x1 + v24 BinopI { op=ne, lhs=v22, rhs_imm=-9223372036854775808 } -> x0 + terminator Bz { cond=v24, target=b12, fall=b11 } (exit_acc=v24) + block 11 start_pc=0 + v25 Imm(6) -> x0 + terminator Return(v25) (exit_acc=v25) + block 12 start_pc=0 + v26 Imm(16) -> x0 + v27 Imm(4) -> x1 + v28 Imm(0) -> x1 + v29 Binop { op=add, lhs=v26, rhs=v28 } -> x0 + v30 BinopI { op=shr, lhs=v29, rhs_imm=2 } -> x0 + v31 BinopI { op=ne, lhs=v30, rhs_imm=4 } -> x0 + terminator Bz { cond=v31, target=b14, fall=b13 } (exit_acc=v31) + block 13 start_pc=0 + v32 Imm(7) -> x0 + terminator Return(v32) (exit_acc=v32) + block 14 start_pc=0 + v33 Imm(12) -> x0 + v34 Imm(4) -> x1 + v35 Imm(0) -> x1 + v36 Binop { op=add, lhs=v33, rhs=v35 } -> x0 + v37 BinopI { op=shr, lhs=v36, rhs_imm=2 } -> x0 + v38 BinopI { op=ne, lhs=v37, rhs_imm=3 } -> x1 + v39 Imm(0) -> x0 + terminator Bnz { cond=v38, target=b19, fall=b15 } (exit_acc=v38) + block 15 start_pc=0 + v40 ImmData(88) -> x0 + v41 Load { addr=v40, disp=0, kind=I32 } -> x0 + v42 BinopI { op=ne, lhs=v41, rhs_imm=0 } -> x1 + v43 Imm(0) -> x0 + terminator Jmp(b16) (exit_acc=v42) + block 16 start_pc=0 + v44 Phi { incoming=[b19:v38, b15:v42], kind=I64 } -> x1 + v45 LoadLocal { off=-1, kind=I64 } -> x0 + terminator Bz { cond=v44, target=b18, fall=b17 } (exit_acc=v44) + block 17 start_pc=0 + v46 Imm(8) -> x0 + terminator Return(v46) (exit_acc=v46) + block 18 start_pc=0 + v47 Imm(0) -> x0 + terminator Return(v47) (exit_acc=v47) + block 19 start_pc=0 + terminator Jmp(b16) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/decl_specifier_any_order.ssa b/tests/snapshots/ssa/decl_specifier_any_order.ssa new file mode 100644 index 000000000..b296295ce --- /dev/null +++ b/tests/snapshots/ssa/decl_specifier_any_order.ssa @@ -0,0 +1,128 @@ +decl_specifier_any_order.c:29: warning: unused variable `llv` +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=6 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(0) -> x0 + terminator Jmp(b2) (exit_acc=v1) + block 1 start_pc=0 + v2 Imm(1) -> x0 + terminator Return(v2) (exit_acc=v2) + block 2 start_pc=0 + v3 Imm(0) -> x0 + terminator Jmp(b4) (exit_acc=v3) + block 3 start_pc=0 + v4 Imm(2) -> x0 + terminator Return(v4) (exit_acc=v4) + block 4 start_pc=0 + v5 Imm(4294967296) -> x0 + v6 Imm(0) -> x1 + v7 LoadLocal { off=-1, kind=I64 } -> x1 + v8 BinopI { op=shr, lhs=v5, rhs_imm=32 } -> x0 + v9 BinopI { op=ne, lhs=v8, rhs_imm=1 } -> x0 + terminator Bz { cond=v9, target=b6, fall=b5 } (exit_acc=v9) + block 5 start_pc=0 + v10 Imm(3) -> x0 + terminator Return(v10) (exit_acc=v10) + block 6 start_pc=0 + v11 Imm(-1) -> x0 + v12 Imm(0) -> x1 + v13 BinopI { op=and, lhs=v11, rhs_imm=4294967295 } -> x0 + v14 BinopI { op=ugt, lhs=v13, rhs_imm=0 } -> x0 + v15 BinopI { op=eq, lhs=v14, rhs_imm=0 } -> x0 + terminator Bz { cond=v15, target=b8, fall=b7 } (exit_acc=v15) + block 7 start_pc=0 + v16 Imm(4) -> x0 + terminator Return(v16) (exit_acc=v16) + block 8 start_pc=0 + v17 Imm(-1) -> x0 + v18 Imm(0) -> x1 + v19 BinopI { op=and, lhs=v17, rhs_imm=255 } -> x0 + v20 BinopI { op=xor, lhs=v19, rhs_imm=255 } -> x0 + v21 BinopI { op=and, lhs=v20, rhs_imm=4294967295 } -> x0 + v22 BinopI { op=ne, lhs=v21, rhs_imm=0 } -> x0 + terminator Bz { cond=v22, target=b10, fall=b9 } (exit_acc=v22) + block 9 start_pc=0 + v23 Imm(5) -> x0 + terminator Return(v23) (exit_acc=v23) + block 10 start_pc=0 + v24 Imm(-1) -> x0 + v25 Imm(0) -> x0 + v26 Imm(0) -> x0 + terminator Jmp(b12) (exit_acc=v26) + block 11 start_pc=0 + v27 Imm(6) -> x0 + terminator Return(v27) (exit_acc=v27) + block 12 start_pc=0 + v28 Imm(16) -> x0 + v29 Imm(68719476736) -> x0 + v30 Imm(0) -> x0 + terminator Jmp(b14) (exit_acc=v30) + block 13 start_pc=0 + v31 Imm(7) -> x0 + terminator Return(v31) (exit_acc=v31) + block 14 start_pc=0 + v32 LocalAddr(-6) -> x0 + v33 BinopI { op=add, lhs=v32, rhs_imm=8 } -> x1 + v34 Imm(-5) -> x1 + v35 Store { addr=v32, disp=8, value=v34, kind=I64 } -> - + v36 LocalAddr(-6) -> x0 + v37 BinopI { op=add, lhs=v36, rhs_imm=8 } -> x1 + v38 Load { addr=v36, disp=8, kind=I64 } -> x0 + v39 BinopI { op=ge, lhs=v38, rhs_imm=0 } -> x0 + terminator Bz { cond=v39, target=b16, fall=b15 } (exit_acc=v39) + block 15 start_pc=0 + v40 Imm(8) -> x0 + terminator Return(v40) (exit_acc=v40) + block 16 start_pc=0 + v41 Imm(0) -> x0 + terminator Return(v41) (exit_acc=v41) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/int_literal_boundary_types.ssa b/tests/snapshots/ssa/int_literal_boundary_types.ssa new file mode 100644 index 000000000..1a5c96b40 --- /dev/null +++ b/tests/snapshots/ssa/int_literal_boundary_types.ssa @@ -0,0 +1,146 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=4 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(-2147483649) -> x0 + v2 Imm(0) -> x1 + v3 LoadLocal { off=-1, kind=I64 } -> x1 + v4 BinopI { op=ne, lhs=v1, rhs_imm=-2147483649 } -> x0 + terminator Bz { cond=v4, target=b2, fall=b1 } (exit_acc=v4) + block 1 start_pc=0 + v5 Imm(1) -> x0 + terminator Return(v5) (exit_acc=v5) + block 2 start_pc=0 + v6 Imm(0) -> x1 + v7 Imm(0) -> x0 + terminator Jmp(b4) (exit_acc=v6) + block 3 start_pc=0 + v8 Imm(0) -> x1 + v9 Imm(0) -> x0 + terminator Jmp(b4) (exit_acc=v8) + block 4 start_pc=0 + v10 Phi { incoming=[b2:v6, b3:v8], kind=I64 } -> x1 + v11 LoadLocal { off=-2, kind=I64 } -> x0 + terminator Bz { cond=v10, target=b6, fall=b5 } (exit_acc=v10) + block 5 start_pc=0 + v12 Imm(2) -> x0 + terminator Return(v12) (exit_acc=v12) + block 6 start_pc=0 + v13 Imm(-1) -> x0 + v14 Imm(2147483648) -> x0 + v15 Imm(4294967295) -> x1 + v16 Binop { op=ult, lhs=v15, rhs=v14 } -> x0 + terminator Bz { cond=v16, target=b8, fall=b7 } (exit_acc=v16) + block 7 start_pc=0 + v17 Imm(3) -> x0 + terminator Return(v17) (exit_acc=v17) + block 8 start_pc=0 + v18 Imm(0) -> x0 + terminator Jmp(b10) (exit_acc=v18) + block 9 start_pc=0 + v19 Imm(4) -> x0 + terminator Return(v19) (exit_acc=v19) + block 10 start_pc=0 + v20 Imm(1) -> x0 + v21 Imm(0) -> x0 + terminator Jmp(b12) (exit_acc=v21) + block 11 start_pc=0 + v22 Imm(5) -> x0 + terminator Return(v22) (exit_acc=v22) + block 12 start_pc=0 + v23 Imm(-9223372036854775808) -> x0 + v24 Imm(2) -> x0 + v25 Imm(4611686018427387904) -> x0 + v26 Imm(0) -> x0 + terminator Jmp(b14) (exit_acc=v26) + block 13 start_pc=0 + v27 Imm(6) -> x0 + terminator Return(v27) (exit_acc=v27) + block 14 start_pc=0 + v28 Imm(0) -> x0 + v29 Imm(1) -> x2 + v30 Imm(0) -> x1 + terminator Jmp(b15) (exit_acc=v28) + block 15 start_pc=0 + v31 Imm(0) -> x2 + v32 Imm(0) -> x0 + terminator Jmp(b16) (exit_acc=v31) + block 16 start_pc=0 + v33 Phi { incoming=[b14:v29, b15:v31], kind=I64 } -> x2 + v34 LoadLocal { off=-4, kind=I64 } -> x0 + v35 Imm(0) -> x0 + terminator Bnz { cond=v33, target=b23, fall=b17 } (exit_acc=v33) + block 17 start_pc=0 + v36 Imm(0) -> x2 + v37 Imm(0) -> x0 + terminator Jmp(b18) (exit_acc=v36) + block 18 start_pc=0 + v38 Phi { incoming=[b23:v33, b17:v36], kind=I64 } -> x2 + v39 LoadLocal { off=-3, kind=I64 } -> x0 + terminator Bz { cond=v38, target=b20, fall=b19 } (exit_acc=v38) + block 19 start_pc=0 + v40 Imm(7) -> x0 + terminator Return(v40) (exit_acc=v40) + block 20 start_pc=0 + v41 Imm(-1) -> x0 + v42 Imm(8) -> x0 + v43 Imm(4294967295) -> x1 + v44 Binop { op=ult, lhs=v43, rhs=v42 } -> x0 + terminator Bz { cond=v44, target=b22, fall=b21 } (exit_acc=v44) + block 21 start_pc=0 + v45 Imm(8) -> x0 + terminator Return(v45) (exit_acc=v45) + block 22 start_pc=0 + v46 Imm(0) -> x0 + terminator Return(v46) (exit_acc=v46) + block 23 start_pc=0 + terminator Jmp(b18) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/libc_fp_classify.ssa b/tests/snapshots/ssa/libc_fp_classify.ssa index 9552795d2..72af75b50 100644 --- a/tests/snapshots/ssa/libc_fp_classify.ssa +++ b/tests/snapshots/ssa/libc_fp_classify.ssa @@ -74,7 +74,9 @@ fn ent_pc=4 n_params=1 variadic=false locals=1 v6 LocalAddr(-1) -> x0 v7 Load { addr=v6, disp=0, kind=I64 } -> x0 v8 BinopI { op=shru, lhs=v7, rhs_imm=63 } -> x0 - terminator Return(v8) (exit_acc=v8) + v9 BinopI { op=shl, lhs=v8, rhs_imm=32 } -> x1 + v10 Extend { value=v8, kind=I32 } -> x0 + terminator Return(v10) (exit_acc=v10) ; --- SSA dump (ok=true) ent_pc=5 --- ; name=copysign fn ent_pc=5 n_params=2 variadic=false locals=2 diff --git a/tests/snapshots/ssa/math_classify.ssa b/tests/snapshots/ssa/math_classify.ssa index c04ff43ec..b139a45c1 100644 --- a/tests/snapshots/ssa/math_classify.ssa +++ b/tests/snapshots/ssa/math_classify.ssa @@ -110,7 +110,9 @@ fn ent_pc=4 n_params=1 variadic=false locals=1 v6 LocalAddr(-1) -> x0 v7 Load { addr=v6, disp=0, kind=I64 } -> x0 v8 BinopI { op=shru, lhs=v7, rhs_imm=63 } -> x0 - terminator Return(v8) (exit_acc=v8) + v9 BinopI { op=shl, lhs=v8, rhs_imm=32 } -> x1 + v10 Extend { value=v8, kind=I32 } -> x0 + terminator Return(v10) (exit_acc=v10) ; --- SSA dump (ok=true) ent_pc=13 --- ; name=main fn ent_pc=13 n_params=0 variadic=false locals=5 diff --git a/tests/snapshots/ssa/nested_designator_string_member.ssa b/tests/snapshots/ssa/nested_designator_string_member.ssa new file mode 100644 index 000000000..b9ea18718 --- /dev/null +++ b/tests/snapshots/ssa/nested_designator_string_member.ssa @@ -0,0 +1,279 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=str_eq +fn ent_pc=0 n_params=2 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + terminator Jmp(b1) (exit_acc=v3) + block 1 start_pc=0 + v5 Phi { incoming=[b0:v1, b2:v11], kind=I64 } -> x7 + v6 Phi { incoming=[b0:v3, b2:v14], kind=I64 } -> x6 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Load { addr=v5, disp=0, kind=I8 } -> x1 + v9 Imm(0) -> x0 + terminator Bz { cond=v8, target=b6, fall=b4 } (exit_acc=v8) + block 2 start_pc=0 + v10 LoadLocal { off=2, kind=I64 } -> x0 + v11 BinopI { op=add, lhs=v5, rhs_imm=1 } -> x7 + v12 Imm(0) -> x0 + v13 LoadLocal { off=3, kind=I64 } -> x0 + v14 BinopI { op=add, lhs=v6, rhs_imm=1 } -> x6 + v15 Imm(0) -> x0 + terminator Jmp(b1) (exit_acc=v14) + block 3 start_pc=0 + v16 LoadLocal { off=2, kind=I64 } -> x0 + v17 Load { addr=v5, disp=0, kind=I8 } -> x0 + v18 LoadLocal { off=3, kind=I64 } -> x1 + v19 Load { addr=v6, disp=0, kind=I8 } -> x1 + v20 Binop { op=eq, lhs=v17, rhs=v19 } -> x0 + terminator Return(v20) (exit_acc=v20) + block 4 start_pc=0 + v21 LoadLocal { off=2, kind=I64 } -> x0 + v22 Load { addr=v5, disp=0, kind=I8 } -> x0 + v23 LoadLocal { off=3, kind=I64 } -> x1 + v24 Load { addr=v6, disp=0, kind=I8 } -> x1 + v25 Binop { op=eq, lhs=v22, rhs=v24 } -> x1 + v26 Imm(0) -> x0 + terminator Jmp(b5) (exit_acc=v25) + block 5 start_pc=0 + v27 Phi { incoming=[b6:v8, b4:v25], kind=I64 } -> x1 + v28 LoadLocal { off=-1, kind=I64 } -> x0 + terminator Bz { cond=v27, target=b3, fall=b2 } (exit_acc=v27) + block 6 start_pc=0 + terminator Jmp(b5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=2 variadic=false locals=8 + spill_count=0 gpr_used=[3, 12, 13] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x3 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 ImmData(8) -> x12 + v8 BinopI { op=add, lhs=v7, rhs_imm=4 } -> x7 + v9 ImmData(28) -> x6 + v10 Call { target_pc=0, args=[v8, v9], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x0 + v11 BinopI { op=eq, lhs=v10, rhs_imm=0 } -> x0 + terminator Bz { cond=v11, target=b2, fall=b1 } (exit_acc=v11) + block 1 start_pc=0 + v12 Imm(1) -> x0 + terminator Return(v12) (exit_acc=v12) + block 2 start_pc=0 + v13 ImmData(8) -> x0 + v14 BinopI { op=add, lhs=v7, rhs_imm=4 } -> x0 + v15 Imm(3) -> x0 + v16 BinopI { op=add, lhs=v7, rhs_imm=7 } -> x0 + v17 Load { addr=v7, disp=7, kind=I8 } -> x0 + v18 BinopI { op=ne, lhs=v17, rhs_imm=0 } -> x13 + v19 Imm(0) -> x0 + terminator Bnz { cond=v18, target=b21, fall=b3 } (exit_acc=v18) + block 3 start_pc=0 + v20 ImmData(8) -> x0 + v21 BinopI { op=add, lhs=v7, rhs_imm=4 } -> x0 + v22 Imm(7) -> x0 + v23 BinopI { op=add, lhs=v7, rhs_imm=11 } -> x0 + v24 Load { addr=v7, disp=11, kind=I8 } -> x0 + v25 BinopI { op=ne, lhs=v24, rhs_imm=0 } -> x13 + v26 Imm(0) -> x0 + terminator Jmp(b4) (exit_acc=v25) + block 4 start_pc=0 + v27 Phi { incoming=[b21:v18, b3:v25], kind=I64 } -> x13 + v28 LoadLocal { off=-5, kind=I64 } -> x0 + terminator Bz { cond=v27, target=b6, fall=b5 } (exit_acc=v27) + block 5 start_pc=0 + v29 Imm(2) -> x0 + terminator Return(v29) (exit_acc=v29) + block 6 start_pc=0 + v30 ImmData(8) -> x0 + v31 BinopI { op=add, lhs=v7, rhs_imm=12 } -> x0 + v32 Load { addr=v7, disp=12, kind=I32 } -> x0 + v33 BinopI { op=ne, lhs=v32, rhs_imm=7 } -> x13 + v34 Imm(0) -> x0 + terminator Bnz { cond=v33, target=b22, fall=b7 } (exit_acc=v33) + block 7 start_pc=0 + v35 ImmData(8) -> x0 + v36 Load { addr=v7, disp=0, kind=I32 } -> x0 + v37 BinopI { op=ne, lhs=v36, rhs_imm=5 } -> x13 + v38 Imm(0) -> x0 + terminator Jmp(b8) (exit_acc=v37) + block 8 start_pc=0 + v39 Phi { incoming=[b22:v33, b7:v37], kind=I64 } -> x13 + v40 LoadLocal { off=-6, kind=I64 } -> x0 + terminator Bz { cond=v39, target=b10, fall=b9 } (exit_acc=v39) + block 9 start_pc=0 + v41 Imm(3) -> x0 + terminator Return(v41) (exit_acc=v41) + block 10 start_pc=0 + v42 LocalAddr(-2) -> x0 + v43 ImmData(36) -> x1 + v44 Mcpy { dst=v42, src=v43, size=16 } -> x0 + v45 Imm(119) -> x0 + v46 LocalAddr(-2) -> x1 + v47 BinopI { op=add, lhs=v46, rhs_imm=4 } -> x2 + v48 Store { addr=v46, disp=4, value=v45, kind=I8 } -> - + v49 Imm(120) -> x0 + v50 LocalAddr(-2) -> x1 + v51 BinopI { op=add, lhs=v50, rhs_imm=5 } -> x2 + v52 Store { addr=v50, disp=5, value=v49, kind=I8 } -> - + v53 Imm(121) -> x0 + v54 LocalAddr(-2) -> x1 + v55 BinopI { op=add, lhs=v54, rhs_imm=6 } -> x2 + v56 Store { addr=v54, disp=6, value=v53, kind=I8 } -> - + v57 Imm(122) -> x0 + v58 LocalAddr(-2) -> x1 + v59 BinopI { op=add, lhs=v58, rhs_imm=7 } -> x2 + v60 Store { addr=v58, disp=7, value=v57, kind=I8 } -> - + v61 Imm(0) -> x0 + v62 LocalAddr(-2) -> x1 + v63 BinopI { op=add, lhs=v62, rhs_imm=8 } -> x2 + v64 Store { addr=v62, disp=8, value=v61, kind=I8 } -> - + v65 LocalAddr(-2) -> x1 + v66 BinopI { op=add, lhs=v65, rhs_imm=9 } -> x2 + v67 Store { addr=v65, disp=9, value=v61, kind=I8 } -> - + v68 LocalAddr(-2) -> x1 + v69 BinopI { op=add, lhs=v68, rhs_imm=10 } -> x2 + v70 Store { addr=v68, disp=10, value=v61, kind=I8 } -> - + v71 LocalAddr(-2) -> x1 + v72 BinopI { op=add, lhs=v71, rhs_imm=11 } -> x2 + v73 Store { addr=v71, disp=11, value=v61, kind=I8 } -> - + v74 LoadLocal { off=2, kind=I32 } -> x0 + v75 BinopI { op=add, lhs=v1, rhs_imm=6 } -> x0 + v76 BinopI { op=shl, lhs=v75, rhs_imm=32 } -> x1 + v77 Extend { value=v75, kind=I32 } -> x1 + v78 LocalAddr(-2) -> x1 + v79 BinopI { op=add, lhs=v78, rhs_imm=12 } -> x2 + v80 Store { addr=v78, disp=12, value=v75, kind=I32 } -> - + v81 LoadLocal { off=2, kind=I32 } -> x0 + v82 BinopI { op=add, lhs=v1, rhs_imm=4 } -> x0 + v83 BinopI { op=shl, lhs=v82, rhs_imm=32 } -> x1 + v84 Extend { value=v82, kind=I32 } -> x1 + v85 LocalAddr(-2) -> x1 + v86 Store { addr=v85, disp=0, value=v82, kind=I32 } -> - + v87 LocalAddr(-2) -> x0 + v88 BinopI { op=add, lhs=v87, rhs_imm=4 } -> x7 + v89 ImmData(57) -> x6 + v90 Call { target_pc=0, args=[v88, v89], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x0 + v91 BinopI { op=eq, lhs=v90, rhs_imm=0 } -> x0 + terminator Bz { cond=v91, target=b12, fall=b11 } (exit_acc=v91) + block 11 start_pc=0 + v92 Imm(4) -> x0 + terminator Return(v92) (exit_acc=v92) + block 12 start_pc=0 + v93 LocalAddr(-2) -> x0 + v94 BinopI { op=add, lhs=v93, rhs_imm=4 } -> x1 + v95 Imm(4) -> x1 + v96 BinopI { op=add, lhs=v93, rhs_imm=8 } -> x1 + v97 Load { addr=v93, disp=8, kind=I8 } -> x0 + v98 BinopI { op=ne, lhs=v97, rhs_imm=0 } -> x1 + v99 Imm(0) -> x0 + terminator Bnz { cond=v98, target=b23, fall=b13 } (exit_acc=v98) + block 13 start_pc=0 + v100 LocalAddr(-2) -> x0 + v101 BinopI { op=add, lhs=v100, rhs_imm=4 } -> x1 + v102 Imm(7) -> x1 + v103 BinopI { op=add, lhs=v100, rhs_imm=11 } -> x1 + v104 Load { addr=v100, disp=11, kind=I8 } -> x0 + v105 BinopI { op=ne, lhs=v104, rhs_imm=0 } -> x1 + v106 Imm(0) -> x0 + terminator Jmp(b14) (exit_acc=v105) + block 14 start_pc=0 + v107 Phi { incoming=[b23:v98, b13:v105], kind=I64 } -> x1 + v108 LoadLocal { off=-7, kind=I64 } -> x0 + terminator Bz { cond=v107, target=b16, fall=b15 } (exit_acc=v107) + block 15 start_pc=0 + v109 Imm(5) -> x0 + terminator Return(v109) (exit_acc=v109) + block 16 start_pc=0 + v110 LocalAddr(-2) -> x0 + v111 BinopI { op=add, lhs=v110, rhs_imm=12 } -> x1 + v112 Load { addr=v110, disp=12, kind=I32 } -> x0 + v113 LoadLocal { off=2, kind=I32 } -> x1 + v114 BinopI { op=add, lhs=v1, rhs_imm=6 } -> x1 + v115 BinopI { op=shl, lhs=v114, rhs_imm=32 } -> x2 + v116 Extend { value=v114, kind=I32 } -> x1 + v117 Binop { op=ne, lhs=v112, rhs=v116 } -> x1 + v118 Imm(0) -> x0 + terminator Bnz { cond=v117, target=b24, fall=b17 } (exit_acc=v117) + block 17 start_pc=0 + v119 LocalAddr(-2) -> x0 + v120 Load { addr=v119, disp=0, kind=I32 } -> x0 + v121 LoadLocal { off=2, kind=I32 } -> x1 + v122 BinopI { op=add, lhs=v1, rhs_imm=4 } -> x1 + v123 BinopI { op=shl, lhs=v122, rhs_imm=32 } -> x2 + v124 Extend { value=v122, kind=I32 } -> x1 + v125 Binop { op=ne, lhs=v120, rhs=v124 } -> x1 + v126 Imm(0) -> x0 + terminator Jmp(b18) (exit_acc=v125) + block 18 start_pc=0 + v127 Phi { incoming=[b24:v117, b17:v125], kind=I64 } -> x1 + v128 LoadLocal { off=-8, kind=I64 } -> x0 + terminator Bz { cond=v127, target=b20, fall=b19 } (exit_acc=v127) + block 19 start_pc=0 + v129 Imm(6) -> x0 + terminator Return(v129) (exit_acc=v129) + block 20 start_pc=0 + v130 Imm(0) -> x0 + terminator Return(v130) (exit_acc=v130) + block 21 start_pc=0 + terminator Jmp(b4) + block 22 start_pc=0 + terminator Jmp(b8) + block 23 start_pc=0 + terminator Jmp(b14) + block 24 start_pc=0 + terminator Jmp(b18) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/packed_bitfield_repack.ssa b/tests/snapshots/ssa/packed_bitfield_repack.ssa new file mode 100644 index 000000000..b85f525bd --- /dev/null +++ b/tests/snapshots/ssa/packed_bitfield_repack.ssa @@ -0,0 +1,335 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=14 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(0) -> x1 + v2 Imm(0) -> x0 + terminator Jmp(b1) (exit_acc=v1) + block 1 start_pc=0 + v3 Imm(0) -> x1 + v4 Imm(1) -> x0 + v5 Imm(0) -> x0 + terminator Jmp(b2) (exit_acc=v3) + block 2 start_pc=0 + v6 Phi { incoming=[b0:v1, b1:v3], kind=I64 } -> x1 + v7 LoadLocal { off=-5, kind=I64 } -> x0 + terminator Bz { cond=v6, target=b4, fall=b3 } (exit_acc=v6) + block 3 start_pc=0 + v8 Imm(1) -> x0 + terminator Return(v8) (exit_acc=v8) + block 4 start_pc=0 + v9 Imm(0) -> x1 + v10 Imm(0) -> x0 + terminator Jmp(b5) (exit_acc=v9) + block 5 start_pc=0 + v11 Imm(0) -> x1 + v12 Imm(4) -> x0 + v13 Imm(0) -> x0 + terminator Jmp(b6) (exit_acc=v11) + block 6 start_pc=0 + v14 Phi { incoming=[b4:v9, b5:v11], kind=I64 } -> x1 + v15 LoadLocal { off=-6, kind=I64 } -> x0 + terminator Bz { cond=v14, target=b8, fall=b7 } (exit_acc=v14) + block 7 start_pc=0 + v16 Imm(2) -> x0 + terminator Return(v16) (exit_acc=v16) + block 8 start_pc=0 + v17 Imm(0) -> x1 + v18 Imm(0) -> x0 + terminator Jmp(b9) (exit_acc=v17) + block 9 start_pc=0 + v19 Imm(0) -> x1 + v20 Imm(2) -> x0 + v21 Imm(0) -> x0 + terminator Jmp(b10) (exit_acc=v19) + block 10 start_pc=0 + v22 Phi { incoming=[b8:v17, b9:v19], kind=I64 } -> x1 + v23 LoadLocal { off=-7, kind=I64 } -> x0 + terminator Bz { cond=v22, target=b12, fall=b11 } (exit_acc=v22) + block 11 start_pc=0 + v24 Imm(3) -> x0 + terminator Return(v24) (exit_acc=v24) + block 12 start_pc=0 + v25 Imm(0) -> x0 + terminator Jmp(b14) (exit_acc=v25) + block 13 start_pc=0 + v26 Imm(4) -> x0 + terminator Return(v26) (exit_acc=v26) + block 14 start_pc=0 + v27 LocalAddr(-1) -> x0 + v28 Imm(85) -> x1 + v29 Load { addr=v27, disp=0, kind=U8 } -> x2 + v30 BinopI { op=and, lhs=v29, rhs_imm=-256 } -> x2 + v31 Binop { op=or, lhs=v30, rhs=v28 } -> x1 + v32 Store { addr=v27, disp=0, value=v31, kind=I8 } -> - + v33 Imm(6124895493223874560) -> x0 + v34 LocalAddr(-1) -> x0 + v35 BinopI { op=add, lhs=v34, rhs_imm=1 } -> x1 + v36 Imm(7) -> x1 + v37 Store { addr=v34, disp=1, value=v36, kind=I8 } -> - + v38 Imm(504403158265495552) -> x0 + v39 LocalAddr(-1) -> x0 + v40 Load { addr=v39, disp=0, kind=U8 } -> x0 + v41 BinopI { op=shl, lhs=v40, rhs_imm=56 } -> x1 + v42 Extend { value=v40, kind=I8 } -> x0 + v43 BinopI { op=ne, lhs=v42, rhs_imm=85 } -> x1 + v44 Imm(0) -> x0 + terminator Bnz { cond=v43, target=b39, fall=b15 } (exit_acc=v43) + block 15 start_pc=0 + v45 LocalAddr(-1) -> x0 + v46 BinopI { op=add, lhs=v45, rhs_imm=1 } -> x1 + v47 Load { addr=v45, disp=1, kind=I8 } -> x0 + v48 BinopI { op=ne, lhs=v47, rhs_imm=7 } -> x1 + v49 Imm(0) -> x0 + terminator Jmp(b16) (exit_acc=v48) + block 16 start_pc=0 + v50 Phi { incoming=[b39:v43, b15:v48], kind=I64 } -> x1 + v51 LoadLocal { off=-8, kind=I64 } -> x0 + terminator Bz { cond=v50, target=b18, fall=b17 } (exit_acc=v50) + block 17 start_pc=0 + v52 Imm(5) -> x0 + terminator Return(v52) (exit_acc=v52) + block 18 start_pc=0 + v53 LocalAddr(-2) -> x0 + v54 Imm(65000) -> x1 + v55 Load { addr=v53, disp=0, kind=U32 } -> x2 + v56 BinopI { op=and, lhs=v55, rhs_imm=-131072 } -> x2 + v57 Binop { op=or, lhs=v56, rhs=v54 } -> x1 + v58 Store { addr=v53, disp=0, value=v57, kind=I32 } -> - + v59 Imm(9147936743096320000) -> x0 + v60 LocalAddr(-2) -> x0 + v61 BinopI { op=add, lhs=v60, rhs_imm=2 } -> x1 + v62 Imm(500) -> x1 + v63 Load { addr=v60, disp=2, kind=U16 } -> x1 + v64 BinopI { op=and, lhs=v63, rhs_imm=-2047 } -> x1 + v65 Imm(1000) -> x2 + v66 Binop { op=or, lhs=v64, rhs=v65 } -> x1 + v67 Store { addr=v60, disp=2, value=v66, kind=I16 } -> - + v68 Imm(9007199254740992000) -> x0 + v69 LocalAddr(-2) -> x0 + v70 BinopI { op=add, lhs=v69, rhs_imm=4 } -> x1 + v71 Imm(9) -> x1 + v72 Store { addr=v69, disp=4, value=v71, kind=I8 } -> - + v73 Imm(648518346341351424) -> x0 + v74 LocalAddr(-2) -> x0 + v75 Load { addr=v74, disp=0, kind=U32 } -> x0 + v76 BinopI { op=and, lhs=v75, rhs_imm=131071 } -> x0 + v77 BinopI { op=shl, lhs=v76, rhs_imm=47 } -> x0 + v78 BinopI { op=shr, lhs=v77, rhs_imm=47 } -> x0 + v79 BinopI { op=ne, lhs=v78, rhs_imm=65000 } -> x0 + v80 Imm(1) -> x2 + v81 Imm(0) -> x1 + terminator Bnz { cond=v79, target=b40, fall=b19 } (exit_acc=v79) + block 19 start_pc=0 + v82 LocalAddr(-2) -> x0 + v83 BinopI { op=add, lhs=v82, rhs_imm=2 } -> x1 + v84 Load { addr=v82, disp=2, kind=U16 } -> x0 + v85 BinopI { op=shr, lhs=v84, rhs_imm=1 } -> x0 + v86 BinopI { op=and, lhs=v85, rhs_imm=1023 } -> x0 + v87 BinopI { op=shl, lhs=v86, rhs_imm=54 } -> x0 + v88 BinopI { op=shr, lhs=v87, rhs_imm=54 } -> x0 + v89 BinopI { op=ne, lhs=v88, rhs_imm=500 } -> x0 + v90 BinopI { op=ne, lhs=v89, rhs_imm=0 } -> x2 + v91 Imm(0) -> x0 + terminator Jmp(b20) (exit_acc=v90) + block 20 start_pc=0 + v92 Phi { incoming=[b40:v80, b19:v90], kind=I64 } -> x2 + v93 LoadLocal { off=-10, kind=I64 } -> x0 + v94 Imm(0) -> x0 + terminator Bnz { cond=v92, target=b41, fall=b21 } (exit_acc=v92) + block 21 start_pc=0 + v95 LocalAddr(-2) -> x0 + v96 BinopI { op=add, lhs=v95, rhs_imm=4 } -> x1 + v97 Load { addr=v95, disp=4, kind=I8 } -> x0 + v98 BinopI { op=ne, lhs=v97, rhs_imm=9 } -> x2 + v99 Imm(0) -> x0 + terminator Jmp(b22) (exit_acc=v98) + block 22 start_pc=0 + v100 Phi { incoming=[b41:v92, b21:v98], kind=I64 } -> x2 + v101 LoadLocal { off=-9, kind=I64 } -> x0 + terminator Bz { cond=v100, target=b24, fall=b23 } (exit_acc=v100) + block 23 start_pc=0 + v102 Imm(6) -> x0 + terminator Return(v102) (exit_acc=v102) + block 24 start_pc=0 + v103 LocalAddr(-3) -> x0 + v104 Imm(3) -> x1 + v105 Load { addr=v103, disp=0, kind=U8 } -> x2 + v106 BinopI { op=and, lhs=v105, rhs_imm=-8 } -> x2 + v107 Binop { op=or, lhs=v106, rhs=v104 } -> x1 + v108 Store { addr=v103, disp=0, value=v107, kind=I8 } -> - + v109 Imm(6917529027641081856) -> x0 + v110 LocalAddr(-3) -> x0 + v111 Imm(60) -> x1 + v112 Load { addr=v110, disp=0, kind=U16 } -> x1 + v113 BinopI { op=and, lhs=v112, rhs_imm=-1017 } -> x1 + v114 Imm(480) -> x2 + v115 Binop { op=or, lhs=v113, rhs=v114 } -> x1 + v116 Store { addr=v110, disp=0, value=v115, kind=I16 } -> - + v117 Imm(8646911284551352320) -> x0 + v118 LocalAddr(-3) -> x0 + v119 BinopI { op=add, lhs=v118, rhs_imm=2 } -> x1 + v120 Imm(4) -> x1 + v121 Store { addr=v118, disp=2, value=v120, kind=I8 } -> - + v122 Imm(288230376151711744) -> x0 + v123 LocalAddr(-3) -> x0 + v124 Load { addr=v123, disp=0, kind=U8 } -> x0 + v125 BinopI { op=and, lhs=v124, rhs_imm=7 } -> x0 + v126 BinopI { op=shl, lhs=v125, rhs_imm=61 } -> x0 + v127 BinopI { op=shr, lhs=v126, rhs_imm=61 } -> x0 + v128 BinopI { op=ne, lhs=v127, rhs_imm=3 } -> x0 + v129 Imm(1) -> x2 + v130 Imm(0) -> x1 + terminator Bnz { cond=v128, target=b42, fall=b25 } (exit_acc=v128) + block 25 start_pc=0 + v131 LocalAddr(-3) -> x0 + v132 Load { addr=v131, disp=0, kind=U16 } -> x0 + v133 BinopI { op=shr, lhs=v132, rhs_imm=3 } -> x0 + v134 BinopI { op=and, lhs=v133, rhs_imm=127 } -> x0 + v135 BinopI { op=shl, lhs=v134, rhs_imm=57 } -> x0 + v136 BinopI { op=shr, lhs=v135, rhs_imm=57 } -> x0 + v137 BinopI { op=ne, lhs=v136, rhs_imm=60 } -> x0 + v138 BinopI { op=ne, lhs=v137, rhs_imm=0 } -> x2 + v139 Imm(0) -> x0 + terminator Jmp(b26) (exit_acc=v138) + block 26 start_pc=0 + v140 Phi { incoming=[b42:v129, b25:v138], kind=I64 } -> x2 + v141 LoadLocal { off=-12, kind=I64 } -> x0 + v142 Imm(0) -> x0 + terminator Bnz { cond=v140, target=b43, fall=b27 } (exit_acc=v140) + block 27 start_pc=0 + v143 LocalAddr(-3) -> x0 + v144 BinopI { op=add, lhs=v143, rhs_imm=2 } -> x1 + v145 Load { addr=v143, disp=2, kind=I8 } -> x0 + v146 BinopI { op=ne, lhs=v145, rhs_imm=4 } -> x2 + v147 Imm(0) -> x0 + terminator Jmp(b28) (exit_acc=v146) + block 28 start_pc=0 + v148 Phi { incoming=[b43:v140, b27:v146], kind=I64 } -> x2 + v149 LoadLocal { off=-11, kind=I64 } -> x0 + terminator Bz { cond=v148, target=b30, fall=b29 } (exit_acc=v148) + block 29 start_pc=0 + v150 Imm(7) -> x0 + terminator Return(v150) (exit_acc=v150) + block 30 start_pc=0 + v151 LocalAddr(-4) -> x0 + v152 Imm(11) -> x1 + v153 Store { addr=v151, disp=0, value=v152, kind=I8 } -> - + v154 Imm(792633534417207296) -> x0 + v155 LocalAddr(-4) -> x0 + v156 BinopI { op=add, lhs=v155, rhs_imm=1 } -> x0 + v157 Imm(30000) -> x1 + v158 Load { addr=v156, disp=0, kind=U16 } -> x2 + v159 BinopI { op=and, lhs=v158, rhs_imm=-65536 } -> x2 + v160 Binop { op=or, lhs=v159, rhs=v157 } -> x1 + v161 Store { addr=v156, disp=0, value=v160, kind=I16 } -> - + v162 Imm(8444249301319680000) -> x0 + v163 LocalAddr(-4) -> x0 + v164 Load { addr=v163, disp=0, kind=I8 } -> x0 + v165 BinopI { op=ne, lhs=v164, rhs_imm=11 } -> x1 + v166 Imm(0) -> x0 + terminator Bnz { cond=v165, target=b44, fall=b31 } (exit_acc=v165) + block 31 start_pc=0 + v167 LocalAddr(-4) -> x0 + v168 BinopI { op=add, lhs=v167, rhs_imm=1 } -> x0 + v169 Load { addr=v168, disp=0, kind=U16 } -> x0 + v170 BinopI { op=shl, lhs=v169, rhs_imm=48 } -> x1 + v171 Extend { value=v169, kind=I16 } -> x0 + v172 BinopI { op=ne, lhs=v171, rhs_imm=30000 } -> x1 + v173 Imm(0) -> x0 + terminator Jmp(b32) (exit_acc=v172) + block 32 start_pc=0 + v174 Phi { incoming=[b44:v165, b31:v172], kind=I64 } -> x1 + v175 LoadLocal { off=-13, kind=I64 } -> x0 + terminator Bz { cond=v174, target=b34, fall=b33 } (exit_acc=v174) + block 33 start_pc=0 + v176 Imm(8) -> x0 + terminator Return(v176) (exit_acc=v176) + block 34 start_pc=0 + v177 ImmData(8) -> x0 + v178 Load { addr=v177, disp=0, kind=U8 } -> x0 + v179 BinopI { op=shl, lhs=v178, rhs_imm=56 } -> x1 + v180 Extend { value=v178, kind=I8 } -> x0 + v181 BinopI { op=ne, lhs=v180, rhs_imm=85 } -> x1 + v182 Imm(0) -> x0 + terminator Bnz { cond=v181, target=b45, fall=b35 } (exit_acc=v181) + block 35 start_pc=0 + v183 ImmData(8) -> x0 + v184 BinopI { op=add, lhs=v183, rhs_imm=1 } -> x1 + v185 Load { addr=v183, disp=1, kind=I8 } -> x0 + v186 BinopI { op=ne, lhs=v185, rhs_imm=7 } -> x1 + v187 Imm(0) -> x0 + terminator Jmp(b36) (exit_acc=v186) + block 36 start_pc=0 + v188 Phi { incoming=[b45:v181, b35:v186], kind=I64 } -> x1 + v189 LoadLocal { off=-14, kind=I64 } -> x0 + terminator Bz { cond=v188, target=b38, fall=b37 } (exit_acc=v188) + block 37 start_pc=0 + v190 Imm(9) -> x0 + terminator Return(v190) (exit_acc=v190) + block 38 start_pc=0 + v191 Imm(0) -> x0 + terminator Return(v191) (exit_acc=v191) + block 39 start_pc=0 + terminator Jmp(b16) + block 40 start_pc=0 + terminator Jmp(b20) + block 41 start_pc=0 + terminator Jmp(b22) + block 42 start_pc=0 + terminator Jmp(b26) + block 43 start_pc=0 + terminator Jmp(b28) + block 44 start_pc=0 + terminator Jmp(b32) + block 45 start_pc=0 + terminator Jmp(b36) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/shift_result_promoted_type.ssa b/tests/snapshots/ssa/shift_result_promoted_type.ssa new file mode 100644 index 000000000..1b42b4b32 --- /dev/null +++ b/tests/snapshots/ssa/shift_result_promoted_type.ssa @@ -0,0 +1,109 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=6 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(-8589934592) -> x0 + v2 Imm(0) -> x1 + v3 LoadLocal { off=-1, kind=I64 } -> x1 + v4 BinopI { op=shr, lhs=v1, rhs_imm=1 } -> x0 + v5 Imm(0) -> x1 + v6 LoadLocal { off=-2, kind=I64 } -> x1 + v7 BinopI { op=ne, lhs=v4, rhs_imm=-4294967296 } -> x0 + terminator Bz { cond=v7, target=b2, fall=b1 } (exit_acc=v7) + block 1 start_pc=0 + v8 Imm(1) -> x0 + terminator Return(v8) (exit_acc=v8) + block 2 start_pc=0 + v9 Imm(-9223372036854775808) -> x0 + v10 Imm(0) -> x1 + v11 LoadLocal { off=-3, kind=I64 } -> x1 + v12 BinopI { op=shru, lhs=v9, rhs_imm=63 } -> x0 + v13 BinopI { op=ne, lhs=v12, rhs_imm=1 } -> x0 + terminator Bz { cond=v13, target=b4, fall=b3 } (exit_acc=v13) + block 3 start_pc=0 + v14 Imm(2) -> x0 + terminator Return(v14) (exit_acc=v14) + block 4 start_pc=0 + v15 Imm(2147483648) -> x0 + v16 Imm(0) -> x1 + v17 LoadLocal { off=-4, kind=U32 } -> x1 + v18 BinopI { op=shru, lhs=v15, rhs_imm=31 } -> x0 + v19 BinopI { op=xor, lhs=v18, rhs_imm=1 } -> x0 + v20 BinopI { op=and, lhs=v19, rhs_imm=4294967295 } -> x0 + v21 BinopI { op=ne, lhs=v20, rhs_imm=0 } -> x0 + terminator Bz { cond=v21, target=b6, fall=b5 } (exit_acc=v21) + block 5 start_pc=0 + v22 Imm(3) -> x0 + terminator Return(v22) (exit_acc=v22) + block 6 start_pc=0 + v23 Imm(-16) -> x0 + v24 Imm(0) -> x1 + v25 LoadLocal { off=-5, kind=I32 } -> x1 + v26 BinopI { op=shr, lhs=v23, rhs_imm=2 } -> x0 + v27 BinopI { op=ne, lhs=v26, rhs_imm=-4 } -> x0 + terminator Bz { cond=v27, target=b8, fall=b7 } (exit_acc=v27) + block 7 start_pc=0 + v28 Imm(4) -> x0 + terminator Return(v28) (exit_acc=v28) + block 8 start_pc=0 + v29 Imm(128) -> x0 + v30 Imm(0) -> x1 + v31 LoadLocal { off=-6, kind=U8 } -> x1 + v32 BinopI { op=shru, lhs=v29, rhs_imm=3 } -> x0 + v33 BinopI { op=ne, lhs=v32, rhs_imm=16 } -> x0 + terminator Bz { cond=v33, target=b10, fall=b9 } (exit_acc=v33) + block 9 start_pc=0 + v34 Imm(5) -> x0 + terminator Return(v34) (exit_acc=v34) + block 10 start_pc=0 + v35 Imm(0) -> x0 + terminator Return(v35) (exit_acc=v35) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/switch_case_label_promoted.ssa b/tests/snapshots/ssa/switch_case_label_promoted.ssa new file mode 100644 index 000000000..e59f06333 --- /dev/null +++ b/tests/snapshots/ssa/switch_case_label_promoted.ssa @@ -0,0 +1,140 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=4 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(-2147483648) -> x0 + v2 Imm(-9223372036854775808) -> x1 + v3 Imm(0) -> x1 + v4 Imm(0) -> x1 + v5 Imm(0) -> x1 + v6 LoadLocal { off=-1, kind=I32 } -> x1 + v7 BinopI { op=eq, lhs=v1, rhs_imm=-2147483648 } -> x0 + terminator Bnz { cond=v7, target=b2, fall=b3 } (exit_acc=v7) + block 1 start_pc=0 + v8 Phi { incoming=[b2:v11, b3:v13], kind=I64 } -> x0 + v9 Extend { value=v8, kind=I32 } -> x0 + v10 BinopI { op=ne, lhs=v9, rhs_imm=1 } -> x0 + terminator Bz { cond=v10, target=b6, fall=b5 } (exit_acc=v10) + block 2 start_pc=0 + v11 Imm(1) -> x0 + v12 Imm(0) -> x1 + terminator Jmp(b1) (exit_acc=v11) + block 3 start_pc=0 + v13 Imm(2) -> x0 + v14 Imm(0) -> x1 + terminator Jmp(b1) (exit_acc=v13) + block 4 start_pc=0 + terminator Jmp(b2) + block 5 start_pc=0 + v15 Imm(1) -> x0 + terminator Return(v15) (exit_acc=v15) + block 6 start_pc=0 + v16 Imm(4294967294) -> x0 + v17 Imm(0) -> x1 + v18 LoadLocal { off=-3, kind=U32 } -> x1 + v19 BinopI { op=eq, lhs=v16, rhs_imm=4294967294 } -> x0 + terminator Bnz { cond=v19, target=b8, fall=b9 } (exit_acc=v19) + block 7 start_pc=0 + v20 Phi { incoming=[b8:v23, b9:v25], kind=I64 } -> x0 + v21 Extend { value=v20, kind=I32 } -> x0 + v22 BinopI { op=ne, lhs=v21, rhs_imm=3 } -> x0 + terminator Bz { cond=v22, target=b12, fall=b11 } (exit_acc=v22) + block 8 start_pc=0 + v23 Imm(3) -> x0 + v24 Imm(0) -> x1 + terminator Jmp(b7) (exit_acc=v23) + block 9 start_pc=0 + v25 Imm(4) -> x0 + v26 Imm(0) -> x1 + terminator Jmp(b7) (exit_acc=v25) + block 10 start_pc=0 + terminator Jmp(b8) + block 11 start_pc=0 + v27 Imm(2) -> x0 + terminator Return(v27) (exit_acc=v27) + block 12 start_pc=0 + v28 Imm(-4294967296) -> x0 + v29 Imm(0) -> x1 + v30 LoadLocal { off=-4, kind=I64 } -> x1 + v31 BinopI { op=lt, lhs=v28, rhs_imm=2147483648 } -> x1 + terminator Bnz { cond=v31, target=b17, fall=b18 } (exit_acc=v31) + block 13 start_pc=0 + v32 Phi { incoming=[b16:v39, b14:v35, b15:v37], kind=I64 } -> x0 + v33 Extend { value=v32, kind=I32 } -> x0 + v34 BinopI { op=ne, lhs=v33, rhs_imm=5 } -> x0 + terminator Bz { cond=v34, target=b21, fall=b20 } (exit_acc=v34) + block 14 start_pc=0 + v35 Imm(5) -> x0 + v36 Imm(0) -> x1 + terminator Jmp(b13) (exit_acc=v35) + block 15 start_pc=0 + v37 Imm(6) -> x0 + v38 Imm(0) -> x1 + terminator Jmp(b13) (exit_acc=v37) + block 16 start_pc=0 + v39 Imm(7) -> x0 + v40 Imm(0) -> x1 + terminator Jmp(b13) (exit_acc=v39) + block 17 start_pc=0 + v41 BinopI { op=eq, lhs=v28, rhs_imm=-4294967296 } -> x0 + terminator Bnz { cond=v41, target=b14, fall=b16 } (exit_acc=v41) + block 18 start_pc=0 + v42 BinopI { op=eq, lhs=v28, rhs_imm=2147483648 } -> x0 + terminator Bnz { cond=v42, target=b15, fall=b16 } (exit_acc=v42) + block 19 start_pc=0 + terminator Jmp(b14) + block 20 start_pc=0 + v43 Imm(3) -> x0 + terminator Return(v43) (exit_acc=v43) + block 21 start_pc=0 + v44 Imm(0) -> x0 + terminator Return(v44) (exit_acc=v44) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/ternary_arith_common_type.ssa b/tests/snapshots/ssa/ternary_arith_common_type.ssa new file mode 100644 index 000000000..0314ec40b --- /dev/null +++ b/tests/snapshots/ssa/ternary_arith_common_type.ssa @@ -0,0 +1,148 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=9 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(0) -> x0 + v2 Imm(0) -> x1 + v3 LoadLocal { off=-1, kind=U32 } -> x1 + v4 BinopI { op=eq, lhs=v1, rhs_imm=0 } -> x1 + terminator Bz { cond=v4, target=b2, fall=b1 } (exit_acc=v4) + block 1 start_pc=0 + v5 Imm(1) -> x2 + v6 Imm(0) -> x1 + terminator Jmp(b3) (exit_acc=v5) + block 2 start_pc=0 + v7 Imm(-1) -> x1 + v8 Imm(4294967295) -> x2 + v9 Imm(0) -> x1 + terminator Jmp(b3) (exit_acc=v8) + block 3 start_pc=0 + v10 Phi { incoming=[b1:v5, b2:v8], kind=I64 } -> x2 + v11 LoadLocal { off=-6, kind=I64 } -> x1 + v12 Imm(0) -> x1 + v13 LoadLocal { off=-2, kind=I64 } -> x1 + v14 BinopI { op=ne, lhs=v10, rhs_imm=1 } -> x1 + terminator Bz { cond=v14, target=b5, fall=b4 } (exit_acc=v14) + block 4 start_pc=0 + v15 Imm(1) -> x0 + terminator Return(v15) (exit_acc=v15) + block 5 start_pc=0 + v16 LoadLocal { off=-1, kind=U32 } -> x1 + v17 BinopI { op=ne, lhs=v1, rhs_imm=0 } -> x1 + terminator Bz { cond=v17, target=b7, fall=b6 } (exit_acc=v17) + block 6 start_pc=0 + v18 Imm(1) -> x2 + v19 Imm(0) -> x1 + terminator Jmp(b8) (exit_acc=v18) + block 7 start_pc=0 + v20 Imm(-1) -> x1 + v21 Imm(4294967295) -> x2 + v22 Imm(0) -> x1 + terminator Jmp(b8) (exit_acc=v21) + block 8 start_pc=0 + v23 Phi { incoming=[b6:v18, b7:v21], kind=I64 } -> x2 + v24 LoadLocal { off=-7, kind=I64 } -> x1 + v25 Imm(0) -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 BinopI { op=ne, lhs=v23, rhs_imm=4294967295 } -> x1 + terminator Bz { cond=v27, target=b10, fall=b9 } (exit_acc=v27) + block 9 start_pc=0 + v28 Imm(2) -> x0 + terminator Return(v28) (exit_acc=v28) + block 10 start_pc=0 + v29 LoadLocal { off=-1, kind=U32 } -> x1 + v30 BinopI { op=eq, lhs=v1, rhs_imm=0 } -> x1 + terminator Bz { cond=v30, target=b12, fall=b11 } (exit_acc=v30) + block 11 start_pc=0 + v31 Imm(-1) -> x1 + v32 Imm(4294967295) -> x2 + v33 Imm(0) -> x1 + terminator Jmp(b13) (exit_acc=v32) + block 12 start_pc=0 + v34 Imm(1) -> x2 + v35 Imm(0) -> x1 + terminator Jmp(b13) (exit_acc=v34) + block 13 start_pc=0 + v36 Phi { incoming=[b11:v32, b12:v34], kind=I64 } -> x2 + v37 LoadLocal { off=-8, kind=I64 } -> x1 + v38 Imm(0) -> x1 + v39 LoadLocal { off=-4, kind=I64 } -> x1 + v40 BinopI { op=ne, lhs=v36, rhs_imm=4294967295 } -> x1 + terminator Bz { cond=v40, target=b15, fall=b14 } (exit_acc=v40) + block 14 start_pc=0 + v41 Imm(3) -> x0 + terminator Return(v41) (exit_acc=v41) + block 15 start_pc=0 + v42 LoadLocal { off=-1, kind=U32 } -> x1 + v43 BinopI { op=eq, lhs=v1, rhs_imm=0 } -> x0 + terminator Bz { cond=v43, target=b17, fall=b16 } (exit_acc=v43) + block 16 start_pc=0 + v44 Imm(-1) -> x1 + v45 Imm(0) -> x0 + terminator Jmp(b18) (exit_acc=v44) + block 17 start_pc=0 + v46 Imm(0) -> x1 + v47 Imm(0) -> x0 + terminator Jmp(b18) (exit_acc=v46) + block 18 start_pc=0 + v48 Phi { incoming=[b16:v44, b17:v46], kind=I64 } -> x1 + v49 LoadLocal { off=-9, kind=I64 } -> x0 + v50 Imm(0) -> x0 + v51 LoadLocal { off=-5, kind=I64 } -> x0 + v52 BinopI { op=ne, lhs=v48, rhs_imm=-1 } -> x0 + terminator Bz { cond=v52, target=b20, fall=b19 } (exit_acc=v52) + block 19 start_pc=0 + v53 Imm(4) -> x0 + terminator Return(v53) (exit_acc=v53) + block 20 start_pc=0 + v54 Imm(0) -> x0 + terminator Return(v54) (exit_acc=v54) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/union_member_unbraced_init.ssa b/tests/snapshots/ssa/union_member_unbraced_init.ssa new file mode 100644 index 000000000..efe072450 --- /dev/null +++ b/tests/snapshots/ssa/union_member_unbraced_init.ssa @@ -0,0 +1,269 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=15 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ImmData(8) -> x0 + v2 Load { addr=v1, disp=0, kind=F64 } -> d0 + v3 Imm(4613937818241073152) -> x1 + v4 Binop { op=fne, lhs=v2, rhs=v3 } -> x2 + v5 Imm(0) -> x1 + terminator Bnz { cond=v4, target=b37, fall=b1 } (exit_acc=v4) + block 1 start_pc=0 + v6 ImmData(8) -> x1 + v7 BinopI { op=add, lhs=v1, rhs_imm=16 } -> x1 + v8 Load { addr=v1, disp=16, kind=I32 } -> x1 + v9 BinopI { op=ne, lhs=v8, rhs_imm=42 } -> x2 + v10 Imm(0) -> x1 + terminator Jmp(b2) (exit_acc=v9) + block 2 start_pc=0 + v11 Phi { incoming=[b37:v4, b1:v9], kind=I64 } -> x2 + v12 LoadLocal { off=-8, kind=I64 } -> x1 + terminator Bz { cond=v11, target=b4, fall=b3 } (exit_acc=v11) + block 3 start_pc=0 + v13 Imm(1) -> x0 + terminator Return(v13) (exit_acc=v13) + block 4 start_pc=0 + v14 Imm(8) -> x2 + v15 Imm(0) -> x1 + terminator Jmp(b5) (exit_acc=v14) + block 5 start_pc=0 + v16 Phi { incoming=[b4:v14, b6:v20], kind=I64 } -> x2 + v17 Extend { value=v16, kind=I32 } -> x1 + v18 BinopI { op=lt, lhs=v17, rhs_imm=16 } -> x1 + terminator Bz { cond=v18, target=b8, fall=b7 } (exit_acc=v18) + block 6 start_pc=0 + v19 Extend { value=v16, kind=I32 } -> x1 + v20 BinopI { op=add, lhs=v19, rhs_imm=1 } -> x2 + v21 Imm(0) -> x1 + terminator Jmp(b5) (exit_acc=v20) + block 7 start_pc=0 + v22 ImmData(8) -> x1 + v23 Extend { value=v16, kind=I32 } -> x1 + v24 Binop { op=add, lhs=v1, rhs=v23 } -> x1 + v25 Load { addr=v24, disp=0, kind=I8 } -> x1 + v26 BinopI { op=ne, lhs=v25, rhs_imm=0 } -> x1 + terminator Bz { cond=v26, target=b10, fall=b9 } (exit_acc=v26) + block 8 start_pc=0 + v27 ImmData(32) -> x0 + v28 Load { addr=v27, disp=0, kind=F64 } -> d0 + v29 Imm(4617315517961601024) -> x0 + v30 Binop { op=fne, lhs=v28, rhs=v29 } -> x1 + v31 Imm(0) -> x0 + terminator Bnz { cond=v30, target=b38, fall=b11 } (exit_acc=v30) + block 9 start_pc=0 + v32 Imm(2) -> x0 + terminator Return(v32) (exit_acc=v32) + block 10 start_pc=0 + terminator Jmp(b6) + block 11 start_pc=0 + v33 ImmData(32) -> x0 + v34 BinopI { op=add, lhs=v33, rhs_imm=8 } -> x1 + v35 Load { addr=v33, disp=8, kind=I32 } -> x0 + v36 BinopI { op=ne, lhs=v35, rhs_imm=43 } -> x1 + v37 Imm(0) -> x0 + terminator Jmp(b12) (exit_acc=v36) + block 12 start_pc=0 + v38 Phi { incoming=[b38:v30, b11:v36], kind=I64 } -> x1 + v39 LoadLocal { off=-9, kind=I64 } -> x0 + terminator Bz { cond=v38, target=b14, fall=b13 } (exit_acc=v38) + block 13 start_pc=0 + v40 Imm(3) -> x0 + terminator Return(v40) (exit_acc=v40) + block 14 start_pc=0 + v41 ImmData(48) -> x0 + v42 Load { addr=v41, disp=0, kind=I32 } -> x0 + v43 BinopI { op=ne, lhs=v42, rhs_imm=1 } -> x0 + v44 Imm(1) -> x2 + v45 Imm(0) -> x1 + terminator Bnz { cond=v43, target=b39, fall=b15 } (exit_acc=v43) + block 15 start_pc=0 + v46 ImmData(48) -> x0 + v47 BinopI { op=add, lhs=v46, rhs_imm=4 } -> x1 + v48 Load { addr=v46, disp=4, kind=I32 } -> x0 + v49 BinopI { op=ne, lhs=v48, rhs_imm=2 } -> x0 + v50 BinopI { op=ne, lhs=v49, rhs_imm=0 } -> x2 + v51 Imm(0) -> x0 + terminator Jmp(b16) (exit_acc=v50) + block 16 start_pc=0 + v52 Phi { incoming=[b39:v44, b15:v50], kind=I64 } -> x2 + v53 LoadLocal { off=-11, kind=I64 } -> x0 + v54 Imm(0) -> x0 + terminator Bnz { cond=v52, target=b40, fall=b17 } (exit_acc=v52) + block 17 start_pc=0 + v55 ImmData(48) -> x0 + v56 BinopI { op=add, lhs=v55, rhs_imm=8 } -> x1 + v57 Load { addr=v55, disp=8, kind=I32 } -> x0 + v58 BinopI { op=ne, lhs=v57, rhs_imm=9 } -> x2 + v59 Imm(0) -> x0 + terminator Jmp(b18) (exit_acc=v58) + block 18 start_pc=0 + v60 Phi { incoming=[b40:v52, b17:v58], kind=I64 } -> x2 + v61 LoadLocal { off=-10, kind=I64 } -> x0 + terminator Bz { cond=v60, target=b20, fall=b19 } (exit_acc=v60) + block 19 start_pc=0 + v62 Imm(4) -> x0 + terminator Return(v62) (exit_acc=v62) + block 20 start_pc=0 + v63 ImmData(64) -> x0 + v64 Imm(0) -> x1 + v65 Load { addr=v63, disp=0, kind=F64 } -> d0 + v66 Imm(4613937818241073152) -> x0 + v67 Binop { op=fne, lhs=v65, rhs=v66 } -> x1 + v68 Imm(0) -> x0 + terminator Bnz { cond=v67, target=b41, fall=b21 } (exit_acc=v67) + block 21 start_pc=0 + v69 ImmData(64) -> x0 + v70 Imm(0) -> x1 + v71 BinopI { op=add, lhs=v69, rhs_imm=16 } -> x1 + v72 Load { addr=v69, disp=16, kind=I32 } -> x0 + v73 BinopI { op=ne, lhs=v72, rhs_imm=42 } -> x1 + v74 Imm(0) -> x0 + terminator Jmp(b22) (exit_acc=v73) + block 22 start_pc=0 + v75 Phi { incoming=[b41:v67, b21:v73], kind=I64 } -> x1 + v76 LoadLocal { off=-12, kind=I64 } -> x0 + terminator Bz { cond=v75, target=b24, fall=b23 } (exit_acc=v75) + block 23 start_pc=0 + v77 Imm(5) -> x0 + terminator Return(v77) (exit_acc=v77) + block 24 start_pc=0 + v78 ImmData(64) -> x0 + v79 Imm(24) -> x1 + v80 BinopI { op=add, lhs=v78, rhs_imm=24 } -> x0 + v81 Load { addr=v80, disp=0, kind=F64 } -> d0 + v82 Imm(4616189618054758400) -> x0 + v83 Binop { op=fne, lhs=v81, rhs=v82 } -> x1 + v84 Imm(0) -> x0 + terminator Bnz { cond=v83, target=b42, fall=b25 } (exit_acc=v83) + block 25 start_pc=0 + v85 ImmData(64) -> x0 + v86 Imm(24) -> x1 + v87 BinopI { op=add, lhs=v85, rhs_imm=24 } -> x1 + v88 BinopI { op=add, lhs=v85, rhs_imm=40 } -> x1 + v89 Load { addr=v85, disp=40, kind=I32 } -> x0 + v90 BinopI { op=ne, lhs=v89, rhs_imm=43 } -> x1 + v91 Imm(0) -> x0 + terminator Jmp(b26) (exit_acc=v90) + block 26 start_pc=0 + v92 Phi { incoming=[b42:v83, b25:v90], kind=I64 } -> x1 + v93 LoadLocal { off=-13, kind=I64 } -> x0 + terminator Bz { cond=v92, target=b28, fall=b27 } (exit_acc=v92) + block 27 start_pc=0 + v94 Imm(6) -> x0 + terminator Return(v94) (exit_acc=v94) + block 28 start_pc=0 + v95 LocalAddr(-4) -> x0 + v96 ImmData(112) -> x1 + v97 Mcpy { dst=v95, src=v96, size=24 } -> x0 + v98 LocalAddr(-4) -> x0 + v99 Load { addr=v98, disp=0, kind=F64 } -> d0 + v100 Imm(4613937818241073152) -> x0 + v101 Binop { op=fne, lhs=v99, rhs=v100 } -> x1 + v102 Imm(0) -> x0 + terminator Bnz { cond=v101, target=b43, fall=b29 } (exit_acc=v101) + block 29 start_pc=0 + v103 LocalAddr(-4) -> x0 + v104 BinopI { op=add, lhs=v103, rhs_imm=16 } -> x1 + v105 Load { addr=v103, disp=16, kind=I32 } -> x0 + v106 BinopI { op=ne, lhs=v105, rhs_imm=42 } -> x1 + v107 Imm(0) -> x0 + terminator Jmp(b30) (exit_acc=v106) + block 30 start_pc=0 + v108 Phi { incoming=[b43:v101, b29:v106], kind=I64 } -> x1 + v109 LoadLocal { off=-14, kind=I64 } -> x0 + terminator Bz { cond=v108, target=b32, fall=b31 } (exit_acc=v108) + block 31 start_pc=0 + v110 Imm(7) -> x0 + terminator Return(v110) (exit_acc=v110) + block 32 start_pc=0 + v111 LocalAddr(-7) -> x0 + v112 ImmData(136) -> x1 + v113 Mcpy { dst=v111, src=v112, size=24 } -> x0 + v114 LocalAddr(-7) -> x0 + v115 Load { addr=v114, disp=0, kind=F64 } -> d0 + v116 Imm(4618441417868443648) -> x0 + v117 Binop { op=fne, lhs=v115, rhs=v116 } -> x1 + v118 Imm(0) -> x0 + terminator Bnz { cond=v117, target=b44, fall=b33 } (exit_acc=v117) + block 33 start_pc=0 + v119 LocalAddr(-7) -> x0 + v120 BinopI { op=add, lhs=v119, rhs_imm=16 } -> x1 + v121 Load { addr=v119, disp=16, kind=I32 } -> x0 + v122 BinopI { op=ne, lhs=v121, rhs_imm=44 } -> x1 + v123 Imm(0) -> x0 + terminator Jmp(b34) (exit_acc=v122) + block 34 start_pc=0 + v124 Phi { incoming=[b44:v117, b33:v122], kind=I64 } -> x1 + v125 LoadLocal { off=-15, kind=I64 } -> x0 + terminator Bz { cond=v124, target=b36, fall=b35 } (exit_acc=v124) + block 35 start_pc=0 + v126 Imm(8) -> x0 + terminator Return(v126) (exit_acc=v126) + block 36 start_pc=0 + v127 Imm(0) -> x0 + terminator Return(v127) (exit_acc=v127) + block 37 start_pc=0 + terminator Jmp(b2) + block 38 start_pc=0 + terminator Jmp(b12) + block 39 start_pc=0 + terminator Jmp(b16) + block 40 start_pc=0 + terminator Jmp(b18) + block 41 start_pc=0 + terminator Jmp(b22) + block 42 start_pc=0 + terminator Jmp(b26) + block 43 start_pc=0 + terminator Jmp(b30) + block 44 start_pc=0 + terminator Jmp(b34) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) From 10acec96c7db13aec65c8a146994cafe5e9c098e Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 18:53:22 -0700 Subject: [PATCH 12/67] headers: bundle TargetConditionals.h; sqlite3 demo passes its include dir The fatal missing-include diagnostic surfaced two latent gaps: macOS code includes under __APPLE__ (bundle the platform-dispatch macros with macOS values, zeros elsewhere), and the demo's stdin pipeline never could resolve shell.c's quoted sqlite3.h include (pass the demo directory as -I, as any compiler needs for stdin input). Co-Authored-By: Claude Fable 5 --- demos/sqlite3/smoke.py | 4 +++ headers/include/TargetConditionals.h | 44 ++++++++++++++++++++++++++++ src/c5/headers.rs | 4 +++ 3 files changed, 52 insertions(+) create mode 100644 headers/include/TargetConditionals.h diff --git a/demos/sqlite3/smoke.py b/demos/sqlite3/smoke.py index 9d0e49e17..25cc10dcf 100755 --- a/demos/sqlite3/smoke.py +++ b/demos/sqlite3/smoke.py @@ -92,6 +92,10 @@ def build_shell(badc: Path, combined: bytes, out_path: Path, optimize: bool) -> cmd: list[str | os.PathLike[str]] = [str(badc)] if optimize: cmd.append("-O") + # stdin input has no source directory, so shell.c's quoted + # `#include "sqlite3.h"` needs the demo directory on the search + # path (gcc would need the same -I for a stdin pipeline). + cmd += ["-I", str(Path(__file__).resolve().parent)] cmd += ["-include", "msvc_compat.h", "-", "-o", str(out_path)] cmd += [f"-D{d}" for d in BUILD_DEFINES] subprocess.run(cmd, input=combined, check=True) diff --git a/headers/include/TargetConditionals.h b/headers/include/TargetConditionals.h new file mode 100644 index 000000000..d96886b60 --- /dev/null +++ b/headers/include/TargetConditionals.h @@ -0,0 +1,44 @@ +/* Apple platform-dispatch macros. The SDK header classifies the +** compilation target; code gates on TARGET_OS_* after including it +** unconditionally under __APPLE__. badc targets macOS only, so the +** macOS values are fixed; every other platform macro is 0. On +** non-Apple targets everything is 0, matching code that includes +** this header without an __APPLE__ guard. */ +#pragma once + +#ifdef __APPLE__ +#define TARGET_OS_MAC 1 +#define TARGET_OS_OSX 1 +#else +#define TARGET_OS_MAC 0 +#define TARGET_OS_OSX 0 +#endif +#define TARGET_OS_WIN32 0 +#define TARGET_OS_WINDOWS 0 +#define TARGET_OS_UNIX 0 +#define TARGET_OS_LINUX 0 +#define TARGET_OS_IPHONE 0 +#define TARGET_OS_IOS 0 +#define TARGET_OS_WATCH 0 +#define TARGET_OS_TV 0 +#define TARGET_OS_VISION 0 +#define TARGET_OS_SIMULATOR 0 +#define TARGET_OS_EMBEDDED 0 +#define TARGET_OS_MACCATALYST 0 +#define TARGET_OS_DRIVERKIT 0 + +#ifdef __aarch64__ +#define TARGET_CPU_ARM64 1 +#define TARGET_CPU_X86_64 0 +#else +#define TARGET_CPU_ARM64 0 +#define TARGET_CPU_X86_64 1 +#endif +#define TARGET_CPU_ARM 0 +#define TARGET_CPU_X86 0 +#define TARGET_CPU_PPC 0 +#define TARGET_CPU_PPC64 0 + +#define TARGET_RT_LITTLE_ENDIAN 1 +#define TARGET_RT_BIG_ENDIAN 0 +#define TARGET_RT_64_BIT 1 diff --git a/src/c5/headers.rs b/src/c5/headers.rs index c9067dd88..5522a65d0 100644 --- a/src/c5/headers.rs +++ b/src/c5/headers.rs @@ -264,6 +264,10 @@ pub(super) const EMBEDDED_HEADERS: &[(&str, &str)] = &[ include_str!("../../headers/include/semaphore.h"), ), ("dlfcn.h", include_str!("../../headers/include/dlfcn.h")), + ( + "TargetConditionals.h", + include_str!("../../headers/include/TargetConditionals.h"), + ), ("windows.h", include_str!("../../headers/include/windows.h")), ( "wincrypt.h", From e67269e68d0261a9fa39a0e079a3050dbabffc19 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:00:35 -0700 Subject: [PATCH 13/67] headers: bundle fenv.h and the MSVC io.h surface The fatal missing-include diagnostic surfaced two more corpus gaps: C99 7.6 fenv (rounding-mode encodings are per-arch on Linux/macOS, UCRT abstract values on Windows; legacy msvcrt predates C99 fenv so the bindings target ucrtbase) and the underscored fd-level io.h Windows sources include directly. fegetenv and the environment object are TODO. Co-Authored-By: Claude Fable 5 --- headers/include/fenv.h | 72 ++++++++++++++++++++++++++++++++++++++++++ headers/include/io.h | 43 +++++++++++++++++++++++++ src/c5/headers.rs | 2 ++ 3 files changed, 117 insertions(+) create mode 100644 headers/include/fenv.h create mode 100644 headers/include/io.h diff --git a/headers/include/fenv.h b/headers/include/fenv.h new file mode 100644 index 000000000..5ca418f5a --- /dev/null +++ b/headers/include/fenv.h @@ -0,0 +1,72 @@ +/* C99 7.6 floating-point environment: the rounding-mode and +** exception-flag surface. Macro values must match the CRT that +** implements the functions: hardware encodings on Linux/macOS +** (x87/SSE control word on x86_64, FPCR on aarch64), the UCRT's +** abstract values on Windows. fegetenv/feholdexcept and the +** environment object are TODO. */ +#pragma once + +#ifdef _WIN32 +#define FE_TONEAREST 0x000 +#define FE_DOWNWARD 0x100 +#define FE_UPWARD 0x200 +#define FE_TOWARDZERO 0x300 +#define FE_INEXACT 0x01 +#define FE_UNDERFLOW 0x02 +#define FE_OVERFLOW 0x04 +#define FE_DIVBYZERO 0x08 +#define FE_INVALID 0x10 +#define FE_ALL_EXCEPT 0x1f +#elif defined(__aarch64__) +#define FE_TONEAREST 0x000000 +#define FE_UPWARD 0x400000 +#define FE_DOWNWARD 0x800000 +#define FE_TOWARDZERO 0xc00000 +#define FE_INVALID 0x01 +#define FE_DIVBYZERO 0x02 +#define FE_OVERFLOW 0x04 +#define FE_UNDERFLOW 0x08 +#define FE_INEXACT 0x10 +#define FE_ALL_EXCEPT 0x1f +#else +#define FE_TONEAREST 0x000 +#define FE_DOWNWARD 0x400 +#define FE_UPWARD 0x800 +#define FE_TOWARDZERO 0xc00 +#define FE_INVALID 0x01 +#define FE_DIVBYZERO 0x04 +#define FE_OVERFLOW 0x08 +#define FE_UNDERFLOW 0x10 +#define FE_INEXACT 0x20 +#define FE_ALL_EXCEPT 0x3d +#endif + +#ifdef __APPLE__ +#pragma dylib(libc, "/usr/lib/libSystem.B.dylib") +#pragma binding(libc::fegetround, "_fegetround") +#pragma binding(libc::fesetround, "_fesetround") +#pragma binding(libc::feclearexcept, "_feclearexcept") +#pragma binding(libc::fetestexcept, "_fetestexcept") +#pragma binding(libc::feraiseexcept, "_feraiseexcept") +#elif defined(__linux__) +#pragma dylib(libm, "libm.so.6") +#pragma binding(libm::fegetround, "fegetround") +#pragma binding(libm::fesetround, "fesetround") +#pragma binding(libm::feclearexcept, "feclearexcept") +#pragma binding(libm::fetestexcept, "fetestexcept") +#pragma binding(libm::feraiseexcept, "feraiseexcept") +#elif defined(_WIN32) +/* Legacy msvcrt.dll predates C99 fenv; the UCRT exports it. */ +#pragma dylib(ucrtbase, "ucrtbase.dll") +#pragma binding(ucrtbase::fegetround, "fegetround") +#pragma binding(ucrtbase::fesetround, "fesetround") +#pragma binding(ucrtbase::feclearexcept, "feclearexcept") +#pragma binding(ucrtbase::fetestexcept, "fetestexcept") +#pragma binding(ucrtbase::feraiseexcept, "feraiseexcept") +#endif + +int fegetround(void); +int fesetround(int round); +int feclearexcept(int excepts); +int fetestexcept(int excepts); +int feraiseexcept(int excepts); diff --git a/headers/include/io.h b/headers/include/io.h new file mode 100644 index 000000000..d60e7c1d9 --- /dev/null +++ b/headers/include/io.h @@ -0,0 +1,43 @@ +/* MSVC low-level I/O (). Underscored POSIX-shaped calls over +** msvcrt. The C99-visible stream API lives in ; this header +** carries the fd-level surface Windows sources reach for directly. */ +#pragma once + +#ifdef _WIN32 + +#pragma dylib(msvcrt, "msvcrt.dll") +#pragma binding(msvcrt::_open, "_open") +#pragma binding(msvcrt::_close, "_close") +#pragma binding(msvcrt::_read, "_read") +#pragma binding(msvcrt::_write, "_write") +#pragma binding(msvcrt::_lseek, "_lseek") +#pragma binding(msvcrt::_lseeki64, "_lseeki64") +#pragma binding(msvcrt::_unlink, "_unlink") +#pragma binding(msvcrt::_chmod, "_chmod") +#pragma binding(msvcrt::_dup, "_dup") +#pragma binding(msvcrt::_dup2, "_dup2") +#pragma binding(msvcrt::_fileno, "_fileno") +#pragma binding(msvcrt::_isatty, "_isatty") +#pragma binding(msvcrt::_setmode, "_setmode") +#pragma binding(msvcrt::_access, "_access") +#pragma binding(msvcrt::_commit, "_commit") + +int _open(char *path, int oflag, int pmode); +int _close(int fd); +int _read(int fd, void *buf, unsigned int count); +int _write(int fd, void *buf, unsigned int count); +long _lseek(int fd, long offset, int origin); +long long _lseeki64(int fd, long long offset, int origin); +int _unlink(char *path); +int _chmod(char *path, int mode); +int _dup(int fd); +int _dup2(int fd1, int fd2); +int _isatty(int fd); +int _setmode(int fd, int mode); +int _access(char *path, int mode); +int _commit(int fd); + +#define _S_IREAD 0400 +#define _S_IWRITE 0200 + +#endif diff --git a/src/c5/headers.rs b/src/c5/headers.rs index 5522a65d0..02e335728 100644 --- a/src/c5/headers.rs +++ b/src/c5/headers.rs @@ -264,6 +264,8 @@ pub(super) const EMBEDDED_HEADERS: &[(&str, &str)] = &[ include_str!("../../headers/include/semaphore.h"), ), ("dlfcn.h", include_str!("../../headers/include/dlfcn.h")), + ("fenv.h", include_str!("../../headers/include/fenv.h")), + ("io.h", include_str!("../../headers/include/io.h")), ( "TargetConditionals.h", include_str!("../../headers/include/TargetConditionals.h"), From c3d41ae1542ef3fbed7a0a4b64378f94ec84394d Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:11:00 -0700 Subject: [PATCH 14/67] headers: bundle direct.h and intrin.h; case-insensitive Windows include lookup Windows sources reach and under _MSC_VER, and spell bundled headers in any case (): resolve embedded headers case-insensitively for Windows targets, matching the platform's filesystems. intrin.h binds the msvcrt byte-swap exports and defines the compiler-reordering fence as an opaque no-op call; the remaining intrinsics stay undeclared so their use fails loudly. Co-Authored-By: Claude Fable 5 --- headers/include/direct.h | 18 ++++++++++++++++++ headers/include/intrin.h | 24 ++++++++++++++++++++++++ src/c5/headers.rs | 2 ++ src/c5/preprocessor.rs | 18 +++++++++++++++++- 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 headers/include/direct.h create mode 100644 headers/include/intrin.h diff --git a/headers/include/direct.h b/headers/include/direct.h new file mode 100644 index 000000000..0310a74f3 --- /dev/null +++ b/headers/include/direct.h @@ -0,0 +1,18 @@ +/* MSVC directory-management (): underscored POSIX-shaped +** calls over msvcrt. */ +#pragma once + +#ifdef _WIN32 + +#pragma dylib(msvcrt, "msvcrt.dll") +#pragma binding(msvcrt::_mkdir, "_mkdir") +#pragma binding(msvcrt::_rmdir, "_rmdir") +#pragma binding(msvcrt::_chdir, "_chdir") +#pragma binding(msvcrt::_getcwd, "_getcwd") + +int _mkdir(char *path); +int _rmdir(char *path); +int _chdir(char *path); +char *_getcwd(char *buf, int size); + +#endif diff --git a/headers/include/intrin.h b/headers/include/intrin.h new file mode 100644 index 000000000..617d2277e --- /dev/null +++ b/headers/include/intrin.h @@ -0,0 +1,24 @@ +/* MSVC compiler intrinsics (). Only the byte-swap family +** has a CRT export to bind; the remaining intrinsics are +** compiler-generated and stay undeclared so their use fails loudly +** at compile time rather than miscompiling. TODO: lower the +** barrier / bit-scan / mul128 families in the compiler. */ +#pragma once + +#ifdef _WIN32 + +#pragma dylib(msvcrt, "msvcrt.dll") +#pragma binding(msvcrt::_byteswap_ushort, "_byteswap_ushort") +#pragma binding(msvcrt::_byteswap_ulong, "_byteswap_ulong") +#pragma binding(msvcrt::_byteswap_uint64, "_byteswap_uint64") + +unsigned short _byteswap_ushort(unsigned short value); +unsigned long _byteswap_ulong(unsigned long value); +unsigned long long _byteswap_uint64(unsigned long long value); + +/* Compiler-reordering fence. c5 does not reorder memory accesses +** across calls, so an opaque no-op call carries the required +** ordering. TODO: a fence IR op once pass-level reordering exists. */ +static void _ReadWriteBarrier(void) {} + +#endif diff --git a/src/c5/headers.rs b/src/c5/headers.rs index 02e335728..8d3b19bf0 100644 --- a/src/c5/headers.rs +++ b/src/c5/headers.rs @@ -266,6 +266,8 @@ pub(super) const EMBEDDED_HEADERS: &[(&str, &str)] = &[ ("dlfcn.h", include_str!("../../headers/include/dlfcn.h")), ("fenv.h", include_str!("../../headers/include/fenv.h")), ("io.h", include_str!("../../headers/include/io.h")), + ("direct.h", include_str!("../../headers/include/direct.h")), + ("intrin.h", include_str!("../../headers/include/intrin.h")), ( "TargetConditionals.h", include_str!("../../headers/include/TargetConditionals.h"), diff --git a/src/c5/preprocessor.rs b/src/c5/preprocessor.rs index 26e36bb13..16c4c9095 100644 --- a/src/c5/preprocessor.rs +++ b/src/c5/preprocessor.rs @@ -177,6 +177,9 @@ pub(crate) struct Preprocessor { // string-prefix compares were the leftover frontend hot spot // after the symbol-table fix went in. macros: HashMap, + /// Compilation target; Windows include resolution is + /// case-insensitive, matching its filesystems. + target: Target, fn_macros: HashMap, /// One entry per `#pragma dylib(name, "path")`, in the order /// declared. Each entry collects the bindings whose @@ -558,6 +561,7 @@ impl Preprocessor { } Self { macros, + target, fn_macros, dylibs: Vec::new(), exports: Vec::new(), @@ -2800,7 +2804,19 @@ impl Preprocessor { } } let _ = source_dir; - embedded_header(name).map(|s| (s.to_string(), name.to_string())) + if let Some(body) = embedded_header(name) { + return Some((body.to_string(), name.to_string())); + } + // Windows resolves includes case-insensitively (its filesystems + // are); match the embedded registry the same way there. + if matches!(self.target, Target::WindowsX64 | Target::WindowsAarch64) { + let lower = name.to_ascii_lowercase(); + return super::headers::embedded_headers() + .iter() + .find(|(n, _)| n.eq_ignore_ascii_case(&lower)) + .map(|(n, body)| (body.to_string(), n.to_string())); + } + None } /// Resolve `name` for `#include_next`: skip search-path entries up to From 6976cf92aef6b37365942b605a420087dd395e9f Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:20:15 -0700 Subject: [PATCH 15/67] demos/raylib: complete the shim tree for includes the fatal diagnostic surfaced X11/Xresource.h routes to Xutil.h, which already carries the Xrm types and prototypes; minwinbase.h / minwindef.h / sdkddkver.h follow the existing winuser.h forward-to-windows.h convention. All were silently empty includes before missing headers became fatal. Co-Authored-By: Claude Fable 5 --- demos/raylib/include/X11/Xresource.h | 10 ++++++++++ demos/raylib/include/minwinbase.h | 6 ++++++ demos/raylib/include/minwindef.h | 6 ++++++ demos/raylib/include/sdkddkver.h | 6 ++++++ 4 files changed, 28 insertions(+) create mode 100644 demos/raylib/include/X11/Xresource.h create mode 100644 demos/raylib/include/minwinbase.h create mode 100644 demos/raylib/include/minwindef.h create mode 100644 demos/raylib/include/sdkddkver.h diff --git a/demos/raylib/include/X11/Xresource.h b/demos/raylib/include/X11/Xresource.h new file mode 100644 index 000000000..498a9f667 --- /dev/null +++ b/demos/raylib/include/X11/Xresource.h @@ -0,0 +1,10 @@ +/* Xrm (resource manager) surface for the RGFW desktop backend. This + * shim tree keeps the Xrm types and prototypes in Xutil.h; the system + * header split is not mirrored here. */ +#ifndef _X11_XRESOURCE_H_ +#define _X11_XRESOURCE_H_ + +#include +#include + +#endif diff --git a/demos/raylib/include/minwinbase.h b/demos/raylib/include/minwinbase.h new file mode 100644 index 000000000..1e19cdc35 --- /dev/null +++ b/demos/raylib/include/minwinbase.h @@ -0,0 +1,6 @@ +/* Demo-local . The Windows SDK sub-header split is not + * mirrored here; the bundled carries the surface. */ +#ifndef RGFW_DEMO_MINWINBASE_H +#define RGFW_DEMO_MINWINBASE_H +#include +#endif diff --git a/demos/raylib/include/minwindef.h b/demos/raylib/include/minwindef.h new file mode 100644 index 000000000..3f7a5dbec --- /dev/null +++ b/demos/raylib/include/minwindef.h @@ -0,0 +1,6 @@ +/* Demo-local . The Windows SDK sub-header split is not + * mirrored here; the bundled carries the surface. */ +#ifndef RGFW_DEMO_MINWINDEF_H +#define RGFW_DEMO_MINWINDEF_H +#include +#endif diff --git a/demos/raylib/include/sdkddkver.h b/demos/raylib/include/sdkddkver.h new file mode 100644 index 000000000..aa685d684 --- /dev/null +++ b/demos/raylib/include/sdkddkver.h @@ -0,0 +1,6 @@ +/* Demo-local . The Windows SDK sub-header split is not + * mirrored here; the bundled carries the surface. */ +#ifndef RGFW_DEMO_SDKDDKVER_H +#define RGFW_DEMO_SDKDDKVER_H +#include +#endif From 59cfd5cab916477bea8c9f8734dcc6037fd9faf9 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:29:26 -0700 Subject: [PATCH 16/67] headers: bundle bcrypt.h; demos/curl: _mingw.h shim curl's Windows RNG includes (the bound CNG surface already lives in the bundled ) and defines __MINGW32__, whose internal <_mingw.h> glue the demo resolves with an empty-guard shim. All demo translation units now cross-compile for windows-x64 with no missing includes. Co-Authored-By: Claude Fable 5 --- .gitignore | 1 + demos/curl/_mingw.h | 6 ++++++ headers/include/bcrypt.h | 6 ++++++ src/c5/headers.rs | 1 + 4 files changed, 14 insertions(+) create mode 100644 demos/curl/_mingw.h create mode 100644 headers/include/bcrypt.h diff --git a/.gitignore b/.gitignore index 4481f7683..222e7fa1e 100644 --- a/.gitignore +++ b/.gitignore @@ -88,6 +88,7 @@ demos/curl/* !demos/curl/curl_client.c !demos/curl/curl_config.h !demos/curl/curl_syslink.h +!demos/curl/_mingw.h # stb -- a collection of single-file public-domain headers. # `setup.py` pulls the upstream archive from the vendor-deps # release and drops a curated set of headers into `demos/stb/`; diff --git a/demos/curl/_mingw.h b/demos/curl/_mingw.h new file mode 100644 index 000000000..6074c9db8 --- /dev/null +++ b/demos/curl/_mingw.h @@ -0,0 +1,6 @@ +/* Demo-local <_mingw.h>. MinGW's internal glue header; the demo + * defines __MINGW32__ only to select curl's MinGW code paths, and the + * bundled headers already carry the referenced surface. */ +#ifndef CURL_DEMO_MINGW_H +#define CURL_DEMO_MINGW_H +#endif diff --git a/headers/include/bcrypt.h b/headers/include/bcrypt.h new file mode 100644 index 000000000..d4c2e7b1b --- /dev/null +++ b/headers/include/bcrypt.h @@ -0,0 +1,6 @@ +/* Windows CNG (). The bound surface lives in the bundled +** ; this header resolves the SDK's include split. */ +#pragma once +#ifdef _WIN32 +#include +#endif diff --git a/src/c5/headers.rs b/src/c5/headers.rs index 8d3b19bf0..4e7475eee 100644 --- a/src/c5/headers.rs +++ b/src/c5/headers.rs @@ -268,6 +268,7 @@ pub(super) const EMBEDDED_HEADERS: &[(&str, &str)] = &[ ("io.h", include_str!("../../headers/include/io.h")), ("direct.h", include_str!("../../headers/include/direct.h")), ("intrin.h", include_str!("../../headers/include/intrin.h")), + ("bcrypt.h", include_str!("../../headers/include/bcrypt.h")), ( "TargetConditionals.h", include_str!("../../headers/include/TargetConditionals.h"), From 24958b7197ae0f7599981e3697cdfa6f105b3d93 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:47:41 -0700 Subject: [PATCH 17/67] volatile: carry the qualifier from the parser through the IR to emit The volatile qualifier was parsed and discarded, so every optimization level violated C99 5.1.2.3p2 / 6.7.3p6: an unused volatile read was deleted even at -O0, mem2reg promoted volatile locals (reverting a store made between setjmp and longjmp, 7.13.2.1p3), and store_forward forwarded across volatile accesses. The type tag gains VOLATILE_BIT, orthogonal to UNSIGNED_BIT and stripped by strip_unsigned; the declaration-specifier, declarator, pointer-level, and cast parses set it. Inst::{Load, Store, LoadLocal, StoreLocal} carry a volatile flag the walker sets from the accessed lvalue's tag (locals, globals, TLS, derefs, members, bitfields, initializers, read-modify-writes). Gated consumers: the builder's load-local CSE, is_pure_inst / is_dead_pure (an unused volatile load emits at every level), mem2reg promotion, slot coalescing, store_forward, index_fold, and struct_return_reg. A volatile read-modify-write no longer re-reads the object for its result value; it narrows the stored value in a register. An aggregate copy of a volatile object stays unmarked (TODO on Inst::Mcpy). Regression: volatile_setjmp_longjmp.c, volatile_ptr_alias_loop.c, volatile_unused_read.c on the native and JIT parity lists, plus SSA-level tests in mem2reg, store_forward, and reg_alloc. Co-Authored-By: Claude Fable 5 --- src/c5/ast/mod.rs | 4 +- src/c5/ast/walk.rs | 117 +++++++++------ src/c5/codegen/aarch64/emit.rs | 13 +- src/c5/codegen/passes/dedup_imm.rs | 2 + .../codegen/passes/drop_redundant_extend.rs | 6 + src/c5/codegen/passes/index_fold.rs | 8 + src/c5/codegen/passes/store_forward.rs | 140 ++++++++++++++++-- src/c5/codegen/passes/struct_return_reg.rs | 17 ++- src/c5/codegen/ssa/build.rs | 70 +++++++-- src/c5/codegen/ssa/dump.rs | 43 ++++-- src/c5/codegen/ssa/emit_common.rs | 13 +- src/c5/codegen/ssa/mem2reg.rs | 84 ++++++++++- src/c5/codegen/ssa/reg_alloc.rs | 55 ++++++- src/c5/codegen/ssa/slot_coalesce.rs | 10 ++ src/c5/codegen/x86_64/emit.rs | 13 +- src/c5/compiler/aggregate.rs | 4 +- src/c5/compiler/decl_base.rs | 46 ++++-- src/c5/compiler/declarator.rs | 9 +- src/c5/compiler/diag.rs | 7 +- src/c5/compiler/expr.rs | 1 + src/c5/compiler/function.rs | 1 + src/c5/compiler/global_init.rs | 6 +- src/c5/compiler/initializer.rs | 24 +-- src/c5/compiler/locals.rs | 13 +- src/c5/compiler/run_compile.rs | 19 ++- src/c5/compiler/type_layout.rs | 14 +- src/c5/compiler/types.rs | 32 +++- src/c5/ir.rs | 25 +++- src/c5/object/dwarf_reloc.rs | 4 +- src/c5/object/elf_reloc.rs | 5 +- src/c5/tests/jit.rs | 5 + src/c5/tests/native.rs | 6 + src/c5/vm/ssa.rs | 11 +- tests/fixtures/c/volatile_ptr_alias_loop.c | 16 ++ tests/fixtures/c/volatile_setjmp_longjmp.c | 16 ++ tests/fixtures/c/volatile_unused_read.c | 12 ++ 36 files changed, 696 insertions(+), 175 deletions(-) create mode 100644 tests/fixtures/c/volatile_ptr_alias_loop.c create mode 100644 tests/fixtures/c/volatile_setjmp_longjmp.c create mode 100644 tests/fixtures/c/volatile_unused_read.c diff --git a/src/c5/ast/mod.rs b/src/c5/ast/mod.rs index c645063a1..82275bb7e 100644 --- a/src/c5/ast/mod.rs +++ b/src/c5/ast/mod.rs @@ -839,10 +839,10 @@ impl Ast { /// tags carried outside the AST (e.g. `FinishedFunction::param_tys`, /// `Symbol::type_`). pub(crate) fn remap_struct_ty(ty: i64, remap: &[usize]) -> i64 { - use crate::c5::compiler::types::UNSIGNED_BIT; use crate::c5::compiler::types::{STRUCT_BASE, STRUCT_STRIDE}; + use crate::c5::compiler::types::{UNSIGNED_BIT, VOLATILE_BIT}; let unsigned = ty & UNSIGNED_BIT; - let stripped = ty & !UNSIGNED_BIT; + let stripped = ty & !(UNSIGNED_BIT | VOLATILE_BIT); if stripped < STRUCT_BASE { return ty; } diff --git a/src/c5/ast/walk.rs b/src/c5/ast/walk.rs index b306770ea..11d23ae83 100644 --- a/src/c5/ast/walk.rs +++ b/src/c5/ast/walk.rs @@ -12,8 +12,8 @@ use alloc::string::String; use super::super::codegen::Target; use super::super::compiler::types::{ - STRUCT_BASE, STRUCT_STRIDE, UNSIGNED_BIT, is_pointer_ty, is_struct_ty, load_kind, - struct_ptr_depth, + STRUCT_BASE, STRUCT_STRIDE, UNSIGNED_BIT, VOLATILE_BIT, is_pointer_ty, is_struct_ty, + is_volatile_ty, load_kind, struct_ptr_depth, }; use super::super::ir::{AtomicRmwOp, BinOp, FunctionSsa, LoadKind, StoreKind}; use super::super::symbol::Symbol; @@ -709,7 +709,7 @@ impl<'a> Walker<'a> { /// struct id is out of range (defensive -- the parser /// shouldn't emit such a type). fn struct_size(&self, ty: i64) -> i64 { - let stripped = ty & !UNSIGNED_BIT; + let stripped = ty & !(UNSIGNED_BIT | VOLATILE_BIT); if stripped < STRUCT_BASE { return 0; } @@ -720,6 +720,12 @@ impl<'a> Walker<'a> { 0 } } + /// True when the expression's type tag carries the volatile + /// qualifier (C99 6.7.3); `false` for node shapes without a type. + fn expr_is_volatile(&self, id: ExprId) -> bool { + expr_ty(self.ast.expr(id)).is_some_and(is_volatile_ty) + } + /// Walk a statement. Returns `true` when the statement /// terminates the current block (an unconditional return / /// jmp), letting the caller stop iterating siblings that @@ -771,7 +777,7 @@ impl<'a> Walker<'a> { // the result register at full width. `_Bool` is excluded: its // conversion is a boolean `!= 0` (6.3.1.2), not a width mask, // and the rvalue walk already normalizes it to 0/1. - let stripped = self.scalar_return_ty & !UNSIGNED_BIT; + let stripped = self.scalar_return_ty & !(UNSIGNED_BIT | VOLATILE_BIT); let rs = type_size_bytes(self.scalar_return_ty, self.target); if !is_floating_scalar(self.scalar_return_ty) && !is_pointer_ty(self.scalar_return_ty) @@ -1222,7 +1228,7 @@ impl<'a> Walker<'a> { // A direct `StoreLocal` keeps the slot mem2reg-promotable. // The `F32` s-view store is narrowed by the per-arch emit // when the value is still double. - b.store_local(slot, v, kind); + b.store_local_vol(slot, v, kind, is_volatile_ty(ty)); Ok(()) } super::super::ast::LocalInit::Aggregate { @@ -1265,7 +1271,7 @@ impl<'a> Walker<'a> { continue; } let kind = store_kind_for(elem.ty, self.target); - b.store(addr, v, kind); + b.store_vol(addr, v, kind, is_volatile_ty(elem.ty)); } Ok(()) } @@ -1697,8 +1703,9 @@ impl<'a> Walker<'a> { field_off, bitfield, rhs, - .. + ty, } => { + let vol = is_volatile_ty(*ty) || self.expr_is_volatile(*obj); // C99 6.7.2.1: bitfield write -- load the storage // unit, clear the destination slice, mask + shift // the new value into place, OR the cleared old @@ -1742,7 +1749,7 @@ impl<'a> Walker<'a> { // this read-modify-write, else its store is clobbered. let rhs_v = self.walk_expr_rvalue(b, *rhs)?; let masked = b.binop_imm(BinOp::And, rhs_v, mask); - let old = b.load(addr, load_kind); + let old = b.load_vol(addr, load_kind, vol); let cleared = b.binop_imm(BinOp::And, old, clear_mask); let shifted = if bf.bit_offset > 0 { b.binop_imm(BinOp::Shl, masked, bf.bit_offset as i64) @@ -1750,7 +1757,7 @@ impl<'a> Walker<'a> { masked }; let combined = b.binop(BinOp::Or, cleared, shifted); - b.store(addr, combined, store_kind); + b.store_vol(addr, combined, store_kind, vol); // C99 6.5.16p3: the value of the assignment is the value // stored in the bitfield converted to its declared type -- // the right-aligned masked field value, sign-extended for a @@ -1786,6 +1793,7 @@ impl<'a> Walker<'a> { // promotable. The `F32` s-view is narrowed below before // the store so the assignment yields the f32 value. let kind = store_kind_for(*ty, self.target); + let vol = is_volatile_ty(*ty) || self.expr_is_volatile(*lhs); if let Expr::Ident { class, val, @@ -1803,7 +1811,7 @@ impl<'a> Walker<'a> { if matches!(kind, StoreKind::F32) { value = b.fp_narrow_to_f32(value); } - b.store_local(slot, value, kind); + b.store_local_vol(slot, value, kind, vol); // C99 6.5.16p3: the assignment expression's value has // the converted type of the left operand. The store // truncated the stored bytes; the value carried @@ -1823,7 +1831,7 @@ impl<'a> Walker<'a> { if matches!(kind, StoreKind::F32) { value = b.fp_narrow_to_f32(value); } - b.store(addr, value, kind); + b.store_vol(addr, value, kind, vol); // C99 6.5.16p3: the assignment expression's value has the // converted type of the left operand. The store truncated // the stored bytes; the value carried forward to an @@ -2756,7 +2764,8 @@ impl<'a> Walker<'a> { 4 => super::super::ir::LoadKind::U32, _ => super::super::ir::LoadKind::I64, }; - let mut v = b.load(addr, unit_kind); + let vol = is_volatile_ty(*ty) || self.expr_is_volatile(*obj); + let mut v = b.load_vol(addr, unit_kind, vol); if bf.bit_offset > 0 { v = b.binop_imm(BinOp::Shr, v, bf.bit_offset as i64); } @@ -2788,7 +2797,8 @@ impl<'a> Walker<'a> { return Ok(addr); } let kind = load_kind_for(*ty, self.target); - Ok(b.load(addr, kind)) + let vol = is_volatile_ty(*ty) || self.expr_is_volatile(*obj); + Ok(b.load_vol(addr, kind, vol)) } Expr::Index { array, idx, ty } => { let arr = self.walk_expr_rvalue(b, *array)?; @@ -2816,7 +2826,7 @@ impl<'a> Walker<'a> { return Ok(addr); } let kind = load_kind_for(*ty, self.target); - Ok(b.load(addr, kind)) + Ok(b.load_vol(addr, kind, is_volatile_ty(*ty))) } Expr::Cast { child, to_ty } => { let v = self.walk_expr_rvalue(b, *child)?; @@ -2878,7 +2888,7 @@ impl<'a> Walker<'a> { // where the signed convert yields a negative result, // so it takes the unsigned converter. Narrower // unsigned types fit the signed range zero-extended. - let stripped = src_ty & !UNSIGNED_BIT; + let stripped = src_ty & !(UNSIGNED_BIT | VOLATILE_BIT); let unsigned_64 = (src_ty & UNSIGNED_BIT) != 0 && (stripped == Ty::Long as i64 || stripped == Ty::LongLong as i64); let kind = if unsigned_64 { @@ -2900,7 +2910,7 @@ impl<'a> Walker<'a> { // takes the unsigned converter. Narrower unsigned // targets fit the signed range. let d = b.fp_widen_to_f64(v); - let stripped_to = *to_ty & !UNSIGNED_BIT; + let stripped_to = *to_ty & !(UNSIGNED_BIT | VOLATILE_BIT); let target_unsigned_64 = (*to_ty & UNSIGNED_BIT) != 0 && (stripped_to == Ty::Long as i64 || stripped_to == Ty::LongLong as i64); let kind = if target_unsigned_64 { @@ -2937,8 +2947,9 @@ impl<'a> Walker<'a> { // (post-op) value per the same clause. let load_kind = load_kind_for(*ty, self.target); let store_kind = store_kind_for(*ty, self.target); + let vol = is_volatile_ty(*ty) || self.expr_is_volatile(*lhs); let place = self.rmw_place(b, *lhs, store_kind)?; - let old = place.load(b, load_kind); + let old = place.load(b, load_kind, vol); // Constant-rhs short-circuit (mirror of the // `Expr::Binary` path): an integer-literal rhs // routes through `binop_imm` so the per-arch @@ -3030,26 +3041,36 @@ impl<'a> Walker<'a> { b.binop(*op, lv, rhs_val) } }; - place.store(b, new_val, store_kind); + place.store(b, new_val, store_kind, vol); // C99 6.5.16.2p3: the value of `E1 op= E2` is the // post-update value of E1 in E1's type. For a // sub-64-bit lvalue the 64-bit binop result is not // narrowed; reload through `load_kind` so the // returned ValueId reflects what was actually // stored (with the kind's sign / zero extension). + // A volatile lvalue is accessed exactly once per read + // and once per write (C99 6.7.3p6); its result is the + // stored value narrowed in a register, never a re-read. Ok(if matches!(load_kind, LoadKind::I64) { new_val + } else if vol { + if is_floating_scalar(*ty) { + new_val + } else { + self.narrow_int_to_ty(b, new_val, Ty::LongLong as i64, *ty) + } } else { - place.load(b, load_kind) + place.load(b, load_kind, false) }) } Expr::PreInc { lvalue, by, ty } => { let kind = load_kind_for(*ty, self.target); let store_kind = store_kind_for(*ty, self.target); + let vol = is_volatile_ty(*ty) || self.expr_is_volatile(*lvalue); let place = self.rmw_place(b, *lvalue, store_kind)?; - let old = place.load(b, kind); + let old = place.load(b, kind, vol); let stepped = self.increment_value(b, old, *by, *ty); - place.store(b, stepped, store_kind); + place.store(b, stepped, store_kind, vol); // C99 6.5.3.1p3 + 6.5.16.2: the value of `++E` is // the post-update value of E in E's type. Reload // through `kind` for sub-64-bit lvalues so a @@ -3057,21 +3078,26 @@ impl<'a> Walker<'a> { // wrapped u8/u16/u32 value rather than the wider // Add result that overflows past the storage width. // A floating result is already at storage width. + // A volatile lvalue is not re-read (C99 6.7.3p6); the + // result is the stored value narrowed in a register. Ok( if matches!(kind, LoadKind::I64) || is_floating_scalar(*ty) { stepped + } else if vol { + self.narrow_int_to_ty(b, stepped, Ty::LongLong as i64, *ty) } else { - place.load(b, kind) + place.load(b, kind, false) }, ) } Expr::PostInc { lvalue, by, ty } => { let kind = load_kind_for(*ty, self.target); let store_kind = store_kind_for(*ty, self.target); + let vol = is_volatile_ty(*ty) || self.expr_is_volatile(*lvalue); let place = self.rmw_place(b, *lvalue, store_kind)?; - let old = place.load(b, kind); + let old = place.load(b, kind, vol); let stepped = self.increment_value(b, old, *by, *ty); - place.store(b, stepped, store_kind); + place.store(b, stepped, store_kind, vol); // C99 6.5.2.4p3: the expression's value is the // pre-update value (`old`). Ok(old) @@ -3098,7 +3124,7 @@ impl<'a> Walker<'a> { Ok(b.local_addr(slot)) } else { let kind = load_kind_for(ty, self.target); - Ok(b.load_local(slot, kind)) + Ok(b.load_local_vol(slot, kind, is_volatile_ty(ty))) } } Expr::Comma { lhs, rhs, .. } => { @@ -3691,7 +3717,7 @@ impl<'a> Walker<'a> { return Ok(addr); } let kind = load_kind_for(ty, self.target); - Ok(b.load(addr, kind)) + Ok(b.load_vol(addr, kind, is_volatile_ty(ty))) } } } @@ -3843,23 +3869,24 @@ impl<'a> Walker<'a> { }); } } + let vol = is_volatile_ty(ty); if class == Token::Loc as i64 { let kind = load_kind_for(ty, self.target); - Ok(b.load_local(val, kind)) + Ok(b.load_local_vol(val, kind, vol)) } else if let Some(addr) = glo_addr { let addr_v = match addr { GloAddr::Extern => b.imm_data_extern(_sym), GloAddr::Resolved(off) => b.imm_data(off), }; let kind = load_kind_for(ty, self.target); - Ok(b.load(addr_v, kind)) + Ok(b.load_vol(addr_v, kind, vol)) } else if class == Token::Glo as i64 && is_thread_local { let addr = match self.live_tls_addr(_sym, val) { GloAddr::Extern => b.tls_addr_extern(_sym), GloAddr::Resolved(off) => b.tls_addr(off), }; let kind = load_kind_for(ty, self.target); - Ok(b.load(addr, kind)) + Ok(b.load_vol(addr, kind, vol)) } else if class == Token::Fun as i64 { if val == 0 { Ok(b.imm_code_extern(_sym)) @@ -3909,10 +3936,11 @@ impl RmwPlace { &self, b: &mut super::super::codegen::ssa::build::SsaBuilder, kind: LoadKind, + vol: bool, ) -> super::super::ir::ValueId { match *self { - RmwPlace::Slot(off) => b.load_local(off, kind), - RmwPlace::Addr(addr) => b.load(addr, kind), + RmwPlace::Slot(off) => b.load_local_vol(off, kind, vol), + RmwPlace::Addr(addr) => b.load_vol(addr, kind, vol), RmwPlace::Bitfield { addr, bf } => { // C99 6.7.2.1: load the unit, shift the slice to bit 0, // mask, and sign-extend when the field type is signed. @@ -3922,7 +3950,7 @@ impl RmwPlace { 4 => LoadKind::U32, _ => LoadKind::I64, }; - let mut v = b.load(addr, unit_kind); + let mut v = b.load_vol(addr, unit_kind, vol); if bf.bit_offset > 0 { v = b.binop_imm(BinOp::Shr, v, bf.bit_offset as i64); } @@ -3947,13 +3975,14 @@ impl RmwPlace { b: &mut super::super::codegen::ssa::build::SsaBuilder, value: super::super::ir::ValueId, kind: StoreKind, + vol: bool, ) { match *self { RmwPlace::Slot(off) => { - b.store_local(off, value, kind); + b.store_local_vol(off, value, kind, vol); } RmwPlace::Addr(addr) => { - b.store(addr, value, kind); + b.store_vol(addr, value, kind, vol); } RmwPlace::Bitfield { addr, bf } => { // C99 6.7.2.1: load the unit, clear the slice, mask + shift @@ -3970,7 +3999,7 @@ impl RmwPlace { (1i64 << bf.bit_width) - 1 }; let clear_mask: i64 = !(mask << bf.bit_offset); - let old = b.load(addr, load_kind); + let old = b.load_vol(addr, load_kind, vol); let cleared = b.binop_imm(BinOp::And, old, clear_mask); let masked = b.binop_imm(BinOp::And, value, mask); let shifted = if bf.bit_offset > 0 { @@ -3979,7 +4008,7 @@ impl RmwPlace { masked }; let combined = b.binop(BinOp::Or, cleared, shifted); - b.store(addr, combined, store_kind); + b.store_vol(addr, combined, store_kind, vol); } } } @@ -3994,7 +4023,7 @@ fn load_kind_for(ty: i64, target: Target) -> LoadKind { /// Mirror of [`load_kind_for`] for stores. fn store_kind_for(ty: i64, target: Target) -> StoreKind { - let stripped = ty & !UNSIGNED_BIT; + let stripped = ty & !(UNSIGNED_BIT | VOLATILE_BIT); if is_pointer_ty(ty) { return StoreKind::I64; } @@ -4042,7 +4071,7 @@ fn is_comparison_op(op: BinOp) -> bool { /// Test for floating-point scalar types. fn is_floating_scalar(ty: i64) -> bool { - let stripped = ty & !UNSIGNED_BIT; + let stripped = ty & !(UNSIGNED_BIT | VOLATILE_BIT); stripped == Ty::Float as i64 || stripped == Ty::Double as i64 } @@ -4050,14 +4079,14 @@ fn is_floating_scalar(ty: i64) -> bool { /// float` at type `float` (single precision); the walker tags the /// result and feeds the single-precision codegen path. fn is_float_ty(ty: i64) -> bool { - (ty & !UNSIGNED_BIT) == Ty::Float as i64 + (ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Float as i64 } /// True for the scalar `_Bool` type (not a pointer to one). Used by /// the cast lowering to apply the C99 6.3.1.2 conversion (any /// nonzero scalar becomes 1). fn is_bool_scalar(ty: i64) -> bool { - (ty & !UNSIGNED_BIT) == Ty::Bool as i64 + (ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Bool as i64 } /// Sign- or zero-extend a scalar call result to the full 64-bit @@ -4079,7 +4108,7 @@ fn extend_scalar_call_result( target: Target, ) -> super::super::ir::ValueId { use super::super::ir::BinOp; - let stripped = ty & !UNSIGNED_BIT; + let stripped = ty & !(UNSIGNED_BIT | VOLATILE_BIT); let rs = type_size_bytes(ty, target); if is_floating_scalar(ty) || is_pointer_ty(ty) @@ -4258,7 +4287,7 @@ fn expr_ty(e: &Expr) -> Option { /// the walker can't compute (struct types, function types -- the /// walker doesn't currently consume those in cast positions). fn type_size_bytes(ty: i64, target: Target) -> usize { - let stripped = ty & !UNSIGNED_BIT; + let stripped = ty & !(UNSIGNED_BIT | VOLATILE_BIT); if is_pointer_ty(ty) { return 8; } @@ -4285,7 +4314,7 @@ fn type_size_bytes(ty: i64, target: Target) -> usize { /// signed type. Takes only the common type tag and lets the /// walker apply the mask through `BinopI(And, _, mask)`. fn unsigned_narrow_mask(ty: i64) -> i64 { - let stripped = ty & !UNSIGNED_BIT; + let stripped = ty & !(UNSIGNED_BIT | VOLATILE_BIT); let unsigned = (ty & UNSIGNED_BIT) != 0; if !unsigned { return 0; @@ -4495,7 +4524,7 @@ mod tests { .insts .iter() .filter_map(|i| match i { - Inst::LoadLocal { off, kind } => Some((*off, *kind)), + Inst::LoadLocal { off, kind, .. } => Some((*off, *kind)), _ => None, }) .collect(); diff --git a/src/c5/codegen/aarch64/emit.rs b/src/c5/codegen/aarch64/emit.rs index 8a9430a60..561a3bc5d 100644 --- a/src/c5/codegen/aarch64/emit.rs +++ b/src/c5/codegen/aarch64/emit.rs @@ -2022,7 +2022,9 @@ fn emit_inst( // (it needs the local block_offsets table for its PC-relative // fixup), so it never reaches emit_inst. Inst::LocalAddr(off) => emit_local_addr(code, dst, *off, frame), - Inst::Load { addr, disp, kind } => emit_load( + Inst::Load { + addr, disp, kind, .. + } => emit_load( code, dst, *addr, @@ -2038,15 +2040,16 @@ fn emit_inst( disp, value, kind, + .. } => emit_store( code, dst, *addr, *disp, *value, *kind, alloc, frame, scratch, ), - Inst::LoadLocal { off, kind } => { + Inst::LoadLocal { off, kind, .. } => { emit_load_local(code, dst, *off, *kind, alloc.is_f32(v), frame, scratch) } - Inst::StoreLocal { off, value, kind } => { - emit_store_local(code, dst, *off, *value, *kind, alloc, frame, scratch) - } + Inst::StoreLocal { + off, value, kind, .. + } => emit_store_local(code, dst, *off, *value, *kind, alloc, frame, scratch), Inst::LoadIndexed { base, index, diff --git a/src/c5/codegen/passes/dedup_imm.rs b/src/c5/codegen/passes/dedup_imm.rs index a9ecdb8cd..c3edafacf 100644 --- a/src/c5/codegen/passes/dedup_imm.rs +++ b/src/c5/codegen/passes/dedup_imm.rs @@ -273,12 +273,14 @@ mod tests { addr: 0, disp: 0, kind: LoadKind::I64, + volatile: false, }, Inst::ImmData(7), Inst::Load { addr: 2, disp: 0, kind: LoadKind::I64, + volatile: false, }, ], alloc::vec![ diff --git a/src/c5/codegen/passes/drop_redundant_extend.rs b/src/c5/codegen/passes/drop_redundant_extend.rs index 11c052ba6..d50336a44 100644 --- a/src/c5/codegen/passes/drop_redundant_extend.rs +++ b/src/c5/codegen/passes/drop_redundant_extend.rs @@ -432,6 +432,7 @@ mod tests { addr: 0, disp: 0, kind: LoadKind::I32, + volatile: false, }, Inst::Extend { value: 1, @@ -465,6 +466,7 @@ mod tests { addr: 0, disp: 0, kind: LoadKind::I32, + volatile: false, }, Inst::Extend { value: 1, @@ -492,6 +494,7 @@ mod tests { addr: 0, disp: 0, kind: LoadKind::U32, + volatile: false, }, Inst::Extend { value: 1, @@ -536,6 +539,7 @@ mod tests { addr: 0, disp: 0, kind: LoadKind::I32, + volatile: false, }, Inst::Binop { op: BinOp::Add, @@ -551,6 +555,7 @@ mod tests { disp: 0, value: 3, kind: store_kind, + volatile: false, }, ], vec![Block { @@ -594,6 +599,7 @@ mod tests { addr: 0, disp: 0, kind: LoadKind::I32, + volatile: false, }, Inst::Binop { op: BinOp::Mul, diff --git a/src/c5/codegen/passes/index_fold.rs b/src/c5/codegen/passes/index_fold.rs index 2cb30b95e..2904b7d63 100644 --- a/src/c5/codegen/passes/index_fold.rs +++ b/src/c5/codegen/passes/index_fold.rs @@ -133,11 +133,13 @@ fn foldable_scaled_addresses( addr, disp: 0, kind, + volatile: false, } => (*addr, load_width(*kind)), Inst::Store { addr, disp: 0, kind, + volatile: false, .. } => (*addr, store_width(*kind)), _ => continue, @@ -202,11 +204,13 @@ fn foldable_displaced_addresses( addr, disp: 0, kind, + volatile: false, } => (*addr, load_width(*kind)), Inst::Store { addr, disp: 0, kind, + volatile: false, .. } => (*addr, store_width(*kind)), _ => continue, @@ -318,6 +322,7 @@ pub(crate) fn run(funcs: &mut [FunctionSsa]) { addr, disp: 0, kind, + volatile: false, } => { if let Some(width) = load_width(*kind) { if let Some(&(base, index, scale)) = scaled.get(addr) { @@ -338,6 +343,7 @@ pub(crate) fn run(funcs: &mut [FunctionSsa]) { addr: base, disp, kind: *kind, + volatile: false, }, )); } @@ -348,6 +354,7 @@ pub(crate) fn run(funcs: &mut [FunctionSsa]) { disp: 0, value, kind, + volatile: false, } => { if let Some(width) = store_width(*kind) { if let Some(&(base, index, scale)) = scaled.get(addr) { @@ -370,6 +377,7 @@ pub(crate) fn run(funcs: &mut [FunctionSsa]) { disp, value: *value, kind: *kind, + volatile: false, }, )); } diff --git a/src/c5/codegen/passes/store_forward.rs b/src/c5/codegen/passes/store_forward.rs index 159e73d62..05865988f 100644 --- a/src/c5/codegen/passes/store_forward.rs +++ b/src/c5/codegen/passes/store_forward.rs @@ -133,7 +133,17 @@ fn run_one(func: &mut FunctionSsa) { break; } match &func.insts[i] { - Inst::Load { addr, disp, kind } => { + // A volatile load must perform its own memory access + // (C99 5.1.2.3p2 / 6.7.3p6): it neither reuses an + // available value nor seeds one. It reads only, so + // existing entries stay valid. + Inst::Load { volatile: true, .. } => {} + Inst::Load { + addr, + disp, + kind, + volatile: false, + } => { let addr = *addr; let disp = *disp; let kind = *kind; @@ -202,16 +212,21 @@ fn run_one(func: &mut FunctionSsa) { disp, value, kind, + volatile, } => { let addr = *addr; let disp = *disp; let value = *value; let kind = *kind; + let volatile = *volatile; let w = store_width(kind); // Drop every entry not provably disjoint from the // written range. table.retain(|e| e.addr == addr && !overlaps(e.disp, e.width, disp, w)); - if is_int_store(kind) { + // A volatile store invalidates like any store but + // seeds no forward: a later load of the location + // must read memory (C99 6.7.3p6). + if is_int_store(kind) && !volatile { table.push(Entry { addr, disp, @@ -443,12 +458,14 @@ mod tests { addr: 0, disp: 0, value: 1, - kind: StoreKind::I64 + kind: StoreKind::I64, + volatile: false, }, Inst::Load { addr: 0, disp: 0, - kind: LoadKind::I64 + kind: LoadKind::I64, + volatile: false, }, ], Terminator::Return(3), @@ -479,12 +496,14 @@ mod tests { addr: 0, disp: 0, value: 1, - kind: StoreKind::I32 + kind: StoreKind::I32, + volatile: false, }, Inst::Load { addr: 0, disp: 0, - kind: LoadKind::I32 + kind: LoadKind::I32, + volatile: false, }, ], Terminator::Return(3), @@ -522,12 +541,14 @@ mod tests { addr: 0, disp: 0, value: 1, - kind: StoreKind::I8 + kind: StoreKind::I8, + volatile: false, }, Inst::Load { addr: 0, disp: 0, - kind: LoadKind::U8 + kind: LoadKind::U8, + volatile: false, }, ], Terminator::Return(3), @@ -540,7 +561,8 @@ mod tests { Inst::Load { addr: 0, disp: 0, - kind: LoadKind::U8 + kind: LoadKind::U8, + volatile: false, } ), "an unsigned sub-width reload must not forward", @@ -567,7 +589,8 @@ mod tests { addr: 0, disp: 0, value: 1, - kind: StoreKind::I64 + kind: StoreKind::I64, + volatile: false, }, Inst::Mcpy { dst: 0, @@ -577,7 +600,8 @@ mod tests { Inst::Load { addr: 0, disp: 0, - kind: LoadKind::I64 + kind: LoadKind::I64, + volatile: false, }, ], Terminator::Return(4), @@ -591,6 +615,94 @@ mod tests { assert!(matches!(f.insts[4], Inst::Load { .. })); } + /// A volatile store seeds no forwarding entry: the reload after it + /// must read memory (C99 6.7.3p6). + #[test] + fn volatile_store_seeds_no_forward() { + let mut f = fresh( + alloc::vec![ + Inst::ParamRef { + idx: 0, + kind: LoadKind::I64 + }, + Inst::ParamRef { + idx: 1, + kind: LoadKind::I64 + }, + Inst::Store { + addr: 0, + disp: 0, + value: 1, + kind: StoreKind::I64, + volatile: true, + }, + Inst::Load { + addr: 0, + disp: 0, + kind: LoadKind::I64, + volatile: false, + }, + ], + Terminator::Return(3), + 3, + ); + run_one(&mut f); + assert!( + matches!(f.blocks[0].terminator, Terminator::Return(3)), + "a load after a volatile store must not forward", + ); + assert!(matches!(f.insts[3], Inst::Load { .. })); + } + + /// A volatile load neither reuses an available value nor seeds one: + /// each source-level read performs its own access (C99 5.1.2.3p2). + #[test] + fn volatile_load_neither_reuses_nor_seeds() { + let mut f = fresh( + alloc::vec![ + Inst::ParamRef { + idx: 0, + kind: LoadKind::I64 + }, + Inst::ParamRef { + idx: 1, + kind: LoadKind::I64 + }, + Inst::Store { + addr: 0, + disp: 0, + value: 1, + kind: StoreKind::I64, + volatile: false, + }, + Inst::Load { + addr: 0, + disp: 0, + kind: LoadKind::I64, + volatile: true, + }, + Inst::Load { + addr: 0, + disp: 0, + kind: LoadKind::I64, + volatile: true, + }, + Inst::Binop { + op: crate::c5::ir::BinOp::Add, + lhs: 3, + rhs: 4 + }, + ], + Terminator::Return(5), + 5, + ); + run_one(&mut f); + assert!( + matches!(f.insts[5], Inst::Binop { lhs: 3, rhs: 4, .. }), + "volatile loads must not forward from the store or each other", + ); + } + /// Two loads of the same location with no write between: the second /// forwards to the first. #[test] @@ -608,12 +720,14 @@ mod tests { Inst::Load { addr: 0, disp: 0, - kind: LoadKind::I64 + kind: LoadKind::I64, + volatile: false, }, Inst::Load { addr: 0, disp: 0, - kind: LoadKind::I64 + kind: LoadKind::I64, + volatile: false, }, Inst::Binop { op: crate::c5::ir::BinOp::Add, diff --git a/src/c5/codegen/passes/struct_return_reg.rs b/src/c5/codegen/passes/struct_return_reg.rs index 1542c6b56..435f9c6ff 100644 --- a/src/c5/codegen/passes/struct_return_reg.rs +++ b/src/c5/codegen/passes/struct_return_reg.rs @@ -214,12 +214,13 @@ fn promote_once(func: &mut FunctionSsa) -> bool { disp, value, kind, + volatile, } => { if let Some(&s) = la_slot.get(addr) { // A write into a tracked slot. Promotable only as a - // single full-width store at offset 0; any other - // store shape disqualifies the slot. - let full = *disp == 0 && store_width(*kind) == 8; + // single full-width non-volatile store at offset 0; + // any other store shape disqualifies the slot. + let full = *disp == 0 && store_width(*kind) == 8 && !*volatile; let u = slots.entry(s).or_insert_with(SlotUse::empty); if !u.disqualified && u.store_idx == 0 && full { u.store_idx = idx; @@ -234,9 +235,14 @@ fn promote_once(func: &mut FunctionSsa) -> bool { mark_disq(&mut slots, s); } } - Inst::Load { addr, disp, kind } => { + Inst::Load { + addr, + disp, + kind, + volatile, + } => { if let Some(&s) = la_slot.get(addr) { - if *disp == 0 { + if *disp == 0 && !*volatile { slots .entry(s) .or_insert_with(SlotUse::empty) @@ -383,6 +389,7 @@ fn promote_once(func: &mut FunctionSsa) -> bool { disp: 0, value: u.word, kind: u.kind, + volatile: false, }, )); // A reference to the copy's result reads the stored value. diff --git a/src/c5/codegen/ssa/build.rs b/src/c5/codegen/ssa/build.rs index 4b6d5c575..9884bd595 100644 --- a/src/c5/codegen/ssa/build.rs +++ b/src/c5/codegen/ssa/build.rs @@ -540,10 +540,16 @@ impl SsaBuilder { /// 6.3.1.8); tag it f32 so the codegen keeps it in the s-view of an /// FP register without a widening conversion. pub(crate) fn load(&mut self, addr: ValueId, kind: LoadKind) -> ValueId { + self.load_vol(addr, kind, false) + } + + /// [`Self::load`] with an explicit volatile mark (C99 6.7.3p6). + pub(crate) fn load_vol(&mut self, addr: ValueId, kind: LoadKind, volatile: bool) -> ValueId { let v = self.push(Inst::Load { addr, disp: 0, kind, + volatile, }); if matches!(kind, LoadKind::F32) { self.mark_f32(v); @@ -558,12 +564,24 @@ impl SsaBuilder { /// alias a local whose address escaped earlier; drop every /// CSE entry so a later `load_local` re-reads the slot. pub(crate) fn store(&mut self, addr: ValueId, value: ValueId, kind: StoreKind) -> ValueId { + self.store_vol(addr, value, kind, false) + } + + /// [`Self::store`] with an explicit volatile mark (C99 6.7.3p6). + pub(crate) fn store_vol( + &mut self, + addr: ValueId, + value: ValueId, + kind: StoreKind, + volatile: bool, + ) -> ValueId { self.local_cache.clear(); self.push(Inst::Store { addr, disp: 0, value, kind, + volatile, }) } @@ -575,23 +593,39 @@ impl SsaBuilder { /// instructions; the codegen drops one local-slot load per /// match. pub(crate) fn load_local(&mut self, off: i64, kind: LoadKind) -> ValueId { - for entry in &self.local_cache { - if entry.off == off && entry.kind == kind { - return entry.value; + self.load_local_vol(off, kind, false) + } + + /// [`Self::load_local`] with an explicit volatile mark. A volatile + /// load bypasses the CSE cache both ways: it never reuses a cached + /// value and never seeds one, so every source-level read performs + /// a memory access (C99 5.1.2.3p2). + pub(crate) fn load_local_vol(&mut self, off: i64, kind: LoadKind, volatile: bool) -> ValueId { + if !volatile { + for entry in &self.local_cache { + if entry.off == off && entry.kind == kind { + return entry.value; + } } } - let v = self.push(Inst::LoadLocal { off, kind }); + let v = self.push(Inst::LoadLocal { + off, + kind, + volatile, + }); // A `float`-typed local load is single precision (C99 6.3.1.8); // tag it f32 so the codegen keeps it in the s-view of an FP // register without a widening conversion. if matches!(kind, LoadKind::F32) { self.mark_f32(v); } - self.local_cache.push(LocalCacheEntry { - off, - kind, - value: v, - }); + if !volatile { + self.local_cache.push(LocalCacheEntry { + off, + kind, + value: v, + }); + } v } @@ -605,8 +639,24 @@ impl SsaBuilder { /// load would be safe, but special-casing it isn't worth the /// surface area; the next `load_local` simply re-emits. pub(crate) fn store_local(&mut self, off: i64, value: ValueId, kind: StoreKind) -> ValueId { + self.store_local_vol(off, value, kind, false) + } + + /// [`Self::store_local`] with an explicit volatile mark. + pub(crate) fn store_local_vol( + &mut self, + off: i64, + value: ValueId, + kind: StoreKind, + volatile: bool, + ) -> ValueId { self.local_cache.retain(|e| e.off != off); - self.push(Inst::StoreLocal { off, value, kind }) + self.push(Inst::StoreLocal { + off, + value, + kind, + volatile, + }) } /// `Inst::Binop`. In-block CSE: a prior `binop(op, lhs, rhs)` diff --git a/src/c5/codegen/ssa/dump.rs b/src/c5/codegen/ssa/dump.rs index 57683cc30..1d1bfcb57 100644 --- a/src/c5/codegen/ssa/dump.rs +++ b/src/c5/codegen/ssa/dump.rs @@ -89,25 +89,45 @@ fn fmt_inst(inst: &Inst) -> String { BlockAddr(b) => format!("BlockAddr(block={b})"), LocalAddr(n) => format!("LocalAddr({n})"), TlsAddr(o) => format!("TlsAddr({o})"), - Load { addr, disp, kind } => format!( - "Load {{ addr=v{addr}, disp={disp}, kind={} }}", - fmt_load_kind(*kind) + Load { + addr, + disp, + kind, + volatile, + } => format!( + "Load {{ addr=v{addr}, disp={disp}, kind={}{} }}", + fmt_load_kind(*kind), + fmt_volatile(*volatile), ), Store { addr, disp, value, kind, + volatile, } => format!( - "Store {{ addr=v{addr}, disp={disp}, value=v{value}, kind={} }}", + "Store {{ addr=v{addr}, disp={disp}, value=v{value}, kind={}{} }}", fmt_store_kind(*kind), + fmt_volatile(*volatile), ), - LoadLocal { off, kind } => { - format!("LoadLocal {{ off={off}, kind={} }}", fmt_load_kind(*kind),) - } - StoreLocal { off, value, kind } => format!( - "StoreLocal {{ off={off}, value=v{value}, kind={} }}", + LoadLocal { + off, + kind, + volatile, + } => format!( + "LoadLocal {{ off={off}, kind={}{} }}", + fmt_load_kind(*kind), + fmt_volatile(*volatile), + ), + StoreLocal { + off, + value, + kind, + volatile, + } => format!( + "StoreLocal {{ off={off}, value=v{value}, kind={}{} }}", fmt_store_kind(*kind), + fmt_volatile(*volatile), ), LoadIndexed { base, @@ -271,6 +291,11 @@ fn fmt_place(p: Place) -> String { } } +/// Rendered only when set so non-volatile dumps are unchanged. +fn fmt_volatile(v: bool) -> &'static str { + if v { ", volatile" } else { "" } +} + fn fmt_load_kind(k: LoadKind) -> &'static str { match k { LoadKind::I64 => "I64", diff --git a/src/c5/codegen/ssa/emit_common.rs b/src/c5/codegen/ssa/emit_common.rs index a179654b4..ab7375724 100644 --- a/src/c5/codegen/ssa/emit_common.rs +++ b/src/c5/codegen/ssa/emit_common.rs @@ -714,6 +714,9 @@ pub(crate) fn is_dead_pure( alloc: &super::reg_alloc::Allocation, ) -> bool { use super::super::ir::Inst::*; + // A volatile load is never pure: the access itself is the side + // effect (C99 5.1.2.3p2 / 6.7.3p6), so it is emitted even with no + // consumers, at every optimization level. let pure = matches!( inst, Imm(_) @@ -721,8 +724,14 @@ pub(crate) fn is_dead_pure( | ImmCode(_) | LocalAddr(_) | TlsAddr(_) - | Load { .. } - | LoadLocal { .. } + | Load { + volatile: false, + .. + } + | LoadLocal { + volatile: false, + .. + } | LoadIndexed { .. } | Binop { .. } | BinopI { .. } diff --git a/src/c5/codegen/ssa/mem2reg.rs b/src/c5/codegen/ssa/mem2reg.rs index 645016e09..5754cac7b 100644 --- a/src/c5/codegen/ssa/mem2reg.rs +++ b/src/c5/codegen/ssa/mem2reg.rs @@ -32,6 +32,16 @@ pub(crate) fn promotable_slots(func: &FunctionSsa) -> BTreeSet { let mut address_taken: BTreeSet = BTreeSet::new(); for inst in &func.insts { match inst { + // A volatile access pins the slot to memory: every read and + // write must be performed as the abstract machine specifies + // (C99 6.7.3p6), and the object must retain its last store + // across control transfers the CFG does not model (7.13.2.1 + // longjmp), so the slot is never lifted into a register. + Inst::LoadLocal { off, volatile, .. } | Inst::StoreLocal { off, volatile, .. } + if *volatile => + { + address_taken.insert(*off); + } Inst::LoadLocal { off, .. } | Inst::StoreLocal { off, .. } => { touched.insert(*off); } @@ -539,7 +549,7 @@ fn for_each_operand_mut(inst: &mut Inst, mut f: impl FnMut(&mut ValueId)) { fn slot_is_full_width(func: &FunctionSsa, slot: i64) -> bool { for inst in &func.insts { match inst { - Inst::LoadLocal { off, kind } if *off == slot && *kind != LoadKind::I64 => { + Inst::LoadLocal { off, kind, .. } if *off == slot && *kind != LoadKind::I64 => { return false; } Inst::StoreLocal { off, kind, .. } if *off == slot && *kind != StoreKind::I64 => { @@ -571,7 +581,7 @@ fn slot_narrow_load_kind(func: &FunctionSsa, slot: i64) -> Option { let mut store_kind: Option = None; for inst in &func.insts { match inst { - Inst::LoadLocal { off, kind } if *off == slot => match load_kind { + Inst::LoadLocal { off, kind, .. } if *off == slot => match load_kind { None => load_kind = Some(*kind), Some(k) if k == *kind => {} Some(_) => return None, @@ -724,7 +734,7 @@ fn slot_class(func: &FunctionSsa, slot: i64) -> Option { saw_int_store = true; } } - Inst::LoadLocal { off, kind } if *off == slot => match kind { + Inst::LoadLocal { off, kind, .. } if *off == slot => match kind { LoadKind::F32 | LoadKind::F64 => { saw_fp_load = true; match fp_load_kind { @@ -1286,16 +1296,19 @@ mod tests { off: -1, value: 0, kind: StoreKind::I64, + volatile: false, }, Inst::LoadLocal { off: -1, kind: LoadKind::I64, + volatile: false, }, Inst::LocalAddr(-2), Inst::StoreLocal { off: -2, value: 0, kind: StoreKind::I64, + volatile: false, }, ]; let blocks = alloc::vec![empty_block(Terminator::Return(NO_VALUE))]; @@ -1308,6 +1321,33 @@ mod tests { ); } + #[test] + fn volatile_slot_is_not_promotable() { + // Slot -1 is accessed only through volatile LoadLocal / + // StoreLocal (C99 6.7.3p6): every access must reach memory, + // so the slot is excluded from promotion. + let insts = alloc::vec![ + Inst::Imm(1), + Inst::StoreLocal { + off: -1, + value: 0, + kind: StoreKind::I64, + volatile: true, + }, + Inst::LoadLocal { + off: -1, + kind: LoadKind::I64, + volatile: true, + }, + ]; + let blocks = alloc::vec![empty_block(Terminator::Return(2))]; + let f = func_with(insts, blocks); + assert!( + !promotable_slots(&f).contains(&-1), + "volatile-accessed slot -1 must stay memory-resident" + ); + } + #[test] fn run_neutralises_writes_to_write_only_slot() { // Address-free slot -1 is stored twice (two distinct int @@ -1320,12 +1360,14 @@ mod tests { off: -1, value: 0, kind: StoreKind::I32, + volatile: false, }, Inst::Imm(2), Inst::StoreLocal { off: -1, value: 2, kind: StoreKind::I32, + volatile: false, }, Inst::Imm(99), ]; @@ -1438,10 +1480,12 @@ mod tests { off: -1, value: 0, kind: StoreKind::I64, + volatile: false, }, Inst::LoadLocal { off: -1, kind: LoadKind::I64, + volatile: false, }, ]; let blocks = alloc::vec![ @@ -1476,11 +1520,13 @@ mod tests { off: -1, value: 0, kind: StoreKind::I64, + volatile: false, }, Inst::LocalAddr(-1), Inst::LoadLocal { off: -1, kind: LoadKind::I64, + volatile: false, }, ]; let blocks = alloc::vec![Block { @@ -1509,10 +1555,12 @@ mod tests { off: -1, value: 0, kind: StoreKind::I8, + volatile: false, }, Inst::LoadLocal { off: -1, kind: LoadKind::I8, + volatile: false, }, ]; let blocks = alloc::vec![Block { @@ -1548,10 +1596,12 @@ mod tests { off: -1, value: 0, kind: StoreKind::I8, + volatile: false, }, Inst::LoadLocal { off: -1, kind: LoadKind::U8, + volatile: false, }, ]; let blocks = alloc::vec![Block { @@ -1588,16 +1638,19 @@ mod tests { off: -1, value: 1, kind: StoreKind::I64, + volatile: false, }, Inst::Imm(2), // block 2 Inst::StoreLocal { off: -1, value: 3, kind: StoreKind::I64, + volatile: false, }, Inst::LoadLocal { off: -1, kind: LoadKind::I64, + volatile: false, }, // block 3 ]; let blocks = alloc::vec![ @@ -1655,6 +1708,7 @@ mod tests { off: -1, value: 1, kind: StoreKind::I64, + volatile: false, }, // block 2 Inst::Imm(2), @@ -1662,11 +1716,13 @@ mod tests { off: -1, value: 3, kind: StoreKind::I64, + volatile: false, }, // block 3 Inst::LoadLocal { off: -1, kind: LoadKind::I64, + volatile: false, }, ]; let blocks = alloc::vec![ @@ -1725,7 +1781,7 @@ mod tests { } // The LoadLocal slid forward by one phi. match &f.insts[6] { - Inst::LoadLocal { off, kind } => { + Inst::LoadLocal { off, kind, .. } => { assert_eq!(*off, -1); assert_eq!(*kind, LoadKind::I64); } @@ -1774,16 +1830,19 @@ mod tests { off: -1, value: 1, kind: StoreKind::I64, + volatile: false, }, Inst::Imm(2), Inst::StoreLocal { off: -1, value: 3, kind: StoreKind::I64, + volatile: false, }, Inst::LoadLocal { off: -1, kind: LoadKind::I64, + volatile: false, }, Inst::ImmData(0), ]; @@ -1857,6 +1916,7 @@ mod tests { off: -1, value: 1, kind: StoreKind::I64, + volatile: false, }, // block 2: ids 3..5 Inst::Imm(22), @@ -1864,11 +1924,13 @@ mod tests { off: -1, value: 3, kind: StoreKind::I64, + volatile: false, }, // block 3: id 5 Inst::LoadLocal { off: -1, kind: LoadKind::I64, + volatile: false, }, ]; let blocks = alloc::vec![ @@ -1987,10 +2049,12 @@ mod tests { off: -1, value: 1, kind: StoreKind::I64, + volatile: false, }, Inst::LoadLocal { off: -1, kind: LoadKind::I64, + volatile: false, }, // block 2 ]; let blocks = alloc::vec![ @@ -2087,7 +2151,8 @@ mod tests { Inst::StoreLocal { off: -1, value: 0, - kind: StoreKind::I64 + kind: StoreKind::I64, + volatile: false, }, // v1 // b1: condition operand (placeholder; the body emits a // constant so the branch is deterministic; not subject @@ -2098,18 +2163,21 @@ mod tests { Inst::StoreLocal { off: -1, value: 3, - kind: StoreKind::I64 + kind: StoreKind::I64, + volatile: false, }, // v4 Inst::Imm(9), // v5 Inst::StoreLocal { off: -1, value: 5, - kind: StoreKind::I64 + kind: StoreKind::I64, + volatile: false, }, // v6 // b3: load -1 Inst::LoadLocal { off: -1, - kind: LoadKind::I64 + kind: LoadKind::I64, + volatile: false, }, // v7 ]; let blocks = alloc::vec![ diff --git a/src/c5/codegen/ssa/reg_alloc.rs b/src/c5/codegen/ssa/reg_alloc.rs index 9e0702577..b5e63fd39 100644 --- a/src/c5/codegen/ssa/reg_alloc.rs +++ b/src/c5/codegen/ssa/reg_alloc.rs @@ -1140,6 +1140,9 @@ fn compute_use_counts(func: &FunctionSsa) -> Vec { /// True when the inst has no side effects and can be DCE'd if its /// result is unread. Mirrors `is_dead_pure` in ssa_emit_common but /// kept here to drive the allocator's use-count fixed-point pass. +/// A volatile load is an access the abstract machine performs even +/// when the value is unused (C99 5.1.2.3p2 / 6.7.3p6), so it is +/// never pure. fn is_pure_inst(inst: &Inst) -> bool { matches!( inst, @@ -1149,8 +1152,14 @@ fn is_pure_inst(inst: &Inst) -> bool { | Inst::ImmExtCode(_) | Inst::LocalAddr(_) | Inst::TlsAddr(_) - | Inst::Load { .. } - | Inst::LoadLocal { .. } + | Inst::Load { + volatile: false, + .. + } + | Inst::LoadLocal { + volatile: false, + .. + } | Inst::LoadIndexed { .. } | Inst::Binop { .. } | Inst::BinopI { .. } @@ -2308,6 +2317,48 @@ int main(void) { return 0; } /// Allocate every function in quicksort.c on aarch64. The /// fixture has straight-line control flow and short /// expressions; the allocator should never spill. + #[test] + fn unused_volatile_reads_survive_dead_pure_skip() { + // C99 5.1.2.3p2: a volatile read is a side effect. The emit's + // dead-code skip must keep the unused loads and their address + // chains at every optimization level. + let funcs = lift("tests/fixtures/c/volatile_unused_read.c"); + let main = funcs.iter().find(|f| f.name == "main").expect("main"); + let alloc = allocate(main, Target::host()); + let mut volatile_loads = 0; + for (v, inst) in main.insts.iter().enumerate() { + match inst { + Inst::Load { + volatile: true, + addr, + .. + } => { + volatile_loads += 1; + assert!( + !super::super::emit_common::is_dead_pure(inst, v as ValueId, &alloc), + "volatile Load v{v} must not be skipped as dead" + ); + assert_ne!( + alloc.use_counts[*addr as usize], 0, + "the volatile load's address chain must stay live" + ); + } + Inst::LoadLocal { volatile: true, .. } => { + volatile_loads += 1; + assert!( + !super::super::emit_common::is_dead_pure(inst, v as ValueId, &alloc), + "volatile LoadLocal v{v} must not be skipped as dead" + ); + } + _ => {} + } + } + assert!( + volatile_loads >= 2, + "expected the global and the local volatile reads in SSA, saw {volatile_loads}" + ); + } + #[test] fn allocate_quicksort_no_spill() { let funcs = lift("tests/fixtures/c/quicksort.c"); diff --git a/src/c5/codegen/ssa/slot_coalesce.rs b/src/c5/codegen/ssa/slot_coalesce.rs index 30ba6535c..990e4c35e 100644 --- a/src/c5/codegen/ssa/slot_coalesce.rs +++ b/src/c5/codegen/ssa/slot_coalesce.rs @@ -202,6 +202,16 @@ fn coalesce(f: &mut FunctionSsa) -> BTreeMap> { Inst::Call { ret_slot_local, .. } | Inst::CallIndirect { ret_slot_local, .. } | Inst::CallExt { ret_slot_local, .. } => *ret_slot_local, + // A volatile-accessed slot keeps its own storage: the + // object must hold its last store across control + // transfers the CFG does not model (C99 7.13.2.1 + // longjmp), so the liveness below cannot justify + // sharing or moving it. + Inst::LoadLocal { off, volatile, .. } | Inst::StoreLocal { off, volatile, .. } + if *volatile => + { + *off + } _ => continue, }; if movable(off) && !agg_cells.contains(&off) { diff --git a/src/c5/codegen/x86_64/emit.rs b/src/c5/codegen/x86_64/emit.rs index a8e59f142..36f721ff4 100644 --- a/src/c5/codegen/x86_64/emit.rs +++ b/src/c5/codegen/x86_64/emit.rs @@ -2863,7 +2863,9 @@ fn emit_inst( spill_dst_to_slot(code, dst, rd, frame); true } - Inst::Load { addr, disp, kind } => emit_load( + Inst::Load { + addr, disp, kind, .. + } => emit_load( code, dst, *addr, @@ -2878,13 +2880,14 @@ fn emit_inst( disp, value, kind, + .. } => emit_store(code, dst, v, *addr, *disp, *value, *kind, alloc, frame), - Inst::LoadLocal { off, kind } => { + Inst::LoadLocal { off, kind, .. } => { emit_load_local(code, dst, *off, *kind, alloc.is_f32(v), frame, func, abi) } - Inst::StoreLocal { off, value, kind } => { - emit_store_local(code, dst, v, *off, *value, *kind, alloc, frame, func, abi) - } + Inst::StoreLocal { + off, value, kind, .. + } => emit_store_local(code, dst, v, *off, *value, *kind, alloc, frame, func, abi), Inst::LoadIndexed { base, index, diff --git a/src/c5/compiler/aggregate.rs b/src/c5/compiler/aggregate.rs index 26de8dfac..c1e4f5770 100644 --- a/src/c5/compiler/aggregate.rs +++ b/src/c5/compiler/aggregate.rs @@ -314,13 +314,15 @@ impl Compiler { // Trailing specifiers: C99 6.7.2p2 admits any order, so // `int long` / `char unsigned` fields re-derive the base // tag from the folded modifiers. - if self.consume_trailing_decl_modifiers(&mut mods)? { + let (saw_int_mod, trailing_quals) = self.consume_trailing_decl_modifiers(&mut mods)?; + if saw_int_mod { if field_base_tok == Token::Int { field_base = mods.int_base(); } else if field_base_tok == Token::Char { field_base = mods.char_tag(self.target.plain_char_signed()); } } + field_base |= trailing_quals; // Anonymous struct/union member (C11 6.7.2.1p13). The // type-prefix parse just registered an anon-tagged diff --git a/src/c5/compiler/decl_base.rs b/src/c5/compiler/decl_base.rs index c65823382..b95db1e23 100644 --- a/src/c5/compiler/decl_base.rs +++ b/src/c5/compiler/decl_base.rs @@ -31,7 +31,7 @@ use alloc::format; use super::super::error::C5Error; use super::super::token::{Token, Ty}; use super::Compiler; -use super::types::{UNSIGNED_BIT, is_decl_modifier, struct_ty_for}; +use super::types::{UNSIGNED_BIT, VOLATILE_BIT, is_decl_modifier, struct_ty_for}; /// Accumulator for the int-modifier soup that prefixes a C base /// type. `signed` / `unsigned` / `short` / `long` (any count) / @@ -461,6 +461,21 @@ impl Compiler { Ok(Some(bt)) } + /// `VOLATILE_BIT` when the current token is the `volatile` type + /// qualifier (C99 6.7.3), 0 for any other spelling mapped to + /// `Token::TypeQual` (`const`, `restrict`, calling-convention + /// decorations). Qualifier identity lives on the interned keyword + /// symbol; the caller consumes the token. + pub(super) fn lex_volatile_bit(&self) -> i64 { + if self.lex.tk != Token::TypeQual { + return 0; + } + match self.symbols[self.lex.curr_id_idx].name.as_str() { + "volatile" | "__volatile" | "__volatile__" => VOLATILE_BIT, + _ => 0, + } + } + pub(super) fn parse_decl_base_type(&mut self) -> Result { // Reset the void side channel up front so a previous // declaration's bare-void base doesn't leak into this one. @@ -486,6 +501,7 @@ impl Compiler { // collect everything we see, then look at the next token // for the type keyword. let mut m = IntModifiers::default(); + let mut qual_bits: i64 = 0; loop { // C23 6.7.13 `[[...]]` and GNU `__attribute__`/`__declspec` // may lead the declaration specifiers. @@ -514,8 +530,9 @@ impl Compiler { self.pending_noreturn = true; } if !self.try_consume_int_modifier(&mut m)? { - // const / volatile / restrict / _Atomic / etc. -- - // all no-ops in c5, just consume. + // `volatile` sets the tag's qualifier bit (C99 6.7.3); + // const / restrict / _Atomic / etc. are no-ops. + qual_bits |= self.lex_volatile_bit(); self.next()?; } } @@ -594,10 +611,13 @@ impl Compiler { // Trailing specifiers: C99 6.7.2p2 admits the specifier // multiset in any order, so `int long`, `int unsigned`, // `char unsigned`, `double long` re-derive the base tag from - // the folded modifiers. A non-scalar base (typedef, struct, - // enum) has no valid int-modifier combination; the tokens are + // the folded modifiers; trailing qualifiers fold into the + // qualifier bits. A non-scalar base (typedef, struct, enum) + // has no valid int-modifier combination; the tokens are // consumed as before. - if self.consume_trailing_decl_modifiers(&mut m)? { + let (saw_int_mod, trailing_quals) = self.consume_trailing_decl_modifiers(&mut m)?; + qual_bits |= trailing_quals; + if saw_int_mod { if base_tok == Token::Int { bt = m.int_base(); } else if base_tok == Token::Char { @@ -607,19 +627,20 @@ impl Compiler { } } - Ok(bt) + Ok(bt | qual_bits) } /// Consume the specifiers that may trail the base-type keyword: /// int modifiers fold into `m` (the caller re-derives the base - /// tag), qualifiers are no-ops, and `inline` / `_Noreturn` set - /// the same pending flags as in leading position. Returns true - /// when an int modifier was consumed. + /// tag), qualifier bits are returned for the caller to fold into + /// the type, and `inline` / `_Noreturn` set the same pending + /// flags as in leading position. pub(super) fn consume_trailing_decl_modifiers( &mut self, m: &mut IntModifiers, - ) -> Result { + ) -> Result<(bool, i64), C5Error> { let mut saw_int_mod = false; + let mut qual_bits = 0i64; while is_decl_modifier(self.lex.tk) { if self.lex.tk == Token::Attribute { self.skip_attribute_specifiers()?; @@ -635,8 +656,9 @@ impl Compiler { saw_int_mod = true; continue; } + qual_bits |= self.lex_volatile_bit(); self.next()?; } - Ok(saw_int_mod) + Ok((saw_int_mod, qual_bits)) } } diff --git a/src/c5/compiler/declarator.rs b/src/c5/compiler/declarator.rs index 5b072b011..8723f6fc5 100644 --- a/src/c5/compiler/declarator.rs +++ b/src/c5/compiler/declarator.rs @@ -170,6 +170,7 @@ impl Compiler { // it lexes as a no-op type qualifier. Consume any here so it does // not stand in for the declarator name. while self.lex.tk == Token::TypeQual { + ty |= self.lex_volatile_bit(); self.next()?; } let mut leading_ptr_count: i64 = 0; @@ -178,11 +179,13 @@ impl Compiler { ty += Ty::Ptr as i64; leading_ptr_count += 1; // Pointer-level qualifiers: `int *const p`, `int *volatile p`, - // `char *restrict s`. Consumed; no semantic effect. An - // attribute may sit here too (`void * __attribute__((malloc)) - // p`). + // `char *restrict s`. A pointer-level `volatile` sets the + // tag's qualifier bit (C99 6.7.3; the single bit does not + // record the level). An attribute may sit here too + // (`void * __attribute__((malloc)) p`). loop { if self.lex.tk == Token::TypeQual { + ty |= self.lex_volatile_bit(); self.next()?; } else if self.lex.tk == Token::Attribute { self.skip_attribute_specifiers()?; diff --git a/src/c5/compiler/diag.rs b/src/c5/compiler/diag.rs index 5b934a3e0..604648583 100644 --- a/src/c5/compiler/diag.rs +++ b/src/c5/compiler/diag.rs @@ -13,7 +13,7 @@ use super::super::error::C5Error; use super::super::token::Ty; use super::Compiler; use super::types::{ - UNSIGNED_BIT, is_floating_scalar, is_pointer_ty, is_struct_ty, struct_ptr_depth, + UNSIGNED_BIT, VOLATILE_BIT, is_floating_scalar, is_pointer_ty, is_struct_ty, struct_ptr_depth, }; impl Compiler { @@ -378,8 +378,9 @@ impl Compiler { // are all interchangeable here -- the compatibility rule // is "is this any kind of byte pointer?", not "do the // signedness tags line up". - let decl_is_char_ptr = decl_is_ptr && (declared & !UNSIGNED_BIT) == char_ptr; - let act_is_char_ptr = act_is_ptr && (actual & !UNSIGNED_BIT) == char_ptr; + let decl_is_char_ptr = + decl_is_ptr && (declared & !(UNSIGNED_BIT | VOLATILE_BIT)) == char_ptr; + let act_is_char_ptr = act_is_ptr && (actual & !(UNSIGNED_BIT | VOLATILE_BIT)) == char_ptr; if decl_is_char_ptr && act_is_ptr { return None; } diff --git a/src/c5/compiler/expr.rs b/src/c5/compiler/expr.rs index 4aed51089..bb8f35d06 100644 --- a/src/c5/compiler/expr.rs +++ b/src/c5/compiler/expr.rs @@ -1504,6 +1504,7 @@ impl Compiler { } } while self.lex.tk == Token::TypeQual { + t |= self.lex_volatile_bit(); self.next()?; } } diff --git a/src/c5/compiler/function.rs b/src/c5/compiler/function.rs index e31e4a0a2..8fe143f85 100644 --- a/src/c5/compiler/function.rs +++ b/src/c5/compiler/function.rs @@ -109,6 +109,7 @@ impl Compiler { ty += Ty::Ptr as i64; leading_ptr_count += 1; while self.lex.tk == Token::TypeQual { + ty |= self.lex_volatile_bit(); self.next()?; } } diff --git a/src/c5/compiler/global_init.rs b/src/c5/compiler/global_init.rs index 05f0256be..b10911a97 100644 --- a/src/c5/compiler/global_init.rs +++ b/src/c5/compiler/global_init.rs @@ -21,7 +21,9 @@ use alloc::format; use super::super::error::C5Error; use super::super::token::{Token, Ty}; use super::Compiler; -use super::types::{UNSIGNED_BIT, is_pointer_ty, is_struct_ty, struct_id_of, struct_ptr_depth}; +use super::types::{ + UNSIGNED_BIT, VOLATILE_BIT, is_pointer_ty, is_struct_ty, struct_id_of, struct_ptr_depth, +}; impl Compiler { /// After a leading `(TYPE)` cast in a global initializer, returns @@ -529,7 +531,7 @@ impl Compiler { // full 8 bytes the slot was sized for; a future // f32-narrow-storage path would shrink it for `float`. let var_is_float = { - let stripped = var_ty & !UNSIGNED_BIT; + let stripped = var_ty & !(UNSIGNED_BIT | VOLATILE_BIT); stripped == Ty::Float as i64 || stripped == Ty::Double as i64 }; // Constant expression, evaluated at compile time. Handles diff --git a/src/c5/compiler/initializer.rs b/src/c5/compiler/initializer.rs index d6fab27a9..a76321e5e 100644 --- a/src/c5/compiler/initializer.rs +++ b/src/c5/compiler/initializer.rs @@ -38,7 +38,7 @@ use super::super::error::C5Error; use super::super::token::{Token, Ty}; use super::Compiler; use super::const_expr::ConstVal; -use super::types::{UNSIGNED_BIT, is_struct_ty, struct_id_of, struct_ptr_depth}; +use super::types::{UNSIGNED_BIT, VOLATILE_BIT, is_struct_ty, struct_id_of, struct_ptr_depth}; /// Relocation kind for one initializer-element value. Tracks /// whether the bytes need to be patched at link / load time so @@ -168,7 +168,7 @@ impl Compiler { /// slots (Data / Code relocs) pass through unchanged. Callers /// write `size_of_type(elem_ty)` low bytes of the result. pub(super) fn to_storage_bits(&self, value: i64, reloc: InitElemReloc, elem_ty: i64) -> i64 { - let stripped = elem_ty & !UNSIGNED_BIT; + let stripped = elem_ty & !(UNSIGNED_BIT | VOLATILE_BIT); let is_float = stripped == Ty::Float as i64; let is_double = stripped == Ty::Double as i64; if !is_float && !is_double { @@ -289,7 +289,7 @@ impl Compiler { // a multi-dimensional char array (`char c[2][6] = {"a", // "b"}`, one string per row) has a string as its first // element and must stay a brace list. - let is_char_array = (elem_ty & !UNSIGNED_BIT) == Ty::Char as i64; + let is_char_array = (elem_ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Char as i64; if inner_dims.is_empty() && self.lex.tk == '"' && (self.lex.str_is_wide || is_char_array) @@ -313,7 +313,7 @@ impl Compiler { depth += 1; self.next()?; } - let is_char_array = (elem_ty & !UNSIGNED_BIT) == Ty::Char as i64; + let is_char_array = (elem_ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Char as i64; if self.lex.tk == '"' && (self.lex.str_is_wide || is_char_array) { paren_depth = depth; } else { @@ -357,7 +357,7 @@ impl Compiler { self.expect_close_parens(paren_depth)?; return Ok(elems); } - if self.lex.tk == '"' && (elem_ty & !UNSIGNED_BIT) == Ty::Char as i64 { + if self.lex.tk == '"' && (elem_ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Char as i64 { let start_addr = self.take_concat_string_literal()?; let char_count = self.data.len() - start_addr; // C99 6.7.8p14: a string-literal initializer for a @@ -483,7 +483,7 @@ impl Compiler { if self.lex.tk == '"' && !self.lex.str_is_wide && inner_dims.len() == 1 - && (elem_ty & !UNSIGNED_BIT) == Ty::Char as i64 + && (elem_ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Char as i64 { let row = inner_dims[0] as usize; let start_addr = self.take_concat_string_literal()?; @@ -1620,7 +1620,7 @@ impl Compiler { data.resize(end, 0); } }; - if self.lex.tk == '"' && (elem_ty & !UNSIGNED_BIT) == Ty::Char as i64 { + if self.lex.tk == '"' && (elem_ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Char as i64 { let start_addr = self.take_concat_string_literal()?; self.data.push(0); // ensure NUL terminator in the literal's bytes let mut idx = 0usize; @@ -1918,7 +1918,7 @@ impl Compiler { let mut char_array_brace_string = false; if field.array_size > 0 && field.inner_array_size == 0 - && (field.ty & !UNSIGNED_BIT) == Ty::Char as i64 + && (field.ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Char as i64 && self.lex.tk == '{' { let snap = self.lex.snapshot(); @@ -1944,7 +1944,7 @@ impl Compiler { let mut char_array_paren_depth = 0usize; if field.array_size > 0 && field.inner_array_size == 0 - && (field.ty & !UNSIGNED_BIT) == Ty::Char as i64 + && (field.ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Char as i64 && self.lex.tk == '(' { let snap = self.lex.snapshot(); @@ -1963,7 +1963,7 @@ impl Compiler { } if field.array_size > 0 && self.lex.tk == '"' - && (field.ty & !UNSIGNED_BIT) == Ty::Char as i64 + && (field.ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Char as i64 { // `struct S { char a[N]; } x = { "..." };` -- copy the // string bytes (including the trailing NUL) into the @@ -2302,9 +2302,9 @@ impl Compiler { self.pending_local_init_ast = self.ast_acc; if is_struct_ty(ty) && struct_ptr_depth(ty) == 0 { self.mark_emit_other(); - } else if (ty & !UNSIGNED_BIT) == Ty::Char as i64 { + } else if (ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Char as i64 { self.ast_assign(); - } else if (ty & !UNSIGNED_BIT) == Ty::Float as i64 { + } else if (ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Float as i64 { // `float`-typed local: narrow the accumulator (an f64 // bit pattern from the RHS) to single-precision and // store 4 bytes. The slot reserved by diff --git a/src/c5/compiler/locals.rs b/src/c5/compiler/locals.rs index a476805e7..3e8bad31d 100644 --- a/src/c5/compiler/locals.rs +++ b/src/c5/compiler/locals.rs @@ -31,7 +31,9 @@ use alloc::format; use super::super::error::C5Error; use super::super::token::{Token, Ty}; use super::Compiler; -use super::types::{UNSIGNED_BIT, is_pointer_ty, is_struct_ty, struct_id_of, struct_ptr_depth}; +use super::types::{ + UNSIGNED_BIT, VOLATILE_BIT, is_pointer_ty, is_struct_ty, struct_id_of, struct_ptr_depth, +}; impl Compiler { /// Drain the three pending local-initializer carriers into a single @@ -81,6 +83,7 @@ impl Compiler { let mut is_static = false; let mut is_extern = false; let mut saw_specifier = false; + let mut qual_bits: i64 = 0; while self.lex.tk == Token::Extern || self.lex.tk == Token::Static || self.lex.tk == Token::FuncSpec @@ -92,6 +95,8 @@ impl Compiler { if self.lex.tk == Token::Extern { is_extern = true; } + // `volatile` qualifies the declared type (C99 6.7.3). + qual_bits |= self.lex_volatile_bit(); saw_specifier = true; self.next()?; } @@ -103,7 +108,7 @@ impl Compiler { Ty::Int as i64 } else { self.parse_decl_base_type()? - }; + } | qual_bits; // A function-pointer typedef base type contributes its lineage to // every declarator in the list (`fn_t a, b;` makes both a and b // function pointers). The per-declarator symbol creation consumes @@ -1487,7 +1492,7 @@ impl Compiler { if final_field.array_size > 0 { if self.lex.tk == '"' && !self.lex.str_is_wide - && (final_field.ty & !UNSIGNED_BIT) == Ty::Char as i64 + && (final_field.ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Char as i64 { let start_addr = self.take_concat_string_literal()?; self.data.push(0); // ensure NUL terminator @@ -1575,7 +1580,7 @@ impl Compiler { // it composes with non-constant sibling fields. if self.lex.tk == '"' && !self.lex.str_is_wide - && (field.ty & !UNSIGNED_BIT) == Ty::Char as i64 + && (field.ty & !(UNSIGNED_BIT | VOLATILE_BIT)) == Ty::Char as i64 { let start_addr = self.take_concat_string_literal()?; self.data.push(0); // ensure NUL terminator diff --git a/src/c5/compiler/run_compile.rs b/src/c5/compiler/run_compile.rs index c492bc3d6..d9a042708 100644 --- a/src/c5/compiler/run_compile.rs +++ b/src/c5/compiler/run_compile.rs @@ -25,8 +25,8 @@ use super::super::token::{Token, Ty}; use super::Compiler; use super::decl_base; use super::types::{ - UNSIGNED_BIT, format_signature, is_decl_modifier, is_pointer_ty, is_struct_ty, struct_id_of, - struct_ptr_depth, + UNSIGNED_BIT, VOLATILE_BIT, format_signature, is_decl_modifier, is_pointer_ty, is_struct_ty, + struct_id_of, struct_ptr_depth, }; impl Compiler { @@ -79,6 +79,7 @@ impl Compiler { let mut static_seen = false; let mut extern_seen = false; let mut atomic_base: Option = None; + let mut qual_bits: i64 = 0; let mut m = decl_base::IntModifiers::default(); // `_Noreturn`, `__declspec(thread)`, `__declspec(dllexport)`, and // `inline` scope to this declaration; clear the carriers so they @@ -126,6 +127,8 @@ impl Compiler { if self.lex.tk == Token::Noreturn { self.pending_noreturn = true; } + // `volatile` qualifies the declared type (C99 6.7.3). + qual_bits |= self.lex_volatile_bit(); self.next()?; } else { break; @@ -214,15 +217,17 @@ impl Compiler { } // Trailing qualifiers / int modifiers between the base // type and the declarators -- `Foo const *p`, `int long - // x`, etc. The base type is already chosen; these are - // pure no-ops in c5 but appear in real C source. + // x`, etc. The base type is already chosen; a trailing + // `volatile` still qualifies it (C99 6.7.3). while is_decl_modifier(self.lex.tk) { if self.lex.tk == Token::Attribute { self.skip_attribute_specifiers()?; continue; } + qual_bits |= self.lex_volatile_bit(); self.next()?; } + bt |= qual_bits; // A function-pointer typedef base type contributes its lineage // to every declarator in the list (`fn_t a, b;`). The @@ -781,11 +786,13 @@ impl Compiler { // neither a specifier nor a type nor a parameter // name -- that is the function body. let mut saw_specifier = false; + let mut qual_bits: i64 = 0; while self.lex.tk == Token::FuncSpec || self.lex.tk == Token::Static || self.lex.tk == Token::Extern || self.lex.tk == Token::TypeQual { + qual_bits |= self.lex_volatile_bit(); self.next()?; saw_specifier = true; } @@ -795,7 +802,7 @@ impl Compiler { Ty::Int as i64 } else { break; - }; + } | qual_bits; while self.lex.tk != ';' && self.lex.tk != 0 { let (decl_idx, mut decl_ty, decl_arr) = self.parse_declarator(base)?; if decl_idx != usize::MAX { @@ -957,7 +964,7 @@ impl Compiler { // float-typed code expects, and the load/store // semantics stay consistent. for &idx in params.indices.iter() { - let pty = self.symbols[idx].type_ & !UNSIGNED_BIT; + let pty = self.symbols[idx].type_ & !(UNSIGNED_BIT | VOLATILE_BIT); if pty != Ty::Float as i64 { continue; } diff --git a/src/c5/compiler/type_layout.rs b/src/c5/compiler/type_layout.rs index 07a3c0f01..8b6c079d0 100644 --- a/src/c5/compiler/type_layout.rs +++ b/src/c5/compiler/type_layout.rs @@ -17,8 +17,8 @@ use super::super::token::{Token, Ty}; use super::Compiler; use super::StructDef; use super::types::{ - UNSIGNED_BIT, is_pointer_ty, is_struct_ty, is_type_start_token, pointee_size_no_struct, - struct_id_of, struct_ptr_depth, + UNSIGNED_BIT, VOLATILE_BIT, is_pointer_ty, is_struct_ty, is_type_start_token, + pointee_size_no_struct, struct_id_of, struct_ptr_depth, }; impl Compiler { @@ -34,7 +34,7 @@ impl Compiler { // struct value, whose size lives in the struct table. return self.structs[struct_id_of(ptr_ty)].size as i64; } - let stripped = ptr_ty & !UNSIGNED_BIT; + let stripped = ptr_ty & !(UNSIGNED_BIT | VOLATILE_BIT); if stripped == (Ty::Long as i64) + (Ty::Ptr as i64) && self.target.is_windows() { return 4; } @@ -173,7 +173,7 @@ impl Compiler { // Unsigned bit is orthogonal to width: `unsigned char` is // still 1 byte, `unsigned int` is still 4 bytes. Strip it // before consulting the band identity. - let ty = ty & !UNSIGNED_BIT; + let ty = ty & !(UNSIGNED_BIT | VOLATILE_BIT); if is_struct_ty(ty) { if struct_ptr_depth(ty) > 0 { 8 @@ -215,7 +215,7 @@ impl Compiler { /// alignment of their fields, but c5 currently caps struct /// alignment at 8 to match the rest of the IR's slot model. pub(super) fn align_of_type(&self, ty: i64) -> usize { - let ty = ty & !UNSIGNED_BIT; + let ty = ty & !(UNSIGNED_BIT | VOLATILE_BIT); if ty == Ty::Float as i64 { // `float` is 4 bytes; its natural alignment matches. // Same rule the rest of the integer / pointer family @@ -270,7 +270,7 @@ fn flat_scalar_size(ty: i64, target: Target) -> u32 { if is_pointer_ty(ty) { return 8; } - let bare = ty & !UNSIGNED_BIT; + let bare = ty & !(UNSIGNED_BIT | VOLATILE_BIT); if bare == Ty::Bool as i64 || bare == Ty::Char as i64 { 1 } else if bare == Ty::Short as i64 { @@ -319,7 +319,7 @@ pub(crate) fn flatten_struct_fields( if is_struct_value { flatten_struct_fields(structs, target, struct_id_of(elem_ty), off, out); } else { - let bare = elem_ty & !UNSIGNED_BIT; + let bare = elem_ty & !(UNSIGNED_BIT | VOLATILE_BIT); let kind = if is_pointer_ty(elem_ty) { ScalarKind::Int } else if bare == Ty::Float as i64 { diff --git a/src/c5/compiler/types.rs b/src/c5/compiler/types.rs index 6dc052a80..688c63f40 100644 --- a/src/c5/compiler/types.rs +++ b/src/c5/compiler/types.rs @@ -66,6 +66,22 @@ pub(crate) fn is_unsigned_ty(ty: i64) -> bool { (ty & UNSIGNED_BIT) != 0 } +/// High-bit flag marking a type tag `volatile`-qualified (C99 6.7.3). +/// Orthogonal to the band scheme like [`UNSIGNED_BIT`]: stripped by +/// [`strip_unsigned`] before any band classifier consults the tag. The +/// single bit does not record which indirection level carries the +/// qualifier, so `volatile T *`, `T * volatile`, and `volatile T` +/// all set it; every access through such a tag is treated as a +/// volatile access (a conservative over-approximation -- extra +/// volatility only inhibits optimization, per 5.1.2.3p2 an access to +/// a volatile object may not be elided or coalesced). +pub(crate) const VOLATILE_BIT: i64 = 1 << 29; + +/// `true` if `ty` carries the volatile qualifier at any level. +pub(crate) fn is_volatile_ty(ty: i64) -> bool { + (ty & VOLATILE_BIT) != 0 +} + /// Apply a C99 6.3.1.3 integer conversion to a constant value: /// narrow to `bytes` width and re-interpret by the target's /// signedness. `_Bool` maps any nonzero value to 1 (6.3.1.2). An @@ -91,14 +107,14 @@ pub(crate) fn narrow_const_int(bytes: usize, unsigned: bool, is_bool: bool, v: i } } -/// Drop the unsigned bit. Use to recover the bare band-encoded type -/// before consulting a helper that classifies by band. Most of the -/// helpers in this module call this at their entry; outside callers -/// only need it when storing a type tag where a non-bit-flagged tag -/// is expected (e.g., switch-table comparisons against `Ty::Int as -/// i64`). +/// Drop the qualifier bits (`UNSIGNED_BIT`, `VOLATILE_BIT`). Use to +/// recover the bare band-encoded type before consulting a helper that +/// classifies by band. Most of the helpers in this module call this at +/// their entry; outside callers only need it when storing a type tag +/// where a non-bit-flagged tag is expected (e.g., switch-table +/// comparisons against `Ty::Int as i64`). pub(crate) fn strip_unsigned(ty: i64) -> i64 { - ty & !UNSIGNED_BIT + ty & !(UNSIGNED_BIT | VOLATILE_BIT) } /// Round `x` up to the nearest multiple of `alignment` (which must @@ -649,7 +665,7 @@ mod ty_tag { // `is_pointer_ty`. The base band ([0, 100): char / int) admits any // offset >= Ty::Ptr; every other band reserves even offsets. fn pointer_by_even_stride(ty: i64) -> bool { - let stripped = ty & !UNSIGNED_BIT; + let stripped = ty & !(UNSIGNED_BIT | VOLATILE_BIT); let base = stripped - (stripped % 100); let off = stripped - base; if base == 0 { diff --git a/src/c5/ir.rs b/src/c5/ir.rs index 682661fdf..956127439 100644 --- a/src/c5/ir.rs +++ b/src/c5/ir.rs @@ -79,29 +79,41 @@ pub(crate) enum Inst { /// Load from `addr + disp`. Width / signedness driven by the /// source load op. `disp` is a byte offset folded from a constant /// pointer addition (a struct field offset) into the addressing - /// mode; it is zero for a plain dereference. + /// mode; it is zero for a plain dereference. `volatile` marks an + /// access to a volatile-qualified object (C99 6.7.3p6): the load + /// must be performed strictly per the abstract machine, so no pass + /// may delete, duplicate, or forward it (5.1.2.3p2). Load { addr: ValueId, disp: i32, kind: LoadKind, + volatile: bool, }, /// Store to `addr + disp`. The c5 semantics leave the stored value /// in the accumulator afterward; downstream uses of this /// instruction's id read that value. `disp` is a byte offset folded /// from a constant pointer addition, zero for a plain dereference. + /// `volatile` as for [`Self::Load`]. Store { addr: ValueId, disp: i32, value: ValueId, kind: StoreKind, + volatile: bool, }, /// Load from a local / parameter slot. Equivalent to a /// `LocalAddr(off)` followed by `Load { kind }`, but /// represented as a single instruction so the per-arch emit /// folds the address into the load's addressing mode and /// the allocator does not need to assign a register to the - /// intermediate address. - LoadLocal { off: i64, kind: LoadKind }, + /// intermediate address. `volatile` as for [`Self::Load`]; a + /// slot with any volatile access also stays out of mem2reg + /// promotion and slot coalescing. + LoadLocal { + off: i64, + kind: LoadKind, + volatile: bool, + }, /// Store to a local / parameter slot. Same shape as /// [`Self::Store`] but with the address represented as a /// constant slot offset, so the emit folds it into the @@ -110,6 +122,7 @@ pub(crate) enum Inst { off: i64, value: ValueId, kind: StoreKind, + volatile: bool, }, /// Load from `base + index * scale`. Folded form of /// `Add(base, Mul/Shl(index, scale))` followed by a `Load`, @@ -117,7 +130,8 @@ pub(crate) enum Inst { /// (`ldr Wt, [Xn, Xm, lsl #log2(scale)]` on aarch64, scaled /// SIB on x86_64). `scale` is in bytes and matches the /// natural width of `kind` (1 for I8/U8, 2 for I16/U16, 4 for - /// I32/U32, 8 for I64). + /// I32/U32, 8 for I64). Carries no volatile flag: `index_fold` + /// leaves volatile accesses on the plain `Load` / `Store` forms. LoadIndexed { base: ValueId, index: ValueId, @@ -281,6 +295,9 @@ pub(crate) enum Inst { /// (control transfers out). TailExt(i64), /// Whole-struct memory copy. + /// TODO: carries no volatile flag; a copy of a volatile-qualified + /// aggregate (C99 6.7.3p6) is not marked. Scalar volatile + /// accesses ride `Load` / `Store`, which cover the defined uses. Mcpy { dst: ValueId, src: ValueId, diff --git a/src/c5/object/dwarf_reloc.rs b/src/c5/object/dwarf_reloc.rs index 9a8c7442a..5f4beb3d5 100644 --- a/src/c5/object/dwarf_reloc.rs +++ b/src/c5/object/dwarf_reloc.rs @@ -1357,7 +1357,7 @@ fn decompose_pointer_chain(type_tag: i64) -> Option { const STRUCT_BASE: i64 = 1000; const STRUCT_STRIDE: i64 = 1000; let unsigned = (type_tag & UNSIGNED_BIT) != 0; - let bare = type_tag & !UNSIGNED_BIT; + let bare = crate::c5::compiler::types::strip_unsigned(type_tag); if bare < 0 { return None; } @@ -1417,7 +1417,7 @@ fn base_type_for_leaf( ) -> Option { const UNSIGNED_BIT: i64 = 1 << 30; let unsigned = (leaf & UNSIGNED_BIT) != 0; - let bare = leaf & !UNSIGNED_BIT; + let bare = crate::c5::compiler::types::strip_unsigned(leaf); let desc = if bare == Ty::Bool as i64 { BaseTypeDesc { name: "_Bool", diff --git a/src/c5/object/elf_reloc.rs b/src/c5/object/elf_reloc.rs index 74c9a0d91..40ed64eae 100644 --- a/src/c5/object/elf_reloc.rs +++ b/src/c5/object/elf_reloc.rs @@ -257,14 +257,13 @@ fn e_machine_for(machine: Machine) -> u16 { /// COPY-relocated data import (`environ`), whose `st_size` the loader /// compares against the host symbol's. fn data_global_byte_size(sym: &crate::c5::symbol::Symbol) -> u64 { - use crate::c5::compiler::types::is_pointer_ty; + use crate::c5::compiler::types::{is_pointer_ty, strip_unsigned}; use crate::c5::token::Ty; - const UNSIGNED_BIT: i64 = 1 << 30; let ty = sym.type_; let elem: u64 = if is_pointer_ty(ty) { 8 } else { - let stripped = ty & !UNSIGNED_BIT; + let stripped = strip_unsigned(ty); if stripped == Ty::Char as i64 || stripped == Ty::Bool as i64 { 1 } else if stripped == Ty::Short as i64 { diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index 6cdb64c5a..60cdc9f3d 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1542,6 +1542,11 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ // an operand; the fix routes through r13 (outside both // `caller_gprs` and `callee_gprs`). ("ssa_va_start_va_copy_aliasing.c", 0), + // C99 6.7.3p6 / 5.1.2.3p2 volatile access preservation (the + // setjmp variant lives only in the native lists; setjmp is not + // wired for the JIT lane). + ("volatile_ptr_alias_loop.c", 0), + ("volatile_unused_read.c", 0), // `thread_local_*.c` aren't here -- the JIT path's host is // macOS arm64 in this repo, where TLS lowering isn't // implemented yet (Mach-O __thread_data + dyld diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index f4f6dadbf..b82f84fdb 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -703,6 +703,12 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ // expansions in the codegen replace the missing CRT // surface. ("setjmp_longjmp_roundtrip.c", 0), + // C99 7.13.2.1p3 / 6.7.3p6 / 5.1.2.3p2: volatile objects keep + // their post-longjmp value, are re-read through aliases, and + // unused volatile reads still execute. + ("volatile_setjmp_longjmp.c", 0), + ("volatile_ptr_alias_loop.c", 0), + ("volatile_unused_read.c", 0), ("struct_basic.c", 25), ("struct_linked_list.c", 10), ("global_initializer_int.c", 141), diff --git a/src/c5/vm/ssa.rs b/src/c5/vm/ssa.rs index da40d3fff..2dcd86182 100644 --- a/src/c5/vm/ssa.rs +++ b/src/c5/vm/ssa.rs @@ -803,7 +803,9 @@ fn run_inst( frame.regs[v as usize] = (prog.tls_base as i64).wrapping_add(*off); return Ok(()); } - Inst::Load { addr, disp, kind } => { + Inst::Load { + addr, disp, kind, .. + } => { let a = frame.regs[*addr as usize].wrapping_add(*disp as i64); if a & CODE_ADDR_MASK != 0 || a < 0 @@ -823,6 +825,7 @@ fn run_inst( disp, value, kind, + .. } => { let a = frame.regs[*addr as usize].wrapping_add(*disp as i64); if a & CODE_ADDR_MASK != 0 @@ -842,14 +845,16 @@ fn run_inst( frame.regs[v as usize] = stored; return Ok(()); } - Inst::LoadLocal { off, kind } => { + Inst::LoadLocal { off, kind, .. } => { let addr = frame.slot_addr(*off).ok_or_else(|| { C5Error::Runtime(format!("vm_ssa: LoadLocal: slot {off} out of range")) })?; frame.regs[v as usize] = load_from_memory(mem, addr, *kind)?; return Ok(()); } - Inst::StoreLocal { off, value, kind } => { + Inst::StoreLocal { + off, value, kind, .. + } => { let addr = frame.slot_addr(*off).ok_or_else(|| { C5Error::Runtime(format!("vm_ssa: StoreLocal: slot {off} out of range")) })?; diff --git a/tests/fixtures/c/volatile_ptr_alias_loop.c b/tests/fixtures/c/volatile_ptr_alias_loop.c new file mode 100644 index 000000000..5ced3d794 --- /dev/null +++ b/tests/fixtures/c/volatile_ptr_alias_loop.c @@ -0,0 +1,16 @@ +/* C99 6.7.3p6: a loop whose controlling expression reads a volatile + flag must re-read it on every iteration; the body writes the flag + through a pointer alias, so any cached read diverges. */ +int main(void) { + volatile int flag = 0; + volatile int *p = &flag; + int iters = 0; + while (flag < 3) { + *p = flag + 1; + iters++; + if (iters > 10) { + return 1; + } + } + return iters == 3 ? 0 : 2; +} diff --git a/tests/fixtures/c/volatile_setjmp_longjmp.c b/tests/fixtures/c/volatile_setjmp_longjmp.c new file mode 100644 index 000000000..691a51bf2 --- /dev/null +++ b/tests/fixtures/c/volatile_setjmp_longjmp.c @@ -0,0 +1,16 @@ +/* C99 7.13.2.1p3: after longjmp, a volatile-qualified auto object + modified between setjmp and longjmp keeps its last stored value. + The slot must stay memory-resident (no mem2reg promotion) so the + post-longjmp read observes the store. */ +#include + +static jmp_buf env; + +int main(void) { + volatile int x = 1; + if (setjmp(env) == 0) { + x = 2; + longjmp(env, 1); + } + return x == 2 ? 0 : 1; +} diff --git a/tests/fixtures/c/volatile_unused_read.c b/tests/fixtures/c/volatile_unused_read.c new file mode 100644 index 000000000..fa47203f9 --- /dev/null +++ b/tests/fixtures/c/volatile_unused_read.c @@ -0,0 +1,12 @@ +/* C99 5.1.2.3p2: reading a volatile object is a side effect; an + expression statement consisting of just that read still performs + the access at every optimization level. The values are checked + afterward so the program also exercises the load results. */ +volatile int ready = 5; + +int main(void) { + ready; + volatile int local = 7; + local; + return (ready == 5 && local == 7) ? 0 : 1; +} From e25f8a30b01b0a585173b4c6a0c5733f68eaf758 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:56:48 -0700 Subject: [PATCH 18/67] tests: snapshots for volatile-honoring codegen Fixtures that declare volatile now keep their accesses in memory as 6.7.3 requires; the drift is confined to those fixtures plus the three new volatile regression fixtures. Co-Authored-By: Claude Fable 5 --- .../asm/add_sub_negative_imm.aarch64.asm | 60 +++-- .../asm/add_sub_negative_imm.x64.asm | 61 +++-- .../asm/add_three_operand_lea.aarch64.asm | 34 ++- .../asm/add_three_operand_lea.x64.asm | 34 ++- .../snapshots/asm/bitwise_not_mvn.aarch64.asm | 62 +++-- tests/snapshots/asm/bitwise_not_mvn.x64.asm | 57 +++-- .../asm/builtin_bit_count.aarch64.asm | 147 +++++------ tests/snapshots/asm/builtin_bit_count.x64.asm | 189 +++++++------- .../asm/builtin_bswap_expect.aarch64.asm | 2 + .../asm/builtin_bswap_expect.x64.asm | 3 +- .../asm/c11_atomic_specifier.aarch64.asm | 8 +- .../asm/c11_atomic_specifier.x64.asm | 9 +- .../asm/clock_monotonic_advances.aarch64.asm | 13 +- .../asm/clock_monotonic_advances.x64.asm | 15 +- .../local_array_partial_init_zero.aarch64.asm | 8 + .../asm/local_array_partial_init_zero.x64.asm | 10 +- .../asm/rotate_variable_count.aarch64.asm | 38 +-- .../asm/rotate_variable_count.x64.asm | 44 ++-- .../snapshots/asm/setjmp_longjmp.aarch64.asm | 26 +- tests/snapshots/asm/setjmp_longjmp.x64.asm | 23 +- .../asm/slot_coalesce_alloca.aarch64.asm | 22 +- .../asm/slot_coalesce_alloca.x64.asm | 24 +- .../strength_reduce_pow2_divmod.aarch64.asm | 173 +++++++------ .../asm/strength_reduce_pow2_divmod.x64.asm | 223 ++++++++++------- .../asm/volatile_ptr_alias_loop.aarch64.asm | 47 ++++ .../asm/volatile_ptr_alias_loop.x64.asm | 48 ++++ .../asm/volatile_setjmp_longjmp.aarch64.asm | 44 ++++ .../asm/volatile_setjmp_longjmp.x64.asm | 45 ++++ .../asm/volatile_unused_read.aarch64.asm | 37 +++ .../asm/volatile_unused_read.x64.asm | 41 +++ tests/snapshots/ssa/add_sub_negative_imm.ssa | 115 +++++---- tests/snapshots/ssa/add_three_operand_lea.ssa | 109 ++++---- tests/snapshots/ssa/bitwise_not_mvn.ssa | 123 ++++----- tests/snapshots/ssa/builtin_bit_count.ssa | 180 ++++++------- tests/snapshots/ssa/builtin_bswap_expect.ssa | 12 +- tests/snapshots/ssa/c11_atomic_specifier.ssa | 12 +- .../ssa/clock_monotonic_advances.ssa | 105 ++++---- .../ssa/local_array_partial_init_zero.ssa | 4 +- tests/snapshots/ssa/rotate_variable_count.ssa | 50 ++-- tests/snapshots/ssa/setjmp_longjmp.ssa | 20 +- .../ssa/setjmp_longjmp_roundtrip.ssa | 26 +- tests/snapshots/ssa/slot_coalesce_alloca.ssa | 26 +- .../ssa/strength_reduce_pow2_divmod.ssa | 236 +++++++++--------- .../snapshots/ssa/volatile_ptr_alias_loop.ssa | 98 ++++++++ .../snapshots/ssa/volatile_setjmp_longjmp.ssa | 82 ++++++ tests/snapshots/ssa/volatile_unused_read.ssa | 85 +++++++ 46 files changed, 1781 insertions(+), 1049 deletions(-) create mode 100644 tests/snapshots/asm/volatile_ptr_alias_loop.aarch64.asm create mode 100644 tests/snapshots/asm/volatile_ptr_alias_loop.x64.asm create mode 100644 tests/snapshots/asm/volatile_setjmp_longjmp.aarch64.asm create mode 100644 tests/snapshots/asm/volatile_setjmp_longjmp.x64.asm create mode 100644 tests/snapshots/asm/volatile_unused_read.aarch64.asm create mode 100644 tests/snapshots/asm/volatile_unused_read.x64.asm create mode 100644 tests/snapshots/ssa/volatile_ptr_alias_loop.ssa create mode 100644 tests/snapshots/ssa/volatile_setjmp_longjmp.ssa create mode 100644 tests/snapshots/ssa/volatile_unused_read.ssa diff --git a/tests/snapshots/asm/add_sub_negative_imm.aarch64.asm b/tests/snapshots/asm/add_sub_negative_imm.aarch64.asm index b77cf180b..7c8ae87b8 100644 --- a/tests/snapshots/asm/add_sub_negative_imm.aarch64.asm +++ b/tests/snapshots/asm/add_sub_negative_imm.aarch64.asm @@ -14,57 +14,66 @@ Disassembly of section .text: mov x29, sp sub sp, sp, #0x20 mov x0, #0xa // =10 - mov x1, #0x3e8 // =1000 - sub x2, x0, #0x5 - sxtw x2, w2 - cmp x2, #0x5 + stur w0, [x29, #-0x8] + mov x0, #0x3e8 // =1000 + stur x0, [x29, #-0x10] + ldursw x0, [x29, #-0x8] + sub x0, x0, #0x5 + sxtw x0, w0 + cmp x0, #0x5 b.eq mov x0, #0x1 // =1 add sp, sp, #0x20 ldp x29, x30, [sp], #0x10 ret - sub x2, x0, #0xa - sxtw x2, w2 - cmp x2, #0x0 + ldursw x0, [x29, #-0x8] + sub x0, x0, #0xa + sxtw x0, w0 + cmp x0, #0x0 b.eq mov x0, #0x2 // =2 add sp, sp, #0x20 ldp x29, x30, [sp], #0x10 ret - add x2, x0, #0x7 - sxtw x2, w2 - cmp x2, #0x11 + ldursw x0, [x29, #-0x8] + add x0, x0, #0x7 + sxtw x0, w0 + cmp x0, #0x11 b.eq mov x0, #0x3 // =3 add sp, sp, #0x20 ldp x29, x30, [sp], #0x10 ret - sub x2, x1, #0x64 - cmp x2, #0x384 + ldur x0, [x29, #-0x10] + sub x0, x0, #0x64 + cmp x0, #0x384 b.eq mov x0, #0x4 // =4 add sp, sp, #0x20 ldp x29, x30, [sp], #0x10 ret - add x1, x1, #0x64 - cmp x1, #0x44c + ldur x0, [x29, #-0x10] + add x0, x0, #0x64 + cmp x0, #0x44c b.eq mov x0, #0x5 // =5 add sp, sp, #0x20 ldp x29, x30, [sp], #0x10 ret - sub x1, x0, #0xfff - sxtw x1, w1 + ldursw x0, [x29, #-0x8] + sub x0, x0, #0xfff + sxtw x0, w0 mov x17, #0xf00b // =61451 movk x17, #0xffff, lsl #16 movk x17, #0xffff, lsl #32 movk x17, #0xffff, lsl #48 - cmp x1, x17 + cmp x0, x17 b.eq mov x0, #0x6 // =6 add sp, sp, #0x20 ldp x29, x30, [sp], #0x10 ret + ldursw x0, [x29, #-0x8] mov x17, #0xf000 // =61440 movk x17, #0xffff, lsl #16 movk x17, #0xffff, lsl #32 @@ -81,18 +90,21 @@ Disassembly of section .text: add sp, sp, #0x20 ldp x29, x30, [sp], #0x10 ret - mov x2, #0x0 // =0 - mov x1, #0x5 // =5 - sxtw x0, w1 + mov x1, #0x0 // =0 + mov x0, #0x5 // =5 + stur w0, [x29, #-0x20] + ldursw x0, [x29, #-0x20] cmp x0, #0x0 b.le b - sxtw x0, w1 - sub x1, x0, #0x1 + ldursw x0, [x29, #-0x20] + sub x0, x0, #0x1 + stur w0, [x29, #-0x20] b - add x2, x2, x1 + ldursw x0, [x29, #-0x20] + add x1, x1, x0 b - sxtw x0, w2 + sxtw x0, w1 cmp x0, #0xf b.eq mov x0, #0x8 // =8 diff --git a/tests/snapshots/asm/add_sub_negative_imm.x64.asm b/tests/snapshots/asm/add_sub_negative_imm.x64.asm index c309e6399..d3ba4d596 100644 --- a/tests/snapshots/asm/add_sub_negative_imm.x64.asm +++ b/tests/snapshots/asm/add_sub_negative_imm.x64.asm @@ -15,53 +15,62 @@ Disassembly of section .text: movq %rsp, %rbp subq $0x20, %rsp movl $0xa, %eax - movl $0x3e8, %ecx # imm = 0x3E8 - leaq -0x5(%rax), %rdx - movslq %edx, %rdx - cmpq $0x5, %rdx + movl %eax, -0x8(%rbp) + movl $0x3e8, %eax # imm = 0x3E8 + movq %rax, -0x10(%rbp) + movslq -0x8(%rbp), %rax + addq $-0x5, %rax + movslq %eax, %rax + cmpq $0x5, %rax je movl $0x1, %eax addq $0x20, %rsp popq %rbp retq - leaq -0xa(%rax), %rdx - movslq %edx, %rdx - testq %rdx, %rdx + movslq -0x8(%rbp), %rax + addq $-0xa, %rax + movslq %eax, %rax + testq %rax, %rax je movl $0x2, %eax addq $0x20, %rsp popq %rbp retq - leaq 0x7(%rax), %rdx - movslq %edx, %rdx - cmpq $0x11, %rdx + movslq -0x8(%rbp), %rax + subq $-0x7, %rax + movslq %eax, %rax + cmpq $0x11, %rax je movl $0x3, %eax addq $0x20, %rsp popq %rbp retq - leaq -0x64(%rcx), %rdx - cmpq $0x384, %rdx # imm = 0x384 + movq -0x10(%rbp), %rax + addq $-0x64, %rax + cmpq $0x384, %rax # imm = 0x384 je movl $0x4, %eax addq $0x20, %rsp popq %rbp retq - subq $-0x64, %rcx - cmpq $0x44c, %rcx # imm = 0x44C + movq -0x10(%rbp), %rax + subq $-0x64, %rax + cmpq $0x44c, %rax # imm = 0x44C je movl $0x5, %eax addq $0x20, %rsp popq %rbp retq - leaq -0xfff(%rax), %rcx - movslq %ecx, %rcx - cmpq $-0xff5, %rcx # imm = 0xF00B + movslq -0x8(%rbp), %rax + addq $-0xfff, %rax # imm = 0xF001 + movslq %eax, %rax + cmpq $-0xff5, %rax # imm = 0xF00B je movl $0x6, %eax addq $0x20, %rsp popq %rbp retq + movslq -0x8(%rbp), %rax addq $-0x1000, %rax # imm = 0xF000 movslq %eax, %rax cmpq $-0xff6, %rax # imm = 0xF00A @@ -70,18 +79,21 @@ Disassembly of section .text: addq $0x20, %rsp popq %rbp retq - xorq %rdx, %rdx - movl $0x5, %ecx - movslq %ecx, %rax + xorq %rcx, %rcx + movl $0x5, %eax + movl %eax, -0x20(%rbp) + movslq -0x20(%rbp), %rax testq %rax, %rax jle jmp - movslq %ecx, %rax - leaq -0x1(%rax), %rcx + movslq -0x20(%rbp), %rax + decq %rax + movl %eax, -0x20(%rbp) jmp - addq %rcx, %rdx + movslq -0x20(%rbp), %rax + addq %rax, %rcx jmp - movslq %edx, %rax + movslq %ecx, %rax cmpq $0xf, %rax je movl $0x8, %eax @@ -92,3 +104,4 @@ Disassembly of section .text: addq $0x20, %rsp popq %rbp retq + addb %al, (%rax) diff --git a/tests/snapshots/asm/add_three_operand_lea.aarch64.asm b/tests/snapshots/asm/add_three_operand_lea.aarch64.asm index 5ce2abccb..a405ebb00 100644 --- a/tests/snapshots/asm/add_three_operand_lea.aarch64.asm +++ b/tests/snapshots/asm/add_three_operand_lea.aarch64.asm @@ -14,18 +14,27 @@ Disassembly of section .text: mov x29, sp sub sp, sp, #0x30 mov x0, #0x3 // =3 - mov x1, #0x4 // =4 - mov x2, #0x5 // =5 - add x3, x0, x1 - cmp x3, #0x7 + stur x0, [x29, #-0x8] + mov x0, #0x4 // =4 + stur x0, [x29, #-0x10] + mov x0, #0x5 // =5 + stur x0, [x29, #-0x18] + ldur x0, [x29, #-0x8] + ldur x1, [x29, #-0x10] + add x0, x0, x1 + cmp x0, #0x7 b.eq mov x0, #0x1 // =1 add sp, sp, #0x30 ldp x29, x30, [sp], #0x10 ret - add x3, x0, x1 - add x0, x0, x2 - add x0, x3, x0 + ldur x0, [x29, #-0x8] + ldur x1, [x29, #-0x10] + add x0, x0, x1 + ldur x1, [x29, #-0x8] + ldur x2, [x29, #-0x18] + add x1, x1, x2 + add x0, x0, x1 cmp x0, #0xf b.eq mov x0, #0x2 // =2 @@ -36,6 +45,9 @@ Disassembly of section .text: movk x0, #0xffff, lsl #16 movk x0, #0xffff, lsl #32 movk x0, #0xffff, lsl #48 + stur x0, [x29, #-0x8] + ldur x0, [x29, #-0x8] + ldur x1, [x29, #-0x10] add x0, x0, x1 mov x17, #0xffff // =65535 movk x17, #0xffff, lsl #16 @@ -49,7 +61,11 @@ Disassembly of section .text: ret mov x0, #0x9400 // =37888 movk x0, #0x7735, lsl #16 - add x0, x0, x0 + stur w0, [x29, #-0x20] + stur w0, [x29, #-0x28] + ldursw x0, [x29, #-0x20] + ldursw x1, [x29, #-0x28] + add x0, x0, x1 sxtw x0, w0 mov x17, #0x2800 // =10240 movk x17, #0xee6b, lsl #16 @@ -65,6 +81,8 @@ Disassembly of section .text: movk x0, #0xffff, lsl #16 movk x0, #0xffff, lsl #32 movk x0, #0x7fff, lsl #48 + stur x0, [x29, #-0x30] + ldur x0, [x29, #-0x30] add x0, x0, #0x1 mov x17, #-0x8000000000000000 // =-9223372036854775808 cmp x0, x17 diff --git a/tests/snapshots/asm/add_three_operand_lea.x64.asm b/tests/snapshots/asm/add_three_operand_lea.x64.asm index 3e941fcdf..cd09c7828 100644 --- a/tests/snapshots/asm/add_three_operand_lea.x64.asm +++ b/tests/snapshots/asm/add_three_operand_lea.x64.asm @@ -15,18 +15,27 @@ Disassembly of section .text: movq %rsp, %rbp subq $0x30, %rsp movl $0x3, %eax - movl $0x4, %ecx - movl $0x5, %edx - leaq (%rax,%rcx), %rsi - cmpq $0x7, %rsi + movq %rax, -0x8(%rbp) + movl $0x4, %eax + movq %rax, -0x10(%rbp) + movl $0x5, %eax + movq %rax, -0x18(%rbp) + movq -0x8(%rbp), %rax + movq -0x10(%rbp), %rcx + addq %rcx, %rax + cmpq $0x7, %rax je movl $0x1, %eax addq $0x30, %rsp popq %rbp retq - leaq (%rax,%rcx), %rsi - addq %rdx, %rax - addq %rsi, %rax + movq -0x8(%rbp), %rax + movq -0x10(%rbp), %rcx + addq %rcx, %rax + movq -0x8(%rbp), %rcx + movq -0x18(%rbp), %rdx + addq %rdx, %rcx + addq %rcx, %rax cmpq $0xf, %rax je movl $0x2, %eax @@ -34,6 +43,9 @@ Disassembly of section .text: popq %rbp retq movabsq $-0x5, %rax + movq %rax, -0x8(%rbp) + movq -0x8(%rbp), %rax + movq -0x10(%rbp), %rcx addq %rcx, %rax cmpq $-0x1, %rax je @@ -42,7 +54,11 @@ Disassembly of section .text: popq %rbp retq movl $0x77359400, %eax # imm = 0x77359400 - addq %rax, %rax + movl %eax, -0x20(%rbp) + movl %eax, -0x28(%rbp) + movslq -0x20(%rbp), %rax + movslq -0x28(%rbp), %rcx + addq %rcx, %rax movslq %eax, %rax cmpq $-0x1194d800, %rax # imm = 0xEE6B2800 je @@ -51,6 +67,8 @@ Disassembly of section .text: popq %rbp retq movabsq $0x7fffffffffffffff, %rax # imm = 0x7FFFFFFFFFFFFFFF + movq %rax, -0x30(%rbp) + movq -0x30(%rbp), %rax incq %rax movabsq $-0x8000000000000000, %r11 # imm = 0x8000000000000000 cmpq %r11, %rax diff --git a/tests/snapshots/asm/bitwise_not_mvn.aarch64.asm b/tests/snapshots/asm/bitwise_not_mvn.aarch64.asm index 6d26a7082..d48ea59ba 100644 --- a/tests/snapshots/asm/bitwise_not_mvn.aarch64.asm +++ b/tests/snapshots/asm/bitwise_not_mvn.aarch64.asm @@ -33,47 +33,65 @@ Disassembly of section .text: movk x0, #0x89ab, lsl #16 movk x0, #0x4567, lsl #32 movk x0, #0x123, lsl #48 - mov x1, #0x3210 // =12816 - movk x1, #0x7654, lsl #16 - movk x1, #0xba98, lsl #32 - movk x1, #0xfedc, lsl #48 - mov x2, #0x5555 // =21845 - movk x2, #0xaaaa, lsl #16 - movk x2, #0x5555, lsl #32 - movk x2, #0xaaaa, lsl #48 - mvn x3, x0 - mvn x4, x0 - cmp x3, x4 + stur x0, [x29, #-0x8] + mov x0, #0x3210 // =12816 + movk x0, #0x7654, lsl #16 + movk x0, #0xba98, lsl #32 + movk x0, #0xfedc, lsl #48 + stur x0, [x29, #-0x10] + mov x0, #0x5555 // =21845 + movk x0, #0xaaaa, lsl #16 + movk x0, #0x5555, lsl #32 + movk x0, #0xaaaa, lsl #48 + stur x0, [x29, #-0x18] + ldur x0, [x29, #-0x8] + mvn x0, x0 + ldur x1, [x29, #-0x8] + mvn x1, x1 + cmp x0, x1 b.eq mov x0, #0x1 // =1 add sp, sp, #0x30 ldp x29, x30, [sp], #0x10 ret - mvn x3, x0 - and x3, x3, x1 - mvn x4, x0 - and x4, x4, x1 - cmp x3, x4 + ldur x0, [x29, #-0x8] + ldur x1, [x29, #-0x10] + mvn x0, x0 + and x0, x0, x1 + ldur x1, [x29, #-0x8] + mvn x1, x1 + ldur x2, [x29, #-0x10] + and x1, x1, x2 + cmp x0, x1 b.eq mov x0, #0x2 // =2 add sp, sp, #0x30 ldp x29, x30, [sp], #0x10 ret - and x3, x0, x1 - mvn x4, x0 - and x4, x4, x2 - eor x3, x3, x4 + ldur x0, [x29, #-0x8] + ldur x1, [x29, #-0x10] + ldur x2, [x29, #-0x18] and x1, x0, x1 mvn x0, x0 and x0, x0, x2 eor x0, x1, x0 - cmp x3, x0 + ldur x1, [x29, #-0x8] + ldur x2, [x29, #-0x10] + and x1, x1, x2 + ldur x2, [x29, #-0x8] + mvn x2, x2 + ldur x3, [x29, #-0x18] + and x2, x2, x3 + eor x1, x1, x2 + cmp x0, x1 b.eq mov x0, #0x3 // =3 add sp, sp, #0x30 ldp x29, x30, [sp], #0x10 ret mov x0, #0x0 // =0 + stur x0, [x29, #-0x8] + ldur x0, [x29, #-0x8] mvn x0, x0 mov x17, #0xffff // =65535 movk x17, #0xffff, lsl #16 @@ -89,6 +107,8 @@ Disassembly of section .text: movk x0, #0xffff, lsl #16 movk x0, #0xffff, lsl #32 movk x0, #0xffff, lsl #48 + stur x0, [x29, #-0x8] + ldur x0, [x29, #-0x8] mvn x0, x0 cmp x0, #0x0 b.eq diff --git a/tests/snapshots/asm/bitwise_not_mvn.x64.asm b/tests/snapshots/asm/bitwise_not_mvn.x64.asm index fcf40fa4a..0757f43cc 100644 --- a/tests/snapshots/asm/bitwise_not_mvn.x64.asm +++ b/tests/snapshots/asm/bitwise_not_mvn.x64.asm @@ -35,47 +35,59 @@ Disassembly of section .text: movq %rsp, %rbp subq $0x30, %rsp movabsq $0x123456789abcdef, %rax # imm = 0x123456789ABCDEF - movabsq $-0x123456789abcdf0, %rcx # imm = 0xFEDCBA9876543210 - movabsq $-0x5555aaaa5555aaab, %rdx # imm = 0xAAAA5555AAAA5555 - movq %rax, %rsi - xorq $-0x1, %rsi - movq %rax, %rdi - xorq $-0x1, %rdi - cmpq %rdi, %rsi + movq %rax, -0x8(%rbp) + movabsq $-0x123456789abcdf0, %rax # imm = 0xFEDCBA9876543210 + movq %rax, -0x10(%rbp) + movabsq $-0x5555aaaa5555aaab, %rax # imm = 0xAAAA5555AAAA5555 + movq %rax, -0x18(%rbp) + movq -0x8(%rbp), %rax + xorq $-0x1, %rax + movq -0x8(%rbp), %rcx + xorq $-0x1, %rcx + cmpq %rcx, %rax je movl $0x1, %eax addq $0x30, %rsp popq %rbp retq - movq %rax, %rsi - xorq $-0x1, %rsi - andq %rcx, %rsi - movq %rax, %rdi - xorq $-0x1, %rdi - andq %rcx, %rdi - cmpq %rdi, %rsi + movq -0x8(%rbp), %rax + movq -0x10(%rbp), %rcx + xorq $-0x1, %rax + andq %rcx, %rax + movq -0x8(%rbp), %rcx + xorq $-0x1, %rcx + movq -0x10(%rbp), %rdx + andq %rdx, %rcx + cmpq %rcx, %rax je movl $0x2, %eax addq $0x30, %rsp popq %rbp retq - movq %rax, %rsi - andq %rcx, %rsi - movq %rax, %rdi - xorq $-0x1, %rdi - andq %rdx, %rdi - xorq %rdi, %rsi + movq -0x8(%rbp), %rax + movq -0x10(%rbp), %rcx + movq -0x18(%rbp), %rdx andq %rax, %rcx xorq $-0x1, %rax andq %rdx, %rax xorq %rcx, %rax - cmpq %rax, %rsi + movq -0x8(%rbp), %rcx + movq -0x10(%rbp), %rdx + andq %rdx, %rcx + movq -0x8(%rbp), %rdx + xorq $-0x1, %rdx + movq -0x18(%rbp), %rsi + andq %rsi, %rdx + xorq %rdx, %rcx + cmpq %rcx, %rax je movl $0x3, %eax addq $0x30, %rsp popq %rbp retq xorq %rax, %rax + movq %rax, -0x8(%rbp) + movq -0x8(%rbp), %rax xorq $-0x1, %rax cmpq $-0x1, %rax je @@ -84,6 +96,8 @@ Disassembly of section .text: popq %rbp retq movabsq $-0x1, %rax + movq %rax, -0x8(%rbp) + movq -0x8(%rbp), %rax xorq $-0x1, %rax testq %rax, %rax je @@ -95,4 +109,5 @@ Disassembly of section .text: addq $0x30, %rsp popq %rbp retq + addb %al, (%rax) addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/builtin_bit_count.aarch64.asm b/tests/snapshots/asm/builtin_bit_count.aarch64.asm index f5fa3feab..087096912 100644 --- a/tests/snapshots/asm/builtin_bit_count.aarch64.asm +++ b/tests/snapshots/asm/builtin_bit_count.aarch64.asm @@ -947,89 +947,93 @@ Disassembly of section .text: ret mov x0, #0xff // =255 movk x0, #0xff, lsl #16 + stur w0, [x29, #-0x8] + ldur w0, [x29, #-0x8] lsr x1, x0, #1 mov x17, #0x5555 // =21845 movk x17, #0x5555, lsl #16 and x1, x1, x17 - sub x1, x0, x1 + sub x0, x0, x1 mov x17, #0x3333 // =13107 movk x17, #0x3333, lsl #16 - and x2, x1, x17 - lsr x1, x1, #2 + and x1, x0, x17 + lsr x0, x0, #2 mov x17, #0x3333 // =13107 movk x17, #0x3333, lsl #16 - and x1, x1, x17 - add x1, x2, x1 - lsr x2, x1, #4 - add x1, x1, x2 + and x0, x0, x17 + add x0, x1, x0 + lsr x1, x0, #4 + add x0, x0, x1 mov x17, #0xf0f // =3855 movk x17, #0xf0f, lsl #16 - and x1, x1, x17 - lsr x2, x1, #8 - add x1, x1, x2 - lsr x2, x1, #16 - add x1, x1, x2 + and x0, x0, x17 + lsr x1, x0, #8 + add x0, x0, x1 + lsr x1, x0, #16 + add x0, x0, x1 mov x17, #0x7f // =127 - and x1, x1, x17 - mov x2, #0x10 // =16 + and x0, x0, x17 + mov x1, #0x10 // =16 + sxtw x0, w0 sxtw x1, w1 - sxtw x2, w2 - cmp x1, x2 - cset x1, eq - cmp x1, #0x0 + cmp x0, x1 + cset x0, eq + cmp x0, #0x0 b.ne mov x0, #0x15 // =21 add sp, sp, #0x20 ldp x29, x30, [sp], #0x10 ret + ldur w0, [x29, #-0x8] + lsr x1, x0, #1 + orr x0, x0, x1 + lsr x1, x0, #2 + orr x0, x0, x1 + lsr x1, x0, #4 + orr x0, x0, x1 + lsr x1, x0, #8 + orr x0, x0, x1 + lsr x1, x0, #16 + orr x0, x0, x1 + mov w0, w0 lsr x1, x0, #1 - orr x1, x0, x1 - lsr x2, x1, #2 - orr x1, x1, x2 - lsr x2, x1, #4 - orr x1, x1, x2 - lsr x2, x1, #8 - orr x1, x1, x2 - lsr x2, x1, #16 - orr x1, x1, x2 - mov w1, w1 - lsr x2, x1, #1 mov x17, #0x5555 // =21845 movk x17, #0x5555, lsl #16 - and x2, x2, x17 - sub x1, x1, x2 + and x1, x1, x17 + sub x0, x0, x1 mov x17, #0x3333 // =13107 movk x17, #0x3333, lsl #16 - and x2, x1, x17 - lsr x1, x1, #2 + and x1, x0, x17 + lsr x0, x0, #2 mov x17, #0x3333 // =13107 movk x17, #0x3333, lsl #16 - and x1, x1, x17 - add x1, x2, x1 - lsr x2, x1, #4 - add x1, x1, x2 + and x0, x0, x17 + add x0, x1, x0 + lsr x1, x0, #4 + add x0, x0, x1 mov x17, #0xf0f // =3855 movk x17, #0xf0f, lsl #16 - and x1, x1, x17 - lsr x2, x1, #8 - add x1, x1, x2 - lsr x2, x1, #16 - add x1, x1, x2 + and x0, x0, x17 + lsr x1, x0, #8 + add x0, x0, x1 + lsr x1, x0, #16 + add x0, x0, x1 mov x17, #0x7f // =127 - and x1, x1, x17 - mov x2, #0x20 // =32 - sub x1, x2, x1 - mov x2, #0x8 // =8 + and x0, x0, x17 + mov x1, #0x20 // =32 + sub x0, x1, x0 + mov x1, #0x8 // =8 + sxtw x0, w0 sxtw x1, w1 - sxtw x2, w2 - cmp x1, x2 - cset x1, eq - cmp x1, #0x0 + cmp x0, x1 + cset x0, eq + cmp x0, #0x0 b.ne mov x0, #0x16 // =22 add sp, sp, #0x20 ldp x29, x30, [sp], #0x10 ret + ldur w0, [x29, #-0x8] sub x1, x0, #0x1 mvn x0, x0 and x0, x1, x0 @@ -1256,51 +1260,54 @@ Disassembly of section .text: ret mov x0, #0xff // =255 movk x0, #0xff, lsl #16 + stur x0, [x29, #-0x10] + ldur x0, [x29, #-0x10] lsr x1, x0, #1 mov x17, #0x5555 // =21845 movk x17, #0x5555, lsl #16 movk x17, #0x5555, lsl #32 movk x17, #0x5555, lsl #48 and x1, x1, x17 - sub x1, x0, x1 + sub x0, x0, x1 mov x17, #0x3333 // =13107 movk x17, #0x3333, lsl #16 movk x17, #0x3333, lsl #32 movk x17, #0x3333, lsl #48 - and x2, x1, x17 - lsr x1, x1, #2 + and x1, x0, x17 + lsr x0, x0, #2 mov x17, #0x3333 // =13107 movk x17, #0x3333, lsl #16 movk x17, #0x3333, lsl #32 movk x17, #0x3333, lsl #48 - and x1, x1, x17 - add x1, x2, x1 - lsr x2, x1, #4 - add x1, x1, x2 + and x0, x0, x17 + add x0, x1, x0 + lsr x1, x0, #4 + add x0, x0, x1 mov x17, #0xf0f // =3855 movk x17, #0xf0f, lsl #16 movk x17, #0xf0f, lsl #32 movk x17, #0xf0f, lsl #48 - and x1, x1, x17 - lsr x2, x1, #8 - add x1, x1, x2 - lsr x2, x1, #16 - add x1, x1, x2 - lsr x2, x1, #32 - add x1, x1, x2 + and x0, x0, x17 + lsr x1, x0, #8 + add x0, x0, x1 + lsr x1, x0, #16 + add x0, x0, x1 + lsr x1, x0, #32 + add x0, x0, x1 mov x17, #0x7f // =127 - and x1, x1, x17 - mov x2, #0x10 // =16 + and x0, x0, x17 + mov x1, #0x10 // =16 + sxtw x0, w0 sxtw x1, w1 - sxtw x2, w2 - cmp x1, x2 - cset x1, eq - cmp x1, #0x0 + cmp x0, x1 + cset x0, eq + cmp x0, #0x0 b.ne mov x0, #0x1c // =28 add sp, sp, #0x20 ldp x29, x30, [sp], #0x10 ret + ldur x0, [x29, #-0x10] sub x1, x0, #0x1 mvn x0, x0 and x0, x1, x0 diff --git a/tests/snapshots/asm/builtin_bit_count.x64.asm b/tests/snapshots/asm/builtin_bit_count.x64.asm index ab0c9b501..e987812b2 100644 --- a/tests/snapshots/asm/builtin_bit_count.x64.asm +++ b/tests/snapshots/asm/builtin_bit_count.x64.asm @@ -870,92 +870,94 @@ Disassembly of section .text: popq %rbp retq movl $0xff00ff, %eax # imm = 0xFF00FF + movl %eax, -0x8(%rbp) + movl -0x8(%rbp), %eax movq %rax, %rcx shrq $0x1, %rcx andq $0x55555555, %rcx # imm = 0x55555555 - movq %rcx, %r10 + subq %rcx, %rax movq %rax, %rcx - subq %r10, %rcx - movq %rcx, %rdx - andq $0x33333333, %rdx # imm = 0x33333333 - shrq $0x2, %rcx andq $0x33333333, %rcx # imm = 0x33333333 - addq %rdx, %rcx - movq %rcx, %rdx - shrq $0x4, %rdx - addq %rdx, %rcx - andq $0xf0f0f0f, %rcx # imm = 0xF0F0F0F - movq %rcx, %rdx - shrq $0x8, %rdx - addq %rdx, %rcx - movq %rcx, %rdx - shrq $0x10, %rdx - addq %rdx, %rcx - andq $0x7f, %rcx - movl $0x10, %edx + shrq $0x2, %rax + andq $0x33333333, %rax # imm = 0x33333333 + addq %rcx, %rax + movq %rax, %rcx + shrq $0x4, %rcx + addq %rcx, %rax + andq $0xf0f0f0f, %rax # imm = 0xF0F0F0F + movq %rax, %rcx + shrq $0x8, %rcx + addq %rcx, %rax + movq %rax, %rcx + shrq $0x10, %rcx + addq %rcx, %rax + andq $0x7f, %rax + movl $0x10, %ecx + movslq %eax, %rax movslq %ecx, %rcx - movslq %edx, %rdx - cmpq %rdx, %rcx - sete %cl - movzbq %cl, %rcx - testq %rcx, %rcx + cmpq %rcx, %rax + sete %al + movzbq %al, %rax + testq %rax, %rax jne movl $0x15, %eax addq $0x20, %rsp popq %rbp retq + movl -0x8(%rbp), %eax movq %rax, %rcx shrq $0x1, %rcx - orq %rax, %rcx - movq %rcx, %rdx - shrq $0x2, %rdx - orq %rdx, %rcx - movq %rcx, %rdx - shrq $0x4, %rdx - orq %rdx, %rcx - movq %rcx, %rdx - shrq $0x8, %rdx - orq %rdx, %rcx - movq %rcx, %rdx - shrq $0x10, %rdx - orq %rdx, %rcx - movl %ecx, %ecx - movq %rcx, %rdx - shrq $0x1, %rdx - andq $0x55555555, %rdx # imm = 0x55555555 - subq %rdx, %rcx - movq %rcx, %rdx - andq $0x33333333, %rdx # imm = 0x33333333 + orq %rcx, %rax + movq %rax, %rcx shrq $0x2, %rcx + orq %rcx, %rax + movq %rax, %rcx + shrq $0x4, %rcx + orq %rcx, %rax + movq %rax, %rcx + shrq $0x8, %rcx + orq %rcx, %rax + movq %rax, %rcx + shrq $0x10, %rcx + orq %rcx, %rax + movl %eax, %eax + movq %rax, %rcx + shrq $0x1, %rcx + andq $0x55555555, %rcx # imm = 0x55555555 + subq %rcx, %rax + movq %rax, %rcx andq $0x33333333, %rcx # imm = 0x33333333 - addq %rdx, %rcx - movq %rcx, %rdx - shrq $0x4, %rdx - addq %rdx, %rcx - andq $0xf0f0f0f, %rcx # imm = 0xF0F0F0F - movq %rcx, %rdx - shrq $0x8, %rdx - addq %rdx, %rcx - movq %rcx, %rdx - shrq $0x10, %rdx - addq %rdx, %rcx - andq $0x7f, %rcx - movl $0x20, %edx - movq %rcx, %r10 - movq %rdx, %rcx - subq %r10, %rcx - movl $0x8, %edx + shrq $0x2, %rax + andq $0x33333333, %rax # imm = 0x33333333 + addq %rcx, %rax + movq %rax, %rcx + shrq $0x4, %rcx + addq %rcx, %rax + andq $0xf0f0f0f, %rax # imm = 0xF0F0F0F + movq %rax, %rcx + shrq $0x8, %rcx + addq %rcx, %rax + movq %rax, %rcx + shrq $0x10, %rcx + addq %rcx, %rax + andq $0x7f, %rax + movl $0x20, %ecx + movq %rax, %r10 + movq %rcx, %rax + subq %r10, %rax + movl $0x8, %ecx + movslq %eax, %rax movslq %ecx, %rcx - movslq %edx, %rdx - cmpq %rdx, %rcx - sete %cl - movzbq %cl, %rcx - testq %rcx, %rcx + cmpq %rcx, %rax + sete %al + movzbq %al, %rax + testq %rax, %rax jne movl $0x16, %eax addq $0x20, %rsp popq %rbp retq + movl -0x8(%rbp), %eax leaq -0x1(%rax), %rcx xorq $-0x1, %rax andq %rcx, %rax @@ -1146,46 +1148,47 @@ Disassembly of section .text: popq %rbp retq movl $0xff00ff, %eax # imm = 0xFF00FF + movq %rax, -0x10(%rbp) + movq -0x10(%rbp), %rax movq %rax, %rcx shrq $0x1, %rcx movabsq $0x5555555555555555, %r11 # imm = 0x5555555555555555 andq %r11, %rcx - movq %rcx, %r10 - movq %rax, %rcx - subq %r10, %rcx - movabsq $0x3333333333333333, %rdx # imm = 0x3333333333333333 - andq %rcx, %rdx - shrq $0x2, %rcx + subq %rcx, %rax + movabsq $0x3333333333333333, %rcx # imm = 0x3333333333333333 + andq %rax, %rcx + shrq $0x2, %rax movabsq $0x3333333333333333, %r11 # imm = 0x3333333333333333 - andq %r11, %rcx - addq %rdx, %rcx - movq %rcx, %rdx - shrq $0x4, %rdx - addq %rdx, %rcx + andq %r11, %rax + addq %rcx, %rax + movq %rax, %rcx + shrq $0x4, %rcx + addq %rcx, %rax movabsq $0xf0f0f0f0f0f0f0f, %r11 # imm = 0xF0F0F0F0F0F0F0F - andq %r11, %rcx - movq %rcx, %rdx - shrq $0x8, %rdx - addq %rdx, %rcx - movq %rcx, %rdx - shrq $0x10, %rdx - addq %rdx, %rcx - movq %rcx, %rdx - shrq $0x20, %rdx - addq %rdx, %rcx - andq $0x7f, %rcx - movl $0x10, %edx + andq %r11, %rax + movq %rax, %rcx + shrq $0x8, %rcx + addq %rcx, %rax + movq %rax, %rcx + shrq $0x10, %rcx + addq %rcx, %rax + movq %rax, %rcx + shrq $0x20, %rcx + addq %rcx, %rax + andq $0x7f, %rax + movl $0x10, %ecx + movslq %eax, %rax movslq %ecx, %rcx - movslq %edx, %rdx - cmpq %rdx, %rcx - sete %cl - movzbq %cl, %rcx - testq %rcx, %rcx + cmpq %rcx, %rax + sete %al + movzbq %al, %rax + testq %rax, %rax jne movl $0x1c, %eax addq $0x20, %rsp popq %rbp retq + movq -0x10(%rbp), %rax leaq -0x1(%rax), %rcx xorq $-0x1, %rax andq %rcx, %rax diff --git a/tests/snapshots/asm/builtin_bswap_expect.aarch64.asm b/tests/snapshots/asm/builtin_bswap_expect.aarch64.asm index 8a8297ee6..367f9a005 100644 --- a/tests/snapshots/asm/builtin_bswap_expect.aarch64.asm +++ b/tests/snapshots/asm/builtin_bswap_expect.aarch64.asm @@ -68,6 +68,8 @@ Disassembly of section .text: ret mov x0, #0xccdd // =52445 movk x0, #0xaabb, lsl #16 + stur w0, [x29, #-0x8] + ldur w0, [x29, #-0x8] mov x17, #0xff // =255 and x1, x0, x17 lsl x1, x1, #24 diff --git a/tests/snapshots/asm/builtin_bswap_expect.x64.asm b/tests/snapshots/asm/builtin_bswap_expect.x64.asm index b39218345..498a282dd 100644 --- a/tests/snapshots/asm/builtin_bswap_expect.x64.asm +++ b/tests/snapshots/asm/builtin_bswap_expect.x64.asm @@ -59,6 +59,8 @@ Disassembly of section .text: popq %rbp retq movl $0xaabbccdd, %eax # imm = 0xAABBCCDD + movl %eax, -0x8(%rbp) + movl -0x8(%rbp), %eax movq %rax, %rcx andq $0xff, %rcx shlq $0x18, %rcx @@ -105,4 +107,3 @@ Disassembly of section .text: addq $0x10, %rsp popq %rbp retq - addb %al, (%rax) diff --git a/tests/snapshots/asm/c11_atomic_specifier.aarch64.asm b/tests/snapshots/asm/c11_atomic_specifier.aarch64.asm index fb52d410b..b5455bdb1 100644 --- a/tests/snapshots/asm/c11_atomic_specifier.aarch64.asm +++ b/tests/snapshots/asm/c11_atomic_specifier.aarch64.asm @@ -89,12 +89,13 @@ Disassembly of section .text: stur w0, [x29, #-0x30] mov x0, #0x63 // =99 mov x1, #0xd // =13 - ldursw x2, [x29, #-0x30] + sturh w1, [x29, #-0x40] + ldursw x1, [x29, #-0x30] mov x17, #0xfff9 // =65529 movk x17, #0xffff, lsl #16 movk x17, #0xffff, lsl #32 movk x17, #0xffff, lsl #48 - cmp x2, x17 + cmp x1, x17 b.eq mov x0, #0x7 // =7 add sp, sp, #0x50 @@ -106,7 +107,8 @@ Disassembly of section .text: add sp, sp, #0x50 ldp x29, x30, [sp], #0x10 ret - cmp x1, #0xd + ldursh x0, [x29, #-0x40] + cmp x0, #0xd b.eq mov x0, #0x9 // =9 add sp, sp, #0x50 diff --git a/tests/snapshots/asm/c11_atomic_specifier.x64.asm b/tests/snapshots/asm/c11_atomic_specifier.x64.asm index 99bf6b633..5363dbf32 100644 --- a/tests/snapshots/asm/c11_atomic_specifier.x64.asm +++ b/tests/snapshots/asm/c11_atomic_specifier.x64.asm @@ -75,8 +75,9 @@ Disassembly of section .text: movl %eax, -0x30(%rbp) movl $0x63, %eax movl $0xd, %ecx - movslq -0x30(%rbp), %rdx - cmpq $-0x7, %rdx + movw %cx, -0x40(%rbp) + movslq -0x30(%rbp), %rcx + cmpq $-0x7, %rcx je movl $0x7, %eax addq $0x50, %rsp @@ -88,7 +89,8 @@ Disassembly of section .text: addq $0x50, %rsp popq %rbp retq - cmpq $0xd, %rcx + movswq -0x40(%rbp), %rax + cmpq $0xd, %rax je movl $0x9, %eax addq $0x50, %rsp @@ -108,4 +110,3 @@ Disassembly of section .text: addq $0x50, %rsp popq %rbp retq - addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/clock_monotonic_advances.aarch64.asm b/tests/snapshots/asm/clock_monotonic_advances.aarch64.asm index 0001d4221..2c9fd8e6f 100644 --- a/tests/snapshots/asm/clock_monotonic_advances.aarch64.asm +++ b/tests/snapshots/asm/clock_monotonic_advances.aarch64.asm @@ -88,18 +88,19 @@ Disassembly of section .text: ldp x29, x30, [sp], #0x10 ret mov x1, #0x0 // =0 - mov x0, x1 - sxtw x2, w1 + stur w1, [x29, #-0x28] + sxtw x0, w1 mov x17, #0x4240 // =16960 movk x17, #0xf, lsl #16 - cmp x2, x17 + cmp x0, x17 b.ge b - sxtw x1, w1 - add x1, x1, #0x1 + sxtw x0, w1 + add x1, x0, #0x1 b + ldursw x0, [x29, #-0x28] add x0, x0, #0x1 - sxtw x0, w0 + stur w0, [x29, #-0x28] b mov x0, #0x1 // =1 sub x1, x29, #0x20 diff --git a/tests/snapshots/asm/clock_monotonic_advances.x64.asm b/tests/snapshots/asm/clock_monotonic_advances.x64.asm index fc3e8e176..9292601ae 100644 --- a/tests/snapshots/asm/clock_monotonic_advances.x64.asm +++ b/tests/snapshots/asm/clock_monotonic_advances.x64.asm @@ -80,16 +80,17 @@ Disassembly of section .text: popq %rbp retq xorq %rcx, %rcx - movq %rcx, %rax - movslq %ecx, %rdx - cmpq $0xf4240, %rdx # imm = 0xF4240 + movl %ecx, -0x28(%rbp) + movslq %ecx, %rax + cmpq $0xf4240, %rax # imm = 0xF4240 jge jmp - movslq %ecx, %rcx - incq %rcx + movslq %ecx, %rax + leaq 0x1(%rax), %rcx jmp + movslq -0x28(%rbp), %rax incq %rax - movslq %eax, %rax + movl %eax, -0x28(%rbp) jmp movl $0x1, %edi leaq -0x20(%rbp), %rsi @@ -145,4 +146,4 @@ Disassembly of section .text: jmp jmp jmp - addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/local_array_partial_init_zero.aarch64.asm b/tests/snapshots/asm/local_array_partial_init_zero.aarch64.asm index 8b8d99b4e..f4d7921df 100644 --- a/tests/snapshots/asm/local_array_partial_init_zero.aarch64.asm +++ b/tests/snapshots/asm/local_array_partial_init_zero.aarch64.asm @@ -26,7 +26,15 @@ Disassembly of section .text: mov w4, w0 str w4, [x1, x3, lsl #2] b + sub x0, x29, #0xa0 mov x1, #0x0 // =0 + ldr w0, [x0] + sub x2, x29, #0xa0 + ldr w2, [x2, #0x9c] + add x0, x0, x2 + mov w0, w0 + stur w0, [x29, #-0xb0] + ldur w0, [x29, #-0xb0] mov x0, x1 add sp, sp, #0xb0 ldp x29, x30, [sp], #0x10 diff --git a/tests/snapshots/asm/local_array_partial_init_zero.x64.asm b/tests/snapshots/asm/local_array_partial_init_zero.x64.asm index bd83f8e7a..6f3bed646 100644 --- a/tests/snapshots/asm/local_array_partial_init_zero.x64.asm +++ b/tests/snapshots/asm/local_array_partial_init_zero.x64.asm @@ -27,7 +27,15 @@ Disassembly of section .text: movl %edi, %esi movl %esi, (%rax,%rdx,4) jmp + leaq -0xa0(%rbp), %rax xorq %rcx, %rcx + movl (%rax), %eax + leaq -0xa0(%rbp), %rdx + movl 0x9c(%rdx), %edx + addq %rdx, %rax + movl %eax, %eax + movl %eax, -0xb0(%rbp) + movl -0xb0(%rbp), %eax movq %rcx, %rax addq $0xb0, %rsp popq %rbp @@ -126,5 +134,3 @@ Disassembly of section .text: addq $0x10, %rsp popq %rbp retq - addb %al, (%rax) - addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/rotate_variable_count.aarch64.asm b/tests/snapshots/asm/rotate_variable_count.aarch64.asm index 19dee3af5..d9bf4ba51 100644 --- a/tests/snapshots/asm/rotate_variable_count.aarch64.asm +++ b/tests/snapshots/asm/rotate_variable_count.aarch64.asm @@ -50,10 +50,9 @@ Disassembly of section .text:
: stp x29, x30, [sp, #-0x10]! mov x29, sp - sub sp, sp, #0x80 + sub sp, sp, #0x70 str x20, [sp] str x21, [sp, #0x8] - str x22, [sp, #0x10] sub x0, x29, #0x30 adrp x1, add x1, x1, @@ -84,59 +83,62 @@ Disassembly of section .text: mov w0, w20 add x20, x0, #0x1 b - mov x21, #0x1 // =1 + mov x0, #0x1 // =1 + stur w0, [x29, #-0x40] b mov x0, #0xcdef // =52719 movk x0, #0x89ab, lsl #16 movk x0, #0x4567, lsl #32 movk x0, #0x123, lsl #48 - ror x20, x0, #0x7 + stur x0, [x29, #-0x48] + ldur x1, [x29, #-0x48] + lsr x1, x1, #7 + ldur x2, [x29, #-0x48] + lsl x2, x2, #57 + orr x20, x1, x2 mov x1, #0x7 // =7 bl cmp x20, x0 b.eq b - sxtw x0, w21 + ldursw x0, [x29, #-0x40] cmp x0, #0x40 b.ge b - sxtw x0, w21 - add x21, x0, #0x1 + ldursw x0, [x29, #-0x40] + add x0, x0, #0x1 + stur w0, [x29, #-0x40] b sub x0, x29, #0x30 mov w1, w20 ldr x0, [x0, x1, lsl #3] - sxtw x1, w21 - sxtw x1, w1 - ror x22, x0, x1 + ldursw x1, [x29, #-0x40] + ror x21, x0, x1 sub x0, x29, #0x30 mov w1, w20 ldr x0, [x0, x1, lsl #3] - sxtw x1, w21 + ldursw x1, [x29, #-0x40] bl - cmp x22, x0 + cmp x21, x0 b.eq b b mov x0, #0x1 // =1 ldr x20, [sp] ldr x21, [sp, #0x8] - ldr x22, [sp, #0x10] - add sp, sp, #0x80 + add sp, sp, #0x70 ldp x29, x30, [sp], #0x10 ret b mov x0, #0x2 // =2 ldr x20, [sp] ldr x21, [sp, #0x8] - ldr x22, [sp, #0x10] - add sp, sp, #0x80 + add sp, sp, #0x70 ldp x29, x30, [sp], #0x10 ret mov x0, #0x0 // =0 ldr x20, [sp] ldr x21, [sp, #0x8] - ldr x22, [sp, #0x10] - add sp, sp, #0x80 + add sp, sp, #0x70 ldp x29, x30, [sp], #0x10 ret diff --git a/tests/snapshots/asm/rotate_variable_count.x64.asm b/tests/snapshots/asm/rotate_variable_count.x64.asm index e0f2892fb..e12af4e80 100644 --- a/tests/snapshots/asm/rotate_variable_count.x64.asm +++ b/tests/snapshots/asm/rotate_variable_count.x64.asm @@ -61,10 +61,9 @@ Disassembly of section .text:
: pushq %rbp movq %rsp, %rbp - subq $0x80, %rsp + subq $0x70, %rsp movq %rbx, (%rsp) movq %r12, 0x8(%rsp) - movq %r13, 0x10(%rsp) leaq -0x30(%rbp), %rax leaq , %rcx pushq %rdx @@ -94,60 +93,61 @@ Disassembly of section .text: movl %ebx, %eax leaq 0x1(%rax), %rbx jmp - movl $0x1, %r12d + movl $0x1, %eax + movl %eax, -0x40(%rbp) jmp movabsq $0x123456789abcdef, %rdi # imm = 0x123456789ABCDEF - movq %rdi, %rbx - rorq $0x7, %rbx + movq %rdi, -0x48(%rbp) + movq -0x48(%rbp), %rax + shrq $0x7, %rax + movq -0x48(%rbp), %rcx + shlq $0x39, %rcx + movq %rax, %rbx + orq %rcx, %rbx movl $0x7, %esi callq cmpq %rax, %rbx je jmp - movslq %r12d, %rax + movslq -0x40(%rbp), %rax cmpq $0x40, %rax jge jmp - movslq %r12d, %rax - leaq 0x1(%rax), %r12 + movslq -0x40(%rbp), %rax + incq %rax + movl %eax, -0x40(%rbp) jmp leaq -0x30(%rbp), %rax movl %ebx, %ecx movq (%rax,%rcx,8), %rax - movslq %r12d, %rcx - movslq %ecx, %rcx - movq %rax, %r13 - rorq %cl, %r13 + movslq -0x40(%rbp), %rcx + movq %rax, %r12 + rorq %cl, %r12 leaq -0x30(%rbp), %rax movl %ebx, %ecx movq (%rax,%rcx,8), %rdi - movslq %r12d, %rsi + movslq -0x40(%rbp), %rsi callq - cmpq %rax, %r13 + cmpq %rax, %r12 je jmp jmp movl $0x1, %eax movq (%rsp), %rbx movq 0x8(%rsp), %r12 - movq 0x10(%rsp), %r13 - addq $0x80, %rsp + addq $0x70, %rsp popq %rbp retq jmp movl $0x2, %eax movq (%rsp), %rbx movq 0x8(%rsp), %r12 - movq 0x10(%rsp), %r13 - addq $0x80, %rsp + addq $0x70, %rsp popq %rbp retq xorq %rax, %rax movq (%rsp), %rbx movq 0x8(%rsp), %r12 - movq 0x10(%rsp), %r13 - addq $0x80, %rsp + addq $0x70, %rsp popq %rbp retq - addb %al, (%rax) - addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/setjmp_longjmp.aarch64.asm b/tests/snapshots/asm/setjmp_longjmp.aarch64.asm index 1e57f42b2..acb009f3d 100644 --- a/tests/snapshots/asm/setjmp_longjmp.aarch64.asm +++ b/tests/snapshots/asm/setjmp_longjmp.aarch64.asm @@ -29,49 +29,53 @@ Disassembly of section .text: mov x29, sp sub sp, sp, #0x250 str x20, [sp] - str x21, [sp, #0x8] str x19, [sp, #0x10] b mov x0, #0xb // =11 ldr x20, [sp] - ldr x21, [sp, #0x8] ldr x19, [sp, #0x10] add sp, sp, #0x250 ldp x29, x30, [sp], #0x10 ret - mov x20, #0x0 // =0 + mov x0, #0x0 // =0 + sub x17, x29, #0x210 + str w0, [x17] sub x0, x29, #0x208 bl sxtw x0, w0 - mov x21, x0 - sxtw x0, w21 + mov x20, x0 + sxtw x0, w20 cmp x0, #0x0 b.ne + sub x16, x29, #0x210 + ldrsw x0, [x16] + add x0, x0, #0x1 + sub x17, x29, #0x210 + str w0, [x17] sub x0, x29, #0x208 mov x1, #0x7 // =7 bl mov x0, #0xc // =12 ldr x20, [sp] - ldr x21, [sp, #0x8] ldr x19, [sp, #0x10] add sp, sp, #0x250 ldp x29, x30, [sp], #0x10 ret - sxtw x0, w21 + sxtw x0, w20 cmp x0, #0x7 b.eq mov x0, #0xd // =13 ldr x20, [sp] - ldr x21, [sp, #0x8] ldr x19, [sp, #0x10] add sp, sp, #0x250 ldp x29, x30, [sp], #0x10 ret - cmp x20, #0x1 + sub x16, x29, #0x210 + ldrsw x0, [x16] + cmp x0, #0x1 b.eq mov x0, #0xe // =14 ldr x20, [sp] - ldr x21, [sp, #0x8] ldr x19, [sp, #0x10] add sp, sp, #0x250 ldp x29, x30, [sp], #0x10 @@ -82,14 +86,12 @@ Disassembly of section .text: b.eq mov x0, #0xf // =15 ldr x20, [sp] - ldr x21, [sp, #0x8] ldr x19, [sp, #0x10] add sp, sp, #0x250 ldp x29, x30, [sp], #0x10 ret mov x0, #0x0 // =0 ldr x20, [sp] - ldr x21, [sp, #0x8] ldr x19, [sp, #0x10] add sp, sp, #0x250 ldp x29, x30, [sp], #0x10 diff --git a/tests/snapshots/asm/setjmp_longjmp.x64.asm b/tests/snapshots/asm/setjmp_longjmp.x64.asm index 53eeb202a..9433b7070 100644 --- a/tests/snapshots/asm/setjmp_longjmp.x64.asm +++ b/tests/snapshots/asm/setjmp_longjmp.x64.asm @@ -27,46 +27,46 @@ Disassembly of section .text: movq %rsp, %rbp subq $0x240, %rsp # imm = 0x240 movq %rbx, (%rsp) - movq %r12, 0x8(%rsp) jmp movl $0xb, %eax movq (%rsp), %rbx - movq 0x8(%rsp), %r12 addq $0x240, %rsp # imm = 0x240 popq %rbp retq - xorq %rbx, %rbx + xorq %rax, %rax + movl %eax, -0x210(%rbp) leaq -0x208(%rbp), %rdi xorl %eax, %eax callq movslq %eax, %rax - movq %rax, %r12 - movslq %r12d, %rax + movq %rax, %rbx + movslq %ebx, %rax testq %rax, %rax jne + movslq -0x210(%rbp), %rax + incq %rax + movl %eax, -0x210(%rbp) leaq -0x208(%rbp), %rdi movl $0x7, %esi callq movl $0xc, %eax movq (%rsp), %rbx - movq 0x8(%rsp), %r12 addq $0x240, %rsp # imm = 0x240 popq %rbp retq - movslq %r12d, %rax + movslq %ebx, %rax cmpq $0x7, %rax je movl $0xd, %eax movq (%rsp), %rbx - movq 0x8(%rsp), %r12 addq $0x240, %rsp # imm = 0x240 popq %rbp retq - cmpq $0x1, %rbx + movslq -0x210(%rbp), %rax + cmpq $0x1, %rax je movl $0xe, %eax movq (%rsp), %rbx - movq 0x8(%rsp), %r12 addq $0x240, %rsp # imm = 0x240 popq %rbp retq @@ -76,14 +76,13 @@ Disassembly of section .text: je movl $0xf, %eax movq (%rsp), %rbx - movq 0x8(%rsp), %r12 addq $0x240, %rsp # imm = 0x240 popq %rbp retq xorq %rax, %rax movq (%rsp), %rbx - movq 0x8(%rsp), %r12 addq $0x240, %rsp # imm = 0x240 popq %rbp retq + addb %al, (%rax) addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/slot_coalesce_alloca.aarch64.asm b/tests/snapshots/asm/slot_coalesce_alloca.aarch64.asm index 5b5ffeb23..09efdbb38 100644 --- a/tests/snapshots/asm/slot_coalesce_alloca.aarch64.asm +++ b/tests/snapshots/asm/slot_coalesce_alloca.aarch64.asm @@ -14,8 +14,8 @@ Disassembly of section .text: mov x29, sp sub sp, sp, #0xe0 sxtw x0, w0 - mov x6, #0x0 // =0 - mov x1, x6 + mov x5, #0x0 // =0 + mov x1, x5 sxtw x2, w1 cmp x2, #0x18 b.ge @@ -25,10 +25,12 @@ Disassembly of section .text: b sub x2, x29, #0xc0 sxtw x3, w1 - add x4, x3, #0x1 - sxtw x4, w4 - mul x4, x4, x0 - str x4, [x2, x3, lsl #3] + lsl x4, x3, #3 + add x2, x2, x4 + add x3, x3, #0x1 + sxtw x3, w3 + mul x3, x3, x0 + str x3, [x2] b mov x1, #0x0 // =0 sxtw x0, w1 @@ -40,10 +42,12 @@ Disassembly of section .text: b sub x0, x29, #0xc0 sxtw x2, w1 - ldr x0, [x0, x2, lsl #3] - add x6, x6, x0 + lsl x2, x2, #3 + add x0, x0, x2 + ldr x0, [x0] + add x5, x5, x0 b - mov x0, x6 + mov x0, x5 add sp, sp, #0xe0 ldp x29, x30, [sp], #0x10 ret diff --git a/tests/snapshots/asm/slot_coalesce_alloca.x64.asm b/tests/snapshots/asm/slot_coalesce_alloca.x64.asm index 8b500135a..6bc55e22e 100644 --- a/tests/snapshots/asm/slot_coalesce_alloca.x64.asm +++ b/tests/snapshots/asm/slot_coalesce_alloca.x64.asm @@ -15,8 +15,8 @@ Disassembly of section .text: movq %rsp, %rbp subq $0xe0, %rsp movslq %edi, %rdi - xorq %r9, %r9 - movq %r9, %rax + xorq %r8, %r8 + movq %r8, %rax movslq %eax, %rcx cmpq $0x18, %rcx jge @@ -26,10 +26,13 @@ Disassembly of section .text: jmp leaq -0xc0(%rbp), %rcx movslq %eax, %rdx - leaq 0x1(%rdx), %rsi - movslq %esi, %rsi - imulq %rdi, %rsi - movq %rsi, (%rcx,%rdx,8) + movq %rdx, %rsi + shlq $0x3, %rsi + addq %rsi, %rcx + incq %rdx + movslq %edx, %rdx + imulq %rdi, %rdx + movq %rdx, (%rcx) jmp xorq %rcx, %rcx movslq %ecx, %rax @@ -41,10 +44,12 @@ Disassembly of section .text: jmp leaq -0xc0(%rbp), %rax movslq %ecx, %rdx - movq (%rax,%rdx,8), %rax - addq %rax, %r9 + shlq $0x3, %rdx + addq %rdx, %rax + movq (%rax), %rax + addq %rax, %r8 jmp - movq %r9, %rax + movq %r8, %rax addq $0xe0, %rsp popq %rbp retq @@ -166,4 +171,5 @@ Disassembly of section .text: popq %rbp retq jmp + addb %al, (%rax) addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/strength_reduce_pow2_divmod.aarch64.asm b/tests/snapshots/asm/strength_reduce_pow2_divmod.aarch64.asm index 18f697929..08ac89d65 100644 --- a/tests/snapshots/asm/strength_reduce_pow2_divmod.aarch64.asm +++ b/tests/snapshots/asm/strength_reduce_pow2_divmod.aarch64.asm @@ -17,17 +17,20 @@ Disassembly of section .text: movk x0, #0xffff, lsl #16 movk x0, #0xffff, lsl #32 movk x0, #0xffff, lsl #48 + stur w0, [x29, #-0x8] + ldursw x0, [x29, #-0x8] asr x1, x0, #63 lsr x1, x1, #63 - add x1, x0, x1 - asr x1, x1, #1 + add x0, x0, x1 + asr x0, x0, #1 mov x17, #0xfffd // =65533 movk x17, #0xffff, lsl #16 movk x17, #0xffff, lsl #32 movk x17, #0xffff, lsl #48 - cmp x1, x17 - cset x2, ne - cbnz x2, + cmp x0, x17 + cset x1, ne + cbnz x1, + ldursw x0, [x29, #-0x8] asr x1, x0, #63 lsr x1, x1, #63 add x0, x0, x1 @@ -39,8 +42,8 @@ Disassembly of section .text: movk x17, #0xffff, lsl #32 movk x17, #0xffff, lsl #48 cmp x0, x17 - cset x2, ne - cbz x2, + cset x1, ne + cbz x1, mov x0, #0x1 // =1 add sp, sp, #0xa0 ldp x29, x30, [sp], #0x10 @@ -49,17 +52,20 @@ Disassembly of section .text: movk x0, #0xffff, lsl #16 movk x0, #0xffff, lsl #32 movk x0, #0xffff, lsl #48 + stur w0, [x29, #-0x8] + ldursw x0, [x29, #-0x8] asr x1, x0, #63 lsr x1, x1, #60 - add x1, x0, x1 - asr x1, x1, #4 + add x0, x0, x1 + asr x0, x0, #4 mov x17, #0xffff // =65535 movk x17, #0xffff, lsl #16 movk x17, #0xffff, lsl #32 movk x17, #0xffff, lsl #48 - cmp x1, x17 - cset x2, ne - cbnz x2, + cmp x0, x17 + cset x1, ne + cbnz x1, + ldursw x0, [x29, #-0x8] asr x1, x0, #63 lsr x1, x1, #60 add x0, x0, x1 @@ -67,8 +73,8 @@ Disassembly of section .text: and x0, x0, x17 sub x0, x0, x1 cmp x0, #0x0 - cset x2, ne - cbz x2, + cset x1, ne + cbz x1, mov x0, #0x2 // =2 add sp, sp, #0xa0 ldp x29, x30, [sp], #0x10 @@ -77,17 +83,20 @@ Disassembly of section .text: movk x0, #0xffff, lsl #16 movk x0, #0xffff, lsl #32 movk x0, #0xffff, lsl #48 + stur w0, [x29, #-0x8] + ldursw x0, [x29, #-0x8] asr x1, x0, #63 lsr x1, x1, #60 - add x1, x0, x1 - asr x1, x1, #4 + add x0, x0, x1 + asr x0, x0, #4 mov x17, #0xffff // =65535 movk x17, #0xffff, lsl #16 movk x17, #0xffff, lsl #32 movk x17, #0xffff, lsl #48 - cmp x1, x17 - cset x2, ne - cbnz x2, + cmp x0, x17 + cset x1, ne + cbnz x1, + ldursw x0, [x29, #-0x8] asr x1, x0, #63 lsr x1, x1, #60 add x0, x0, x1 @@ -99,20 +108,23 @@ Disassembly of section .text: movk x17, #0xffff, lsl #32 movk x17, #0xffff, lsl #48 cmp x0, x17 - cset x2, ne - cbz x2, + cset x1, ne + cbz x1, mov x0, #0x3 // =3 add sp, sp, #0xa0 ldp x29, x30, [sp], #0x10 ret mov x0, #0x64 // =100 + stur w0, [x29, #-0x8] + ldursw x0, [x29, #-0x8] asr x1, x0, #63 lsr x1, x1, #61 - add x1, x0, x1 - asr x1, x1, #3 - cmp x1, #0xc - cset x2, ne - cbnz x2, + add x0, x0, x1 + asr x0, x0, #3 + cmp x0, #0xc + cset x1, ne + cbnz x1, + ldursw x0, [x29, #-0x8] asr x1, x0, #63 lsr x1, x1, #61 add x0, x0, x1 @@ -120,8 +132,8 @@ Disassembly of section .text: and x0, x0, x17 sub x0, x0, x1 cmp x0, #0x4 - cset x2, ne - cbz x2, + cset x1, ne + cbz x1, mov x0, #0x4 // =4 add sp, sp, #0xa0 ldp x29, x30, [sp], #0x10 @@ -129,16 +141,19 @@ Disassembly of section .text: mov x0, #0x80000000 // =2147483648 movk x0, #0xffff, lsl #32 movk x0, #0xffff, lsl #48 + stur w0, [x29, #-0x8] + ldursw x0, [x29, #-0x8] asr x1, x0, #63 lsr x1, x1, #63 - add x1, x0, x1 - asr x1, x1, #1 + add x0, x0, x1 + asr x0, x0, #1 mov x17, #0xc0000000 // =3221225472 movk x17, #0xffff, lsl #32 movk x17, #0xffff, lsl #48 - cmp x1, x17 - cset x2, ne - cbnz x2, + cmp x0, x17 + cset x1, ne + cbnz x1, + ldursw x0, [x29, #-0x8] asr x1, x0, #63 lsr x1, x1, #63 add x0, x0, x1 @@ -146,40 +161,46 @@ Disassembly of section .text: and x0, x0, x17 sub x0, x0, x1 cmp x0, #0x0 - cset x2, ne - cbz x2, + cset x1, ne + cbz x1, mov x0, #0x5 // =5 add sp, sp, #0xa0 ldp x29, x30, [sp], #0x10 ret mov x0, #0xffff // =65535 movk x0, #0xffff, lsl #16 - lsr x1, x0, #1 + stur w0, [x29, #-0x10] + ldur w0, [x29, #-0x10] + lsr x0, x0, #1 mov x17, #0xffff // =65535 movk x17, #0x7fff, lsl #16 - cmp x1, x17 - cset x2, ne - cbnz x2, + cmp x0, x17 + cset x1, ne + cbnz x1, + ldur w0, [x29, #-0x10] mov x17, #0x1 // =1 and x0, x0, x17 cmp x0, #0x1 - cset x2, ne - cbz x2, + cset x1, ne + cbz x1, mov x0, #0x6 // =6 add sp, sp, #0xa0 ldp x29, x30, [sp], #0x10 ret mov x0, #0x80000000 // =2147483648 - lsr x1, x0, #4 + stur w0, [x29, #-0x10] + ldur w0, [x29, #-0x10] + lsr x0, x0, #4 mov x17, #0x8000000 // =134217728 - cmp x1, x17 - cset x2, ne - cbnz x2, + cmp x0, x17 + cset x1, ne + cbnz x1, + ldur w0, [x29, #-0x10] mov x17, #0xf // =15 and x0, x0, x17 cmp x0, #0x0 - cset x2, ne - cbz x2, + cset x1, ne + cbz x1, mov x0, #0x7 // =7 add sp, sp, #0xa0 ldp x29, x30, [sp], #0x10 @@ -188,16 +209,19 @@ Disassembly of section .text: movk x0, #0xffed, lsl #16 movk x0, #0xffff, lsl #32 movk x0, #0xffff, lsl #48 - asr x1, x0, #63 - lsr x1, x1, #54 - add x1, x0, x1 + stur x0, [x29, #-0x38] + ldur x1, [x29, #-0x38] + asr x2, x1, #63 + lsr x2, x2, #54 + add x1, x1, x2 asr x1, x1, #10 mov x2, #0x3ff // =1023 - add x2, x0, x2 - asr x2, x2, #10 - cmp x1, x2 - cset x2, ne - cbnz x2, + add x0, x0, x2 + asr x0, x0, #10 + cmp x1, x0 + cset x1, ne + cbnz x1, + ldur x0, [x29, #-0x38] asr x1, x0, #63 lsr x1, x1, #54 add x0, x0, x1 @@ -214,21 +238,24 @@ Disassembly of section .text: and x1, x1, x17 sub x1, x1, x2 cmp x0, x1 - cset x2, ne - cbz x2, + cset x1, ne + cbz x1, mov x0, #0x8 // =8 add sp, sp, #0xa0 ldp x29, x30, [sp], #0x10 ret mov x0, #-0x8000000000000000 // =-9223372036854775808 + stur x0, [x29, #-0x38] + ldur x0, [x29, #-0x38] asr x1, x0, #63 lsr x1, x1, #63 - add x1, x0, x1 - asr x1, x1, #1 + add x0, x0, x1 + asr x0, x0, #1 mov x17, #-0x4000000000000000 // =-4611686018427387904 - cmp x1, x17 - cset x2, ne - cbnz x2, + cmp x0, x17 + cset x1, ne + cbnz x1, + ldur x0, [x29, #-0x38] asr x1, x0, #63 lsr x1, x1, #63 add x0, x0, x1 @@ -236,8 +263,8 @@ Disassembly of section .text: and x0, x0, x17 sub x0, x0, x1 cmp x0, #0x0 - cset x2, ne - cbz x2, + cset x1, ne + cbz x1, mov x0, #0x9 // =9 add sp, sp, #0xa0 ldp x29, x30, [sp], #0x10 @@ -246,19 +273,22 @@ Disassembly of section .text: movk x0, #0xffff, lsl #16 movk x0, #0xffff, lsl #32 movk x0, #0xffff, lsl #48 - lsr x1, x0, #1 + stur x0, [x29, #-0x40] + ldur x0, [x29, #-0x40] + lsr x0, x0, #1 mov x17, #0xffff // =65535 movk x17, #0xffff, lsl #16 movk x17, #0xffff, lsl #32 movk x17, #0x7fff, lsl #48 - cmp x1, x17 - cset x2, ne - cbnz x2, + cmp x0, x17 + cset x1, ne + cbnz x1, + ldur x0, [x29, #-0x40] mov x17, #0xff // =255 and x0, x0, x17 cmp x0, #0xff - cset x2, ne - cbz x2, + cset x1, ne + cbz x1, mov x0, #0xa // =10 add sp, sp, #0xa0 ldp x29, x30, [sp], #0x10 @@ -267,6 +297,8 @@ Disassembly of section .text: movk x0, #0xffff, lsl #16 movk x0, #0xffff, lsl #32 movk x0, #0xffff, lsl #48 + stur w0, [x29, #-0x8] + ldursw x0, [x29, #-0x8] mov x17, #0xfffb // =65531 movk x17, #0xffff, lsl #16 movk x17, #0xffff, lsl #32 @@ -274,6 +306,7 @@ Disassembly of section .text: cmp x0, x17 cset x1, ne cbnz x1, + ldursw x0, [x29, #-0x8] mov x1, #0x0 // =0 cbz x1, mov x0, #0xb // =11 diff --git a/tests/snapshots/asm/strength_reduce_pow2_divmod.x64.asm b/tests/snapshots/asm/strength_reduce_pow2_divmod.x64.asm index 130021bbb..3202a769c 100644 --- a/tests/snapshots/asm/strength_reduce_pow2_divmod.x64.asm +++ b/tests/snapshots/asm/strength_reduce_pow2_divmod.x64.asm @@ -15,16 +15,19 @@ Disassembly of section .text: movq %rsp, %rbp subq $0xa0, %rsp movabsq $-0x7, %rax + movl %eax, -0x8(%rbp) + movslq -0x8(%rbp), %rax movq %rax, %rcx sarq $0x3f, %rcx shrq $0x3f, %rcx - addq %rax, %rcx - sarq $0x1, %rcx - cmpq $-0x3, %rcx - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + addq %rcx, %rax + sarq $0x1, %rax + cmpq $-0x3, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx jne + movslq -0x8(%rbp), %rax movq %rax, %rcx sarq $0x3f, %rcx shrq $0x3f, %rcx @@ -32,25 +35,28 @@ Disassembly of section .text: andq $0x1, %rax subq %rcx, %rax cmpq $-0x1, %rax - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx je movl $0x1, %eax addq $0xa0, %rsp popq %rbp retq movabsq $-0x10, %rax + movl %eax, -0x8(%rbp) + movslq -0x8(%rbp), %rax movq %rax, %rcx sarq $0x3f, %rcx shrq $0x3c, %rcx - addq %rax, %rcx - sarq $0x4, %rcx - cmpq $-0x1, %rcx - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + addq %rcx, %rax + sarq $0x4, %rax + cmpq $-0x1, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx jne + movslq -0x8(%rbp), %rax movq %rax, %rcx sarq $0x3f, %rcx shrq $0x3c, %rcx @@ -58,25 +64,28 @@ Disassembly of section .text: andq $0xf, %rax subq %rcx, %rax testq %rax, %rax - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx je movl $0x2, %eax addq $0xa0, %rsp popq %rbp retq movabsq $-0x11, %rax + movl %eax, -0x8(%rbp) + movslq -0x8(%rbp), %rax movq %rax, %rcx sarq $0x3f, %rcx shrq $0x3c, %rcx - addq %rax, %rcx - sarq $0x4, %rcx - cmpq $-0x1, %rcx - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + addq %rcx, %rax + sarq $0x4, %rax + cmpq $-0x1, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx jne + movslq -0x8(%rbp), %rax movq %rax, %rcx sarq $0x3f, %rcx shrq $0x3c, %rcx @@ -84,25 +93,28 @@ Disassembly of section .text: andq $0xf, %rax subq %rcx, %rax cmpq $-0x1, %rax - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx je movl $0x3, %eax addq $0xa0, %rsp popq %rbp retq movl $0x64, %eax + movl %eax, -0x8(%rbp) + movslq -0x8(%rbp), %rax movq %rax, %rcx sarq $0x3f, %rcx shrq $0x3d, %rcx - addq %rax, %rcx - sarq $0x3, %rcx - cmpq $0xc, %rcx - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + addq %rcx, %rax + sarq $0x3, %rax + cmpq $0xc, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx jne + movslq -0x8(%rbp), %rax movq %rax, %rcx sarq $0x3f, %rcx shrq $0x3d, %rcx @@ -110,25 +122,28 @@ Disassembly of section .text: andq $0x7, %rax subq %rcx, %rax cmpq $0x4, %rax - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx je movl $0x4, %eax addq $0xa0, %rsp popq %rbp retq movabsq $-0x80000000, %rax # imm = 0x80000000 + movl %eax, -0x8(%rbp) + movslq -0x8(%rbp), %rax movq %rax, %rcx sarq $0x3f, %rcx shrq $0x3f, %rcx - addq %rax, %rcx - sarq $0x1, %rcx - cmpq $-0x40000000, %rcx # imm = 0xC0000000 - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + addq %rcx, %rax + sarq $0x1, %rax + cmpq $-0x40000000, %rax # imm = 0xC0000000 + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx jne + movslq -0x8(%rbp), %rax movq %rax, %rcx sarq $0x3f, %rcx shrq $0x3f, %rcx @@ -136,64 +151,71 @@ Disassembly of section .text: andq $0x1, %rax subq %rcx, %rax testq %rax, %rax - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx je movl $0x5, %eax addq $0xa0, %rsp popq %rbp retq movl $0xffffffff, %eax # imm = 0xFFFFFFFF - movq %rax, %rcx - shrq $0x1, %rcx - cmpq $0x7fffffff, %rcx # imm = 0x7FFFFFFF - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + movl %eax, -0x10(%rbp) + movl -0x10(%rbp), %eax + shrq $0x1, %rax + cmpq $0x7fffffff, %rax # imm = 0x7FFFFFFF + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx jne + movl -0x10(%rbp), %eax andq $0x1, %rax cmpq $0x1, %rax - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx je movl $0x6, %eax addq $0xa0, %rsp popq %rbp retq movl $0x80000000, %eax # imm = 0x80000000 - movq %rax, %rcx - shrq $0x4, %rcx - cmpq $0x8000000, %rcx # imm = 0x8000000 - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + movl %eax, -0x10(%rbp) + movl -0x10(%rbp), %eax + shrq $0x4, %rax + cmpq $0x8000000, %rax # imm = 0x8000000 + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx jne + movl -0x10(%rbp), %eax andq $0xf, %rax testq %rax, %rax - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx je movl $0x7, %eax addq $0xa0, %rsp popq %rbp retq movabsq $-0x12d687, %rax # imm = 0xFFED2979 - movq %rax, %rcx - sarq $0x3f, %rcx - shrq $0x36, %rcx - addq %rax, %rcx + movq %rax, -0x38(%rbp) + movq -0x38(%rbp), %rcx + movq %rcx, %rdx + sarq $0x3f, %rdx + shrq $0x36, %rdx + addq %rdx, %rcx sarq $0xa, %rcx movl $0x3ff, %edx # imm = 0x3FF - addq %rax, %rdx - sarq $0xa, %rdx - cmpq %rdx, %rcx - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + addq %rdx, %rax + sarq $0xa, %rax + cmpq %rax, %rcx + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx jne + movq -0x38(%rbp), %rax movq %rax, %rcx sarq $0x3f, %rcx shrq $0x36, %rcx @@ -206,27 +228,30 @@ Disassembly of section .text: andq $0x3ff, %rcx # imm = 0x3FF subq %rdx, %rcx cmpq %rcx, %rax - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx je movl $0x8, %eax addq $0xa0, %rsp popq %rbp retq movabsq $-0x8000000000000000, %rax # imm = 0x8000000000000000 + movq %rax, -0x38(%rbp) + movq -0x38(%rbp), %rax movq %rax, %rcx sarq $0x3f, %rcx shrq $0x3f, %rcx - addq %rax, %rcx - sarq $0x1, %rcx + addq %rcx, %rax + sarq $0x1, %rax movabsq $-0x4000000000000000, %r11 # imm = 0xC000000000000000 - movq %rcx, %rdx - cmpq %r11, %rcx - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + movq %rax, %rcx + cmpq %r11, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx jne + movq -0x38(%rbp), %rax movq %rax, %rcx sarq $0x3f, %rcx shrq $0x3f, %rcx @@ -234,40 +259,45 @@ Disassembly of section .text: andq $0x1, %rax subq %rcx, %rax testq %rax, %rax - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx je movl $0x9, %eax addq $0xa0, %rsp popq %rbp retq movabsq $-0x1, %rax - movq %rax, %rcx - shrq $0x1, %rcx + movq %rax, -0x40(%rbp) + movq -0x40(%rbp), %rax + shrq $0x1, %rax movabsq $0x7fffffffffffffff, %r11 # imm = 0x7FFFFFFFFFFFFFFF - movq %rcx, %rdx - cmpq %r11, %rcx - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + movq %rax, %rcx + cmpq %r11, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx jne + movq -0x40(%rbp), %rax andq $0xff, %rax cmpq $0xff, %rax - setne %dl - movzbq %dl, %rdx - testq %rdx, %rdx + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx je movl $0xa, %eax addq $0xa0, %rsp popq %rbp retq movabsq $-0x5, %rax + movl %eax, -0x8(%rbp) + movslq -0x8(%rbp), %rax cmpq $-0x5, %rax setne %cl movzbq %cl, %rcx testq %rcx, %rcx jne + movslq -0x8(%rbp), %rax xorq %rcx, %rcx testq %rcx, %rcx je @@ -291,3 +321,4 @@ Disassembly of section .text: jmp jmp addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/volatile_ptr_alias_loop.aarch64.asm b/tests/snapshots/asm/volatile_ptr_alias_loop.aarch64.asm new file mode 100644 index 000000000..64920fc27 --- /dev/null +++ b/tests/snapshots/asm/volatile_ptr_alias_loop.aarch64.asm @@ -0,0 +1,47 @@ + +volatile_ptr_alias_loop.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x20 + mov x1, #0x0 // =0 + stur w1, [x29, #-0x8] + sub x0, x29, #0x8 + stur x0, [x29, #-0x10] + ldursw x0, [x29, #-0x8] + cmp x0, #0x3 + b.ge + ldur x0, [x29, #-0x10] + ldursw x2, [x29, #-0x8] + add x2, x2, #0x1 + str w2, [x0] + add x1, x1, #0x1 + sxtw x0, w1 + cmp x0, #0xa + b.le + b + sxtw x0, w1 + cmp x0, #0x3 + b.ne + b + mov x0, #0x1 // =1 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + b + mov x1, #0x0 // =0 + b + mov x1, #0x2 // =2 + mov x0, x1 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/volatile_ptr_alias_loop.x64.asm b/tests/snapshots/asm/volatile_ptr_alias_loop.x64.asm new file mode 100644 index 000000000..9380e032e --- /dev/null +++ b/tests/snapshots/asm/volatile_ptr_alias_loop.x64.asm @@ -0,0 +1,48 @@ + +volatile_ptr_alias_loop.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x20, %rsp + xorq %rcx, %rcx + movl %ecx, -0x8(%rbp) + leaq -0x8(%rbp), %rax + movq %rax, -0x10(%rbp) + movslq -0x8(%rbp), %rax + cmpq $0x3, %rax + jge + movq -0x10(%rbp), %rax + movslq -0x8(%rbp), %rdx + incq %rdx + movl %edx, (%rax) + incq %rcx + movslq %ecx, %rax + cmpq $0xa, %rax + jle + jmp + movslq %ecx, %rax + cmpq $0x3, %rax + jne + jmp + movl $0x1, %eax + addq $0x20, %rsp + popq %rbp + retq + jmp + xorq %rcx, %rcx + jmp + movl $0x2, %ecx + movq %rcx, %rax + addq $0x20, %rsp + popq %rbp + retq diff --git a/tests/snapshots/asm/volatile_setjmp_longjmp.aarch64.asm b/tests/snapshots/asm/volatile_setjmp_longjmp.aarch64.asm new file mode 100644 index 000000000..6f3173e21 --- /dev/null +++ b/tests/snapshots/asm/volatile_setjmp_longjmp.aarch64.asm @@ -0,0 +1,44 @@ + +volatile_setjmp_longjmp.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x2a0 // =672 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x40 + str x20, [sp] + str x19, [sp, #0x10] + mov x0, #0x1 // =1 + stur w0, [x29, #-0x8] + adrp x20, + add x20, x20, + mov x0, x20 + bl + sxtw x0, w0 + cmp x0, #0x0 + b.ne + mov x0, #0x2 // =2 + stur w0, [x29, #-0x8] + mov x1, #0x1 // =1 + mov x0, x20 + bl + uxtb w0, w0 + ldursw x0, [x29, #-0x8] + cmp x0, #0x2 + b.ne + mov x1, #0x0 // =0 + b + mov x1, #0x1 // =1 + mov x0, x1 + ldr x20, [sp] + ldr x19, [sp, #0x10] + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/volatile_setjmp_longjmp.x64.asm b/tests/snapshots/asm/volatile_setjmp_longjmp.x64.asm new file mode 100644 index 000000000..15c66763e --- /dev/null +++ b/tests/snapshots/asm/volatile_setjmp_longjmp.x64.asm @@ -0,0 +1,45 @@ + +volatile_setjmp_longjmp.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x30, %rsp + movq %rbx, (%rsp) + movl $0x1, %eax + movl %eax, -0x8(%rbp) + leaq , %rbx + movq %rbx, %rdi + xorl %eax, %eax + callq + movslq %eax, %rax + testq %rax, %rax + jne + movl $0x2, %eax + movl %eax, -0x8(%rbp) + movl $0x1, %esi + movq %rbx, %rdi + xorl %eax, %eax + callq + movzbq %al, %rax + movslq -0x8(%rbp), %rax + cmpq $0x2, %rax + jne + xorq %rcx, %rcx + jmp + movl $0x1, %ecx + movq (%rsp), %rbx + movq %rcx, %rax + addq $0x30, %rsp + popq %rbp + retq + addb %al, (%rax) diff --git a/tests/snapshots/asm/volatile_unused_read.aarch64.asm b/tests/snapshots/asm/volatile_unused_read.aarch64.asm new file mode 100644 index 000000000..bd6be7743 --- /dev/null +++ b/tests/snapshots/asm/volatile_unused_read.aarch64.asm @@ -0,0 +1,37 @@ + +volatile_unused_read.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x20 + adrp x0, + add x0, x0, + ldrsw x1, [x0] + mov x1, #0x7 // =7 + stur w1, [x29, #-0x8] + ldursw x1, [x29, #-0x8] + ldrsw x0, [x0] + cmp x0, #0x5 + cset x1, eq + cbz x1, + ldursw x0, [x29, #-0x8] + cmp x0, #0x7 + cset x1, eq + cbz x1, + mov x1, #0x0 // =0 + b + mov x1, #0x1 // =1 + mov x0, x1 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + b diff --git a/tests/snapshots/asm/volatile_unused_read.x64.asm b/tests/snapshots/asm/volatile_unused_read.x64.asm new file mode 100644 index 000000000..c216c17cc --- /dev/null +++ b/tests/snapshots/asm/volatile_unused_read.x64.asm @@ -0,0 +1,41 @@ + +volatile_unused_read.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x20, %rsp + leaq , %rax + movslq (%rax), %rcx + movl $0x7, %ecx + movl %ecx, -0x8(%rbp) + movslq -0x8(%rbp), %rcx + movslq (%rax), %rax + cmpq $0x5, %rax + sete %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movslq -0x8(%rbp), %rax + cmpq $0x7, %rax + sete %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + xorq %rcx, %rcx + jmp + movl $0x1, %ecx + movq %rcx, %rax + addq $0x20, %rsp + popq %rbp + retq + jmp diff --git a/tests/snapshots/ssa/add_sub_negative_imm.ssa b/tests/snapshots/ssa/add_sub_negative_imm.ssa index 6fc5b4d80..1355c00ca 100644 --- a/tests/snapshots/ssa/add_sub_negative_imm.ssa +++ b/tests/snapshots/ssa/add_sub_negative_imm.ssa @@ -5,69 +5,69 @@ fn ent_pc=0 n_params=0 variadic=false locals=4 block 0 start_pc=0 v0 AllocaInit(0) -> - v1 Imm(10) -> x0 - v2 Imm(0) -> x1 - v3 Imm(1000) -> x1 - v4 Imm(0) -> x2 - v5 LoadLocal { off=-1, kind=I32 } -> x2 - v6 BinopI { op=add, lhs=v1, rhs_imm=-5 } -> x2 - v7 BinopI { op=shl, lhs=v6, rhs_imm=32 } -> x6 - v8 Extend { value=v6, kind=I32 } -> x2 - v9 BinopI { op=ne, lhs=v8, rhs_imm=5 } -> x2 + v2 StoreLocal { off=-1, value=v1, kind=I32, volatile } -> - + v3 Imm(1000) -> x0 + v4 StoreLocal { off=-2, value=v3, kind=I64, volatile } -> - + v5 LoadLocal { off=-1, kind=I32, volatile } -> x0 + v6 BinopI { op=add, lhs=v5, rhs_imm=-5 } -> x0 + v7 BinopI { op=shl, lhs=v6, rhs_imm=32 } -> x1 + v8 Extend { value=v6, kind=I32 } -> x0 + v9 BinopI { op=ne, lhs=v8, rhs_imm=5 } -> x0 terminator Bz { cond=v9, target=b2, fall=b1 } (exit_acc=v9) block 1 start_pc=0 v10 Imm(1) -> x0 terminator Return(v10) (exit_acc=v10) block 2 start_pc=0 - v11 LoadLocal { off=-1, kind=I32 } -> x2 - v12 BinopI { op=add, lhs=v1, rhs_imm=-10 } -> x2 - v13 BinopI { op=shl, lhs=v12, rhs_imm=32 } -> x6 - v14 Extend { value=v12, kind=I32 } -> x2 - v15 BinopI { op=ne, lhs=v14, rhs_imm=0 } -> x2 + v11 LoadLocal { off=-1, kind=I32, volatile } -> x0 + v12 BinopI { op=add, lhs=v11, rhs_imm=-10 } -> x0 + v13 BinopI { op=shl, lhs=v12, rhs_imm=32 } -> x1 + v14 Extend { value=v12, kind=I32 } -> x0 + v15 BinopI { op=ne, lhs=v14, rhs_imm=0 } -> x0 terminator Bz { cond=v15, target=b4, fall=b3 } (exit_acc=v15) block 3 start_pc=0 v16 Imm(2) -> x0 terminator Return(v16) (exit_acc=v16) block 4 start_pc=0 - v17 LoadLocal { off=-1, kind=I32 } -> x2 - v18 BinopI { op=sub, lhs=v1, rhs_imm=-7 } -> x2 - v19 BinopI { op=shl, lhs=v18, rhs_imm=32 } -> x6 - v20 Extend { value=v18, kind=I32 } -> x2 - v21 BinopI { op=ne, lhs=v20, rhs_imm=17 } -> x2 + v17 LoadLocal { off=-1, kind=I32, volatile } -> x0 + v18 BinopI { op=sub, lhs=v17, rhs_imm=-7 } -> x0 + v19 BinopI { op=shl, lhs=v18, rhs_imm=32 } -> x1 + v20 Extend { value=v18, kind=I32 } -> x0 + v21 BinopI { op=ne, lhs=v20, rhs_imm=17 } -> x0 terminator Bz { cond=v21, target=b6, fall=b5 } (exit_acc=v21) block 5 start_pc=0 v22 Imm(3) -> x0 terminator Return(v22) (exit_acc=v22) block 6 start_pc=0 - v23 LoadLocal { off=-2, kind=I64 } -> x2 - v24 BinopI { op=add, lhs=v3, rhs_imm=-100 } -> x2 - v25 BinopI { op=ne, lhs=v24, rhs_imm=900 } -> x2 + v23 LoadLocal { off=-2, kind=I64, volatile } -> x0 + v24 BinopI { op=add, lhs=v23, rhs_imm=-100 } -> x0 + v25 BinopI { op=ne, lhs=v24, rhs_imm=900 } -> x0 terminator Bz { cond=v25, target=b8, fall=b7 } (exit_acc=v25) block 7 start_pc=0 v26 Imm(4) -> x0 terminator Return(v26) (exit_acc=v26) block 8 start_pc=0 - v27 LoadLocal { off=-2, kind=I64 } -> x2 - v28 BinopI { op=sub, lhs=v3, rhs_imm=-100 } -> x1 - v29 BinopI { op=ne, lhs=v28, rhs_imm=1100 } -> x1 + v27 LoadLocal { off=-2, kind=I64, volatile } -> x0 + v28 BinopI { op=sub, lhs=v27, rhs_imm=-100 } -> x0 + v29 BinopI { op=ne, lhs=v28, rhs_imm=1100 } -> x0 terminator Bz { cond=v29, target=b10, fall=b9 } (exit_acc=v29) block 9 start_pc=0 v30 Imm(5) -> x0 terminator Return(v30) (exit_acc=v30) block 10 start_pc=0 - v31 LoadLocal { off=-1, kind=I32 } -> x1 - v32 BinopI { op=add, lhs=v1, rhs_imm=-4095 } -> x1 - v33 BinopI { op=shl, lhs=v32, rhs_imm=32 } -> x2 - v34 Extend { value=v32, kind=I32 } -> x1 - v35 Imm(-4085) -> x2 - v36 Imm(-17544941404160) -> x2 - v37 BinopI { op=ne, lhs=v34, rhs_imm=-4085 } -> x1 + v31 LoadLocal { off=-1, kind=I32, volatile } -> x0 + v32 BinopI { op=add, lhs=v31, rhs_imm=-4095 } -> x0 + v33 BinopI { op=shl, lhs=v32, rhs_imm=32 } -> x1 + v34 Extend { value=v32, kind=I32 } -> x0 + v35 Imm(-4085) -> x1 + v36 Imm(-17544941404160) -> x1 + v37 BinopI { op=ne, lhs=v34, rhs_imm=-4085 } -> x0 terminator Bz { cond=v37, target=b12, fall=b11 } (exit_acc=v37) block 11 start_pc=0 v38 Imm(6) -> x0 terminator Return(v38) (exit_acc=v38) block 12 start_pc=0 - v39 LoadLocal { off=-1, kind=I32 } -> x1 - v40 BinopI { op=add, lhs=v1, rhs_imm=-4096 } -> x0 + v39 LoadLocal { off=-1, kind=I32, volatile } -> x0 + v40 BinopI { op=add, lhs=v39, rhs_imm=-4096 } -> x0 v41 BinopI { op=shl, lhs=v40, rhs_imm=32 } -> x1 v42 Extend { value=v40, kind=I32 } -> x0 v43 Imm(-4086) -> x1 @@ -78,39 +78,38 @@ fn ent_pc=0 n_params=0 variadic=false locals=4 v46 Imm(7) -> x0 terminator Return(v46) (exit_acc=v46) block 14 start_pc=0 - v47 Imm(0) -> x2 + v47 Imm(0) -> x1 v48 Imm(0) -> x0 - v49 Imm(5) -> x1 - v50 Imm(0) -> x0 - terminator Jmp(b15) (exit_acc=v49) + v49 Imm(5) -> x0 + v50 StoreLocal { off=-4, value=v49, kind=I32, volatile } -> - + terminator Jmp(b15) (exit_acc=v50) block 15 start_pc=0 - v51 Phi { incoming=[b14:v49, b16:v56], kind=I64 } -> x1 - v52 Phi { incoming=[b14:v47, b16:v60], kind=I64 } -> x2 - v53 Extend { value=v51, kind=I32 } -> x0 - v54 BinopI { op=gt, lhs=v53, rhs_imm=0 } -> x0 - terminator Bz { cond=v54, target=b18, fall=b17 } (exit_acc=v54) + v51 Phi { incoming=[b14:v47, b16:v59], kind=I64 } -> x1 + v52 LoadLocal { off=-4, kind=I32, volatile } -> x0 + v53 BinopI { op=gt, lhs=v52, rhs_imm=0 } -> x0 + terminator Bz { cond=v53, target=b18, fall=b17 } (exit_acc=v53) block 16 start_pc=0 - v55 Extend { value=v51, kind=I32 } -> x0 - v56 BinopI { op=add, lhs=v55, rhs_imm=-1 } -> x1 - v57 Imm(0) -> x0 + v54 LoadLocal { off=-4, kind=I32, volatile } -> x0 + v55 BinopI { op=add, lhs=v54, rhs_imm=-1 } -> x0 + v56 StoreLocal { off=-4, value=v55, kind=I32, volatile } -> - terminator Jmp(b15) (exit_acc=v56) block 17 start_pc=0 - v58 Extend { value=v52, kind=I32 } -> x0 - v59 Extend { value=v51, kind=I32 } -> x0 - v60 Binop { op=add, lhs=v52, rhs=v51 } -> x2 - v61 Imm(0) -> x0 - v62 Extend { value=v60, kind=I32 } -> x0 - terminator Jmp(b16) (exit_acc=v62) + v57 Extend { value=v51, kind=I32 } -> x0 + v58 LoadLocal { off=-4, kind=I32, volatile } -> x0 + v59 Binop { op=add, lhs=v51, rhs=v58 } -> x1 + v60 Imm(0) -> x0 + v61 Extend { value=v59, kind=I32 } -> x0 + terminator Jmp(b16) (exit_acc=v61) block 18 start_pc=0 - v63 Extend { value=v52, kind=I32 } -> x0 - v64 BinopI { op=ne, lhs=v63, rhs_imm=15 } -> x0 - terminator Bz { cond=v64, target=b20, fall=b19 } (exit_acc=v64) + v62 Extend { value=v51, kind=I32 } -> x0 + v63 BinopI { op=ne, lhs=v62, rhs_imm=15 } -> x0 + terminator Bz { cond=v63, target=b20, fall=b19 } (exit_acc=v63) block 19 start_pc=0 - v65 Imm(8) -> x0 - terminator Return(v65) (exit_acc=v65) + v64 Imm(8) -> x0 + terminator Return(v64) (exit_acc=v64) block 20 start_pc=0 - v66 Imm(0) -> x0 - terminator Return(v66) (exit_acc=v66) + v65 Imm(0) -> x0 + terminator Return(v65) (exit_acc=v65) ; --- SSA dump (ok=true) ent_pc=0 --- ; name=__c5_exit fn ent_pc=0 n_params=1 variadic=false locals=1 diff --git a/tests/snapshots/ssa/add_three_operand_lea.ssa b/tests/snapshots/ssa/add_three_operand_lea.ssa index fcac0d9d9..04dee8856 100644 --- a/tests/snapshots/ssa/add_three_operand_lea.ssa +++ b/tests/snapshots/ssa/add_three_operand_lea.ssa @@ -5,73 +5,74 @@ fn ent_pc=0 n_params=0 variadic=false locals=6 block 0 start_pc=0 v0 AllocaInit(0) -> - v1 Imm(3) -> x0 - v2 Imm(0) -> x1 - v3 Imm(4) -> x1 - v4 Imm(0) -> x2 - v5 Imm(5) -> x2 - v6 Imm(0) -> x6 - v7 LoadLocal { off=-1, kind=I64 } -> x6 - v8 LoadLocal { off=-2, kind=I64 } -> x6 - v9 Binop { op=add, lhs=v1, rhs=v3 } -> x6 - v10 BinopI { op=ne, lhs=v9, rhs_imm=7 } -> x6 + v2 StoreLocal { off=-1, value=v1, kind=I64, volatile } -> - + v3 Imm(4) -> x0 + v4 StoreLocal { off=-2, value=v3, kind=I64, volatile } -> - + v5 Imm(5) -> x0 + v6 StoreLocal { off=-3, value=v5, kind=I64, volatile } -> - + v7 LoadLocal { off=-1, kind=I64, volatile } -> x0 + v8 LoadLocal { off=-2, kind=I64, volatile } -> x1 + v9 Binop { op=add, lhs=v7, rhs=v8 } -> x0 + v10 BinopI { op=ne, lhs=v9, rhs_imm=7 } -> x0 terminator Bz { cond=v10, target=b2, fall=b1 } (exit_acc=v10) block 1 start_pc=0 v11 Imm(1) -> x0 terminator Return(v11) (exit_acc=v11) block 2 start_pc=0 - v12 LoadLocal { off=-1, kind=I64 } -> x6 - v13 LoadLocal { off=-2, kind=I64 } -> x6 - v14 Binop { op=add, lhs=v1, rhs=v3 } -> x6 - v15 LoadLocal { off=-3, kind=I64 } -> x7 - v16 Binop { op=add, lhs=v1, rhs=v5 } -> x0 - v17 Binop { op=add, lhs=v14, rhs=v16 } -> x0 - v18 BinopI { op=ne, lhs=v17, rhs_imm=15 } -> x0 - terminator Bz { cond=v18, target=b4, fall=b3 } (exit_acc=v18) + v12 LoadLocal { off=-1, kind=I64, volatile } -> x0 + v13 LoadLocal { off=-2, kind=I64, volatile } -> x1 + v14 Binop { op=add, lhs=v12, rhs=v13 } -> x0 + v15 LoadLocal { off=-1, kind=I64, volatile } -> x1 + v16 LoadLocal { off=-3, kind=I64, volatile } -> x2 + v17 Binop { op=add, lhs=v15, rhs=v16 } -> x1 + v18 Binop { op=add, lhs=v14, rhs=v17 } -> x0 + v19 BinopI { op=ne, lhs=v18, rhs_imm=15 } -> x0 + terminator Bz { cond=v19, target=b4, fall=b3 } (exit_acc=v19) block 3 start_pc=0 - v19 Imm(2) -> x0 - terminator Return(v19) (exit_acc=v19) + v20 Imm(2) -> x0 + terminator Return(v20) (exit_acc=v20) block 4 start_pc=0 - v20 Imm(-5) -> x0 - v21 Imm(0) -> x2 - v22 LoadLocal { off=-1, kind=I64 } -> x2 - v23 LoadLocal { off=-2, kind=I64 } -> x2 - v24 Binop { op=add, lhs=v20, rhs=v3 } -> x0 - v25 BinopI { op=ne, lhs=v24, rhs_imm=-1 } -> x0 - terminator Bz { cond=v25, target=b6, fall=b5 } (exit_acc=v25) + v21 Imm(-5) -> x0 + v22 StoreLocal { off=-1, value=v21, kind=I64, volatile } -> - + v23 LoadLocal { off=-1, kind=I64, volatile } -> x0 + v24 LoadLocal { off=-2, kind=I64, volatile } -> x1 + v25 Binop { op=add, lhs=v23, rhs=v24 } -> x0 + v26 BinopI { op=ne, lhs=v25, rhs_imm=-1 } -> x0 + terminator Bz { cond=v26, target=b6, fall=b5 } (exit_acc=v26) block 5 start_pc=0 - v26 Imm(3) -> x0 - terminator Return(v26) (exit_acc=v26) + v27 Imm(3) -> x0 + terminator Return(v27) (exit_acc=v27) block 6 start_pc=0 - v27 Imm(2000000000) -> x0 - v28 Imm(0) -> x1 - v29 Imm(0) -> x1 - v30 LoadLocal { off=-4, kind=I32 } -> x1 - v31 LoadLocal { off=-5, kind=I32 } -> x1 - v32 Binop { op=add, lhs=v27, rhs=v27 } -> x0 - v33 BinopI { op=shl, lhs=v32, rhs_imm=32 } -> x1 - v34 Extend { value=v32, kind=I32 } -> x0 - v35 Imm(4000000000) -> x1 - v36 Imm(-1266874889709551616) -> x1 - v37 Imm(-294967296) -> x1 - v38 BinopI { op=ne, lhs=v34, rhs_imm=-294967296 } -> x0 - terminator Bz { cond=v38, target=b8, fall=b7 } (exit_acc=v38) + v28 Imm(2000000000) -> x0 + v29 StoreLocal { off=-4, value=v28, kind=I32, volatile } -> - + v30 StoreLocal { off=-5, value=v28, kind=I32, volatile } -> - + v31 LoadLocal { off=-4, kind=I32, volatile } -> x0 + v32 LoadLocal { off=-5, kind=I32, volatile } -> x1 + v33 Binop { op=add, lhs=v31, rhs=v32 } -> x0 + v34 BinopI { op=shl, lhs=v33, rhs_imm=32 } -> x1 + v35 Extend { value=v33, kind=I32 } -> x0 + v36 Imm(4000000000) -> x1 + v37 Imm(-1266874889709551616) -> x1 + v38 Imm(-294967296) -> x1 + v39 BinopI { op=ne, lhs=v35, rhs_imm=-294967296 } -> x0 + terminator Bz { cond=v39, target=b8, fall=b7 } (exit_acc=v39) block 7 start_pc=0 - v39 Imm(4) -> x0 - terminator Return(v39) (exit_acc=v39) + v40 Imm(4) -> x0 + terminator Return(v40) (exit_acc=v40) block 8 start_pc=0 - v40 Imm(9223372036854775807) -> x0 - v41 Imm(0) -> x1 - v42 LoadLocal { off=-6, kind=I64 } -> x1 - v43 BinopI { op=add, lhs=v40, rhs_imm=1 } -> x0 - v44 Imm(-9223372036854775808) -> x1 - v45 BinopI { op=ne, lhs=v43, rhs_imm=-9223372036854775808 } -> x0 - terminator Bz { cond=v45, target=b10, fall=b9 } (exit_acc=v45) + v41 Imm(9223372036854775807) -> x0 + v42 StoreLocal { off=-6, value=v41, kind=I64, volatile } -> - + v43 LoadLocal { off=-6, kind=I64, volatile } -> x0 + v44 BinopI { op=add, lhs=v43, rhs_imm=1 } -> x0 + v45 Imm(-9223372036854775808) -> x1 + v46 BinopI { op=ne, lhs=v44, rhs_imm=-9223372036854775808 } -> x0 + terminator Bz { cond=v46, target=b10, fall=b9 } (exit_acc=v46) block 9 start_pc=0 - v46 Imm(5) -> x0 - terminator Return(v46) (exit_acc=v46) - block 10 start_pc=0 - v47 Imm(0) -> x0 + v47 Imm(5) -> x0 terminator Return(v47) (exit_acc=v47) + block 10 start_pc=0 + v48 Imm(0) -> x0 + terminator Return(v48) (exit_acc=v48) ; --- SSA dump (ok=true) ent_pc=0 --- ; name=__c5_exit fn ent_pc=0 n_params=1 variadic=false locals=1 diff --git a/tests/snapshots/ssa/bitwise_not_mvn.ssa b/tests/snapshots/ssa/bitwise_not_mvn.ssa index 7c03f8fe6..51dc51b79 100644 --- a/tests/snapshots/ssa/bitwise_not_mvn.ssa +++ b/tests/snapshots/ssa/bitwise_not_mvn.ssa @@ -51,86 +51,87 @@ fn ent_pc=3 n_params=0 variadic=false locals=6 block 0 start_pc=0 v0 AllocaInit(0) -> - v1 Imm(81985529216486895) -> x0 - v2 Imm(0) -> x1 - v3 Imm(-81985529216486896) -> x1 - v4 Imm(0) -> x2 - v5 Imm(-6149008514797120171) -> x2 - v6 Imm(0) -> x6 - v7 LoadLocal { off=-1, kind=I64 } -> x6 - v8 Imm(0) -> x6 - v9 BinopI { op=xor, lhs=v1, rhs_imm=-1 } -> x6 - v10 LoadLocal { off=-1, kind=I64 } -> x7 - v11 BinopI { op=xor, lhs=v1, rhs_imm=-1 } -> x7 - v12 Binop { op=ne, lhs=v9, rhs=v11 } -> x6 + v2 StoreLocal { off=-1, value=v1, kind=I64, volatile } -> - + v3 Imm(-81985529216486896) -> x0 + v4 StoreLocal { off=-2, value=v3, kind=I64, volatile } -> - + v5 Imm(-6149008514797120171) -> x0 + v6 StoreLocal { off=-3, value=v5, kind=I64, volatile } -> - + v7 LoadLocal { off=-1, kind=I64, volatile } -> x0 + v8 Imm(0) -> x1 + v9 BinopI { op=xor, lhs=v7, rhs_imm=-1 } -> x0 + v10 LoadLocal { off=-1, kind=I64, volatile } -> x1 + v11 BinopI { op=xor, lhs=v10, rhs_imm=-1 } -> x1 + v12 Binop { op=ne, lhs=v9, rhs=v11 } -> x0 terminator Bz { cond=v12, target=b2, fall=b1 } (exit_acc=v12) block 1 start_pc=0 v13 Imm(1) -> x0 terminator Return(v13) (exit_acc=v13) block 2 start_pc=0 - v14 LoadLocal { off=-1, kind=I64 } -> x6 - v15 LoadLocal { off=-2, kind=I64 } -> x6 - v16 Imm(0) -> x6 - v17 Imm(0) -> x6 - v18 BinopI { op=xor, lhs=v1, rhs_imm=-1 } -> x6 - v19 Binop { op=and, lhs=v18, rhs=v3 } -> x6 - v20 LoadLocal { off=-1, kind=I64 } -> x7 - v21 BinopI { op=xor, lhs=v1, rhs_imm=-1 } -> x7 - v22 LoadLocal { off=-2, kind=I64 } -> x8 - v23 Binop { op=and, lhs=v21, rhs=v3 } -> x7 - v24 Binop { op=ne, lhs=v19, rhs=v23 } -> x6 + v14 LoadLocal { off=-1, kind=I64, volatile } -> x0 + v15 LoadLocal { off=-2, kind=I64, volatile } -> x1 + v16 Imm(0) -> x2 + v17 Imm(0) -> x2 + v18 BinopI { op=xor, lhs=v14, rhs_imm=-1 } -> x0 + v19 Binop { op=and, lhs=v18, rhs=v15 } -> x0 + v20 LoadLocal { off=-1, kind=I64, volatile } -> x1 + v21 BinopI { op=xor, lhs=v20, rhs_imm=-1 } -> x1 + v22 LoadLocal { off=-2, kind=I64, volatile } -> x2 + v23 Binop { op=and, lhs=v21, rhs=v22 } -> x1 + v24 Binop { op=ne, lhs=v19, rhs=v23 } -> x0 terminator Bz { cond=v24, target=b4, fall=b3 } (exit_acc=v24) block 3 start_pc=0 v25 Imm(2) -> x0 terminator Return(v25) (exit_acc=v25) block 4 start_pc=0 - v26 LoadLocal { off=-1, kind=I64 } -> x6 - v27 LoadLocal { off=-2, kind=I64 } -> x6 - v28 LoadLocal { off=-3, kind=I64 } -> x6 + v26 LoadLocal { off=-1, kind=I64, volatile } -> x0 + v27 LoadLocal { off=-2, kind=I64, volatile } -> x1 + v28 LoadLocal { off=-3, kind=I64, volatile } -> x2 v29 Imm(0) -> x6 v30 Imm(0) -> x6 v31 Imm(0) -> x6 - v32 Binop { op=and, lhs=v1, rhs=v3 } -> x6 - v33 BinopI { op=xor, lhs=v1, rhs_imm=-1 } -> x7 - v34 Binop { op=and, lhs=v33, rhs=v5 } -> x7 - v35 Binop { op=xor, lhs=v32, rhs=v34 } -> x6 - v36 LoadLocal { off=-1, kind=I64 } -> x7 - v37 LoadLocal { off=-2, kind=I64 } -> x7 - v38 Binop { op=and, lhs=v1, rhs=v3 } -> x1 - v39 BinopI { op=xor, lhs=v1, rhs_imm=-1 } -> x0 - v40 LoadLocal { off=-3, kind=I64 } -> x7 - v41 Binop { op=and, lhs=v39, rhs=v5 } -> x0 - v42 Binop { op=xor, lhs=v38, rhs=v41 } -> x0 - v43 Binop { op=ne, lhs=v35, rhs=v42 } -> x0 - terminator Bz { cond=v43, target=b6, fall=b5 } (exit_acc=v43) + v32 Binop { op=and, lhs=v26, rhs=v27 } -> x1 + v33 BinopI { op=xor, lhs=v26, rhs_imm=-1 } -> x0 + v34 Binop { op=and, lhs=v33, rhs=v28 } -> x0 + v35 Binop { op=xor, lhs=v32, rhs=v34 } -> x0 + v36 LoadLocal { off=-1, kind=I64, volatile } -> x1 + v37 LoadLocal { off=-2, kind=I64, volatile } -> x2 + v38 Binop { op=and, lhs=v36, rhs=v37 } -> x1 + v39 LoadLocal { off=-1, kind=I64, volatile } -> x2 + v40 BinopI { op=xor, lhs=v39, rhs_imm=-1 } -> x2 + v41 LoadLocal { off=-3, kind=I64, volatile } -> x6 + v42 Binop { op=and, lhs=v40, rhs=v41 } -> x2 + v43 Binop { op=xor, lhs=v38, rhs=v42 } -> x1 + v44 Binop { op=ne, lhs=v35, rhs=v43 } -> x0 + terminator Bz { cond=v44, target=b6, fall=b5 } (exit_acc=v44) block 5 start_pc=0 - v44 Imm(3) -> x0 - terminator Return(v44) (exit_acc=v44) + v45 Imm(3) -> x0 + terminator Return(v45) (exit_acc=v45) block 6 start_pc=0 - v45 Imm(0) -> x0 - v46 Imm(0) -> x1 - v47 LoadLocal { off=-1, kind=I64 } -> x1 - v48 Imm(0) -> x1 - v49 BinopI { op=xor, lhs=v45, rhs_imm=-1 } -> x0 - v50 Imm(-1) -> x1 - v51 BinopI { op=ne, lhs=v49, rhs_imm=-1 } -> x0 - terminator Bz { cond=v51, target=b8, fall=b7 } (exit_acc=v51) + v46 Imm(0) -> x0 + v47 StoreLocal { off=-1, value=v46, kind=I64, volatile } -> - + v48 LoadLocal { off=-1, kind=I64, volatile } -> x0 + v49 Imm(0) -> x1 + v50 BinopI { op=xor, lhs=v48, rhs_imm=-1 } -> x0 + v51 Imm(-1) -> x1 + v52 BinopI { op=ne, lhs=v50, rhs_imm=-1 } -> x0 + terminator Bz { cond=v52, target=b8, fall=b7 } (exit_acc=v52) block 7 start_pc=0 - v52 Imm(4) -> x0 - terminator Return(v52) (exit_acc=v52) + v53 Imm(4) -> x0 + terminator Return(v53) (exit_acc=v53) block 8 start_pc=0 - v53 Imm(-1) -> x0 - v54 Imm(0) -> x1 - v55 LoadLocal { off=-1, kind=I64 } -> x1 - v56 Imm(0) -> x1 - v57 BinopI { op=xor, lhs=v53, rhs_imm=-1 } -> x0 - v58 BinopI { op=ne, lhs=v57, rhs_imm=0 } -> x0 - terminator Bz { cond=v58, target=b10, fall=b9 } (exit_acc=v58) + v54 Imm(-1) -> x0 + v55 StoreLocal { off=-1, value=v54, kind=I64, volatile } -> - + v56 LoadLocal { off=-1, kind=I64, volatile } -> x0 + v57 Imm(0) -> x1 + v58 BinopI { op=xor, lhs=v56, rhs_imm=-1 } -> x0 + v59 BinopI { op=ne, lhs=v58, rhs_imm=0 } -> x0 + terminator Bz { cond=v59, target=b10, fall=b9 } (exit_acc=v59) block 9 start_pc=0 - v59 Imm(5) -> x0 - terminator Return(v59) (exit_acc=v59) - block 10 start_pc=0 - v60 Imm(0) -> x0 + v60 Imm(5) -> x0 terminator Return(v60) (exit_acc=v60) + block 10 start_pc=0 + v61 Imm(0) -> x0 + terminator Return(v61) (exit_acc=v61) ; --- SSA dump (ok=true) ent_pc=0 --- ; name=__c5_exit fn ent_pc=0 n_params=1 variadic=false locals=1 diff --git a/tests/snapshots/ssa/builtin_bit_count.ssa b/tests/snapshots/ssa/builtin_bit_count.ssa index 498db7437..562ed4174 100644 --- a/tests/snapshots/ssa/builtin_bit_count.ssa +++ b/tests/snapshots/ssa/builtin_bit_count.ssa @@ -707,79 +707,79 @@ fn ent_pc=1 n_params=0 variadic=false locals=4 terminator Return(v608) (exit_acc=v608) block 40 start_pc=0 v609 Imm(16711935) -> x0 - v610 Imm(0) -> x1 - v611 LoadLocal { off=-1, kind=U32 } -> x1 - v612 BinopI { op=shru, lhs=v609, rhs_imm=1 } -> x1 + v610 StoreLocal { off=-1, value=v609, kind=I32, volatile } -> - + v611 LoadLocal { off=-1, kind=U32, volatile } -> x0 + v612 BinopI { op=shru, lhs=v611, rhs_imm=1 } -> x1 v613 BinopI { op=and, lhs=v612, rhs_imm=1431655765 } -> x1 - v614 Binop { op=sub, lhs=v609, rhs=v613 } -> x1 - v615 BinopI { op=and, lhs=v614, rhs_imm=858993459 } -> x2 - v616 BinopI { op=shru, lhs=v614, rhs_imm=2 } -> x1 - v617 BinopI { op=and, lhs=v616, rhs_imm=858993459 } -> x1 - v618 Binop { op=add, lhs=v615, rhs=v617 } -> x1 - v619 BinopI { op=shru, lhs=v618, rhs_imm=4 } -> x2 - v620 Binop { op=add, lhs=v618, rhs=v619 } -> x1 - v621 BinopI { op=and, lhs=v620, rhs_imm=252645135 } -> x1 - v622 BinopI { op=shru, lhs=v621, rhs_imm=8 } -> x2 - v623 Binop { op=add, lhs=v621, rhs=v622 } -> x1 - v624 BinopI { op=shru, lhs=v623, rhs_imm=16 } -> x2 - v625 Binop { op=add, lhs=v623, rhs=v624 } -> x1 - v626 BinopI { op=and, lhs=v625, rhs_imm=127 } -> x1 - v627 Imm(16) -> x2 - v628 Extend { value=v626, kind=I32 } -> x1 - v629 Imm(0) -> x6 - v630 Extend { value=v627, kind=I32 } -> x2 - v631 Imm(0) -> x6 - v632 Binop { op=eq, lhs=v628, rhs=v630 } -> x1 - v633 BinopI { op=eq, lhs=v632, rhs_imm=0 } -> x1 + v614 Binop { op=sub, lhs=v611, rhs=v613 } -> x0 + v615 BinopI { op=and, lhs=v614, rhs_imm=858993459 } -> x1 + v616 BinopI { op=shru, lhs=v614, rhs_imm=2 } -> x0 + v617 BinopI { op=and, lhs=v616, rhs_imm=858993459 } -> x0 + v618 Binop { op=add, lhs=v615, rhs=v617 } -> x0 + v619 BinopI { op=shru, lhs=v618, rhs_imm=4 } -> x1 + v620 Binop { op=add, lhs=v618, rhs=v619 } -> x0 + v621 BinopI { op=and, lhs=v620, rhs_imm=252645135 } -> x0 + v622 BinopI { op=shru, lhs=v621, rhs_imm=8 } -> x1 + v623 Binop { op=add, lhs=v621, rhs=v622 } -> x0 + v624 BinopI { op=shru, lhs=v623, rhs_imm=16 } -> x1 + v625 Binop { op=add, lhs=v623, rhs=v624 } -> x0 + v626 BinopI { op=and, lhs=v625, rhs_imm=127 } -> x0 + v627 Imm(16) -> x1 + v628 Extend { value=v626, kind=I32 } -> x0 + v629 Imm(0) -> x2 + v630 Extend { value=v627, kind=I32 } -> x1 + v631 Imm(0) -> x2 + v632 Binop { op=eq, lhs=v628, rhs=v630 } -> x0 + v633 BinopI { op=eq, lhs=v632, rhs_imm=0 } -> x0 terminator Bz { cond=v633, target=b42, fall=b41 } (exit_acc=v633) block 41 start_pc=0 v634 Imm(21) -> x0 terminator Return(v634) (exit_acc=v634) block 42 start_pc=0 - v635 LoadLocal { off=-1, kind=U32 } -> x1 - v636 BinopI { op=shru, lhs=v609, rhs_imm=1 } -> x1 - v637 Binop { op=or, lhs=v609, rhs=v636 } -> x1 - v638 BinopI { op=shru, lhs=v637, rhs_imm=2 } -> x2 - v639 Binop { op=or, lhs=v637, rhs=v638 } -> x1 - v640 BinopI { op=shru, lhs=v639, rhs_imm=4 } -> x2 - v641 Binop { op=or, lhs=v639, rhs=v640 } -> x1 - v642 BinopI { op=shru, lhs=v641, rhs_imm=8 } -> x2 - v643 Binop { op=or, lhs=v641, rhs=v642 } -> x1 - v644 BinopI { op=shru, lhs=v643, rhs_imm=16 } -> x2 - v645 Binop { op=or, lhs=v643, rhs=v644 } -> x1 - v646 BinopI { op=and, lhs=v645, rhs_imm=4294967295 } -> x1 - v647 BinopI { op=shru, lhs=v646, rhs_imm=1 } -> x2 - v648 BinopI { op=and, lhs=v647, rhs_imm=1431655765 } -> x2 - v649 Binop { op=sub, lhs=v646, rhs=v648 } -> x1 - v650 BinopI { op=and, lhs=v649, rhs_imm=858993459 } -> x2 - v651 BinopI { op=shru, lhs=v649, rhs_imm=2 } -> x1 - v652 BinopI { op=and, lhs=v651, rhs_imm=858993459 } -> x1 - v653 Binop { op=add, lhs=v650, rhs=v652 } -> x1 - v654 BinopI { op=shru, lhs=v653, rhs_imm=4 } -> x2 - v655 Binop { op=add, lhs=v653, rhs=v654 } -> x1 - v656 BinopI { op=and, lhs=v655, rhs_imm=252645135 } -> x1 - v657 BinopI { op=shru, lhs=v656, rhs_imm=8 } -> x2 - v658 Binop { op=add, lhs=v656, rhs=v657 } -> x1 - v659 BinopI { op=shru, lhs=v658, rhs_imm=16 } -> x2 - v660 Binop { op=add, lhs=v658, rhs=v659 } -> x1 - v661 BinopI { op=and, lhs=v660, rhs_imm=127 } -> x1 - v662 Imm(32) -> x2 - v663 Binop { op=sub, lhs=v662, rhs=v661 } -> x1 - v664 Imm(8) -> x2 - v665 Extend { value=v663, kind=I32 } -> x1 - v666 Imm(0) -> x6 - v667 Extend { value=v664, kind=I32 } -> x2 - v668 Imm(0) -> x6 - v669 Binop { op=eq, lhs=v665, rhs=v667 } -> x1 - v670 BinopI { op=eq, lhs=v669, rhs_imm=0 } -> x1 + v635 LoadLocal { off=-1, kind=U32, volatile } -> x0 + v636 BinopI { op=shru, lhs=v635, rhs_imm=1 } -> x1 + v637 Binop { op=or, lhs=v635, rhs=v636 } -> x0 + v638 BinopI { op=shru, lhs=v637, rhs_imm=2 } -> x1 + v639 Binop { op=or, lhs=v637, rhs=v638 } -> x0 + v640 BinopI { op=shru, lhs=v639, rhs_imm=4 } -> x1 + v641 Binop { op=or, lhs=v639, rhs=v640 } -> x0 + v642 BinopI { op=shru, lhs=v641, rhs_imm=8 } -> x1 + v643 Binop { op=or, lhs=v641, rhs=v642 } -> x0 + v644 BinopI { op=shru, lhs=v643, rhs_imm=16 } -> x1 + v645 Binop { op=or, lhs=v643, rhs=v644 } -> x0 + v646 BinopI { op=and, lhs=v645, rhs_imm=4294967295 } -> x0 + v647 BinopI { op=shru, lhs=v646, rhs_imm=1 } -> x1 + v648 BinopI { op=and, lhs=v647, rhs_imm=1431655765 } -> x1 + v649 Binop { op=sub, lhs=v646, rhs=v648 } -> x0 + v650 BinopI { op=and, lhs=v649, rhs_imm=858993459 } -> x1 + v651 BinopI { op=shru, lhs=v649, rhs_imm=2 } -> x0 + v652 BinopI { op=and, lhs=v651, rhs_imm=858993459 } -> x0 + v653 Binop { op=add, lhs=v650, rhs=v652 } -> x0 + v654 BinopI { op=shru, lhs=v653, rhs_imm=4 } -> x1 + v655 Binop { op=add, lhs=v653, rhs=v654 } -> x0 + v656 BinopI { op=and, lhs=v655, rhs_imm=252645135 } -> x0 + v657 BinopI { op=shru, lhs=v656, rhs_imm=8 } -> x1 + v658 Binop { op=add, lhs=v656, rhs=v657 } -> x0 + v659 BinopI { op=shru, lhs=v658, rhs_imm=16 } -> x1 + v660 Binop { op=add, lhs=v658, rhs=v659 } -> x0 + v661 BinopI { op=and, lhs=v660, rhs_imm=127 } -> x0 + v662 Imm(32) -> x1 + v663 Binop { op=sub, lhs=v662, rhs=v661 } -> x0 + v664 Imm(8) -> x1 + v665 Extend { value=v663, kind=I32 } -> x0 + v666 Imm(0) -> x2 + v667 Extend { value=v664, kind=I32 } -> x1 + v668 Imm(0) -> x2 + v669 Binop { op=eq, lhs=v665, rhs=v667 } -> x0 + v670 BinopI { op=eq, lhs=v669, rhs_imm=0 } -> x0 terminator Bz { cond=v670, target=b44, fall=b43 } (exit_acc=v670) block 43 start_pc=0 v671 Imm(22) -> x0 terminator Return(v671) (exit_acc=v671) block 44 start_pc=0 - v672 LoadLocal { off=-1, kind=U32 } -> x1 - v673 BinopI { op=sub, lhs=v609, rhs_imm=1 } -> x1 - v674 BinopI { op=xor, lhs=v609, rhs_imm=-1 } -> x0 + v672 LoadLocal { off=-1, kind=U32, volatile } -> x0 + v673 BinopI { op=sub, lhs=v672, rhs_imm=1 } -> x1 + v674 BinopI { op=xor, lhs=v672, rhs_imm=-1 } -> x0 v675 Binop { op=and, lhs=v673, rhs=v674 } -> x0 v676 BinopI { op=and, lhs=v675, rhs_imm=4294967295 } -> x0 v677 BinopI { op=shru, lhs=v676, rhs_imm=1 } -> x1 @@ -934,40 +934,40 @@ fn ent_pc=1 n_params=0 variadic=false locals=4 terminator Return(v807) (exit_acc=v807) block 54 start_pc=0 v808 Imm(16711935) -> x0 - v809 Imm(0) -> x1 - v810 LoadLocal { off=-2, kind=I64 } -> x1 - v811 BinopI { op=shru, lhs=v808, rhs_imm=1 } -> x1 + v809 StoreLocal { off=-2, value=v808, kind=I64, volatile } -> - + v810 LoadLocal { off=-2, kind=I64, volatile } -> x0 + v811 BinopI { op=shru, lhs=v810, rhs_imm=1 } -> x1 v812 BinopI { op=and, lhs=v811, rhs_imm=6148914691236517205 } -> x1 - v813 Binop { op=sub, lhs=v808, rhs=v812 } -> x1 - v814 BinopI { op=and, lhs=v813, rhs_imm=3689348814741910323 } -> x2 - v815 BinopI { op=shru, lhs=v813, rhs_imm=2 } -> x1 - v816 BinopI { op=and, lhs=v815, rhs_imm=3689348814741910323 } -> x1 - v817 Binop { op=add, lhs=v814, rhs=v816 } -> x1 - v818 BinopI { op=shru, lhs=v817, rhs_imm=4 } -> x2 - v819 Binop { op=add, lhs=v817, rhs=v818 } -> x1 - v820 BinopI { op=and, lhs=v819, rhs_imm=1085102592571150095 } -> x1 - v821 BinopI { op=shru, lhs=v820, rhs_imm=8 } -> x2 - v822 Binop { op=add, lhs=v820, rhs=v821 } -> x1 - v823 BinopI { op=shru, lhs=v822, rhs_imm=16 } -> x2 - v824 Binop { op=add, lhs=v822, rhs=v823 } -> x1 - v825 BinopI { op=shru, lhs=v824, rhs_imm=32 } -> x2 - v826 Binop { op=add, lhs=v824, rhs=v825 } -> x1 - v827 BinopI { op=and, lhs=v826, rhs_imm=127 } -> x1 - v828 Imm(16) -> x2 - v829 Extend { value=v827, kind=I32 } -> x1 - v830 Imm(0) -> x6 - v831 Extend { value=v828, kind=I32 } -> x2 - v832 Imm(0) -> x6 - v833 Binop { op=eq, lhs=v829, rhs=v831 } -> x1 - v834 BinopI { op=eq, lhs=v833, rhs_imm=0 } -> x1 + v813 Binop { op=sub, lhs=v810, rhs=v812 } -> x0 + v814 BinopI { op=and, lhs=v813, rhs_imm=3689348814741910323 } -> x1 + v815 BinopI { op=shru, lhs=v813, rhs_imm=2 } -> x0 + v816 BinopI { op=and, lhs=v815, rhs_imm=3689348814741910323 } -> x0 + v817 Binop { op=add, lhs=v814, rhs=v816 } -> x0 + v818 BinopI { op=shru, lhs=v817, rhs_imm=4 } -> x1 + v819 Binop { op=add, lhs=v817, rhs=v818 } -> x0 + v820 BinopI { op=and, lhs=v819, rhs_imm=1085102592571150095 } -> x0 + v821 BinopI { op=shru, lhs=v820, rhs_imm=8 } -> x1 + v822 Binop { op=add, lhs=v820, rhs=v821 } -> x0 + v823 BinopI { op=shru, lhs=v822, rhs_imm=16 } -> x1 + v824 Binop { op=add, lhs=v822, rhs=v823 } -> x0 + v825 BinopI { op=shru, lhs=v824, rhs_imm=32 } -> x1 + v826 Binop { op=add, lhs=v824, rhs=v825 } -> x0 + v827 BinopI { op=and, lhs=v826, rhs_imm=127 } -> x0 + v828 Imm(16) -> x1 + v829 Extend { value=v827, kind=I32 } -> x0 + v830 Imm(0) -> x2 + v831 Extend { value=v828, kind=I32 } -> x1 + v832 Imm(0) -> x2 + v833 Binop { op=eq, lhs=v829, rhs=v831 } -> x0 + v834 BinopI { op=eq, lhs=v833, rhs_imm=0 } -> x0 terminator Bz { cond=v834, target=b56, fall=b55 } (exit_acc=v834) block 55 start_pc=0 v835 Imm(28) -> x0 terminator Return(v835) (exit_acc=v835) block 56 start_pc=0 - v836 LoadLocal { off=-2, kind=I64 } -> x1 - v837 BinopI { op=sub, lhs=v808, rhs_imm=1 } -> x1 - v838 BinopI { op=xor, lhs=v808, rhs_imm=-1 } -> x0 + v836 LoadLocal { off=-2, kind=I64, volatile } -> x0 + v837 BinopI { op=sub, lhs=v836, rhs_imm=1 } -> x1 + v838 BinopI { op=xor, lhs=v836, rhs_imm=-1 } -> x0 v839 Binop { op=and, lhs=v837, rhs=v838 } -> x0 v840 BinopI { op=shru, lhs=v839, rhs_imm=1 } -> x1 v841 BinopI { op=and, lhs=v840, rhs_imm=6148914691236517205 } -> x1 diff --git a/tests/snapshots/ssa/builtin_bswap_expect.ssa b/tests/snapshots/ssa/builtin_bswap_expect.ssa index 2e89e5e6f..e093fa1ad 100644 --- a/tests/snapshots/ssa/builtin_bswap_expect.ssa +++ b/tests/snapshots/ssa/builtin_bswap_expect.ssa @@ -71,19 +71,19 @@ fn ent_pc=0 n_params=0 variadic=false locals=2 terminator Return(v53) (exit_acc=v53) block 6 start_pc=0 v54 Imm(2864434397) -> x0 - v55 Imm(0) -> x1 - v56 LoadLocal { off=-1, kind=U32 } -> x1 - v57 BinopI { op=and, lhs=v54, rhs_imm=255 } -> x1 + v55 StoreLocal { off=-1, value=v54, kind=I32, volatile } -> - + v56 LoadLocal { off=-1, kind=U32, volatile } -> x0 + v57 BinopI { op=and, lhs=v56, rhs_imm=255 } -> x1 v58 BinopI { op=shl, lhs=v57, rhs_imm=24 } -> x1 - v59 BinopI { op=shru, lhs=v54, rhs_imm=8 } -> x2 + v59 BinopI { op=shru, lhs=v56, rhs_imm=8 } -> x2 v60 BinopI { op=and, lhs=v59, rhs_imm=255 } -> x2 v61 BinopI { op=shl, lhs=v60, rhs_imm=16 } -> x2 v62 Binop { op=or, lhs=v58, rhs=v61 } -> x1 - v63 BinopI { op=shru, lhs=v54, rhs_imm=16 } -> x2 + v63 BinopI { op=shru, lhs=v56, rhs_imm=16 } -> x2 v64 BinopI { op=and, lhs=v63, rhs_imm=255 } -> x2 v65 BinopI { op=shl, lhs=v64, rhs_imm=8 } -> x2 v66 Binop { op=or, lhs=v62, rhs=v65 } -> x1 - v67 BinopI { op=shru, lhs=v54, rhs_imm=24 } -> x0 + v67 BinopI { op=shru, lhs=v56, rhs_imm=24 } -> x0 v68 BinopI { op=and, lhs=v67, rhs_imm=255 } -> x0 v69 Binop { op=or, lhs=v66, rhs=v68 } -> x0 v70 BinopI { op=ne, lhs=v69, rhs_imm=3721182122 } -> x0 diff --git a/tests/snapshots/ssa/c11_atomic_specifier.ssa b/tests/snapshots/ssa/c11_atomic_specifier.ssa index 06ae77c33..8bcb10c36 100644 --- a/tests/snapshots/ssa/c11_atomic_specifier.ssa +++ b/tests/snapshots/ssa/c11_atomic_specifier.ssa @@ -73,23 +73,23 @@ fn ent_pc=0 n_params=0 variadic=false locals=9 v43 Imm(99) -> x0 v44 Imm(0) -> x1 v45 Imm(13) -> x1 - v46 Imm(0) -> x2 - v47 LoadLocal { off=-6, kind=I32 } -> x2 - v48 BinopI { op=ne, lhs=v47, rhs_imm=-7 } -> x2 + v46 StoreLocal { off=-8, value=v45, kind=I16, volatile } -> - + v47 LoadLocal { off=-6, kind=I32 } -> x1 + v48 BinopI { op=ne, lhs=v47, rhs_imm=-7 } -> x1 terminator Bz { cond=v48, target=b14, fall=b13 } (exit_acc=v48) block 13 start_pc=0 v49 Imm(7) -> x0 terminator Return(v49) (exit_acc=v49) block 14 start_pc=0 - v50 LoadLocal { off=-7, kind=I64 } -> x2 + v50 LoadLocal { off=-7, kind=I64 } -> x1 v51 BinopI { op=ne, lhs=v43, rhs_imm=99 } -> x0 terminator Bz { cond=v51, target=b16, fall=b15 } (exit_acc=v51) block 15 start_pc=0 v52 Imm(8) -> x0 terminator Return(v52) (exit_acc=v52) block 16 start_pc=0 - v53 LoadLocal { off=-8, kind=I16 } -> x0 - v54 BinopI { op=ne, lhs=v45, rhs_imm=13 } -> x0 + v53 LoadLocal { off=-8, kind=I16, volatile } -> x0 + v54 BinopI { op=ne, lhs=v53, rhs_imm=13 } -> x0 terminator Bz { cond=v54, target=b18, fall=b17 } (exit_acc=v54) block 17 start_pc=0 v55 Imm(9) -> x0 diff --git a/tests/snapshots/ssa/clock_monotonic_advances.ssa b/tests/snapshots/ssa/clock_monotonic_advances.ssa index dec8ae196..0a14025a6 100644 --- a/tests/snapshots/ssa/clock_monotonic_advances.ssa +++ b/tests/snapshots/ssa/clock_monotonic_advances.ssa @@ -69,74 +69,73 @@ fn ent_pc=5 n_params=0 variadic=false locals=11 terminator Return(v40) (exit_acc=v40) block 12 start_pc=0 v41 Imm(0) -> x1 - v42 Imm(0) -> x0 + v42 StoreLocal { off=-5, value=v41, kind=I32, volatile } -> - v43 Imm(0) -> x0 terminator Jmp(b13) (exit_acc=v41) block 13 start_pc=0 - v44 Phi { incoming=[b12:v41, b14:v49], kind=I64 } -> x1 - v45 Phi { incoming=[b12:v41, b14:v54], kind=I64 } -> x0 - v46 Extend { value=v44, kind=I32 } -> x2 - v47 BinopI { op=lt, lhs=v46, rhs_imm=1000000 } -> x2 - terminator Bz { cond=v47, target=b16, fall=b15 } (exit_acc=v47) + v44 Phi { incoming=[b12:v41, b14:v48], kind=I64 } -> x1 + v45 Extend { value=v44, kind=I32 } -> x0 + v46 BinopI { op=lt, lhs=v45, rhs_imm=1000000 } -> x0 + terminator Bz { cond=v46, target=b16, fall=b15 } (exit_acc=v46) block 14 start_pc=0 - v48 Extend { value=v44, kind=I32 } -> x1 - v49 BinopI { op=add, lhs=v48, rhs_imm=1 } -> x1 - v50 Imm(0) -> x2 - terminator Jmp(b13) (exit_acc=v49) + v47 Extend { value=v44, kind=I32 } -> x0 + v48 BinopI { op=add, lhs=v47, rhs_imm=1 } -> x1 + v49 Imm(0) -> x0 + terminator Jmp(b13) (exit_acc=v48) block 15 start_pc=0 - v51 Extend { value=v45, kind=I32 } -> x2 - v52 BinopI { op=add, lhs=v45, rhs_imm=1 } -> x0 - v53 BinopI { op=shl, lhs=v52, rhs_imm=32 } -> x2 - v54 Extend { value=v52, kind=I32 } -> x0 - v55 Imm(0) -> x2 + v50 LoadLocal { off=-5, kind=I32, volatile } -> x0 + v51 BinopI { op=add, lhs=v50, rhs_imm=1 } -> x0 + v52 BinopI { op=shl, lhs=v51, rhs_imm=32 } -> x2 + v53 Extend { value=v51, kind=I32 } -> x2 + v54 StoreLocal { off=-5, value=v51, kind=I32, volatile } -> - terminator Jmp(b14) (exit_acc=v54) block 16 start_pc=0 - v56 Imm(1) -> x7 - v57 LocalAddr(-4) -> x6 - v58 CallExt { binding_idx=2, args=[v56, v57], fp_arg_mask=0x0 } -> x0 - v59 BinopI { op=ne, lhs=v58, rhs_imm=0 } -> x0 - terminator Bz { cond=v59, target=b18, fall=b17 } (exit_acc=v59) + v55 Imm(1) -> x7 + v56 LocalAddr(-4) -> x6 + v57 CallExt { binding_idx=2, args=[v55, v56], fp_arg_mask=0x0 } -> x0 + v58 BinopI { op=ne, lhs=v57, rhs_imm=0 } -> x0 + terminator Bz { cond=v58, target=b18, fall=b17 } (exit_acc=v58) block 17 start_pc=0 - v60 Imm(5) -> x0 - terminator Return(v60) (exit_acc=v60) + v59 Imm(5) -> x0 + terminator Return(v59) (exit_acc=v59) block 18 start_pc=0 - v61 LocalAddr(-4) -> x0 - v62 Load { addr=v61, disp=0, kind=I64 } -> x0 - v63 LocalAddr(-2) -> x1 - v64 Load { addr=v63, disp=0, kind=I64 } -> x1 - v65 Binop { op=lt, lhs=v62, rhs=v64 } -> x0 - terminator Bz { cond=v65, target=b20, fall=b19 } (exit_acc=v65) + v60 LocalAddr(-4) -> x0 + v61 Load { addr=v60, disp=0, kind=I64 } -> x0 + v62 LocalAddr(-2) -> x1 + v63 Load { addr=v62, disp=0, kind=I64 } -> x1 + v64 Binop { op=lt, lhs=v61, rhs=v63 } -> x0 + terminator Bz { cond=v64, target=b20, fall=b19 } (exit_acc=v64) block 19 start_pc=0 - v66 Imm(6) -> x0 - terminator Return(v66) (exit_acc=v66) + v65 Imm(6) -> x0 + terminator Return(v65) (exit_acc=v65) block 20 start_pc=0 - v67 LocalAddr(-4) -> x0 - v68 Load { addr=v67, disp=0, kind=I64 } -> x0 - v69 LocalAddr(-2) -> x1 - v70 Load { addr=v69, disp=0, kind=I64 } -> x1 - v71 Binop { op=eq, lhs=v68, rhs=v70 } -> x1 - v72 Imm(0) -> x0 - terminator Bz { cond=v71, target=b27, fall=b21 } (exit_acc=v71) + v66 LocalAddr(-4) -> x0 + v67 Load { addr=v66, disp=0, kind=I64 } -> x0 + v68 LocalAddr(-2) -> x1 + v69 Load { addr=v68, disp=0, kind=I64 } -> x1 + v70 Binop { op=eq, lhs=v67, rhs=v69 } -> x1 + v71 Imm(0) -> x0 + terminator Bz { cond=v70, target=b27, fall=b21 } (exit_acc=v70) block 21 start_pc=0 - v73 LocalAddr(-4) -> x0 - v74 BinopI { op=add, lhs=v73, rhs_imm=8 } -> x1 - v75 Load { addr=v73, disp=8, kind=I64 } -> x0 - v76 LocalAddr(-2) -> x1 - v77 BinopI { op=add, lhs=v76, rhs_imm=8 } -> x2 - v78 Load { addr=v76, disp=8, kind=I64 } -> x1 - v79 Binop { op=lt, lhs=v75, rhs=v78 } -> x1 - v80 Imm(0) -> x0 - terminator Jmp(b22) (exit_acc=v79) + v72 LocalAddr(-4) -> x0 + v73 BinopI { op=add, lhs=v72, rhs_imm=8 } -> x1 + v74 Load { addr=v72, disp=8, kind=I64 } -> x0 + v75 LocalAddr(-2) -> x1 + v76 BinopI { op=add, lhs=v75, rhs_imm=8 } -> x2 + v77 Load { addr=v75, disp=8, kind=I64 } -> x1 + v78 Binop { op=lt, lhs=v74, rhs=v77 } -> x1 + v79 Imm(0) -> x0 + terminator Jmp(b22) (exit_acc=v78) block 22 start_pc=0 - v81 Phi { incoming=[b27:v71, b21:v79], kind=I64 } -> x1 - v82 LoadLocal { off=-11, kind=I64 } -> x0 - terminator Bz { cond=v81, target=b24, fall=b23 } (exit_acc=v81) + v80 Phi { incoming=[b27:v70, b21:v78], kind=I64 } -> x1 + v81 LoadLocal { off=-11, kind=I64 } -> x0 + terminator Bz { cond=v80, target=b24, fall=b23 } (exit_acc=v80) block 23 start_pc=0 - v83 Imm(7) -> x0 - terminator Return(v83) (exit_acc=v83) + v82 Imm(7) -> x0 + terminator Return(v82) (exit_acc=v82) block 24 start_pc=0 - v84 Imm(0) -> x0 - terminator Return(v84) (exit_acc=v84) + v83 Imm(0) -> x0 + terminator Return(v83) (exit_acc=v83) block 25 start_pc=0 terminator Jmp(b4) block 26 start_pc=0 diff --git a/tests/snapshots/ssa/local_array_partial_init_zero.ssa b/tests/snapshots/ssa/local_array_partial_init_zero.ssa index 47c475d17..a6e53dca7 100644 --- a/tests/snapshots/ssa/local_array_partial_init_zero.ssa +++ b/tests/snapshots/ssa/local_array_partial_init_zero.ssa @@ -37,8 +37,8 @@ fn ent_pc=0 n_params=1 variadic=false locals=22 v23 Load { addr=v20, disp=156, kind=U32 } -> x2 v24 Binop { op=add, lhs=v19, rhs=v23 } -> x0 v25 BinopI { op=and, lhs=v24, rhs_imm=4294967295 } -> x0 - v26 Imm(0) -> x2 - v27 BinopI { op=and, lhs=v25, rhs_imm=4294967295 } -> x0 + v26 StoreLocal { off=-22, value=v25, kind=I32, volatile } -> - + v27 LoadLocal { off=-22, kind=U32, volatile } -> x0 v28 BinopI { op=and, lhs=v27, rhs_imm=255 } -> x0 terminator Return(v18) (exit_acc=v18) ; --- SSA dump (ok=true) ent_pc=1 --- diff --git a/tests/snapshots/ssa/rotate_variable_count.ssa b/tests/snapshots/ssa/rotate_variable_count.ssa index de5901e7c..65a320067 100644 --- a/tests/snapshots/ssa/rotate_variable_count.ssa +++ b/tests/snapshots/ssa/rotate_variable_count.ssa @@ -76,7 +76,7 @@ fn ent_pc=1 n_params=2 variadic=false locals=3 ; --- SSA dump (ok=true) ent_pc=2 --- ; name=main fn ent_pc=2 n_params=0 variadic=false locals=11 - spill_count=0 gpr_used=[3, 12, 13] fp_used=[] + spill_count=0 gpr_used=[3, 12] fp_used=[] block 0 start_pc=0 v0 AllocaInit(0) -> - v1 LocalAddr(-6) -> x0 @@ -102,53 +102,53 @@ fn ent_pc=2 n_params=0 variadic=false locals=11 v17 Imm(0) -> x0 terminator Jmp(b1) (exit_acc=v16) block 3 start_pc=0 - v18 Imm(1) -> x12 - v19 Imm(0) -> x0 - terminator Jmp(b5) (exit_acc=v18) + v18 Imm(1) -> x0 + v19 StoreLocal { off=-8, value=v18, kind=I32, volatile } -> - + terminator Jmp(b5) (exit_acc=v19) block 4 start_pc=0 v20 Imm(81985529216486895) -> x7 - v21 Imm(0) -> x0 - v22 LoadLocal { off=-9, kind=I64 } -> x0 - v23 BinopI { op=shru, lhs=v20, rhs_imm=7 } -> x0 - v24 BinopI { op=shl, lhs=v20, rhs_imm=57 } -> x0 - v25 BinopI { op=ror, lhs=v20, rhs_imm=7 } -> x3 - v26 Imm(7) -> x6 - v27 Call { target_pc=1, args=[v20, v26], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x0 - v28 Binop { op=ne, lhs=v25, rhs=v27 } -> x0 - terminator Bz { cond=v28, target=b12, fall=b11 } (exit_acc=v28) + v21 StoreLocal { off=-9, value=v20, kind=I64, volatile } -> - + v22 LoadLocal { off=-9, kind=I64, volatile } -> x0 + v23 BinopI { op=shru, lhs=v22, rhs_imm=7 } -> x0 + v24 LoadLocal { off=-9, kind=I64, volatile } -> x1 + v25 BinopI { op=shl, lhs=v24, rhs_imm=57 } -> x1 + v26 Binop { op=or, lhs=v23, rhs=v25 } -> x3 + v27 Imm(7) -> x6 + v28 Call { target_pc=1, args=[v20, v27], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x0 + v29 Binop { op=ne, lhs=v26, rhs=v28 } -> x0 + terminator Bz { cond=v29, target=b12, fall=b11 } (exit_acc=v29) block 5 start_pc=0 - v29 Phi { incoming=[b3:v18, b6:v33], kind=I64 } -> x12 - v30 Extend { value=v29, kind=I32 } -> x0 + v30 LoadLocal { off=-8, kind=I32, volatile } -> x0 v31 BinopI { op=lt, lhs=v30, rhs_imm=64 } -> x0 terminator Bz { cond=v31, target=b8, fall=b7 } (exit_acc=v31) block 6 start_pc=0 - v32 Extend { value=v29, kind=I32 } -> x0 - v33 BinopI { op=add, lhs=v32, rhs_imm=1 } -> x12 - v34 Imm(0) -> x0 - terminator Jmp(b5) (exit_acc=v33) + v32 LoadLocal { off=-8, kind=I32, volatile } -> x0 + v33 BinopI { op=add, lhs=v32, rhs_imm=1 } -> x0 + v34 StoreLocal { off=-8, value=v33, kind=I32, volatile } -> - + terminator Jmp(b5) (exit_acc=v34) block 7 start_pc=0 v35 LocalAddr(-6) -> x0 v36 BinopI { op=and, lhs=v6, rhs_imm=4294967295 } -> x1 v37 BinopI { op=shl, lhs=v36, rhs_imm=3 } -> x2 v38 Binop { op=add, lhs=v35, rhs=v37 } -> x2 v39 LoadIndexed { base=v35, index=v36, scale=8, kind=I64 } -> x0 - v40 Extend { value=v29, kind=I32 } -> x1 + v40 LoadLocal { off=-8, kind=I32, volatile } -> x1 v41 Imm(0) -> x2 - v42 Extend { value=v40, kind=I32 } -> x1 + v42 Extend { value=v40, kind=I32 } -> x2 v43 Imm(0) -> x2 - v44 Binop { op=shru, lhs=v39, rhs=v42 } -> x2 + v44 Binop { op=shru, lhs=v39, rhs=v40 } -> x2 v45 Imm(64) -> x2 - v46 Binop { op=sub, lhs=v45, rhs=v42 } -> x2 + v46 Binop { op=sub, lhs=v45, rhs=v40 } -> x2 v47 BinopI { op=shl, lhs=v46, rhs_imm=32 } -> x6 v48 Extend { value=v46, kind=I32 } -> x2 v49 Binop { op=shl, lhs=v39, rhs=v48 } -> x2 - v50 Binop { op=ror, lhs=v39, rhs=v42 } -> x13 + v50 Binop { op=ror, lhs=v39, rhs=v40 } -> x12 v51 LocalAddr(-6) -> x0 v52 BinopI { op=and, lhs=v6, rhs_imm=4294967295 } -> x1 v53 BinopI { op=shl, lhs=v52, rhs_imm=3 } -> x2 v54 Binop { op=add, lhs=v51, rhs=v53 } -> x2 v55 LoadIndexed { base=v51, index=v52, scale=8, kind=I64 } -> x7 - v56 Extend { value=v29, kind=I32 } -> x6 + v56 LoadLocal { off=-8, kind=I32, volatile } -> x6 v57 Call { target_pc=1, args=[v55, v56], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x0 v58 Binop { op=ne, lhs=v50, rhs=v57 } -> x0 terminator Bz { cond=v58, target=b10, fall=b9 } (exit_acc=v58) diff --git a/tests/snapshots/ssa/setjmp_longjmp.ssa b/tests/snapshots/ssa/setjmp_longjmp.ssa index ba1129278..c50f93c1f 100644 --- a/tests/snapshots/ssa/setjmp_longjmp.ssa +++ b/tests/snapshots/ssa/setjmp_longjmp.ssa @@ -20,7 +20,7 @@ fn ent_pc=0 n_params=2 variadic=false locals=2 ; --- SSA dump (ok=true) ent_pc=1 --- ; name=main fn ent_pc=1 n_params=0 variadic=false locals=69 - spill_count=0 gpr_used=[3, 12] fp_used=[] + spill_count=0 gpr_used=[3] fp_used=[] block 0 start_pc=0 v0 AllocaInit(0) -> - v1 Imm(0) -> x0 @@ -29,20 +29,20 @@ fn ent_pc=1 n_params=0 variadic=false locals=69 v2 Imm(11) -> x0 terminator Return(v2) (exit_acc=v2) block 2 start_pc=0 - v3 Imm(0) -> x3 - v4 Imm(0) -> x0 + v3 Imm(0) -> x0 + v4 StoreLocal { off=-66, value=v3, kind=I32, volatile } -> - v5 LocalAddr(-65) -> x7 - v6 CallExt { binding_idx=0, args=[v5], fp_arg_mask=0x0 } -> x12 + v6 CallExt { binding_idx=0, args=[v5], fp_arg_mask=0x0 } -> x3 v7 Imm(0) -> x0 v8 Extend { value=v6, kind=I32 } -> x0 v9 BinopI { op=eq, lhs=v8, rhs_imm=0 } -> x0 terminator Bz { cond=v9, target=b4, fall=b3 } (exit_acc=v9) block 3 start_pc=0 - v10 LoadLocal { off=-66, kind=I32 } -> x0 - v11 BinopI { op=add, lhs=v3, rhs_imm=1 } -> x0 + v10 LoadLocal { off=-66, kind=I32, volatile } -> x0 + v11 BinopI { op=add, lhs=v10, rhs_imm=1 } -> x0 v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 - v13 Extend { value=v11, kind=I32 } -> x0 - v14 Imm(0) -> x0 + v13 Extend { value=v11, kind=I32 } -> x1 + v14 StoreLocal { off=-66, value=v11, kind=I32, volatile } -> - v15 LocalAddr(-65) -> x7 v16 Imm(7) -> x6 v17 Call { target_pc=0, args=[v15, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x0 @@ -56,8 +56,8 @@ fn ent_pc=1 n_params=0 variadic=false locals=69 v21 Imm(13) -> x0 terminator Return(v21) (exit_acc=v21) block 6 start_pc=0 - v22 LoadLocal { off=-66, kind=I32 } -> x0 - v23 BinopI { op=ne, lhs=v3, rhs_imm=1 } -> x0 + v22 LoadLocal { off=-66, kind=I32, volatile } -> x0 + v23 BinopI { op=ne, lhs=v22, rhs_imm=1 } -> x0 terminator Bz { cond=v23, target=b8, fall=b7 } (exit_acc=v23) block 7 start_pc=0 v24 Imm(14) -> x0 diff --git a/tests/snapshots/ssa/setjmp_longjmp_roundtrip.ssa b/tests/snapshots/ssa/setjmp_longjmp_roundtrip.ssa index 220b7f09b..4fdd962e0 100644 --- a/tests/snapshots/ssa/setjmp_longjmp_roundtrip.ssa +++ b/tests/snapshots/ssa/setjmp_longjmp_roundtrip.ssa @@ -9,11 +9,11 @@ fn ent_pc=0 n_params=2 variadic=false locals=2 v3 ParamRef(1, kind=I32) -> x3 v4 Imm(0) -> x0 v5 ImmData(536) -> x0 - v6 Load { addr=v5, disp=0, kind=I32 } -> x1 + v6 Load { addr=v5, disp=0, kind=I32, volatile } -> x1 v7 BinopI { op=add, lhs=v6, rhs_imm=1 } -> x1 v8 BinopI { op=shl, lhs=v7, rhs_imm=32 } -> x2 v9 Extend { value=v7, kind=I32 } -> x2 - v10 Store { addr=v5, disp=0, value=v7, kind=I32 } -> - + v10 Store { addr=v5, disp=0, value=v7, kind=I32, volatile } -> - v11 LoadLocal { off=2, kind=I32 } -> x0 v12 BinopI { op=gt, lhs=v1, rhs_imm=0 } -> x0 terminator Bz { cond=v12, target=b3, fall=b1 } (exit_acc=v12) @@ -41,7 +41,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=2 v0 AllocaInit(0) -> - v1 ImmData(552) -> x3 v2 Imm(1) -> x0 - v3 Store { addr=v1, disp=0, value=v2, kind=I32 } -> - + v3 Store { addr=v1, disp=0, value=v2, kind=I32, volatile } -> - v4 ImmData(24) -> x12 v5 CallExt { binding_idx=0, args=[v4], fp_arg_mask=0x0 } -> x0 v6 BinopI { op=eq, lhs=v5, rhs_imm=0 } -> x0 @@ -49,7 +49,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=2 block 1 start_pc=0 v7 ImmData(536) -> x0 v8 Imm(0) -> x1 - v9 Store { addr=v7, disp=0, value=v8, kind=I32 } -> - + v9 Store { addr=v7, disp=0, value=v8, kind=I32, volatile } -> - v10 Imm(5) -> x7 v11 Imm(42) -> x6 v12 Call { target_pc=0, args=[v10, v11], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x0 @@ -57,7 +57,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=2 terminator Return(v13) (exit_acc=v13) block 2 start_pc=0 v14 ImmData(536) -> x0 - v15 Load { addr=v14, disp=0, kind=I32 } -> x0 + v15 Load { addr=v14, disp=0, kind=I32, volatile } -> x0 v16 BinopI { op=ne, lhs=v15, rhs_imm=6 } -> x0 terminator Bz { cond=v16, target=b4, fall=b3 } (exit_acc=v16) block 3 start_pc=0 @@ -66,7 +66,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=2 block 4 start_pc=0 v18 ImmData(552) -> x0 v19 Imm(2) -> x0 - v20 Store { addr=v1, disp=0, value=v19, kind=I32 } -> - + v20 Store { addr=v1, disp=0, value=v19, kind=I32, volatile } -> - v21 ImmData(24) -> x0 v22 CallExt { binding_idx=0, args=[v4], fp_arg_mask=0x0 } -> x0 v23 BinopI { op=eq, lhs=v22, rhs_imm=0 } -> x0 @@ -80,23 +80,23 @@ fn ent_pc=1 n_params=0 variadic=false locals=2 block 6 start_pc=0 v28 ImmData(544) -> x0 v29 Imm(0) -> x1 - v30 Store { addr=v28, disp=0, value=v29, kind=I32 } -> - + v30 Store { addr=v28, disp=0, value=v29, kind=I32, volatile } -> - v31 ImmData(24) -> x0 v32 CallExt { binding_idx=0, args=[v4], fp_arg_mask=0x0 } -> x0 v33 BinopI { op=ne, lhs=v32, rhs_imm=0 } -> x0 terminator Bz { cond=v33, target=b9, fall=b7 } (exit_acc=v33) block 7 start_pc=0 v34 ImmData(544) -> x0 - v35 Load { addr=v34, disp=0, kind=I32 } -> x0 + v35 Load { addr=v34, disp=0, kind=I32, volatile } -> x0 v36 BinopI { op=ne, lhs=v35, rhs_imm=1 } -> x0 terminator Bz { cond=v36, target=b11, fall=b10 } (exit_acc=v36) block 8 start_pc=0 v45 ImmData(552) -> x0 v46 Imm(3) -> x0 - v47 Store { addr=v1, disp=0, value=v46, kind=I32 } -> - + v47 Store { addr=v1, disp=0, value=v46, kind=I32, volatile } -> - v48 ImmData(544) -> x0 v49 Imm(0) -> x1 - v50 Store { addr=v48, disp=0, value=v49, kind=I32 } -> - + v50 Store { addr=v48, disp=0, value=v49, kind=I32, volatile } -> - v51 ImmData(24) -> x0 v52 CallExt { binding_idx=0, args=[v4], fp_arg_mask=0x0 } -> x0 v53 BinopI { op=ne, lhs=v52, rhs_imm=0 } -> x0 @@ -104,7 +104,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=2 block 9 start_pc=0 v38 ImmData(544) -> x0 v39 Imm(1) -> x1 - v40 Store { addr=v38, disp=0, value=v39, kind=I32 } -> - + v40 Store { addr=v38, disp=0, value=v39, kind=I32, volatile } -> - v41 ImmData(24) -> x0 v42 Imm(0) -> x6 v43 CallExt { binding_idx=1, args=[v4, v42], fp_arg_mask=0x0 } -> x0 @@ -117,7 +117,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=2 terminator Jmp(b8) block 12 start_pc=0 v54 ImmData(544) -> x0 - v55 Load { addr=v54, disp=0, kind=I32 } -> x0 + v55 Load { addr=v54, disp=0, kind=I32, volatile } -> x0 v56 BinopI { op=ne, lhs=v55, rhs_imm=7 } -> x0 terminator Bz { cond=v56, target=b16, fall=b15 } (exit_acc=v56) block 13 start_pc=0 @@ -126,7 +126,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=2 block 14 start_pc=0 v58 ImmData(544) -> x0 v59 Imm(7) -> x6 - v60 Store { addr=v58, disp=0, value=v59, kind=I32 } -> - + v60 Store { addr=v58, disp=0, value=v59, kind=I32, volatile } -> - v61 ImmData(24) -> x0 v62 CallExt { binding_idx=1, args=[v4, v59], fp_arg_mask=0x0 } -> x0 v63 Imm(31) -> x0 diff --git a/tests/snapshots/ssa/slot_coalesce_alloca.ssa b/tests/snapshots/ssa/slot_coalesce_alloca.ssa index 55529add7..580e272cf 100644 --- a/tests/snapshots/ssa/slot_coalesce_alloca.ssa +++ b/tests/snapshots/ssa/slot_coalesce_alloca.ssa @@ -7,7 +7,7 @@ fn ent_pc=0 n_params=1 variadic=false locals=27 v0 AllocaInit(0) -> - v1 ParamRef(0, kind=I32) -> x7 v2 Imm(0) -> x0 - v3 Imm(0) -> x9 + v3 Imm(0) -> x8 v4 Imm(0) -> x0 v5 Imm(0) -> x0 terminator Jmp(b1) (exit_acc=v3) @@ -25,13 +25,13 @@ fn ent_pc=0 n_params=1 variadic=false locals=27 v12 LocalAddr(-24) -> x1 v13 Extend { value=v6, kind=I32 } -> x2 v14 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x6 - v15 Binop { op=add, lhs=v12, rhs=v14 } -> x6 - v16 BinopI { op=add, lhs=v13, rhs_imm=1 } -> x6 - v17 BinopI { op=shl, lhs=v16, rhs_imm=32 } -> x8 - v18 Extend { value=v16, kind=I32 } -> x6 - v19 LoadLocal { off=2, kind=I32 } -> x8 - v20 Binop { op=mul, lhs=v18, rhs=v1 } -> x6 - v21 StoreIndexed { base=v12, index=v13, scale=8, value=v20, kind=I64 } -> - + v15 Binop { op=add, lhs=v12, rhs=v14 } -> x1 + v16 BinopI { op=add, lhs=v13, rhs_imm=1 } -> x2 + v17 BinopI { op=shl, lhs=v16, rhs_imm=32 } -> x6 + v18 Extend { value=v16, kind=I32 } -> x2 + v19 LoadLocal { off=2, kind=I32 } -> x6 + v20 Binop { op=mul, lhs=v18, rhs=v1 } -> x2 + v21 Store { addr=v15, disp=0, value=v20, kind=I64, volatile } -> - terminator Jmp(b2) (exit_acc=v21) block 4 start_pc=0 v22 Imm(0) -> x1 @@ -39,7 +39,7 @@ fn ent_pc=0 n_params=1 variadic=false locals=27 terminator Jmp(b5) (exit_acc=v22) block 5 start_pc=0 v24 Phi { incoming=[b4:v22, b6:v29], kind=I64 } -> x1 - v25 Phi { incoming=[b4:v3, b6:v37], kind=I64 } -> x9 + v25 Phi { incoming=[b4:v3, b6:v37], kind=I64 } -> x8 v26 Extend { value=v24, kind=I32 } -> x0 v27 BinopI { op=lt, lhs=v26, rhs_imm=24 } -> x0 terminator Bz { cond=v27, target=b8, fall=b7 } (exit_acc=v27) @@ -52,10 +52,10 @@ fn ent_pc=0 n_params=1 variadic=false locals=27 v31 LoadLocal { off=-25, kind=I64 } -> x0 v32 LocalAddr(-24) -> x0 v33 Extend { value=v24, kind=I32 } -> x2 - v34 BinopI { op=shl, lhs=v33, rhs_imm=3 } -> x6 - v35 Binop { op=add, lhs=v32, rhs=v34 } -> x6 - v36 LoadIndexed { base=v32, index=v33, scale=8, kind=I64 } -> x0 - v37 Binop { op=add, lhs=v25, rhs=v36 } -> x9 + v34 BinopI { op=shl, lhs=v33, rhs_imm=3 } -> x2 + v35 Binop { op=add, lhs=v32, rhs=v34 } -> x0 + v36 Load { addr=v35, disp=0, kind=I64, volatile } -> x0 + v37 Binop { op=add, lhs=v25, rhs=v36 } -> x8 v38 Imm(0) -> x0 terminator Jmp(b6) (exit_acc=v37) block 8 start_pc=0 diff --git a/tests/snapshots/ssa/strength_reduce_pow2_divmod.ssa b/tests/snapshots/ssa/strength_reduce_pow2_divmod.ssa index a43e31bfa..10a1f0bfa 100644 --- a/tests/snapshots/ssa/strength_reduce_pow2_divmod.ssa +++ b/tests/snapshots/ssa/strength_reduce_pow2_divmod.ssa @@ -5,29 +5,29 @@ fn ent_pc=0 n_params=0 variadic=false locals=19 block 0 start_pc=0 v0 AllocaInit(0) -> - v1 Imm(-7) -> x0 - v2 Imm(0) -> x1 - v3 LoadLocal { off=-1, kind=I32 } -> x1 + v2 StoreLocal { off=-1, value=v1, kind=I32, volatile } -> - + v3 LoadLocal { off=-1, kind=I32, volatile } -> x0 v4 Imm(2) -> x1 - v5 BinopI { op=shr, lhs=v1, rhs_imm=63 } -> x1 + v5 BinopI { op=shr, lhs=v3, rhs_imm=63 } -> x1 v6 BinopI { op=shru, lhs=v5, rhs_imm=63 } -> x1 - v7 Binop { op=add, lhs=v1, rhs=v6 } -> x1 - v8 BinopI { op=shr, lhs=v7, rhs_imm=1 } -> x1 - v9 BinopI { op=ne, lhs=v8, rhs_imm=-3 } -> x2 - v10 Imm(0) -> x1 + v7 Binop { op=add, lhs=v3, rhs=v6 } -> x0 + v8 BinopI { op=shr, lhs=v7, rhs_imm=1 } -> x0 + v9 BinopI { op=ne, lhs=v8, rhs_imm=-3 } -> x1 + v10 Imm(0) -> x0 terminator Bnz { cond=v9, target=b45, fall=b1 } (exit_acc=v9) block 1 start_pc=0 - v11 LoadLocal { off=-1, kind=I32 } -> x1 + v11 LoadLocal { off=-1, kind=I32, volatile } -> x0 v12 Imm(2) -> x1 - v13 BinopI { op=shr, lhs=v1, rhs_imm=63 } -> x1 + v13 BinopI { op=shr, lhs=v11, rhs_imm=63 } -> x1 v14 BinopI { op=shru, lhs=v13, rhs_imm=63 } -> x1 - v15 Binop { op=add, lhs=v1, rhs=v14 } -> x0 + v15 Binop { op=add, lhs=v11, rhs=v14 } -> x0 v16 BinopI { op=and, lhs=v15, rhs_imm=1 } -> x0 v17 Binop { op=sub, lhs=v16, rhs=v14 } -> x0 - v18 BinopI { op=ne, lhs=v17, rhs_imm=-1 } -> x2 + v18 BinopI { op=ne, lhs=v17, rhs_imm=-1 } -> x1 v19 Imm(0) -> x0 terminator Jmp(b2) (exit_acc=v18) block 2 start_pc=0 - v20 Phi { incoming=[b45:v9, b1:v18], kind=I64 } -> x2 + v20 Phi { incoming=[b45:v9, b1:v18], kind=I64 } -> x1 v21 LoadLocal { off=-9, kind=I64 } -> x0 terminator Bz { cond=v20, target=b4, fall=b3 } (exit_acc=v20) block 3 start_pc=0 @@ -35,29 +35,29 @@ fn ent_pc=0 n_params=0 variadic=false locals=19 terminator Return(v22) (exit_acc=v22) block 4 start_pc=0 v23 Imm(-16) -> x0 - v24 Imm(0) -> x1 - v25 LoadLocal { off=-1, kind=I32 } -> x1 + v24 StoreLocal { off=-1, value=v23, kind=I32, volatile } -> - + v25 LoadLocal { off=-1, kind=I32, volatile } -> x0 v26 Imm(16) -> x1 - v27 BinopI { op=shr, lhs=v23, rhs_imm=63 } -> x1 + v27 BinopI { op=shr, lhs=v25, rhs_imm=63 } -> x1 v28 BinopI { op=shru, lhs=v27, rhs_imm=60 } -> x1 - v29 Binop { op=add, lhs=v23, rhs=v28 } -> x1 - v30 BinopI { op=shr, lhs=v29, rhs_imm=4 } -> x1 - v31 BinopI { op=ne, lhs=v30, rhs_imm=-1 } -> x2 - v32 Imm(0) -> x1 + v29 Binop { op=add, lhs=v25, rhs=v28 } -> x0 + v30 BinopI { op=shr, lhs=v29, rhs_imm=4 } -> x0 + v31 BinopI { op=ne, lhs=v30, rhs_imm=-1 } -> x1 + v32 Imm(0) -> x0 terminator Bnz { cond=v31, target=b46, fall=b5 } (exit_acc=v31) block 5 start_pc=0 - v33 LoadLocal { off=-1, kind=I32 } -> x1 + v33 LoadLocal { off=-1, kind=I32, volatile } -> x0 v34 Imm(16) -> x1 - v35 BinopI { op=shr, lhs=v23, rhs_imm=63 } -> x1 + v35 BinopI { op=shr, lhs=v33, rhs_imm=63 } -> x1 v36 BinopI { op=shru, lhs=v35, rhs_imm=60 } -> x1 - v37 Binop { op=add, lhs=v23, rhs=v36 } -> x0 + v37 Binop { op=add, lhs=v33, rhs=v36 } -> x0 v38 BinopI { op=and, lhs=v37, rhs_imm=15 } -> x0 v39 Binop { op=sub, lhs=v38, rhs=v36 } -> x0 - v40 BinopI { op=ne, lhs=v39, rhs_imm=0 } -> x2 + v40 BinopI { op=ne, lhs=v39, rhs_imm=0 } -> x1 v41 Imm(0) -> x0 terminator Jmp(b6) (exit_acc=v40) block 6 start_pc=0 - v42 Phi { incoming=[b46:v31, b5:v40], kind=I64 } -> x2 + v42 Phi { incoming=[b46:v31, b5:v40], kind=I64 } -> x1 v43 LoadLocal { off=-10, kind=I64 } -> x0 terminator Bz { cond=v42, target=b8, fall=b7 } (exit_acc=v42) block 7 start_pc=0 @@ -65,29 +65,29 @@ fn ent_pc=0 n_params=0 variadic=false locals=19 terminator Return(v44) (exit_acc=v44) block 8 start_pc=0 v45 Imm(-17) -> x0 - v46 Imm(0) -> x1 - v47 LoadLocal { off=-1, kind=I32 } -> x1 + v46 StoreLocal { off=-1, value=v45, kind=I32, volatile } -> - + v47 LoadLocal { off=-1, kind=I32, volatile } -> x0 v48 Imm(16) -> x1 - v49 BinopI { op=shr, lhs=v45, rhs_imm=63 } -> x1 + v49 BinopI { op=shr, lhs=v47, rhs_imm=63 } -> x1 v50 BinopI { op=shru, lhs=v49, rhs_imm=60 } -> x1 - v51 Binop { op=add, lhs=v45, rhs=v50 } -> x1 - v52 BinopI { op=shr, lhs=v51, rhs_imm=4 } -> x1 - v53 BinopI { op=ne, lhs=v52, rhs_imm=-1 } -> x2 - v54 Imm(0) -> x1 + v51 Binop { op=add, lhs=v47, rhs=v50 } -> x0 + v52 BinopI { op=shr, lhs=v51, rhs_imm=4 } -> x0 + v53 BinopI { op=ne, lhs=v52, rhs_imm=-1 } -> x1 + v54 Imm(0) -> x0 terminator Bnz { cond=v53, target=b47, fall=b9 } (exit_acc=v53) block 9 start_pc=0 - v55 LoadLocal { off=-1, kind=I32 } -> x1 + v55 LoadLocal { off=-1, kind=I32, volatile } -> x0 v56 Imm(16) -> x1 - v57 BinopI { op=shr, lhs=v45, rhs_imm=63 } -> x1 + v57 BinopI { op=shr, lhs=v55, rhs_imm=63 } -> x1 v58 BinopI { op=shru, lhs=v57, rhs_imm=60 } -> x1 - v59 Binop { op=add, lhs=v45, rhs=v58 } -> x0 + v59 Binop { op=add, lhs=v55, rhs=v58 } -> x0 v60 BinopI { op=and, lhs=v59, rhs_imm=15 } -> x0 v61 Binop { op=sub, lhs=v60, rhs=v58 } -> x0 - v62 BinopI { op=ne, lhs=v61, rhs_imm=-1 } -> x2 + v62 BinopI { op=ne, lhs=v61, rhs_imm=-1 } -> x1 v63 Imm(0) -> x0 terminator Jmp(b10) (exit_acc=v62) block 10 start_pc=0 - v64 Phi { incoming=[b47:v53, b9:v62], kind=I64 } -> x2 + v64 Phi { incoming=[b47:v53, b9:v62], kind=I64 } -> x1 v65 LoadLocal { off=-11, kind=I64 } -> x0 terminator Bz { cond=v64, target=b12, fall=b11 } (exit_acc=v64) block 11 start_pc=0 @@ -95,29 +95,29 @@ fn ent_pc=0 n_params=0 variadic=false locals=19 terminator Return(v66) (exit_acc=v66) block 12 start_pc=0 v67 Imm(100) -> x0 - v68 Imm(0) -> x1 - v69 LoadLocal { off=-1, kind=I32 } -> x1 + v68 StoreLocal { off=-1, value=v67, kind=I32, volatile } -> - + v69 LoadLocal { off=-1, kind=I32, volatile } -> x0 v70 Imm(8) -> x1 - v71 BinopI { op=shr, lhs=v67, rhs_imm=63 } -> x1 + v71 BinopI { op=shr, lhs=v69, rhs_imm=63 } -> x1 v72 BinopI { op=shru, lhs=v71, rhs_imm=61 } -> x1 - v73 Binop { op=add, lhs=v67, rhs=v72 } -> x1 - v74 BinopI { op=shr, lhs=v73, rhs_imm=3 } -> x1 - v75 BinopI { op=ne, lhs=v74, rhs_imm=12 } -> x2 - v76 Imm(0) -> x1 + v73 Binop { op=add, lhs=v69, rhs=v72 } -> x0 + v74 BinopI { op=shr, lhs=v73, rhs_imm=3 } -> x0 + v75 BinopI { op=ne, lhs=v74, rhs_imm=12 } -> x1 + v76 Imm(0) -> x0 terminator Bnz { cond=v75, target=b48, fall=b13 } (exit_acc=v75) block 13 start_pc=0 - v77 LoadLocal { off=-1, kind=I32 } -> x1 + v77 LoadLocal { off=-1, kind=I32, volatile } -> x0 v78 Imm(8) -> x1 - v79 BinopI { op=shr, lhs=v67, rhs_imm=63 } -> x1 + v79 BinopI { op=shr, lhs=v77, rhs_imm=63 } -> x1 v80 BinopI { op=shru, lhs=v79, rhs_imm=61 } -> x1 - v81 Binop { op=add, lhs=v67, rhs=v80 } -> x0 + v81 Binop { op=add, lhs=v77, rhs=v80 } -> x0 v82 BinopI { op=and, lhs=v81, rhs_imm=7 } -> x0 v83 Binop { op=sub, lhs=v82, rhs=v80 } -> x0 - v84 BinopI { op=ne, lhs=v83, rhs_imm=4 } -> x2 + v84 BinopI { op=ne, lhs=v83, rhs_imm=4 } -> x1 v85 Imm(0) -> x0 terminator Jmp(b14) (exit_acc=v84) block 14 start_pc=0 - v86 Phi { incoming=[b48:v75, b13:v84], kind=I64 } -> x2 + v86 Phi { incoming=[b48:v75, b13:v84], kind=I64 } -> x1 v87 LoadLocal { off=-12, kind=I64 } -> x0 terminator Bz { cond=v86, target=b16, fall=b15 } (exit_acc=v86) block 15 start_pc=0 @@ -126,29 +126,29 @@ fn ent_pc=0 n_params=0 variadic=false locals=19 block 16 start_pc=0 v89 Imm(-2147483648) -> x0 v90 Imm(-9223372036854775808) -> x1 - v91 Imm(0) -> x1 - v92 LoadLocal { off=-1, kind=I32 } -> x1 + v91 StoreLocal { off=-1, value=v89, kind=I32, volatile } -> - + v92 LoadLocal { off=-1, kind=I32, volatile } -> x0 v93 Imm(2) -> x1 - v94 BinopI { op=shr, lhs=v89, rhs_imm=63 } -> x1 + v94 BinopI { op=shr, lhs=v92, rhs_imm=63 } -> x1 v95 BinopI { op=shru, lhs=v94, rhs_imm=63 } -> x1 - v96 Binop { op=add, lhs=v89, rhs=v95 } -> x1 - v97 BinopI { op=shr, lhs=v96, rhs_imm=1 } -> x1 - v98 BinopI { op=ne, lhs=v97, rhs_imm=-1073741824 } -> x2 - v99 Imm(0) -> x1 + v96 Binop { op=add, lhs=v92, rhs=v95 } -> x0 + v97 BinopI { op=shr, lhs=v96, rhs_imm=1 } -> x0 + v98 BinopI { op=ne, lhs=v97, rhs_imm=-1073741824 } -> x1 + v99 Imm(0) -> x0 terminator Bnz { cond=v98, target=b49, fall=b17 } (exit_acc=v98) block 17 start_pc=0 - v100 LoadLocal { off=-1, kind=I32 } -> x1 + v100 LoadLocal { off=-1, kind=I32, volatile } -> x0 v101 Imm(2) -> x1 - v102 BinopI { op=shr, lhs=v89, rhs_imm=63 } -> x1 + v102 BinopI { op=shr, lhs=v100, rhs_imm=63 } -> x1 v103 BinopI { op=shru, lhs=v102, rhs_imm=63 } -> x1 - v104 Binop { op=add, lhs=v89, rhs=v103 } -> x0 + v104 Binop { op=add, lhs=v100, rhs=v103 } -> x0 v105 BinopI { op=and, lhs=v104, rhs_imm=1 } -> x0 v106 Binop { op=sub, lhs=v105, rhs=v103 } -> x0 - v107 BinopI { op=ne, lhs=v106, rhs_imm=0 } -> x2 + v107 BinopI { op=ne, lhs=v106, rhs_imm=0 } -> x1 v108 Imm(0) -> x0 terminator Jmp(b18) (exit_acc=v107) block 18 start_pc=0 - v109 Phi { incoming=[b49:v98, b17:v107], kind=I64 } -> x2 + v109 Phi { incoming=[b49:v98, b17:v107], kind=I64 } -> x1 v110 LoadLocal { off=-13, kind=I64 } -> x0 terminator Bz { cond=v109, target=b20, fall=b19 } (exit_acc=v109) block 19 start_pc=0 @@ -156,22 +156,22 @@ fn ent_pc=0 n_params=0 variadic=false locals=19 terminator Return(v111) (exit_acc=v111) block 20 start_pc=0 v112 Imm(4294967295) -> x0 - v113 Imm(0) -> x1 - v114 LoadLocal { off=-2, kind=U32 } -> x1 + v113 StoreLocal { off=-2, value=v112, kind=I32, volatile } -> - + v114 LoadLocal { off=-2, kind=U32, volatile } -> x0 v115 Imm(2) -> x1 - v116 BinopI { op=shru, lhs=v112, rhs_imm=1 } -> x1 - v117 BinopI { op=ne, lhs=v116, rhs_imm=2147483647 } -> x2 - v118 Imm(0) -> x1 + v116 BinopI { op=shru, lhs=v114, rhs_imm=1 } -> x0 + v117 BinopI { op=ne, lhs=v116, rhs_imm=2147483647 } -> x1 + v118 Imm(0) -> x0 terminator Bnz { cond=v117, target=b50, fall=b21 } (exit_acc=v117) block 21 start_pc=0 - v119 LoadLocal { off=-2, kind=U32 } -> x1 + v119 LoadLocal { off=-2, kind=U32, volatile } -> x0 v120 Imm(2) -> x1 - v121 BinopI { op=and, lhs=v112, rhs_imm=1 } -> x0 - v122 BinopI { op=ne, lhs=v121, rhs_imm=1 } -> x2 + v121 BinopI { op=and, lhs=v119, rhs_imm=1 } -> x0 + v122 BinopI { op=ne, lhs=v121, rhs_imm=1 } -> x1 v123 Imm(0) -> x0 terminator Jmp(b22) (exit_acc=v122) block 22 start_pc=0 - v124 Phi { incoming=[b50:v117, b21:v122], kind=I64 } -> x2 + v124 Phi { incoming=[b50:v117, b21:v122], kind=I64 } -> x1 v125 LoadLocal { off=-14, kind=I64 } -> x0 terminator Bz { cond=v124, target=b24, fall=b23 } (exit_acc=v124) block 23 start_pc=0 @@ -179,22 +179,22 @@ fn ent_pc=0 n_params=0 variadic=false locals=19 terminator Return(v126) (exit_acc=v126) block 24 start_pc=0 v127 Imm(2147483648) -> x0 - v128 Imm(0) -> x1 - v129 LoadLocal { off=-2, kind=U32 } -> x1 + v128 StoreLocal { off=-2, value=v127, kind=I32, volatile } -> - + v129 LoadLocal { off=-2, kind=U32, volatile } -> x0 v130 Imm(16) -> x1 - v131 BinopI { op=shru, lhs=v127, rhs_imm=4 } -> x1 - v132 BinopI { op=ne, lhs=v131, rhs_imm=134217728 } -> x2 - v133 Imm(0) -> x1 + v131 BinopI { op=shru, lhs=v129, rhs_imm=4 } -> x0 + v132 BinopI { op=ne, lhs=v131, rhs_imm=134217728 } -> x1 + v133 Imm(0) -> x0 terminator Bnz { cond=v132, target=b51, fall=b25 } (exit_acc=v132) block 25 start_pc=0 - v134 LoadLocal { off=-2, kind=U32 } -> x1 + v134 LoadLocal { off=-2, kind=U32, volatile } -> x0 v135 Imm(16) -> x1 - v136 BinopI { op=and, lhs=v127, rhs_imm=15 } -> x0 - v137 BinopI { op=ne, lhs=v136, rhs_imm=0 } -> x2 + v136 BinopI { op=and, lhs=v134, rhs_imm=15 } -> x0 + v137 BinopI { op=ne, lhs=v136, rhs_imm=0 } -> x1 v138 Imm(0) -> x0 terminator Jmp(b26) (exit_acc=v137) block 26 start_pc=0 - v139 Phi { incoming=[b51:v132, b25:v137], kind=I64 } -> x2 + v139 Phi { incoming=[b51:v132, b25:v137], kind=I64 } -> x1 v140 LoadLocal { off=-15, kind=I64 } -> x0 terminator Bz { cond=v139, target=b28, fall=b27 } (exit_acc=v139) block 27 start_pc=0 @@ -202,26 +202,26 @@ fn ent_pc=0 n_params=0 variadic=false locals=19 terminator Return(v141) (exit_acc=v141) block 28 start_pc=0 v142 Imm(-1234567) -> x0 - v143 Imm(0) -> x1 - v144 LoadLocal { off=-7, kind=I64 } -> x1 - v145 Imm(1024) -> x1 - v146 BinopI { op=shr, lhs=v142, rhs_imm=63 } -> x1 - v147 BinopI { op=shru, lhs=v146, rhs_imm=54 } -> x1 - v148 Binop { op=add, lhs=v142, rhs=v147 } -> x1 + v143 StoreLocal { off=-7, value=v142, kind=I64, volatile } -> - + v144 LoadLocal { off=-7, kind=I64, volatile } -> x1 + v145 Imm(1024) -> x2 + v146 BinopI { op=shr, lhs=v144, rhs_imm=63 } -> x2 + v147 BinopI { op=shru, lhs=v146, rhs_imm=54 } -> x2 + v148 Binop { op=add, lhs=v144, rhs=v147 } -> x1 v149 BinopI { op=shr, lhs=v148, rhs_imm=10 } -> x1 v150 Imm(-1) -> x2 v151 Imm(1023) -> x2 - v152 Binop { op=add, lhs=v142, rhs=v151 } -> x2 - v153 BinopI { op=shr, lhs=v152, rhs_imm=10 } -> x2 - v154 Binop { op=ne, lhs=v149, rhs=v153 } -> x2 - v155 Imm(0) -> x1 + v152 Binop { op=add, lhs=v142, rhs=v151 } -> x0 + v153 BinopI { op=shr, lhs=v152, rhs_imm=10 } -> x0 + v154 Binop { op=ne, lhs=v149, rhs=v153 } -> x1 + v155 Imm(0) -> x0 terminator Bnz { cond=v154, target=b52, fall=b29 } (exit_acc=v154) block 29 start_pc=0 - v156 LoadLocal { off=-7, kind=I64 } -> x1 + v156 LoadLocal { off=-7, kind=I64, volatile } -> x0 v157 Imm(1024) -> x1 - v158 BinopI { op=shr, lhs=v142, rhs_imm=63 } -> x1 + v158 BinopI { op=shr, lhs=v156, rhs_imm=63 } -> x1 v159 BinopI { op=shru, lhs=v158, rhs_imm=54 } -> x1 - v160 Binop { op=add, lhs=v142, rhs=v159 } -> x0 + v160 Binop { op=add, lhs=v156, rhs=v159 } -> x0 v161 BinopI { op=and, lhs=v160, rhs_imm=1023 } -> x0 v162 Binop { op=sub, lhs=v161, rhs=v159 } -> x0 v163 Imm(-1234567) -> x1 @@ -230,11 +230,11 @@ fn ent_pc=0 n_params=0 variadic=false locals=19 v166 Binop { op=add, lhs=v163, rhs=v165 } -> x1 v167 BinopI { op=and, lhs=v166, rhs_imm=1023 } -> x1 v168 Binop { op=sub, lhs=v167, rhs=v165 } -> x1 - v169 Binop { op=ne, lhs=v162, rhs=v168 } -> x2 + v169 Binop { op=ne, lhs=v162, rhs=v168 } -> x1 v170 Imm(0) -> x0 terminator Jmp(b30) (exit_acc=v169) block 30 start_pc=0 - v171 Phi { incoming=[b52:v154, b29:v169], kind=I64 } -> x2 + v171 Phi { incoming=[b52:v154, b29:v169], kind=I64 } -> x1 v172 LoadLocal { off=-16, kind=I64 } -> x0 terminator Bz { cond=v171, target=b32, fall=b31 } (exit_acc=v171) block 31 start_pc=0 @@ -242,29 +242,29 @@ fn ent_pc=0 n_params=0 variadic=false locals=19 terminator Return(v173) (exit_acc=v173) block 32 start_pc=0 v174 Imm(-9223372036854775808) -> x0 - v175 Imm(0) -> x1 - v176 LoadLocal { off=-7, kind=I64 } -> x1 + v175 StoreLocal { off=-7, value=v174, kind=I64, volatile } -> - + v176 LoadLocal { off=-7, kind=I64, volatile } -> x0 v177 Imm(2) -> x1 - v178 BinopI { op=shr, lhs=v174, rhs_imm=63 } -> x1 + v178 BinopI { op=shr, lhs=v176, rhs_imm=63 } -> x1 v179 BinopI { op=shru, lhs=v178, rhs_imm=63 } -> x1 - v180 Binop { op=add, lhs=v174, rhs=v179 } -> x1 - v181 BinopI { op=shr, lhs=v180, rhs_imm=1 } -> x1 - v182 BinopI { op=ne, lhs=v181, rhs_imm=-4611686018427387904 } -> x2 - v183 Imm(0) -> x1 + v180 Binop { op=add, lhs=v176, rhs=v179 } -> x0 + v181 BinopI { op=shr, lhs=v180, rhs_imm=1 } -> x0 + v182 BinopI { op=ne, lhs=v181, rhs_imm=-4611686018427387904 } -> x1 + v183 Imm(0) -> x0 terminator Bnz { cond=v182, target=b53, fall=b33 } (exit_acc=v182) block 33 start_pc=0 - v184 LoadLocal { off=-7, kind=I64 } -> x1 + v184 LoadLocal { off=-7, kind=I64, volatile } -> x0 v185 Imm(2) -> x1 - v186 BinopI { op=shr, lhs=v174, rhs_imm=63 } -> x1 + v186 BinopI { op=shr, lhs=v184, rhs_imm=63 } -> x1 v187 BinopI { op=shru, lhs=v186, rhs_imm=63 } -> x1 - v188 Binop { op=add, lhs=v174, rhs=v187 } -> x0 + v188 Binop { op=add, lhs=v184, rhs=v187 } -> x0 v189 BinopI { op=and, lhs=v188, rhs_imm=1 } -> x0 v190 Binop { op=sub, lhs=v189, rhs=v187 } -> x0 - v191 BinopI { op=ne, lhs=v190, rhs_imm=0 } -> x2 + v191 BinopI { op=ne, lhs=v190, rhs_imm=0 } -> x1 v192 Imm(0) -> x0 terminator Jmp(b34) (exit_acc=v191) block 34 start_pc=0 - v193 Phi { incoming=[b53:v182, b33:v191], kind=I64 } -> x2 + v193 Phi { incoming=[b53:v182, b33:v191], kind=I64 } -> x1 v194 LoadLocal { off=-17, kind=I64 } -> x0 terminator Bz { cond=v193, target=b36, fall=b35 } (exit_acc=v193) block 35 start_pc=0 @@ -272,22 +272,22 @@ fn ent_pc=0 n_params=0 variadic=false locals=19 terminator Return(v195) (exit_acc=v195) block 36 start_pc=0 v196 Imm(-1) -> x0 - v197 Imm(0) -> x1 - v198 LoadLocal { off=-8, kind=I64 } -> x1 + v197 StoreLocal { off=-8, value=v196, kind=I64, volatile } -> - + v198 LoadLocal { off=-8, kind=I64, volatile } -> x0 v199 Imm(2) -> x1 - v200 BinopI { op=shru, lhs=v196, rhs_imm=1 } -> x1 - v201 BinopI { op=ne, lhs=v200, rhs_imm=9223372036854775807 } -> x2 - v202 Imm(0) -> x1 + v200 BinopI { op=shru, lhs=v198, rhs_imm=1 } -> x0 + v201 BinopI { op=ne, lhs=v200, rhs_imm=9223372036854775807 } -> x1 + v202 Imm(0) -> x0 terminator Bnz { cond=v201, target=b54, fall=b37 } (exit_acc=v201) block 37 start_pc=0 - v203 LoadLocal { off=-8, kind=I64 } -> x1 + v203 LoadLocal { off=-8, kind=I64, volatile } -> x0 v204 Imm(256) -> x1 - v205 BinopI { op=and, lhs=v196, rhs_imm=255 } -> x0 - v206 BinopI { op=ne, lhs=v205, rhs_imm=255 } -> x2 + v205 BinopI { op=and, lhs=v203, rhs_imm=255 } -> x0 + v206 BinopI { op=ne, lhs=v205, rhs_imm=255 } -> x1 v207 Imm(0) -> x0 terminator Jmp(b38) (exit_acc=v206) block 38 start_pc=0 - v208 Phi { incoming=[b54:v201, b37:v206], kind=I64 } -> x2 + v208 Phi { incoming=[b54:v201, b37:v206], kind=I64 } -> x1 v209 LoadLocal { off=-18, kind=I64 } -> x0 terminator Bz { cond=v208, target=b40, fall=b39 } (exit_acc=v208) block 39 start_pc=0 @@ -295,14 +295,14 @@ fn ent_pc=0 n_params=0 variadic=false locals=19 terminator Return(v210) (exit_acc=v210) block 40 start_pc=0 v211 Imm(-5) -> x0 - v212 Imm(0) -> x1 - v213 LoadLocal { off=-1, kind=I32 } -> x1 + v212 StoreLocal { off=-1, value=v211, kind=I32, volatile } -> - + v213 LoadLocal { off=-1, kind=I32, volatile } -> x0 v214 Imm(1) -> x1 - v215 BinopI { op=ne, lhs=v211, rhs_imm=-5 } -> x1 + v215 BinopI { op=ne, lhs=v213, rhs_imm=-5 } -> x1 v216 Imm(0) -> x0 terminator Bnz { cond=v215, target=b55, fall=b41 } (exit_acc=v215) block 41 start_pc=0 - v217 LoadLocal { off=-1, kind=I32 } -> x0 + v217 LoadLocal { off=-1, kind=I32, volatile } -> x0 v218 Imm(1) -> x0 v219 Imm(0) -> x1 v220 Imm(0) -> x0 diff --git a/tests/snapshots/ssa/volatile_ptr_alias_loop.ssa b/tests/snapshots/ssa/volatile_ptr_alias_loop.ssa new file mode 100644 index 000000000..ced7a2a8b --- /dev/null +++ b/tests/snapshots/ssa/volatile_ptr_alias_loop.ssa @@ -0,0 +1,98 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=4 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(0) -> x1 + v2 StoreLocal { off=-1, value=v1, kind=I32, volatile } -> - + v3 LocalAddr(-1) -> x0 + v4 StoreLocal { off=-2, value=v3, kind=I64, volatile } -> - + v5 Imm(0) -> x0 + terminator Jmp(b1) (exit_acc=v1) + block 1 start_pc=0 + v6 Phi { incoming=[b0:v1, b5:v16], kind=I64 } -> x1 + v7 LoadLocal { off=-1, kind=I32, volatile } -> x0 + v8 BinopI { op=lt, lhs=v7, rhs_imm=3 } -> x0 + terminator Bz { cond=v8, target=b3, fall=b2 } (exit_acc=v8) + block 2 start_pc=0 + v9 LoadLocal { off=-2, kind=I64, volatile } -> x0 + v10 LoadLocal { off=-1, kind=I32, volatile } -> x2 + v11 BinopI { op=add, lhs=v10, rhs_imm=1 } -> x2 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x6 + v13 Extend { value=v11, kind=I32 } -> x6 + v14 Store { addr=v9, disp=0, value=v11, kind=I32, volatile } -> - + v15 Extend { value=v6, kind=I32 } -> x0 + v16 BinopI { op=add, lhs=v6, rhs_imm=1 } -> x1 + v17 Imm(0) -> x0 + v18 Extend { value=v16, kind=I32 } -> x0 + v19 BinopI { op=gt, lhs=v18, rhs_imm=10 } -> x0 + terminator Bz { cond=v19, target=b5, fall=b4 } (exit_acc=v19) + block 3 start_pc=0 + v20 Extend { value=v6, kind=I32 } -> x0 + v21 BinopI { op=eq, lhs=v20, rhs_imm=3 } -> x0 + terminator Bz { cond=v21, target=b7, fall=b6 } (exit_acc=v21) + block 4 start_pc=0 + v22 Imm(1) -> x0 + terminator Return(v22) (exit_acc=v22) + block 5 start_pc=0 + terminator Jmp(b1) + block 6 start_pc=0 + v23 Imm(0) -> x1 + v24 Imm(0) -> x0 + terminator Jmp(b8) (exit_acc=v23) + block 7 start_pc=0 + v25 Imm(2) -> x1 + v26 Imm(0) -> x0 + terminator Jmp(b8) (exit_acc=v25) + block 8 start_pc=0 + v27 Phi { incoming=[b6:v23, b7:v25], kind=I64 } -> x1 + v28 LoadLocal { off=-4, kind=I64 } -> x0 + terminator Return(v27) (exit_acc=v27) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/volatile_setjmp_longjmp.ssa b/tests/snapshots/ssa/volatile_setjmp_longjmp.ssa new file mode 100644 index 000000000..f36a666e6 --- /dev/null +++ b/tests/snapshots/ssa/volatile_setjmp_longjmp.ssa @@ -0,0 +1,82 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=4 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(1) -> x0 + v2 StoreLocal { off=-1, value=v1, kind=I32, volatile } -> - + v3 ImmData(24) -> x3 + v4 CallExt { binding_idx=0, args=[v3], fp_arg_mask=0x0 } -> x0 + v5 BinopI { op=eq, lhs=v4, rhs_imm=0 } -> x0 + terminator Bz { cond=v5, target=b2, fall=b1 } (exit_acc=v5) + block 1 start_pc=0 + v6 Imm(2) -> x0 + v7 StoreLocal { off=-1, value=v6, kind=I32, volatile } -> - + v8 ImmData(24) -> x0 + v9 Imm(1) -> x6 + v10 CallExt { binding_idx=1, args=[v3, v9], fp_arg_mask=0x0 } -> x0 + terminator Jmp(b2) (exit_acc=v10) + block 2 start_pc=0 + v11 LoadLocal { off=-1, kind=I32, volatile } -> x0 + v12 BinopI { op=eq, lhs=v11, rhs_imm=2 } -> x0 + terminator Bz { cond=v12, target=b4, fall=b3 } (exit_acc=v12) + block 3 start_pc=0 + v13 Imm(0) -> x1 + v14 Imm(0) -> x0 + terminator Jmp(b5) (exit_acc=v13) + block 4 start_pc=0 + v15 Imm(1) -> x1 + v16 Imm(0) -> x0 + terminator Jmp(b5) (exit_acc=v15) + block 5 start_pc=0 + v17 Phi { incoming=[b3:v13, b4:v15], kind=I64 } -> x1 + v18 LoadLocal { off=-4, kind=I64 } -> x0 + terminator Return(v17) (exit_acc=v17) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/volatile_unused_read.ssa b/tests/snapshots/ssa/volatile_unused_read.ssa new file mode 100644 index 000000000..510a98760 --- /dev/null +++ b/tests/snapshots/ssa/volatile_unused_read.ssa @@ -0,0 +1,85 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=3 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ImmData(8) -> x0 + v2 Load { addr=v1, disp=0, kind=I32, volatile } -> x1 + v3 Imm(7) -> x1 + v4 StoreLocal { off=-1, value=v3, kind=I32, volatile } -> - + v5 LoadLocal { off=-1, kind=I32, volatile } -> x1 + v6 Load { addr=v1, disp=0, kind=I32, volatile } -> x0 + v7 BinopI { op=eq, lhs=v6, rhs_imm=5 } -> x1 + v8 Imm(0) -> x0 + terminator Bz { cond=v7, target=b6, fall=b1 } (exit_acc=v7) + block 1 start_pc=0 + v9 LoadLocal { off=-1, kind=I32, volatile } -> x0 + v10 BinopI { op=eq, lhs=v9, rhs_imm=7 } -> x1 + v11 Imm(0) -> x0 + terminator Jmp(b2) (exit_acc=v10) + block 2 start_pc=0 + v12 Phi { incoming=[b6:v7, b1:v10], kind=I64 } -> x1 + v13 LoadLocal { off=-2, kind=I64 } -> x0 + terminator Bz { cond=v12, target=b4, fall=b3 } (exit_acc=v12) + block 3 start_pc=0 + v14 Imm(0) -> x1 + v15 Imm(0) -> x0 + terminator Jmp(b5) (exit_acc=v14) + block 4 start_pc=0 + v16 Imm(1) -> x1 + v17 Imm(0) -> x0 + terminator Jmp(b5) (exit_acc=v16) + block 5 start_pc=0 + v18 Phi { incoming=[b3:v14, b4:v16], kind=I64 } -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x0 + terminator Return(v18) (exit_acc=v18) + block 6 start_pc=0 + terminator Jmp(b2) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) From cc1f5ccd4bc929d86ad18bc70c6f5711bc59267f Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 20:03:24 -0700 Subject: [PATCH 19/67] diag: qualifiers do not affect assignment compatibility C99 6.5.16.1p1 lets the target add qualifiers; passing a plain struct pointer to a volatile-qualified parameter warned as an incompatible struct type. Co-Authored-By: Claude Fable 5 --- src/c5/compiler/diag.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/c5/compiler/diag.rs b/src/c5/compiler/diag.rs index 604648583..8dd6f99e5 100644 --- a/src/c5/compiler/diag.rs +++ b/src/c5/compiler/diag.rs @@ -341,6 +341,10 @@ impl Compiler { actual_is_zero_literal: bool, actual_is_untyped_call: bool, ) -> Option<&'static str> { + // C99 6.5.16.1p1: the target may add qualifiers; volatility + // never affects assignment compatibility. + let declared = declared & !VOLATILE_BIT; + let actual = actual & !VOLATILE_BIT; if declared == actual { return None; } From e4b76654cf6dcb8cfa7e6ebb8b696b6ac1d39d1e Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 20:22:54 -0700 Subject: [PATCH 20/67] walk: strip both qualifier bits before parameter band classification The walker's parameter-prologue loops masked only UNSIGNED_BIT off the declared tag, so a VOLATILE_BIT-carrying tag never compared equal to its band: a `volatile double` parameter was not marked FP and was seeded as an integer ParamRef reading a stale integer argument register while the caller passed the value in an FP register, a `volatile float` lost its narrow entry copy, and a by-value `volatile struct` lost its entry classification the same way. All five sites now use strip_unsigned, and the mislabeled `is_pointer` UNSIGNED_BIT test is renamed to what it checks: unsigned parameters keep the full-width store/load; pointer tags land in the I64 default arm by band value. Regression: volatile_param_classes.c on the native and JIT parity lists. Co-Authored-By: Claude Fable 5 --- src/c5/ast/walk.rs | 29 ++-- src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + tests/fixtures/c/volatile_param_classes.c | 36 +++++ .../asm/volatile_param_classes.aarch64.asm | 126 +++++++++++++++ .../asm/volatile_param_classes.x64.asm | 140 ++++++++++++++++ .../snapshots/ssa/volatile_param_classes.ssa | 153 ++++++++++++++++++ 7 files changed, 470 insertions(+), 16 deletions(-) create mode 100644 tests/fixtures/c/volatile_param_classes.c create mode 100644 tests/snapshots/asm/volatile_param_classes.aarch64.asm create mode 100644 tests/snapshots/asm/volatile_param_classes.x64.asm create mode 100644 tests/snapshots/ssa/volatile_param_classes.ssa diff --git a/src/c5/ast/walk.rs b/src/c5/ast/walk.rs index 11d23ae83..f71f6c552 100644 --- a/src/c5/ast/walk.rs +++ b/src/c5/ast/walk.rs @@ -13,7 +13,7 @@ use alloc::string::String; use super::super::codegen::Target; use super::super::compiler::types::{ STRUCT_BASE, STRUCT_STRIDE, UNSIGNED_BIT, VOLATILE_BIT, is_pointer_ty, is_struct_ty, - is_volatile_ty, load_kind, struct_ptr_depth, + is_volatile_ty, load_kind, strip_unsigned, struct_ptr_depth, }; use super::super::ir::{AtomicRmwOp, BinOp, FunctionSsa, LoadKind, StoreKind}; use super::super::symbol::Symbol; @@ -202,11 +202,9 @@ pub(crate) fn walk_function( // here exactly as they are from the seed loop below. if !is_variadic && !ret_outptr { for (i, &pty) in param_tys.iter().enumerate() { - let stripped = pty & !(1i64 << 30); - let is_pointer = pty & (1i64 << 30) != 0; - if !is_pointer - && (stripped == crate::c5::token::Ty::Float as i64 - || stripped == crate::c5::token::Ty::Double as i64) + let stripped = strip_unsigned(pty); + if stripped == crate::c5::token::Ty::Float as i64 + || stripped == crate::c5::token::Ty::Double as i64 { b.mark_param_fp(i); } @@ -266,7 +264,7 @@ pub(crate) fn walk_function( if local_slot < 0 { continue; } - let stripped = pty & !(1i64 << 30); + let stripped = strip_unsigned(pty); let is_struct_value = stripped >= STRUCT_BASE && ((stripped - STRUCT_BASE) % STRUCT_STRIDE) / 2 == 0; if is_struct_value { @@ -310,15 +308,14 @@ pub(crate) fn walk_function( ) { continue; } - // Pointer-typed parameters carry the pointer marker - // bit; the body reads them as full-width pointers - // (8 bytes), not as the base type's narrow width. - // Without this check `char *fmt` would store only one - // byte and the high bits would diverge from the - // prologue's full-width spill. + // An unsigned-tagged parameter keeps the full 8-byte + // store/load so the body's zero-extending reads see the + // caller's extension rather than a sign-extended narrow + // reload. Pointer tags land in the I64 default arm by + // band value. use crate::c5::token::Ty; - let is_pointer = pty & (1i64 << 30) != 0; - let (store_kind, load_kind) = if is_pointer { + let unsigned = pty & UNSIGNED_BIT != 0; + let (store_kind, load_kind) = if unsigned { ( super::super::ir::StoreKind::I64, super::super::ir::LoadKind::I64, @@ -354,7 +351,7 @@ pub(crate) fn walk_function( if local_slot >= 0 { continue; } - let stripped = pty & !(1i64 << 30); + let stripped = strip_unsigned(pty); let is_struct_value = stripped >= STRUCT_BASE && ((stripped - STRUCT_BASE) % STRUCT_STRIDE) / 2 == 0; if is_struct_value { diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index 60cdc9f3d..97eda9b95 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1547,6 +1547,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ // wired for the JIT lane). ("volatile_ptr_alias_loop.c", 0), ("volatile_unused_read.c", 0), + ("volatile_param_classes.c", 0), // `thread_local_*.c` aren't here -- the JIT path's host is // macOS arm64 in this repo, where TLS lowering isn't // implemented yet (Mach-O __thread_data + dyld diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index b82f84fdb..1cb685745 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -709,6 +709,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("volatile_setjmp_longjmp.c", 0), ("volatile_ptr_alias_loop.c", 0), ("volatile_unused_read.c", 0), + ("volatile_param_classes.c", 0), ("struct_basic.c", 25), ("struct_linked_list.c", 10), ("global_initializer_int.c", 141), diff --git a/tests/fixtures/c/volatile_param_classes.c b/tests/fixtures/c/volatile_param_classes.c new file mode 100644 index 000000000..b2aa1cddc --- /dev/null +++ b/tests/fixtures/c/volatile_param_classes.c @@ -0,0 +1,36 @@ +/* Volatile-qualified parameters must keep their band classification + (C99 6.7.3, 6.7.5.3): a `volatile double` still arrives in an FP + argument register, a `volatile float` keeps its narrow entry copy, + and the qualifier must not push either onto the integer path. */ +typedef struct Acc { + double sum; + long long cnt; +} Acc; + +static void step(volatile Acc *a, volatile double r) { + volatile double s = a->sum; + a->sum = s + r; +} + +static double half(volatile float f) { + return (double)f * 0.5; +} + +static void bump(Acc *a, double v) { + a->cnt++; + step(a, v); +} + +int main(void) { + Acc a = {0.0, 0}; + bump(&a, 1.5); + bump(&a, 2.5); + bump(&a, 3.5); + if (a.sum != 7.5 || a.cnt != 3) { + return 1; + } + if (half(5.0f) != 2.5) { + return 2; + } + return 0; +} diff --git a/tests/snapshots/asm/volatile_param_classes.aarch64.asm b/tests/snapshots/asm/volatile_param_classes.aarch64.asm new file mode 100644 index 000000000..904d6827a --- /dev/null +++ b/tests/snapshots/asm/volatile_param_classes.aarch64.asm @@ -0,0 +1,126 @@ + +volatile_param_classes.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + fmov x16, d0 + str x16, [sp, #-0x10]! + str x0, [sp, #-0x10]! + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x10 + stur x0, [x29, #0x10] + str d0, [x29, #0x20] + ldur x0, [x29, #0x10] + ldr d0, [x0] + sub x17, x29, #0x8 + str d0, [x17] + ldur x0, [x29, #0x10] + sub x16, x29, #0x8 + ldr d0, [x16] + ldr d1, [x29, #0x20] + fadd d0, d0, d1 + str d0, [x0] + mov x0, #0x0 // =0 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0x20 + ret + +: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x10 + sub x17, x29, #0x8 + str s0, [x17] + sub x16, x29, #0x8 + ldr s0, [x16] + fcvt d0, s0 + mov x0, #0x3fe0000000000000 // =4602678819172646912 + fmov d17, x0 + fmul d0, d0, d17 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + +: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + ldr x1, [x0, #0x8] + add x1, x1, #0x1 + str x1, [x0, #0x8] + bl + mov x0, #0x0 // =0 + ldp x29, x30, [sp], #0x10 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x40 + str x20, [sp] + sub x0, x29, #0x10 + adrp x1, + add x1, x1, + str x10, [sp, #-0x10]! + ldr x10, [x1] + str x10, [x0] + ldr x10, [x1, #0x8] + str x10, [x0, #0x8] + ldr x10, [sp], #0x10 + sub x0, x29, #0x10 + mov x1, #0x3ff8000000000000 // =4609434218613702656 + fmov d0, x1 + bl + sub x0, x29, #0x10 + mov x1, #0x4004000000000000 // =4612811918334230528 + fmov d0, x1 + bl + sub x0, x29, #0x10 + mov x1, #0x400c000000000000 // =4615063718147915776 + fmov d0, x1 + bl + sub x0, x29, #0x10 + ldr d0, [x0] + mov x0, #0x401e000000000000 // =4620130267728707584 + fmov d17, x0 + fcmp d0, d17 + cset x20, ne + cbnz x20, + sub x0, x29, #0x10 + ldr x0, [x0, #0x8] + cmp x0, #0x3 + cset x20, ne + cbz x20, + mov x0, #0x1 // =1 + ldr x20, [sp] + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x4014000000000000 // =4617315517961601024 + fmov d16, x0 + fcvt s0, d16 + bl + mov x0, #0x4004000000000000 // =4612811918334230528 + fmov d17, x0 + fcmp d0, d17 + cset x0, ne + cbz x0, + mov x0, #0x2 // =2 + ldr x20, [sp] + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldr x20, [sp] + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret + b diff --git a/tests/snapshots/asm/volatile_param_classes.x64.asm b/tests/snapshots/asm/volatile_param_classes.x64.asm new file mode 100644 index 000000000..48e885f7b --- /dev/null +++ b/tests/snapshots/asm/volatile_param_classes.x64.asm @@ -0,0 +1,140 @@ + +volatile_param_classes.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + popq %r10 + subq $0x20, %rsp + movq %rdi, (%rsp) + movsd %xmm0, 0x10(%rsp) + pushq %r10 + pushq %rbp + movq %rsp, %rbp + subq $0x10, %rsp + movq %rdi, 0x10(%rbp) + movsd %xmm0, 0x20(%rbp,%riz) + movq 0x10(%rbp), %rax + movsd (%rax,%riz), %xmm0 + movsd %xmm0, -0x8(%rbp,%riz) + movq 0x10(%rbp), %rax + movsd -0x8(%rbp,%riz), %xmm0 + movsd 0x20(%rbp,%riz), %xmm1 + addsd %xmm1, %xmm0 + movsd %xmm0, (%rax,%riz) + xorq %rax, %rax + addq $0x10, %rsp + popq %rbp + popq %r11 + addq $0x20, %rsp + pushq %r11 + retq + +: + pushq %rbp + movq %rsp, %rbp + subq $0x10, %rsp + movss %xmm0, -0x8(%rbp,%riz) + movss -0x8(%rbp,%riz), %xmm0 + cvtss2sd %xmm0, %xmm0 + movabsq $0x3fe0000000000000, %rax # imm = 0x3FE0000000000000 + movq %rax, %xmm15 + mulsd %xmm15, %xmm0 + addq $0x10, %rsp + popq %rbp + retq + +: + pushq %rbp + movq %rsp, %rbp + movq 0x8(%rdi), %rax + incq %rax + movq %rax, 0x8(%rdi) + callq + xorq %rax, %rax + popq %rbp + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x40, %rsp + movq %rbx, (%rsp) + leaq -0x10(%rbp), %rax + leaq , %rcx + pushq %rdx + movq (%rcx), %rdx + movq %rdx, (%rax) + movq 0x8(%rcx), %rdx + movq %rdx, 0x8(%rax) + popq %rdx + leaq -0x10(%rbp), %rdi + movabsq $0x3ff8000000000000, %rsi # imm = 0x3FF8000000000000 + movq %rsi, %xmm0 + callq + leaq -0x10(%rbp), %rdi + movabsq $0x4004000000000000, %rsi # imm = 0x4004000000000000 + movq %rsi, %xmm0 + callq + leaq -0x10(%rbp), %rdi + movabsq $0x400c000000000000, %rsi # imm = 0x400C000000000000 + movq %rsi, %xmm0 + callq + leaq -0x10(%rbp), %rax + movsd (%rax,%riz), %xmm0 + movabsq $0x401e000000000000, %rax # imm = 0x401E000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %bl + movzbq %bl, %rbx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rbx + testq %rbx, %rbx + jne + leaq -0x10(%rbp), %rax + movq 0x8(%rax), %rax + cmpq $0x3, %rax + setne %bl + movzbq %bl, %rbx + testq %rbx, %rbx + je + movl $0x1, %eax + movq (%rsp), %rbx + addq $0x40, %rsp + popq %rbp + retq + movabsq $0x4014000000000000, %rax # imm = 0x4014000000000000 + movq %rax, %xmm14 + cvtsd2ss %xmm14, %xmm0 + callq + movabsq $0x4004000000000000, %rax # imm = 0x4004000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %al + movzbq %al, %rax + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rax + testq %rax, %rax + je + movl $0x2, %eax + movq (%rsp), %rbx + addq $0x40, %rsp + popq %rbp + retq + xorq %rax, %rax + movq (%rsp), %rbx + addq $0x40, %rsp + popq %rbp + retq + jmp + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/ssa/volatile_param_classes.ssa b/tests/snapshots/ssa/volatile_param_classes.ssa new file mode 100644 index 000000000..837baf316 --- /dev/null +++ b/tests/snapshots/ssa/volatile_param_classes.ssa @@ -0,0 +1,153 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=step +fn ent_pc=0 n_params=2 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 StoreLocal { off=2, value=v1, kind=I64 } -> - + v3 ParamRef(1, kind=F64) -> d0 + v4 StoreLocal { off=3, value=v3, kind=F64 } -> - + v5 LoadLocal { off=2, kind=I64, volatile } -> x0 + v6 Load { addr=v5, disp=0, kind=F64, volatile } -> d0 + v7 StoreLocal { off=-1, value=v6, kind=F64, volatile } -> - + v8 LoadLocal { off=2, kind=I64, volatile } -> x0 + v9 LoadLocal { off=-1, kind=F64, volatile } -> d0 + v10 LoadLocal { off=3, kind=F64, volatile } -> d1 + v11 Binop { op=fadd, lhs=v9, rhs=v10 } -> d0 + v12 Store { addr=v8, disp=0, value=v11, kind=F64 } -> - + v13 Imm(0) -> x0 + terminator Return(v13) (exit_acc=v13) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=half +fn ent_pc=1 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=F32) -> d0 [f32] + v2 StoreLocal { off=-1, value=v1, kind=F32 } -> - + v3 LoadLocal { off=-1, kind=F32, volatile } -> d0 [f32] + v4 FpCast { kind=F32ToF64, value=v3 } -> d0 + v5 Imm(4602678819172646912) -> x0 + v6 Binop { op=fmul, lhs=v4, rhs=v5 } -> d0 + terminator Return(v6) (exit_acc=v6) +; --- SSA dump (ok=true) ent_pc=2 --- +; name=bump +fn ent_pc=2 n_params=2 variadic=false locals=2 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=F64) -> d0 + v4 Imm(0) -> x0 + v5 LoadLocal { off=2, kind=I64 } -> x0 + v6 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x0 + v7 Load { addr=v1, disp=8, kind=I64 } -> x0 + v8 BinopI { op=add, lhs=v7, rhs_imm=1 } -> x0 + v9 Store { addr=v1, disp=8, value=v8, kind=I64 } -> - + v10 LoadLocal { off=2, kind=I64 } -> x0 + v11 LoadLocal { off=3, kind=F64 } -> d1 + v12 Call { target_pc=0, args=[v1, v3], fixed_args=2, fp_return=false, fp_arg_mask=0x2 } -> x0 + v13 Imm(0) -> x0 + terminator Return(v13) (exit_acc=v13) +; --- SSA dump (ok=true) ent_pc=3 --- +; name=main +fn ent_pc=3 n_params=0 variadic=false locals=5 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-2) -> x0 + v2 ImmData(8) -> x1 + v3 Mcpy { dst=v1, src=v2, size=16 } -> x0 + v4 LocalAddr(-2) -> x7 + v5 Imm(4609434218613702656) -> x6 + v6 Call { target_pc=2, args=[v4, v5], fixed_args=2, fp_return=false, fp_arg_mask=0x2 } -> x0 + v7 LocalAddr(-2) -> x7 + v8 Imm(4612811918334230528) -> x6 + v9 Call { target_pc=2, args=[v7, v8], fixed_args=2, fp_return=false, fp_arg_mask=0x2 } -> x0 + v10 LocalAddr(-2) -> x7 + v11 Imm(4615063718147915776) -> x6 + v12 Call { target_pc=2, args=[v10, v11], fixed_args=2, fp_return=false, fp_arg_mask=0x2 } -> x0 + v13 LocalAddr(-2) -> x0 + v14 Load { addr=v13, disp=0, kind=F64 } -> d0 + v15 Imm(4620130267728707584) -> x0 + v16 Binop { op=fne, lhs=v14, rhs=v15 } -> x3 + v17 Imm(0) -> x0 + terminator Bnz { cond=v16, target=b7, fall=b1 } (exit_acc=v16) + block 1 start_pc=0 + v18 LocalAddr(-2) -> x0 + v19 BinopI { op=add, lhs=v18, rhs_imm=8 } -> x1 + v20 Load { addr=v18, disp=8, kind=I64 } -> x0 + v21 BinopI { op=ne, lhs=v20, rhs_imm=3 } -> x3 + v22 Imm(0) -> x0 + terminator Jmp(b2) (exit_acc=v21) + block 2 start_pc=0 + v23 Phi { incoming=[b7:v16, b1:v21], kind=I64 } -> x3 + v24 LoadLocal { off=-5, kind=I64 } -> x0 + terminator Bz { cond=v23, target=b4, fall=b3 } (exit_acc=v23) + block 3 start_pc=0 + v25 Imm(1) -> x0 + terminator Return(v25) (exit_acc=v25) + block 4 start_pc=0 + v26 Imm(4617315517961601024) -> x0 + v27 FpCast { kind=F64ToF32, value=v26 } -> d0 [f32] + v28 Call { target_pc=1, args=[v27], fixed_args=1, fp_return=true, fp_arg_mask=0x1 } -> d0 + v29 Imm(4612811918334230528) -> x0 + v30 Binop { op=fne, lhs=v28, rhs=v29 } -> x0 + terminator Bz { cond=v30, target=b6, fall=b5 } (exit_acc=v30) + block 5 start_pc=0 + v31 Imm(2) -> x0 + terminator Return(v31) (exit_acc=v31) + block 6 start_pc=0 + v32 Imm(0) -> x0 + terminator Return(v32) (exit_acc=v32) + block 7 start_pc=0 + terminator Jmp(b2) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) From 9287e8c299fd520a83b9f9d57245c6177688c846 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:07:24 -0700 Subject: [PATCH 21/67] inline: resolve forward references in the multi-block splice splice_multi_block emitted the caller blocks after the splice point in a single pass, so a use of the inlined call's result (mapped only when the callee's Return is spliced) resolved to NO_VALUE and the value was silently dropped at -O. Run the emission to a fixed point, as the flat single-block splice already does. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/passes/inline.rs | 368 ++++++++++-------- src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + .../c/inline_multi_block_result_forward.c | 23 ++ 8 files changed, 226 insertions(+), 171 deletions(-) create mode 100644 tests/fixtures/c/inline_multi_block_result_forward.c diff --git a/src/c5/codegen/passes/inline.rs b/src/c5/codegen/passes/inline.rs index ee57b9d9a..9eba3cdd7 100644 --- a/src/c5/codegen/passes/inline.rs +++ b/src/c5/codegen/passes/inline.rs @@ -706,10 +706,49 @@ fn splice_multi_block( new_f32.push(f32); }; - // Step 1: caller blocks 0..splice_block_idx (unchanged). - for (b_idx, block) in original.blocks.iter().enumerate().take(splice_block_idx) { - let block_start = new_insts.len() as u32; - for pc in block.inst_range.start..block.inst_range.end { + // Neither block array is ordered definitions-before-uses, and the + // call result's mapping only materializes when the callee's Return + // is spliced (Step 6) -- after Step 4 already emitted the caller + // blocks that follow the splice point. Run the emission to a fixed + // point, as the flat single-block splice does: emission is + // structurally identical across passes, so every inst keeps its new + // id and the maps converge one forward-reference level per pass. + let mut guard = original.insts.len() + callee.insts.len() + 2; + loop { + new_insts.clear(); + new_inst_src.clear(); + new_f32.clear(); + new_blocks.clear(); + let remap_before = remap.clone(); + let callee_remap_before = callee_remap.clone(); + + // Step 1: caller blocks 0..splice_block_idx (unchanged). + for (b_idx, block) in original.blocks.iter().enumerate().take(splice_block_idx) { + let block_start = new_insts.len() as u32; + for pc in block.inst_range.start..block.inst_range.end { + emit_caller_inst( + pc, + &mut new_insts, + &mut new_inst_src, + &mut new_f32, + &mut remap, + &original, + ); + } + let term = map_terminator_caller(block.terminator, &remap); + let exit_acc = map_v(block.exit_acc, &remap); + new_blocks.push(Block { + start_pc: block.start_pc, + inst_range: block_start..new_insts.len() as u32, + terminator: term, + exit_acc, + }); + let _ = b_idx; + } + + // Step 2: prefix (caller's splice block, insts up to call). + let prefix_start = new_insts.len() as u32; + for pc in splice_block.inst_range.start..call_pc { emit_caller_inst( pc, &mut new_insts, @@ -719,59 +758,148 @@ fn splice_multi_block( &original, ); } - let term = map_terminator_caller(block.terminator, &remap); - let exit_acc = map_v(block.exit_acc, &remap); + let callee_entry_new_id = callee_block_base; new_blocks.push(Block { - start_pc: block.start_pc, - inst_range: block_start..new_insts.len() as u32, - terminator: term, - exit_acc, + start_pc: splice_block.start_pc, + inst_range: prefix_start..new_insts.len() as u32, + terminator: Terminator::Jmp(callee_entry_new_id), + exit_acc: NO_VALUE, }); - let _ = b_idx; - } + let _ = prefix_id; - // Step 2: prefix (caller's splice block, insts up to call). - let prefix_start = new_insts.len() as u32; - for pc in splice_block.inst_range.start..call_pc { - emit_caller_inst( - pc, - &mut new_insts, - &mut new_inst_src, - &mut new_f32, - &mut remap, - &original, - ); - } - let callee_entry_new_id = callee_block_base; - new_blocks.push(Block { - start_pc: splice_block.start_pc, - inst_range: prefix_start..new_insts.len() as u32, - terminator: Terminator::Jmp(callee_entry_new_id), - exit_acc: NO_VALUE, - }); - let _ = prefix_id; + // Step 3: postfix block placeholder (filled after callee splices). + // We need its ID stable now so the callee's Return -> Jmp(postfix) + // points to it; emit insts + terminator below after the callee. + let postfix_block_slot = new_blocks.len(); + new_blocks.push(Block { + start_pc: 0, + inst_range: 0..0, + terminator: Terminator::Jmp(0), + exit_acc: NO_VALUE, + }); + let _ = postfix_id; + + // Step 4: caller blocks splice_block_idx+1..n_caller (shifted +1). + for (b_idx, block) in original + .blocks + .iter() + .enumerate() + .skip(splice_block_idx + 1) + { + let block_start = new_insts.len() as u32; + for pc in block.inst_range.start..block.inst_range.end { + emit_caller_inst( + pc, + &mut new_insts, + &mut new_inst_src, + &mut new_f32, + &mut remap, + &original, + ); + } + let term = map_terminator_caller(block.terminator, &remap); + let exit_acc = map_v(block.exit_acc, &remap); + new_blocks.push(Block { + start_pc: block.start_pc, + inst_range: block_start..new_insts.len() as u32, + terminator: term, + exit_acc, + }); + let _ = b_idx; + } - // Step 3: postfix block placeholder (filled after callee splices). - // We need its ID stable now so the callee's Return -> Jmp(postfix) - // points to it; emit insts + terminator below after the callee. - let postfix_block_slot = new_blocks.len(); - new_blocks.push(Block { - start_pc: 0, - inst_range: 0..0, - terminator: Terminator::Jmp(0), - exit_acc: NO_VALUE, - }); - let _ = postfix_id; + // Step 5: remap the call's args through the caller's now-built remap. + let remapped_args: Vec = call_args.iter().map(|&a| map_v(a, &remap)).collect(); - // Step 4: caller blocks splice_block_idx+1..n_caller (shifted +1). - for (b_idx, block) in original - .blocks - .iter() - .enumerate() - .skip(splice_block_idx + 1) - { - let block_start = new_insts.len() as u32; - for pc in block.inst_range.start..block.inst_range.end { + // Step 6: splice every callee block. + for cblock in &callee.blocks { + let block_start = new_insts.len() as u32; + for ce_pc in cblock.inst_range.start..cblock.inst_range.end { + let cinst = &callee.insts[ce_pc as usize]; + match cinst { + Inst::ParamRef { idx, kind } => { + let i = *idx as usize; + let arg = if i < remapped_args.len() { + remapped_args[i] + } else { + NO_VALUE + }; + callee_remap[ce_pc as usize] = splice_param_ref( + *kind, + arg, + (0, 0), + &mut new_insts, + &mut new_inst_src, + &mut new_f32, + ); + continue; + } + Inst::LoadLocal { .. } | Inst::StoreLocal { .. } | Inst::AllocaInit(_) => { + callee_remap[ce_pc as usize] = NO_VALUE; + continue; + } + _ => {} + } + if let Some(translated) = rewrite_callee_inst(cinst, &remapped_args, &callee_remap) { + let new_id = new_insts.len() as u32; + callee_remap[ce_pc as usize] = new_id; + new_insts.push(translated); + new_inst_src.push((0, 0)); + new_f32.push( + callee + .f32_values + .get(ce_pc as usize) + .copied() + .unwrap_or(false), + ); + } + } + let new_term = match cblock.terminator { + Terminator::Jmp(b) => Terminator::Jmp(shift_callee_bid(b)), + Terminator::FallThrough(b) => Terminator::Jmp(shift_callee_bid(b)), + Terminator::Bz { + cond, + target, + fall_through, + } => Terminator::Bz { + cond: map_v(cond, &callee_remap), + target: shift_callee_bid(target), + fall_through: shift_callee_bid(fall_through), + }, + Terminator::Bnz { + cond, + target, + fall_through, + } => Terminator::Bnz { + cond: map_v(cond, &callee_remap), + target: shift_callee_bid(target), + fall_through: shift_callee_bid(fall_through), + }, + Terminator::Return(v) => { + remap[call_pc as usize] = map_v(v, &callee_remap); + Terminator::Jmp(postfix_id) + } + Terminator::TailExt(_) => unreachable!("filter rejects TailExt"), + Terminator::GotoIndirect { .. } => { + unreachable!("filter rejects GotoIndirect") + } + }; + let exit_acc = if cblock.exit_acc != NO_VALUE { + map_v(cblock.exit_acc, &callee_remap) + } else { + NO_VALUE + }; + new_blocks.push(Block { + start_pc: 0, + inst_range: block_start..new_insts.len() as u32, + terminator: new_term, + exit_acc, + }); + } + + // Step 7: fill the postfix slot now that the call's remap is set. + let postfix_start = new_insts.len() as u32; + for pc in (call_pc + 1)..splice_block.inst_range.end { emit_caller_inst( pc, &mut new_insts, @@ -781,129 +909,27 @@ fn splice_multi_block( &original, ); } - let term = map_terminator_caller(block.terminator, &remap); - let exit_acc = map_v(block.exit_acc, &remap); - new_blocks.push(Block { - start_pc: block.start_pc, - inst_range: block_start..new_insts.len() as u32, - terminator: term, - exit_acc, - }); - let _ = b_idx; - } - - // Step 5: remap the call's args through the caller's now-built remap. - let remapped_args: Vec = call_args.iter().map(|&a| map_v(a, &remap)).collect(); - - // Step 6: splice every callee block. - for cblock in &callee.blocks { - let block_start = new_insts.len() as u32; - for ce_pc in cblock.inst_range.start..cblock.inst_range.end { - let cinst = &callee.insts[ce_pc as usize]; - match cinst { - Inst::ParamRef { idx, kind } => { - let i = *idx as usize; - let arg = if i < remapped_args.len() { - remapped_args[i] - } else { - NO_VALUE - }; - callee_remap[ce_pc as usize] = splice_param_ref( - *kind, - arg, - (0, 0), - &mut new_insts, - &mut new_inst_src, - &mut new_f32, - ); - continue; - } - Inst::LoadLocal { .. } | Inst::StoreLocal { .. } | Inst::AllocaInit(_) => { - callee_remap[ce_pc as usize] = NO_VALUE; - continue; - } - _ => {} - } - if let Some(translated) = rewrite_callee_inst(cinst, &remapped_args, &callee_remap) { - let new_id = new_insts.len() as u32; - callee_remap[ce_pc as usize] = new_id; - new_insts.push(translated); - new_inst_src.push((0, 0)); - new_f32.push( - callee - .f32_values - .get(ce_pc as usize) - .copied() - .unwrap_or(false), - ); - } - } - let new_term = match cblock.terminator { - Terminator::Jmp(b) => Terminator::Jmp(shift_callee_bid(b)), - Terminator::FallThrough(b) => Terminator::Jmp(shift_callee_bid(b)), - Terminator::Bz { - cond, - target, - fall_through, - } => Terminator::Bz { - cond: map_v(cond, &callee_remap), - target: shift_callee_bid(target), - fall_through: shift_callee_bid(fall_through), - }, - Terminator::Bnz { - cond, - target, - fall_through, - } => Terminator::Bnz { - cond: map_v(cond, &callee_remap), - target: shift_callee_bid(target), - fall_through: shift_callee_bid(fall_through), - }, - Terminator::Return(v) => { - remap[call_pc as usize] = map_v(v, &callee_remap); - Terminator::Jmp(postfix_id) - } - Terminator::TailExt(_) => unreachable!("filter rejects TailExt"), - Terminator::GotoIndirect { .. } => { - unreachable!("filter rejects GotoIndirect") - } - }; - let exit_acc = if cblock.exit_acc != NO_VALUE { - map_v(cblock.exit_acc, &callee_remap) - } else { - NO_VALUE + let postfix_term = match splice_block.terminator { + Terminator::FallThrough(b) => Terminator::Jmp(shift_caller_bid(b)), + other => map_terminator_caller(other, &remap), }; - new_blocks.push(Block { + let postfix_exit_acc = map_v(splice_block.exit_acc, &remap); + new_blocks[postfix_block_slot] = Block { start_pc: 0, - inst_range: block_start..new_insts.len() as u32, - terminator: new_term, - exit_acc, - }); - } + inst_range: postfix_start..new_insts.len() as u32, + terminator: postfix_term, + exit_acc: postfix_exit_acc, + }; - // Step 7: fill the postfix slot now that the call's remap is set. - let postfix_start = new_insts.len() as u32; - for pc in (call_pc + 1)..splice_block.inst_range.end { - emit_caller_inst( - pc, - &mut new_insts, - &mut new_inst_src, - &mut new_f32, - &mut remap, - &original, - ); + if remap == remap_before && callee_remap == callee_remap_before { + break; + } + guard -= 1; + if guard == 0 { + break; + } } - let postfix_term = match splice_block.terminator { - Terminator::FallThrough(b) => Terminator::Jmp(shift_caller_bid(b)), - other => map_terminator_caller(other, &remap), - }; - let postfix_exit_acc = map_v(splice_block.exit_acc, &remap); - new_blocks[postfix_block_slot] = Block { - start_pc: 0, - inst_range: postfix_start..new_insts.len() as u32, - terminator: postfix_term, - exit_acc: postfix_exit_acc, - }; + // Carry both the caller's own and the spliced callee's cross-TU // symbol references onto their new value-ids. The symbol indices diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index 97eda9b95..a1aa26220 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1557,6 +1557,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("packed_bitfield_repack.c", 0), ("nested_designator_string_member.c", 0), ("union_member_unbraced_init.c", 0), + ("inline_multi_block_result_forward.c", 10), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index 1cb685745..dbfe7707e 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -931,6 +931,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("packed_bitfield_repack.c", 0), ("nested_designator_string_member.c", 0), ("union_member_unbraced_init.c", 0), + ("inline_multi_block_result_forward.c", 10), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index 4ed036712..ac6a0b330 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -707,6 +707,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("packed_bitfield_repack.c", 0), ("nested_designator_string_member.c", 0), ("union_member_unbraced_init.c", 0), + ("inline_multi_block_result_forward.c", 10), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 32b0565f2..98ac5cfb5 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -656,6 +656,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("packed_bitfield_repack.c", 0), ("nested_designator_string_member.c", 0), ("union_member_unbraced_init.c", 0), + ("inline_multi_block_result_forward.c", 10), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index 21c9e5115..33d1ed333 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -914,6 +914,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("packed_bitfield_repack.c", 0), ("nested_designator_string_member.c", 0), ("union_member_unbraced_init.c", 0), + ("inline_multi_block_result_forward.c", 10), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index e8f08fdc5..fd13d3945 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -932,6 +932,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("packed_bitfield_repack.c", 0), ("nested_designator_string_member.c", 0), ("union_member_unbraced_init.c", 0), + ("inline_multi_block_result_forward.c", 10), ]; #[test] diff --git a/tests/fixtures/c/inline_multi_block_result_forward.c b/tests/fixtures/c/inline_multi_block_result_forward.c new file mode 100644 index 000000000..7ecbae4ac --- /dev/null +++ b/tests/fixtures/c/inline_multi_block_result_forward.c @@ -0,0 +1,23 @@ +/* The result of an inlined multi-block callee is read in caller blocks + emitted after the splice point; the splice must resolve those forward + references instead of dropping them. */ +static int helper_one(int x) { return x + x; } + +static int helper_two(int x) { + int y; + goto compute; +compute: + y = x << 1; + return y; +} + +int test(int a) { + int r = helper_two(a); + int s = helper_one(a); + if (a > 3) { + return r; + } + return r + s; +} + +int main(void) { return test(5); } From dbca43ad545fde9fa9cd7ef39713d8d07ed7a26e Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:15:17 -0700 Subject: [PATCH 22/67] reg_alloc: gate the sign-narrow shift fold on source-place survival The post-coloring Shl K / Shr K fold reads the Shl source's place when the Shr is emitted, past the source's live range; an intervening definition colored onto the same place (or an inst with fixed emit-level clobbers) invalidates the read. Fold only when the pair shares a block, every intervening inst is clobber-free, and no intervening definition occupies the source's place. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/ssa/reg_alloc.rs | 74 ++++++++++++++++++++ src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + tests/fixtures/c/sxtw_fold_source_liveness.c | 11 +++ 8 files changed, 91 insertions(+) create mode 100644 tests/fixtures/c/sxtw_fold_source_liveness.c diff --git a/src/c5/codegen/ssa/reg_alloc.rs b/src/c5/codegen/ssa/reg_alloc.rs index b5e63fd39..e1b4551b6 100644 --- a/src/c5/codegen/ssa/reg_alloc.rs +++ b/src/c5/codegen/ssa/reg_alloc.rs @@ -529,6 +529,77 @@ pub(crate) fn allocate(func: &FunctionSsa, target: Target) -> Allocation { _ => None, } }; + // The fold reads `places[shl_src]` when the Shr is emitted, past the + // source's coloring-visible live range (its last use is the Shl). It + // is sound only when nothing between the pair can change that place: + // both insts in one block, every intervening inst free of fixed + // emit-level clobbers (calls, div/mod, register-count shifts, + // atomics, mcpy), and no intervening definition colored onto the + // same place. + let mut block_of: Vec = vec![0; func.insts.len()]; + for (b, blk) in func.blocks.iter().enumerate() { + for v in blk.inst_range.clone() { + block_of[v as usize] = b as u32; + } + } + let clobber_free = |inst: &Inst| -> bool { + match inst { + Inst::Imm(_) + | Inst::ImmData(_) + | Inst::ImmCode(_) + | Inst::ImmExtCode(_) + | Inst::BlockAddr(_) + | Inst::LocalAddr(_) + | Inst::Extend { .. } + | Inst::FpCast { .. } + | Inst::Fneg(_) + | Inst::Fma { .. } + | Inst::Load { .. } + | Inst::LoadLocal { .. } + | Inst::LoadIndexed { .. } + | Inst::Store { .. } + | Inst::StoreLocal { .. } + | Inst::StoreIndexed { .. } => true, + Inst::BinopI { op, .. } => { + !matches!(op, BinOp::Div | BinOp::Divu | BinOp::Mod | BinOp::Modu) + } + Inst::Binop { op, .. } => !matches!( + op, + BinOp::Div + | BinOp::Divu + | BinOp::Mod + | BinOp::Modu + | BinOp::Shl + | BinOp::Shr + | BinOp::Shru + ), + _ => false, + } + }; + let fold_preserves_source = |shl_pc: ValueId, shr_pc: ValueId| -> bool { + if block_of[shl_pc as usize] != block_of[shr_pc as usize] { + return false; + } + let src_place = match func.insts.get(shl_pc as usize) { + Some(inst) => match shift_shape(inst) { + Some((_, src, _, _)) => places.get(src as usize).copied().unwrap_or(Place::None), + None => return false, + }, + None => return false, + }; + for p in (shl_pc + 1)..shr_pc { + let inst_p = &func.insts[p as usize]; + if !clobber_free(inst_p) { + return false; + } + if produces_value(inst_p) + && places.get(p as usize).copied().unwrap_or(Place::None) == src_place + { + return false; + } + } + true + }; for (i, inst) in func.insts.iter().enumerate() { let Some((shr_op, shr_lhs, shr_k, shr_imm_v)) = shift_shape(inst) else { continue; @@ -548,6 +619,9 @@ pub(crate) fn allocate(func: &FunctionSsa, target: Target) -> Allocation { if use_counts.get(shr_lhs as usize).copied().unwrap_or(0) != 1 { continue; } + if !fold_preserves_source(shr_lhs, i as ValueId) { + continue; + } sxtw_source[i] = shl_src; sxtw_k[i] = shr_k; use_counts[shr_lhs as usize] = 0; diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index a1aa26220..e1622bd6f 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1558,6 +1558,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("nested_designator_string_member.c", 0), ("union_member_unbraced_init.c", 0), ("inline_multi_block_result_forward.c", 10), + ("sxtw_fold_source_liveness.c", 18), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index dbfe7707e..e0234fd58 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -932,6 +932,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("nested_designator_string_member.c", 0), ("union_member_unbraced_init.c", 0), ("inline_multi_block_result_forward.c", 10), + ("sxtw_fold_source_liveness.c", 18), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index ac6a0b330..95e42abce 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -708,6 +708,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("nested_designator_string_member.c", 0), ("union_member_unbraced_init.c", 0), ("inline_multi_block_result_forward.c", 10), + ("sxtw_fold_source_liveness.c", 18), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 98ac5cfb5..720860fb8 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -657,6 +657,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("nested_designator_string_member.c", 0), ("union_member_unbraced_init.c", 0), ("inline_multi_block_result_forward.c", 10), + ("sxtw_fold_source_liveness.c", 18), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index 33d1ed333..a9dd0e147 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -915,6 +915,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("nested_designator_string_member.c", 0), ("union_member_unbraced_init.c", 0), ("inline_multi_block_result_forward.c", 10), + ("sxtw_fold_source_liveness.c", 18), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index fd13d3945..f1751335e 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -933,6 +933,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("nested_designator_string_member.c", 0), ("union_member_unbraced_init.c", 0), ("inline_multi_block_result_forward.c", 10), + ("sxtw_fold_source_liveness.c", 18), ]; #[test] diff --git a/tests/fixtures/c/sxtw_fold_source_liveness.c b/tests/fixtures/c/sxtw_fold_source_liveness.c new file mode 100644 index 000000000..806a1bb6d --- /dev/null +++ b/tests/fixtures/c/sxtw_fold_source_liveness.c @@ -0,0 +1,11 @@ +/* The Shl/Shr sign-narrow fold reads the Shl source's register at the + Shr; an intervening definition may reuse that register once the + source's live range ends. The fold must verify the place survives. */ +long f(long x, long b) { + long t = x << 32; + long v = x + b; + long y = t >> 32; + return y + v + b; +} + +int main(void) { return (int)f(2, 7); } From ba621cd78187acbcdf375e4f4c5b5d79695a2408 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:20:26 -0700 Subject: [PATCH 23/67] shadow: attribute a one-past-the-end data reloc to its own object A DataReloc target of the &arr[N] address constant equals the next object's start offset, so compaction marked and rebased the wrong object; with bss segregation the neighbor moved and the stored end pointer went stale. Carry the pointed-at object's start offset (target_anchor) on the reloc and resolve intervals through it. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/passes/inline.rs | 4 ++-- src/c5/codegen/ssa/shadow.rs | 25 +++++++++++++++++++--- src/c5/compiler/global_init.rs | 4 ++++ src/c5/compiler/initializer.rs | 5 +++++ src/c5/linker/synth_build.rs | 2 ++ src/c5/program.rs | 7 ++++++ src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + tests/fixtures/c/data_reloc_one_past_end.c | 17 +++++++++++++++ 13 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 tests/fixtures/c/data_reloc_one_past_end.c diff --git a/src/c5/codegen/passes/inline.rs b/src/c5/codegen/passes/inline.rs index 9eba3cdd7..440cadfe3 100644 --- a/src/c5/codegen/passes/inline.rs +++ b/src/c5/codegen/passes/inline.rs @@ -840,7 +840,8 @@ fn splice_multi_block( } _ => {} } - if let Some(translated) = rewrite_callee_inst(cinst, &remapped_args, &callee_remap) { + if let Some(translated) = rewrite_callee_inst(cinst, &remapped_args, &callee_remap) + { let new_id = new_insts.len() as u32; callee_remap[ce_pc as usize] = new_id; new_insts.push(translated); @@ -930,7 +931,6 @@ fn splice_multi_block( } } - // Carry both the caller's own and the spliced callee's cross-TU // symbol references onto their new value-ids. The symbol indices // are translation-unit parser symbols, valid in the merged diff --git a/src/c5/codegen/ssa/shadow.rs b/src/c5/codegen/ssa/shadow.rs index 28725d149..6a446cdba 100644 --- a/src/c5/codegen/ssa/shadow.rs +++ b/src/c5/codegen/ssa/shadow.rs @@ -365,14 +365,17 @@ fn live_data_intervals( live[interval_of(off)] = true; } } + // The target interval is resolved via the anchor: a one-past-the-end + // target coincides with the next object's start and would mark the + // wrong object live. let edges: Vec<(usize, usize)> = program .data_relocs .iter() - .filter(|r| (r.data_offset as i64) < data_len && (r.target_offset as i64) < data_len) + .filter(|r| (r.data_offset as i64) < data_len && (r.target_anchor as i64) < data_len) .map(|r| { ( interval_of(r.data_offset as i64), - interval_of(r.target_offset as i64), + interval_of(r.target_anchor as i64), ) }) .collect(); @@ -554,7 +557,23 @@ pub(crate) fn compact_program_data( } for r in &mut out.data_relocs { r.data_offset = map(r.data_offset as i64) as u64; - r.target_offset = map(r.target_offset as i64) as u64; + // Rebase the target against its own object, resolved via the + // anchor: a one-past-the-end target (C99 6.5.6p8) lies on the + // next object's start and the raw offset would follow that + // object instead. + let anchor = r.target_anchor as i64; + if (0..data_len).contains(&anchor) { + let i = interval_of(anchor); + if new_base[i] >= 0 { + r.target_offset = (new_base[i] + (r.target_offset as i64 - starts[i])) as u64; + } else { + r.target_offset = 0; + } + r.target_anchor = map(anchor) as u64; + } else { + r.target_offset = map(r.target_offset as i64) as u64; + r.target_anchor = r.target_offset; + } } for r in &mut out.code_relocs { r.data_offset = map(r.data_offset as i64) as u64; diff --git a/src/c5/compiler/global_init.rs b/src/c5/compiler/global_init.rs index b10911a97..3fe9480c4 100644 --- a/src/c5/compiler/global_init.rs +++ b/src/c5/compiler/global_init.rs @@ -250,6 +250,7 @@ impl Compiler { self.data_relocs.push(crate::c5::program::DataReloc { data_offset: var_offset as u64, target_offset: target_offset as u64, + target_anchor: target_offset as u64, }); self.data_reloc_sym_idx.push(target_idx); return Ok(()); @@ -273,6 +274,7 @@ impl Compiler { self.data_relocs.push(crate::c5::program::DataReloc { data_offset: var_offset as u64, target_offset: addr as u64, + target_anchor: addr as u64, }); // String-literal target -- no originating // symbol; sentinel marks the entry as @@ -343,6 +345,7 @@ impl Compiler { self.data_relocs.push(crate::c5::program::DataReloc { data_offset: var_offset as u64, target_offset: off as u64, + target_anchor: off as u64, }); self.data_reloc_sym_idx.push(new_idx); return Ok(()); @@ -518,6 +521,7 @@ impl Compiler { self.data_relocs.push(crate::c5::program::DataReloc { data_offset: var_offset as u64, target_offset: target_offset as u64, + target_anchor: self.symbols[target_idx].val as u64, }); self.data_reloc_sym_idx.push(target_idx); return Ok(()); diff --git a/src/c5/compiler/initializer.rs b/src/c5/compiler/initializer.rs index a76321e5e..dabc51430 100644 --- a/src/c5/compiler/initializer.rs +++ b/src/c5/compiler/initializer.rs @@ -113,9 +113,14 @@ impl Compiler { return; } } + let anchor = match src_sym { + Some(sym_idx) => self.symbols[sym_idx].val, + None => value, + }; self.data_relocs.push(crate::c5::program::DataReloc { data_offset: here as u64, target_offset: value as u64, + target_anchor: anchor as u64, }); self.data_reloc_sym_idx.push(src_sym.unwrap_or(usize::MAX)); } diff --git a/src/c5/linker/synth_build.rs b/src/c5/linker/synth_build.rs index fad8cdc9b..cddb77022 100644 --- a/src/c5/linker/synth_build.rs +++ b/src/c5/linker/synth_build.rs @@ -805,6 +805,7 @@ fn synth_relocs(merged: &MergedNative) -> (Vec, Vec) { data_relocs.push(DataReloc { data_offset: r.slot_offset, target_offset: r.target_offset, + target_anchor: r.target_offset, }); } NativeSymSection::Bss => { @@ -815,6 +816,7 @@ fn synth_relocs(merged: &MergedNative) -> (Vec, Vec) { data_relocs.push(DataReloc { data_offset: r.slot_offset, target_offset: merged.data.len() as u64 + r.target_offset, + target_anchor: merged.data.len() as u64 + r.target_offset, }); } NativeSymSection::Text => { diff --git a/src/c5/program.rs b/src/c5/program.rs index b8ec56ac2..e9698e208 100644 --- a/src/c5/program.rs +++ b/src/c5/program.rs @@ -50,6 +50,13 @@ pub struct DataReloc { /// pointed at. Same data segment; cross-segment /// relocations (e.g., into `tls_data`) are future work. pub target_offset: u64, + /// Start offset of the object `target_offset` points into. + /// The raw offset alone cannot attribute a one-past-the-end + /// address (C99 6.5.6p8): it coincides with the next object's + /// start, so data compaction would track the wrong object. + /// Equals `target_offset` when the producer has no object + /// identity. + pub target_anchor: u64, } /// A function-pointer initializer that needs run-time relocation. diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index e1622bd6f..9421aae1f 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1559,6 +1559,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("union_member_unbraced_init.c", 0), ("inline_multi_block_result_forward.c", 10), ("sxtw_fold_source_liveness.c", 18), + ("data_reloc_one_past_end.c", 10), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index e0234fd58..790b1c44b 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -933,6 +933,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("union_member_unbraced_init.c", 0), ("inline_multi_block_result_forward.c", 10), ("sxtw_fold_source_liveness.c", 18), + ("data_reloc_one_past_end.c", 10), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index 95e42abce..52c09c66d 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -709,6 +709,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("union_member_unbraced_init.c", 0), ("inline_multi_block_result_forward.c", 10), ("sxtw_fold_source_liveness.c", 18), + ("data_reloc_one_past_end.c", 10), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 720860fb8..54e8e989b 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -658,6 +658,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("union_member_unbraced_init.c", 0), ("inline_multi_block_result_forward.c", 10), ("sxtw_fold_source_liveness.c", 18), + ("data_reloc_one_past_end.c", 10), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index a9dd0e147..762f88837 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -916,6 +916,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("union_member_unbraced_init.c", 0), ("inline_multi_block_result_forward.c", 10), ("sxtw_fold_source_liveness.c", 18), + ("data_reloc_one_past_end.c", 10), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index f1751335e..d1bc75862 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -934,6 +934,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("union_member_unbraced_init.c", 0), ("inline_multi_block_result_forward.c", 10), ("sxtw_fold_source_liveness.c", 18), + ("data_reloc_one_past_end.c", 10), ]; #[test] diff --git a/tests/fixtures/c/data_reloc_one_past_end.c b/tests/fixtures/c/data_reloc_one_past_end.c new file mode 100644 index 000000000..293a3de25 --- /dev/null +++ b/tests/fixtures/c/data_reloc_one_past_end.c @@ -0,0 +1,17 @@ +/* A one-past-the-end address constant (C99 6.5.6p8) coincides with the + following object's start; data compaction must keep it attributed to + the preceding array when bss segregation moves the neighbor. */ +long arr[4] = {1, 2, 3, 4}; +long zeros[8]; +long *const end_p = &arr[4]; + +int main(void) { + long sum = 0; + long *p = arr; + while (p != end_p) { + sum += *p; + p++; + } + sum += zeros[3]; + return (int)sum; +} From 3c116b1a7a80712f325672dd5226bbf2a83c5dd9 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:32:35 -0700 Subject: [PATCH 24/67] compiler: tail-jump sys trampolines for variadic libc bindings The address-taken trampoline for a variadic libc binding re-pushed only the declared prefix plus one register argument, dropping the variadic tail the caller marshalled per the host convention (stack region on AAPCS64-Darwin, al on System V). Route variadic bindings through the frameless tail jump already used for FP-touching bindings; it forwards every register class and the stack unchanged. Co-Authored-By: Claude Fable 5 --- src/c5/compiler/call_fixups.rs | 101 ++++-------------- src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + .../c/variadic_libc_fnptr_static_init.c | 18 ++++ 8 files changed, 43 insertions(+), 82 deletions(-) create mode 100644 tests/fixtures/c/variadic_libc_fnptr_static_init.c diff --git a/src/c5/compiler/call_fixups.rs b/src/c5/compiler/call_fixups.rs index 597c36497..b161bf373 100644 --- a/src/c5/compiler/call_fixups.rs +++ b/src/c5/compiler/call_fixups.rs @@ -163,12 +163,12 @@ impl Compiler { /// Lev /// ``` /// - /// Variadic libc fns lose anything beyond their declared - /// fixed prefix -- a trampoline can only forward what its - /// signature tells it to push. The known callers (e.g. - /// dispatch-table slots for `fcntl` and `ioctl`) work - /// because the cast at the use site lines up with the fixed - /// prefix the trampoline does forward. + /// Variadic bindings take the frameless tail-jump shape + /// instead: the caller marshalled the tail per the variadic + /// convention (stack region and, on System V, `al`), which a + /// forwarding body of fixed arity cannot repack; a `jmp` + /// passes every register class and the stack through + /// unchanged. pub(super) fn emit_sys_trampolines(&mut self) { use crate::c5::codegen::ssa::build::SsaBuilder; use crate::c5::ir::{LoadKind, NO_VALUE}; @@ -208,12 +208,14 @@ impl Compiler { // return that runs a widening `fcvt d0,s0`, and since `s0` // and `d0` alias `v0`, the widened double's zero low half // overwrites the `s0` the caller reads (C99 6.2.5p10 / - // AAPCS64 6.4.2: a `float` result occupies `s0`). The - // `double` case happened to survive because no widening - // was emitted, but the tail jump is the correct path for - // both. Variadic bindings keep the forwarding body so the - // dispatch-table arg repacking stays in scope; no bound - // variadic libc routine returns a floating-point scalar. + // AAPCS64 6.4.2: a `float` result occupies `s0`). + // + // A variadic binding takes the same tail jump: the caller + // marshalled the tail per the variadic convention (the + // stack region on AAPCS64-Darwin, `al` on System V), and + // only a frameless jump carries that through -- a + // forwarding body of fixed arity would drop everything + // past its declared prefix. let ret_ty = self.symbols[sys_idx].type_; let touches_fp = is_float_ty(ret_ty) || is_double_ty(ret_ty) @@ -221,7 +223,7 @@ impl Compiler { .params .iter() .any(|&p| is_float_ty(p) || is_double_ty(p)); - if !is_variadic && touches_fp { + if is_variadic || touches_fp { let mut sb = SsaBuilder::new(ent_pc, 0, false); sb.set_locals(0); sb.set_name(alloc::format!("__c5_sys_{}", self.symbols[sys_idx].name)); @@ -236,16 +238,9 @@ impl Compiler { continue; } - // Forwarded arg count. Variadic prefix forwards one - // extra so dispatch tables (open / fcntl / ioctl) - // line up. - let nargs_ssa = if fixed_nargs == 0 && !is_variadic { - 0 - } else if is_variadic { - fixed_nargs + 1 - } else { - fixed_nargs - }; + // Forwarded arg count (variadic bindings took the tail + // jump above). + let nargs_ssa = fixed_nargs; // The synthesised trampoline's own signature is a // fixed-arg host-ABI function: callers reach it via // function pointer through `(sys_ptr)open`, which the @@ -292,68 +287,10 @@ impl Compiler { self.synthetic_ssa_funcs.push(func); let synth_idx = self.synthetic_ssa_funcs.len() - 1; - // Two trampoline shapes coexist: - // - // * Prototype-bearing bindings (`int fopen(char *, - // char *);`, ..., or any `int foo(...);`) get the - // classic `Ent + Lea/Li/Psh + JsrExt + Adj + Lev` - // body. The forwarded arg count matches the - // prototype, and the JsrExt lowering's per-arg - // FP-mask + post-call sub-word extension (#48) both - // stay in scope. - // - // * Bindings with *no* declared params (just - // `int Name();`) -- e.g. kernel32 entries that - // real-world dispatch tables cast back to the - // right arity at the call site -- get a tail-call - // body. The trampoline is `jmp [rip+iat]` and the - // caller's indirect-call lowering owns the host-ABI - // arg setup, return-register copy, and stack - // adjustment. Sub-word extension is left to the - // caller (the call site casts the result to the - // right type explicitly), which matches what - // real-world dispatch-table consumers already do. - if fixed_nargs == 0 && !is_variadic { - // The SSA-tier trampoline body is fully built by - // SsaBuilder above; bump the parser PC counter by - // one so the synthesised function's `end_pc` - // stays strictly greater than its `ent_pc`, which - // is what the linker and DWARF range builder - // require. - self.next_ent_pc += 1; - self.synthetic_ssa_funcs[synth_idx].end_pc = self.next_ent_pc; - continue; - } - - // For variadic libc fns the binding-declared param - // count is only the fixed prefix; common dispatch - // tables (open/fcntl/ioctl) want the trampoline to - // forward *one* of the variadic args so the caller's - // 3-argument cast lines up with what `JsrExt` packs - // onto the macOS arm64 variadic-args stack region. - // Callers that pass strictly the fixed prefix end up - // reading one junk slot from above their own pushes, - // but no in-the-wild caller does -- they all add at - // least one extra arg precisely to feed the variadic. - // The general case (forward N variadic args where N - // is unknown at compile time) needs a real va_args - // bridge -- tracked separately with the `c5 va_list` - // work. - let nargs = if is_variadic { - fixed_nargs + 1 - } else { - fixed_nargs - }; - // SSA body fully built by SsaBuilder above. Reserve a // single PC unit so the trampoline's `end_pc` is // strictly greater than `ent_pc`, satisfying the - // linker / DWARF range invariant. The cdecl - // right-to-left arg push, JsrExt + binding, Adj - // cleanup and Lev epilogue used to be tape ops here; - // the matching SSA insts live on - // `synthetic_ssa_funcs[synth_idx]` and drive the codegen. - let _ = (nargs, binding_idx); + // linker / DWARF range invariant. self.next_ent_pc += 1; self.synthetic_ssa_funcs[synth_idx].end_pc = self.next_ent_pc; } diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index 9421aae1f..ee4e44432 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1560,6 +1560,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("inline_multi_block_result_forward.c", 10), ("sxtw_fold_source_liveness.c", 18), ("data_reloc_one_past_end.c", 10), + ("variadic_libc_fnptr_static_init.c", 0), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index 790b1c44b..dcf22c9d7 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -934,6 +934,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("inline_multi_block_result_forward.c", 10), ("sxtw_fold_source_liveness.c", 18), ("data_reloc_one_past_end.c", 10), + ("variadic_libc_fnptr_static_init.c", 0), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index 52c09c66d..138c6dcc4 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -710,6 +710,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("inline_multi_block_result_forward.c", 10), ("sxtw_fold_source_liveness.c", 18), ("data_reloc_one_past_end.c", 10), + ("variadic_libc_fnptr_static_init.c", 0), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 54e8e989b..557fff751 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -659,6 +659,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("inline_multi_block_result_forward.c", 10), ("sxtw_fold_source_liveness.c", 18), ("data_reloc_one_past_end.c", 10), + ("variadic_libc_fnptr_static_init.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index 762f88837..dfcb7f420 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -917,6 +917,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("inline_multi_block_result_forward.c", 10), ("sxtw_fold_source_liveness.c", 18), ("data_reloc_one_past_end.c", 10), + ("variadic_libc_fnptr_static_init.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index d1bc75862..cc9fde132 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -935,6 +935,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("inline_multi_block_result_forward.c", 10), ("sxtw_fold_source_liveness.c", 18), ("data_reloc_one_past_end.c", 10), + ("variadic_libc_fnptr_static_init.c", 0), ]; #[test] diff --git a/tests/fixtures/c/variadic_libc_fnptr_static_init.c b/tests/fixtures/c/variadic_libc_fnptr_static_init.c new file mode 100644 index 000000000..4573f13a1 --- /dev/null +++ b/tests/fixtures/c/variadic_libc_fnptr_static_init.c @@ -0,0 +1,18 @@ +/* A static initializer naming a variadic libc function resolves to the + sys trampoline; the trampoline must forward the variadic tail (stack + region, and al on System V), which only a frameless jump preserves. */ +#include +#include + +typedef int (*psn)(char *, unsigned long, const char *, ...); +psn table[2] = { snprintf, snprintf }; + +int main(void) { + char buf[64]; + buf[0] = 0; + table[1](buf, sizeof buf, "%d %s %d", 42, "mid", 99); + if (strcmp(buf, "42 mid 99") != 0) { + return 1; + } + return 0; +} From d02055c82be8df0f8656b86c1f878aacb0fcce49 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:33:08 -0700 Subject: [PATCH 25/67] compiler: carry the fn-pointer prototype through a block-scope typedef parse_block_typedef recorded the prototype only for the function-type shape; a `typedef RET (*NAME)(args)` declarator left the typedef symbol without params/is_variadic, so indirect calls through variables of that typedef marshalled a variadic tail as fixed register arguments. Mirror the file-scope branch. Co-Authored-By: Claude Fable 5 --- src/c5/compiler/stmt.rs | 14 ++++++++++++++ src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + .../c/block_scope_typedef_variadic_fnptr.c | 17 +++++++++++++++++ 8 files changed, 37 insertions(+) create mode 100644 tests/fixtures/c/block_scope_typedef_variadic_fnptr.c diff --git a/src/c5/compiler/stmt.rs b/src/c5/compiler/stmt.rs index 84bd14389..8020d7e7c 100644 --- a/src/c5/compiler/stmt.rs +++ b/src/c5/compiler/stmt.rs @@ -282,6 +282,20 @@ impl Compiler { if let Some(pp) = typedef_params { self.symbols[id_idx].params = pp.types; self.symbols[id_idx].is_variadic = pp.is_variadic; + } else if let Some((proto_fixed, proto_variadic)) = + self.pending.typedef_fn_proto.take() + { + // `typedef RET (*NAME)(args)` at block scope: the + // declarator captured the pointee prototype. Record it + // as the file-scope branch does, so an indirect call + // through a variable of this typedef narrows arguments + // and routes a variadic tail per the host ABI. + self.symbols[id_idx].params = self + .pending + .fn_ptr_param_types + .take() + .unwrap_or_else(|| alloc::vec![0i64; proto_fixed]); + self.symbols[id_idx].is_variadic = proto_variadic; } self.accept(',')?; } diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index ee4e44432..b552a6e54 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1561,6 +1561,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("sxtw_fold_source_liveness.c", 18), ("data_reloc_one_past_end.c", 10), ("variadic_libc_fnptr_static_init.c", 0), + ("block_scope_typedef_variadic_fnptr.c", 0), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index dcf22c9d7..cbbbab332 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -935,6 +935,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("sxtw_fold_source_liveness.c", 18), ("data_reloc_one_past_end.c", 10), ("variadic_libc_fnptr_static_init.c", 0), + ("block_scope_typedef_variadic_fnptr.c", 0), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index 138c6dcc4..e26bc6604 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -711,6 +711,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("sxtw_fold_source_liveness.c", 18), ("data_reloc_one_past_end.c", 10), ("variadic_libc_fnptr_static_init.c", 0), + ("block_scope_typedef_variadic_fnptr.c", 0), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 557fff751..791c9714b 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -660,6 +660,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("sxtw_fold_source_liveness.c", 18), ("data_reloc_one_past_end.c", 10), ("variadic_libc_fnptr_static_init.c", 0), + ("block_scope_typedef_variadic_fnptr.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index dfcb7f420..e1b6cb6e7 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -918,6 +918,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("sxtw_fold_source_liveness.c", 18), ("data_reloc_one_past_end.c", 10), ("variadic_libc_fnptr_static_init.c", 0), + ("block_scope_typedef_variadic_fnptr.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index cc9fde132..be814a2eb 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -936,6 +936,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("sxtw_fold_source_liveness.c", 18), ("data_reloc_one_past_end.c", 10), ("variadic_libc_fnptr_static_init.c", 0), + ("block_scope_typedef_variadic_fnptr.c", 0), ]; #[test] diff --git a/tests/fixtures/c/block_scope_typedef_variadic_fnptr.c b/tests/fixtures/c/block_scope_typedef_variadic_fnptr.c new file mode 100644 index 000000000..21429c7b7 --- /dev/null +++ b/tests/fixtures/c/block_scope_typedef_variadic_fnptr.c @@ -0,0 +1,17 @@ +/* A block-scope `typedef RET (*NAME)(args, ...)` must carry the pointee + prototype onto variables declared through it, so an indirect call + routes the variadic tail per the host ABI. */ +#include +#include + +int main(void) { + char buf[64]; + typedef int (*psn)(char *, unsigned long, const char *, ...); + static psn sn = snprintf; + buf[0] = 0; + sn(buf, sizeof buf, "%d %s", 7, "tail"); + if (strcmp(buf, "7 tail") != 0) { + return 1; + } + return 0; +} From 7cb22f6187d7b5063e38985b7716a66ae775ea23 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:36:11 -0700 Subject: [PATCH 26/67] aarch64: source atomic operands from the working-register save area emit_atomic_cas / emit_atomic_rmw marshal operands into the borrowed x9..x12 in sequence; an operand the allocator placed in one of those registers could be read after an earlier move overwrote it (a compare-exchange then reported success without exchanging). The values are already saved at [sp..sp+32] before marshalling, so read such operands from their saved slots. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/aarch64/emit.rs | 10 +++++++++ src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + .../c/atomic_operand_in_working_regs.c | 22 +++++++++++++++++++ 8 files changed, 38 insertions(+) create mode 100644 tests/fixtures/c/atomic_operand_in_working_regs.c diff --git a/src/c5/codegen/aarch64/emit.rs b/src/c5/codegen/aarch64/emit.rs index 561a3bc5d..8ad4f02f4 100644 --- a/src/c5/codegen/aarch64/emit.rs +++ b/src/c5/codegen/aarch64/emit.rs @@ -4155,6 +4155,16 @@ fn atomic_operand_into( .get(value as usize) .copied() .unwrap_or(Place::None); + // An operand the allocator placed in a borrowed working register + // (x9..x12) may already have been overwritten by an earlier + // operand move; read its saved copy from the save area instead + // ([sp+0]=x9 .. [sp+24]=x12, laid out by `atomic_save_working`). + if let Place::IntReg(r) = place + && (9..=12).contains(&r) + { + emit_sp_ldr_x(code, target, (r as u32 - 9) * 8); + return true; + } match materialize_int_shifted(code, place, target, frame, sp_shift) { Some(r) => { if r.0 != target.0 { diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index b552a6e54..8fc0cf238 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1562,6 +1562,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("data_reloc_one_past_end.c", 10), ("variadic_libc_fnptr_static_init.c", 0), ("block_scope_typedef_variadic_fnptr.c", 0), + ("atomic_operand_in_working_regs.c", 0), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index cbbbab332..5ab62a1b5 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -936,6 +936,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("data_reloc_one_past_end.c", 10), ("variadic_libc_fnptr_static_init.c", 0), ("block_scope_typedef_variadic_fnptr.c", 0), + ("atomic_operand_in_working_regs.c", 0), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index e26bc6604..28cb6ed89 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -712,6 +712,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("data_reloc_one_past_end.c", 10), ("variadic_libc_fnptr_static_init.c", 0), ("block_scope_typedef_variadic_fnptr.c", 0), + ("atomic_operand_in_working_regs.c", 0), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 791c9714b..8b1cb2fe5 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -661,6 +661,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("data_reloc_one_past_end.c", 10), ("variadic_libc_fnptr_static_init.c", 0), ("block_scope_typedef_variadic_fnptr.c", 0), + ("atomic_operand_in_working_regs.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index e1b6cb6e7..4176d1a96 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -919,6 +919,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("data_reloc_one_past_end.c", 10), ("variadic_libc_fnptr_static_init.c", 0), ("block_scope_typedef_variadic_fnptr.c", 0), + ("atomic_operand_in_working_regs.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index be814a2eb..d7b73f190 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -937,6 +937,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("data_reloc_one_past_end.c", 10), ("variadic_libc_fnptr_static_init.c", 0), ("block_scope_typedef_variadic_fnptr.c", 0), + ("atomic_operand_in_working_regs.c", 0), ]; #[test] diff --git a/tests/fixtures/c/atomic_operand_in_working_regs.c b/tests/fixtures/c/atomic_operand_in_working_regs.c new file mode 100644 index 000000000..c50cc1d7a --- /dev/null +++ b/tests/fixtures/c/atomic_operand_in_working_regs.c @@ -0,0 +1,22 @@ +/* CAS/RMW operands allocated in the borrowed working registers + (x9..x12 on aarch64) must be read from the save area, not from the + registers an earlier operand move already overwrote. */ +#include + +long f(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { + static _Atomic long l = 9; + long want = 100; + int c = atomic_compare_exchange_strong(&l, &want, 5); + long r = atomic_fetch_add(&l, a0 + a1); + /* c must be 0, want must be 9 (observed), l must be 9+3=12, r old=9 */ + if (c != 0) return 1; + if (want != 9) return 2; + if (r != 9) return 3; + if (atomic_load(&l) != 9 + a0 + a1) return 4; + return a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7; /* keep 8 values live */ +} + +int main(void) { + long r = f(1, 2, 3, 4, 5, 6, 7, 8); + return r == 36 ? 0 : (int)r; +} From 1c3bfad82da32ed1b172bac5410d4b705fb32c89 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:40:14 -0700 Subject: [PATCH 27/67] reg_alloc: make the inline setjmp intrinsic a call barrier The windows-arm64 setjmp lowering is an Inst::Intrinsic, which the allocator's call-crossing tests did not match, so a value live across the setjmp site could sit in a caller-saved register that longjmp does not restore (the jmp_buf covers x19-x28, x29, sp, d8-d15 only), violating C99 7.13.2.1p3. Treat the setjmp site like a call in values_live_across_calls and promote_calls_after_def_to_classes. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/ssa/liveness.rs | 3 ++- src/c5/codegen/ssa/reg_alloc.rs | 16 +++++++++++++- src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + tests/fixtures/c/setjmp_value_live_across.c | 24 +++++++++++++++++++++ 9 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/fixtures/c/setjmp_value_live_across.c diff --git a/src/c5/codegen/ssa/liveness.rs b/src/c5/codegen/ssa/liveness.rs index d34e11516..efd0c1797 100644 --- a/src/c5/codegen/ssa/liveness.rs +++ b/src/c5/codegen/ssa/liveness.rs @@ -403,7 +403,8 @@ impl Liveness { let is_call = matches!( inst, Inst::Call { .. } | Inst::CallIndirect { .. } | Inst::CallExt { .. } - ) || (tls_addr_is_call && matches!(inst, Inst::TlsAddr(_))); + ) || (tls_addr_is_call && matches!(inst, Inst::TlsAddr(_))) + || super::reg_alloc::is_setjmp_barrier(inst); if super::reg_alloc::produces_value(inst) { live.remove(&idx); } diff --git a/src/c5/codegen/ssa/reg_alloc.rs b/src/c5/codegen/ssa/reg_alloc.rs index e1b4551b6..42badc604 100644 --- a/src/c5/codegen/ssa/reg_alloc.rs +++ b/src/c5/codegen/ssa/reg_alloc.rs @@ -1244,6 +1244,19 @@ fn is_pure_inst(inst: &Inst) -> bool { ) } +/// Whether `inst` is the inline setjmp intrinsic. A longjmp back to +/// the setjmp site restores only the jmp_buf register set (x19-x28, +/// x29, sp, d8-d15), so for allocation the site clobbers the +/// caller-saved banks exactly like a call (C99 7.13.2.1p3 requires +/// values unmodified since setjmp to survive the second return). +pub(crate) fn is_setjmp_barrier(inst: &Inst) -> bool { + matches!( + inst, + Inst::Intrinsic { kind, .. } + if *kind == crate::c5::op::Intrinsic::SetjmpAArch64 as i64 + ) +} + /// Invoke `f` for each operand `ValueId` referenced by `inst`. pub(crate) fn for_each_operand(inst: &Inst, mut f: impl FnMut(ValueId)) { match inst { @@ -2099,7 +2112,8 @@ fn promote_calls_after_def_to_classes( let is_call = matches!( inst, Inst::Call { .. } | Inst::CallIndirect { .. } | Inst::CallExt { .. } - ) || (tls_addr_is_call && matches!(inst, Inst::TlsAddr(_))); + ) || (tls_addr_is_call && matches!(inst, Inst::TlsAddr(_))) + || is_setjmp_barrier(inst); if is_call { call_pcs.push(idx as u32); } diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index 8fc0cf238..7a88c5ec7 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1563,6 +1563,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("variadic_libc_fnptr_static_init.c", 0), ("block_scope_typedef_variadic_fnptr.c", 0), ("atomic_operand_in_working_regs.c", 0), + ("setjmp_value_live_across.c", 0), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index 5ab62a1b5..2c4cd6068 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -937,6 +937,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("variadic_libc_fnptr_static_init.c", 0), ("block_scope_typedef_variadic_fnptr.c", 0), ("atomic_operand_in_working_regs.c", 0), + ("setjmp_value_live_across.c", 0), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index 28cb6ed89..e834f28fe 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -713,6 +713,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("variadic_libc_fnptr_static_init.c", 0), ("block_scope_typedef_variadic_fnptr.c", 0), ("atomic_operand_in_working_regs.c", 0), + ("setjmp_value_live_across.c", 0), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 8b1cb2fe5..e99d95930 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -662,6 +662,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("variadic_libc_fnptr_static_init.c", 0), ("block_scope_typedef_variadic_fnptr.c", 0), ("atomic_operand_in_working_regs.c", 0), + ("setjmp_value_live_across.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index 4176d1a96..34fa2f379 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -920,6 +920,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("variadic_libc_fnptr_static_init.c", 0), ("block_scope_typedef_variadic_fnptr.c", 0), ("atomic_operand_in_working_regs.c", 0), + ("setjmp_value_live_across.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index d7b73f190..201f8a588 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -938,6 +938,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("variadic_libc_fnptr_static_init.c", 0), ("block_scope_typedef_variadic_fnptr.c", 0), ("atomic_operand_in_working_regs.c", 0), + ("setjmp_value_live_across.c", 0), ]; #[test] diff --git a/tests/fixtures/c/setjmp_value_live_across.c b/tests/fixtures/c/setjmp_value_live_across.c new file mode 100644 index 000000000..67488186f --- /dev/null +++ b/tests/fixtures/c/setjmp_value_live_across.c @@ -0,0 +1,24 @@ +/* C99 7.13.2.1p3: a value unmodified since setjmp keeps its value on + the second return. The setjmp site must be a call barrier for the + allocator so the value survives in a callee-saved register or on + the stack (the inline windows-arm64 expansion restores only the + jmp_buf register set). */ +#include +#include + +static jmp_buf b; + +static void h(void) { longjmp(b, 1); } + +int test(int a, int c) { + int x = a * 7 + c; + if (setjmp(b)) { + return x; + } + h(); + return 0; +} + +int main(void) { + return test(5, 7) == 42 ? 0 : 1; +} From 4f9d9aafab985470607c27abb8534e727d5eb1b2 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:44:54 -0700 Subject: [PATCH 28/67] x86_64: order mixed-aggregate eightbyte loads with the parallel move marshal_args loaded a mixed SSE/INTEGER aggregate's integer eightbyte into its target GPR before the scalar parallel move consumed that GPR as a source (System V AMD64 3.2.3 classifies per eightbyte; the integer targets are argument registers). Route the aggregate's base through its first integer eightbyte register inside the parallel move and load the eightbytes afterwards, base register last; all-SSE aggregates keep the early scratch-based loads. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/x86_64/emit.rs | 97 ++++++++++--------- src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + .../fixtures/c/mixed_sse_int_aggregate_args.c | 27 ++++++ 8 files changed, 85 insertions(+), 45 deletions(-) create mode 100644 tests/fixtures/c/mixed_sse_int_aggregate_args.c diff --git a/src/c5/codegen/x86_64/emit.rs b/src/c5/codegen/x86_64/emit.rs index 36f721ff4..c08d3c74d 100644 --- a/src/c5/codegen/x86_64/emit.rs +++ b/src/c5/codegen/x86_64/emit.rs @@ -1224,18 +1224,20 @@ fn marshal_args( } } - // System V FP-eightbyte aggregate arguments: any aggregate containing - // an SSE eightbyte. regs[0] may be an xmm, so the regs[0]-as-base scheme - // below cannot apply -- materialize the source address into a scratch - // GPR and load each eightbyte into its register (movsd for SSE, mov for - // INTEGER). Runs after the scalar-FP moves (their xmm sources consumed) - // and before the integer marshal (the source address, in a GPR, not yet - // overwritten); the eightbytes are memory loads, joining no xmm cycle. + // System V aggregates whose eightbytes are all SSE: no integer + // eightbyte register can hold the base, so materialize the source + // address into a scratch GPR and load each eightbyte's xmm. Runs + // after the scalar-FP moves (their xmm sources consumed); the loads + // touch only SCRATCH_R10 and the aggregate's own xmm targets, so + // they cannot disturb the integer parallel move below. Mixed + // SSE/INTEGER aggregates are deferred: their integer eightbyte + // targets are argument GPRs that may still be another argument's + // pending source, so their base rides the parallel move instead. for (i, &placement) in plan.placements.iter().enumerate() { let super::ArgPlacement::StructRegs { regs, n } = placement else { continue; }; - if n == 0 || !regs.iter().take(n as usize).any(|c| c.is_fp) { + if n == 0 || !regs.iter().take(n as usize).all(|c| c.is_fp) { continue; } let base = match materialize_int_shifted( @@ -1253,30 +1255,29 @@ fn marshal_args( return false; } }; - // The source address must not share a register with an INTEGER - // eightbyte's destination (an argument GPR): loading that eightbyte - // would clobber the base before a later SSE eightbyte loads from it. - // materialize_int_shifted may return the value's existing register - // (an argument GPR), so stage it in SCRATCH_R10, never an argument - // or aggregate destination. if base.0 != SCRATCH_R10.0 { emit_mov_rr(code, SCRATCH_R10, base); } - let base = SCRATCH_R10; for (k, cr) in regs.iter().take(n as usize).enumerate() { - let off = (k as i32) * 8; - if cr.is_fp { - emit_movsd_xmm_mem(code, Reg(cr.reg), base, off); - } else { - emit_mov_r_mem(code, Reg(cr.reg), base, off); - } + emit_movsd_xmm_mem(code, Reg(cr.reg), SCRATCH_R10, (k as i32) * 8); } } + // First INTEGER eightbyte register of an aggregate, if any: the + // aggregate's base address is routed there by the parallel move and + // the eightbyte loads below read from it (that register's own + // eightbyte loads last). + let agg_base_reg = |regs: &[super::ClassReg; 4], n: u8| -> Option { + regs.iter() + .take(n as usize) + .find(|c| !c.is_fp) + .map(|c| c.reg) + }; + // Integer-register placements plus aggregate base addresses are one // parallel register move (System V AMD64 3.2.3). A scalar `IntReg` // arg moves src->target; a `StructRegs` arg positions its base - // address into its own first eightbyte register `regs[0]`, from + // address into its own first integer eightbyte register, from // which the eightbytes load below (the base register is overwritten // by its own eightbyte last). Routing the base through that per- // aggregate register -- never a shared scratch -- keeps one @@ -1291,12 +1292,10 @@ fn marshal_args( int_moves.push((s, r)); } } - // FP-eightbyte aggregates (an SSE unit) loaded above. - super::ArgPlacement::StructRegs { regs, n } - if n > 0 && !regs.iter().take(n as usize).any(|c| c.is_fp) => - { - let dst = regs[0].reg; - if let Place::IntReg(s) = arg_place(i) + // All-SSE aggregates loaded above. + super::ArgPlacement::StructRegs { regs, n } => { + if let Some(dst) = agg_base_reg(®s, n) + && let Place::IntReg(s) = arg_place(i) && s != dst { int_moves.push((s, dst)); @@ -1343,16 +1342,14 @@ fn marshal_args( } // Aggregate bases not already register-resident (spill / computed) - // materialise into the aggregate's first eightbyte register, the - // same destination the move loop used for the register-resident - // case. + // materialise into the aggregate's first integer eightbyte + // register, the same destination the move loop used for the + // register-resident case. for (i, &placement) in plan.placements.iter().enumerate() { if let super::ArgPlacement::StructRegs { regs, n } = placement - && n > 0 - && !regs.iter().take(n as usize).any(|c| c.is_fp) + && let Some(dst) = agg_base_reg(®s, n) && !matches!(arg_place(i), Place::IntReg(_)) { - let dst = regs[0].reg; let src = match materialize_int_shifted( code, arg_place(i), @@ -1374,21 +1371,31 @@ fn marshal_args( } } - // Load each aggregate's eightbytes from the base now in `regs[0]`. - // High eightbytes first; `regs[0]` (the base) is read last, - // overwritten by its own eightbyte. Integer-only (homogeneous - // floating-point aggregates excluded upstream). + // Load each aggregate's eightbytes from the base now in its first + // integer eightbyte register: SSE eightbytes first (they leave the + // base intact), then the remaining integer eightbytes high-first, + // the base register's own eightbyte last since the load overwrites + // it. All-SSE aggregates were loaded above. for &placement in plan.placements.iter() { - // Integer-class aggregate: load eightbytes from the base in regs[0]. - // FP-eightbyte aggregates (an SSE unit) were loaded above. if let super::ArgPlacement::StructRegs { regs, n } = placement - && !regs.iter().take(n as usize).any(|c| c.is_fp) + && let Some(base) = agg_base_reg(®s, n) { - let base = regs[0].reg; - for k in (1..n as usize).rev() { - emit_mov_r_mem(code, Reg(regs[k].reg), Reg(base), (k as i32) * 8); + for (k, cr) in regs.iter().take(n as usize).enumerate() { + if cr.is_fp { + emit_movsd_xmm_mem(code, Reg(cr.reg), Reg(base), (k as i32) * 8); + } } - emit_mov_r_mem(code, Reg(base), Reg(base), 0); + for (k, cr) in regs.iter().take(n as usize).enumerate().rev() { + if !cr.is_fp && cr.reg != base { + emit_mov_r_mem(code, Reg(cr.reg), Reg(base), (k as i32) * 8); + } + } + let base_off = regs + .iter() + .take(n as usize) + .position(|c| !c.is_fp && c.reg == base) + .unwrap_or(0); + emit_mov_r_mem(code, Reg(base), Reg(base), (base_off as i32) * 8); } } diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index 7a88c5ec7..f0f393e28 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1564,6 +1564,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("block_scope_typedef_variadic_fnptr.c", 0), ("atomic_operand_in_working_regs.c", 0), ("setjmp_value_live_across.c", 0), + ("mixed_sse_int_aggregate_args.c", 0), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index 2c4cd6068..8aa876ba3 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -938,6 +938,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("block_scope_typedef_variadic_fnptr.c", 0), ("atomic_operand_in_working_regs.c", 0), ("setjmp_value_live_across.c", 0), + ("mixed_sse_int_aggregate_args.c", 0), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index e834f28fe..3b5282bc2 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -714,6 +714,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("block_scope_typedef_variadic_fnptr.c", 0), ("atomic_operand_in_working_regs.c", 0), ("setjmp_value_live_across.c", 0), + ("mixed_sse_int_aggregate_args.c", 0), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index e99d95930..616181ff3 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -663,6 +663,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("block_scope_typedef_variadic_fnptr.c", 0), ("atomic_operand_in_working_regs.c", 0), ("setjmp_value_live_across.c", 0), + ("mixed_sse_int_aggregate_args.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index 34fa2f379..a8424025e 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -921,6 +921,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("block_scope_typedef_variadic_fnptr.c", 0), ("atomic_operand_in_working_regs.c", 0), ("setjmp_value_live_across.c", 0), + ("mixed_sse_int_aggregate_args.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index 201f8a588..acaf0f8ed 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -939,6 +939,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("block_scope_typedef_variadic_fnptr.c", 0), ("atomic_operand_in_working_regs.c", 0), ("setjmp_value_live_across.c", 0), + ("mixed_sse_int_aggregate_args.c", 0), ]; #[test] diff --git a/tests/fixtures/c/mixed_sse_int_aggregate_args.c b/tests/fixtures/c/mixed_sse_int_aggregate_args.c new file mode 100644 index 000000000..f4ea52096 --- /dev/null +++ b/tests/fixtures/c/mixed_sse_int_aggregate_args.c @@ -0,0 +1,27 @@ +/* SysV mixed SSE/INTEGER eightbyte aggregates: the integer eightbyte + target GPR may still be another argument's pending source, so the + aggregate loads must join the parallel-move ordering. */ +struct DL { double d; long l; }; +struct LD { long l; double d; }; +struct DD { double a; double b; }; + +static int take3(struct DL s, long x, struct LD t, double f, struct DD u) { + if (s.d != 2.5 || s.l != 7) return 1; + if (x != 4) return 2; + if (t.l != 11 || t.d != 0.5) return 3; + if (f != 1.25) return 4; + if (u.a != 3.5 || u.b != 4.5) return 5; + return 0; +} + +int docall(long x, struct DL *p, struct LD *q, struct DD *r, double f) { + return take3(*p, x, *q, f, *r); +} + +int main(void) { + struct DL s; struct LD t; struct DD u; + s.d = 2.5; s.l = 7; + t.l = 11; t.d = 0.5; + u.a = 3.5; u.b = 4.5; + return docall(4, &s, &t, &u, 1.25); +} From 3e1f033cb8e8f0dbcc87fc76597a3d3296883b13 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:47:39 -0700 Subject: [PATCH 29/67] x86_64: classify a variadic callee's aggregate return eightbytes The Win64 and System V variadic call arms captured a <=16-byte aggregate return from rax:rdx unconditionally; an SSE eightbyte arrives in xmm0/xmm1 (System V AMD64 3.2.3) exactly as on the non-variadic path. Share one classified store across all call shapes. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/x86_64/emit.rs | 139 ++++++------------ src/c5/compiler/stmt.rs | 3 +- src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + .../fixtures/c/variadic_agg_return_classes.c | 27 ++++ 9 files changed, 82 insertions(+), 93 deletions(-) create mode 100644 tests/fixtures/c/variadic_agg_return_classes.c diff --git a/src/c5/codegen/x86_64/emit.rs b/src/c5/codegen/x86_64/emit.rs index c08d3c74d..3f4e18c22 100644 --- a/src/c5/codegen/x86_64/emit.rs +++ b/src/c5/codegen/x86_64/emit.rs @@ -5415,6 +5415,43 @@ fn emit_binop_imm( } #[allow(clippy::too_many_arguments)] +/// Store a register-classed <= 16-byte aggregate return into the +/// caller's result temp at `[rbp + base]`. Eightbytes are classified +/// (System V AMD64 3.2.3): INTEGER arrive in rax:rdx, SSE in +/// xmm0:xmm1; Win64 register returns classify as one INTEGER +/// eightbyte in rax. Variadic and non-variadic callees return +/// identically, so every call shape shares this store. +fn store_agg_return( + code: &mut Vec, + desc: &super::super::ir::AggDesc, + base: i64, + abi: super::Abi, +) { + let eb_classes = match super::abi_classify::classify_aggregate( + desc.size, + desc.align, + &desc.fields, + abi, + true, + ) { + super::abi_classify::AggClass::Regs(c) => c, + _ => alloc::vec::Vec::new(), + }; + let int_ret = [Reg::RAX, Reg::RDX]; + let mut int_i = 0usize; + let mut sse_i = 0u8; + for (k, class) in eb_classes.iter().enumerate() { + let disp = (base + (k as i64) * 8) as i32; + if matches!(class, super::abi_classify::RegClass::Sse) { + emit_movsd_mem_xmm(code, Reg::RBP, disp, Reg(Reg::XMM0.0 + sse_i)); + sse_i += 1; + } else { + emit_mov_mem_r(code, Reg::RBP, disp, int_ret[int_i]); + int_i += 1; + } + } +} + fn emit_call( code: &mut Vec, dst: Place, @@ -5471,17 +5508,12 @@ fn emit_call( if plan.scratch_bytes > 0 { emit_add_rsp_imm32(code, plan.scratch_bytes); } - // A variadic callee may still return a <=16-byte aggregate by - // value in rax:rdx; store it into the caller's result temp, as - // the non-variadic path below does. Without this the struct - // result is dropped (the scalar bridge leaves the slot unwritten). + // A variadic callee returns a <=16-byte aggregate exactly like a + // non-variadic one; classify the eightbytes (SSE ones arrive in + // xmm0/xmm1, not rax:rdx). if let Some(ai) = ret_agg { - let size = agg_descs[ai as usize].size; let base = local_slot_off(ret_slot_local, func, frame, abi); - emit_mov_mem_r(code, Reg::RBP, base as i32, Reg::RAX); - if size > 8 { - emit_mov_mem_r(code, Reg::RBP, (base + 8) as i32, Reg::RDX); - } + store_agg_return(code, &agg_descs[ai as usize], base, abi); return true; } // c5 internal call return convention: an integer / pointer @@ -5542,17 +5574,12 @@ fn emit_call( if plan.scratch_bytes > 0 { emit_add_rsp_imm32(code, plan.scratch_bytes); } - // A variadic callee may still return a <=16-byte aggregate by - // value in rax:rdx; store it into the caller's result temp, as - // the non-variadic path below does. Without this the struct - // result is dropped (the scalar bridge leaves the slot unwritten). + // A variadic callee returns a <=16-byte aggregate exactly like a + // non-variadic one; classify the eightbytes (SSE ones arrive in + // xmm0/xmm1, not rax:rdx). if let Some(ai) = ret_agg { - let size = agg_descs[ai as usize].size; let base = local_slot_off(ret_slot_local, func, frame, abi); - emit_mov_mem_r(code, Reg::RBP, base as i32, Reg::RAX); - if size > 8 { - emit_mov_mem_r(code, Reg::RBP, (base + 8) as i32, Reg::RDX); - } + store_agg_return(code, &agg_descs[ai as usize], base, abi); return true; } // c5 internal call return convention: an integer / pointer @@ -5623,31 +5650,7 @@ fn emit_call( if let Some(ai) = ret_agg { let desc = &agg_descs[ai as usize]; let base = local_slot_off(ret_slot_local, func, frame, abi); - let eb_classes = match super::abi_classify::classify_aggregate( - desc.size, - desc.align, - &desc.fields, - abi, - true, - ) { - super::abi_classify::AggClass::Regs(c) => c, - _ => alloc::vec::Vec::new(), - }; - // SSE eightbytes arrive in xmm0/xmm1, INTEGER in rax/rdx; store each - // into the caller's result temp at its eightbyte offset. - let int_ret = [Reg::RAX, Reg::RDX]; - let mut int_i = 0usize; - let mut sse_i = 0u8; - for (k, class) in eb_classes.iter().enumerate() { - let disp = (base + (k as i64) * 8) as i32; - if matches!(class, super::abi_classify::RegClass::Sse) { - emit_movsd_mem_xmm(code, Reg::RBP, disp, Reg(Reg::XMM0.0 + sse_i)); - sse_i += 1; - } else { - emit_mov_mem_r(code, Reg::RBP, disp, int_ret[int_i]); - int_i += 1; - } - } + store_agg_return(code, desc, base, abi); return true; } // c5 internal call return convention: an integer / pointer @@ -5759,29 +5762,7 @@ fn emit_call_ext( if let Some(ai) = ret_agg { let desc = &agg_descs[ai as usize]; let base = local_slot_off(ret_slot_local, func, frame, abi); - let eb_classes = match super::abi_classify::classify_aggregate( - desc.size, - desc.align, - &desc.fields, - abi, - true, - ) { - super::abi_classify::AggClass::Regs(c) => c, - _ => alloc::vec::Vec::new(), - }; - let int_ret = [Reg::RAX, Reg::RDX]; - let mut int_i = 0usize; - let mut sse_i = 0u8; - for (k, class) in eb_classes.iter().enumerate() { - let disp = (base + (k as i64) * 8) as i32; - if matches!(class, super::abi_classify::RegClass::Sse) { - emit_movsd_mem_xmm(code, Reg::RBP, disp, Reg(Reg::XMM0.0 + sse_i)); - sse_i += 1; - } else { - emit_mov_mem_r(code, Reg::RBP, disp, int_ret[int_i]); - int_i += 1; - } - } + store_agg_return(code, desc, base, abi); return true; } // Sub-word integer returns get the standard sign / zero @@ -6055,31 +6036,7 @@ fn emit_call_indirect( if let Some(ai) = ret_agg { let desc = &agg_descs[ai as usize]; let base = local_slot_off(ret_slot_local, func, frame, abi); - let eb_classes = match super::abi_classify::classify_aggregate( - desc.size, - desc.align, - &desc.fields, - abi, - true, - ) { - super::abi_classify::AggClass::Regs(c) => c, - _ => alloc::vec::Vec::new(), - }; - // SSE eightbytes arrive in xmm0/xmm1, INTEGER in rax/rdx; store each - // into the caller's result temp at its eightbyte offset. - let int_ret = [Reg::RAX, Reg::RDX]; - let mut int_i = 0usize; - let mut sse_i = 0u8; - for (k, class) in eb_classes.iter().enumerate() { - let disp = (base + (k as i64) * 8) as i32; - if matches!(class, super::abi_classify::RegClass::Sse) { - emit_movsd_mem_xmm(code, Reg::RBP, disp, Reg(Reg::XMM0.0 + sse_i)); - sse_i += 1; - } else { - emit_mov_mem_r(code, Reg::RBP, disp, int_ret[int_i]); - int_i += 1; - } - } + store_agg_return(code, desc, base, abi); return true; } // A floating-point return rides xmm0 (C99 6.2.5p10); an integer diff --git a/src/c5/compiler/stmt.rs b/src/c5/compiler/stmt.rs index 8020d7e7c..5e2f9fc8a 100644 --- a/src/c5/compiler/stmt.rs +++ b/src/c5/compiler/stmt.rs @@ -282,8 +282,7 @@ impl Compiler { if let Some(pp) = typedef_params { self.symbols[id_idx].params = pp.types; self.symbols[id_idx].is_variadic = pp.is_variadic; - } else if let Some((proto_fixed, proto_variadic)) = - self.pending.typedef_fn_proto.take() + } else if let Some((proto_fixed, proto_variadic)) = self.pending.typedef_fn_proto.take() { // `typedef RET (*NAME)(args)` at block scope: the // declarator captured the pointee prototype. Record it diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index f0f393e28..8e8894118 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1565,6 +1565,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("atomic_operand_in_working_regs.c", 0), ("setjmp_value_live_across.c", 0), ("mixed_sse_int_aggregate_args.c", 0), + ("variadic_agg_return_classes.c", 0), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index 8aa876ba3..6c1690547 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -939,6 +939,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("atomic_operand_in_working_regs.c", 0), ("setjmp_value_live_across.c", 0), ("mixed_sse_int_aggregate_args.c", 0), + ("variadic_agg_return_classes.c", 0), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index 3b5282bc2..45e0f8af4 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -715,6 +715,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("atomic_operand_in_working_regs.c", 0), ("setjmp_value_live_across.c", 0), ("mixed_sse_int_aggregate_args.c", 0), + ("variadic_agg_return_classes.c", 0), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 616181ff3..c9fc0b2a2 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -664,6 +664,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("atomic_operand_in_working_regs.c", 0), ("setjmp_value_live_across.c", 0), ("mixed_sse_int_aggregate_args.c", 0), + ("variadic_agg_return_classes.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index a8424025e..0c3ed7fcc 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -922,6 +922,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("atomic_operand_in_working_regs.c", 0), ("setjmp_value_live_across.c", 0), ("mixed_sse_int_aggregate_args.c", 0), + ("variadic_agg_return_classes.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index acaf0f8ed..0e7bb982c 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -940,6 +940,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("atomic_operand_in_working_regs.c", 0), ("setjmp_value_live_across.c", 0), ("mixed_sse_int_aggregate_args.c", 0), + ("variadic_agg_return_classes.c", 0), ]; #[test] diff --git a/tests/fixtures/c/variadic_agg_return_classes.c b/tests/fixtures/c/variadic_agg_return_classes.c new file mode 100644 index 000000000..28834383f --- /dev/null +++ b/tests/fixtures/c/variadic_agg_return_classes.c @@ -0,0 +1,27 @@ +/* A variadic callee returning a <=16-byte aggregate uses the same + eightbyte classification as a non-variadic one (System V AMD64 + 3.2.3): SSE eightbytes in xmm0/xmm1, INTEGER in rax/rdx. */ +struct P { double x, y; }; +struct M { double d; long l; }; + +static struct P mkp(int n, ...) { + struct P p; + p.x = 1.5 * n; + p.y = 2.25; + return p; +} + +static struct M mkm(int n, ...) { + struct M m; + m.d = 0.5; + m.l = n + 41; + return m; +} + +int main(void) { + struct P p = mkp(2); + if (p.x != 3.0 || p.y != 2.25) return 1; + struct M m = mkm(1); + if (m.d != 0.5 || m.l != 42) return 2; + return 0; +} From b2bf213d218086df0cbc07e14fbf6cec1616a4ae Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:49:48 -0700 Subject: [PATCH 30/67] x86_64: stop va_copy from borrowing rcx unsaved The System V va_copy lowering materialized the destination pointer into rcx, which sits in the allocator's caller pool and may hold a value live across the intrinsic (va_copy is not a call). Route both pointers through the reserved r10/r11 scratches and borrow the copy temporary around a push/pop pair, as emit_mcpy already does. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/x86_64/emit.rs | 29 +++++++++++++------ src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + tests/fixtures/c/va_copy_under_pressure.c | 34 +++++++++++++++++++++++ 8 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 tests/fixtures/c/va_copy_under_pressure.c diff --git a/src/c5/codegen/x86_64/emit.rs b/src/c5/codegen/x86_64/emit.rs index 3f4e18c22..b243ab054 100644 --- a/src/c5/codegen/x86_64/emit.rs +++ b/src/c5/codegen/x86_64/emit.rs @@ -6324,19 +6324,32 @@ fn emit_intrinsic( return false; } }; - // Three distinct registers: src pointer in r11, dst pointer - // in rcx, the copied word in r10 (all outside the allocator's - // live values for this instruction). Copy the three 8-byte - // words -- gp_offset + fp_offset packed in the first, then - // overflow_arg_area and reg_save_area. - let Some(dst_p) = materialize_int(code, dst_place, SCRATCH_RCX, frame) else { + // Both pointers ride the reserved r10 / r11 scratches (rcx + // is in the allocator's caller pool and may hold a live + // value across the intrinsic). The copied word borrows a + // pool register around a push/pop pair, mirroring + // emit_mcpy; the spill loads above run before the push so + // rsp-relative offsets stay valid. + let Some(dst_p) = materialize_int(code, dst_place, SCRATCH_R10, frame) else { bail_msg("VaCopy: &dst not in int reg / spill"); return false; }; + let temp = if dst_p.0 != Reg::RAX.0 && src_p.0 != Reg::RAX.0 { + Reg::RAX + } else if dst_p.0 != Reg::RCX.0 && src_p.0 != Reg::RCX.0 { + Reg::RCX + } else { + Reg::RDX + }; + emit_push_r(code, temp); + // Copy the three 8-byte `__va_list_tag` words (ABI 3.5.7): + // gp_offset + fp_offset packed in the first, then + // overflow_arg_area and reg_save_area. for off in [0i32, 8, 16] { - emit_mov_r_mem(code, SCRATCH_R10, src_p, off); - emit_mov_mem_r(code, dst_p, off, SCRATCH_R10); + emit_mov_r_mem(code, temp, src_p, off); + emit_mov_mem_r(code, dst_p, off, temp); } + emit_pop_r(code, temp); true } I::VaStart => { diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index 8e8894118..cba75cec4 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1566,6 +1566,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("setjmp_value_live_across.c", 0), ("mixed_sse_int_aggregate_args.c", 0), ("variadic_agg_return_classes.c", 0), + ("va_copy_under_pressure.c", 0), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index 6c1690547..b0817a194 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -940,6 +940,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("setjmp_value_live_across.c", 0), ("mixed_sse_int_aggregate_args.c", 0), ("variadic_agg_return_classes.c", 0), + ("va_copy_under_pressure.c", 0), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index 45e0f8af4..e62c405b2 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -716,6 +716,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("setjmp_value_live_across.c", 0), ("mixed_sse_int_aggregate_args.c", 0), ("variadic_agg_return_classes.c", 0), + ("va_copy_under_pressure.c", 0), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index c9fc0b2a2..9644c342e 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -665,6 +665,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("setjmp_value_live_across.c", 0), ("mixed_sse_int_aggregate_args.c", 0), ("variadic_agg_return_classes.c", 0), + ("va_copy_under_pressure.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index 0c3ed7fcc..164c8e344 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -923,6 +923,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("setjmp_value_live_across.c", 0), ("mixed_sse_int_aggregate_args.c", 0), ("variadic_agg_return_classes.c", 0), + ("va_copy_under_pressure.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index 0e7bb982c..da22401f4 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -941,6 +941,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("setjmp_value_live_across.c", 0), ("mixed_sse_int_aggregate_args.c", 0), ("variadic_agg_return_classes.c", 0), + ("va_copy_under_pressure.c", 0), ]; #[test] diff --git a/tests/fixtures/c/va_copy_under_pressure.c b/tests/fixtures/c/va_copy_under_pressure.c new file mode 100644 index 000000000..dc07eae21 --- /dev/null +++ b/tests/fixtures/c/va_copy_under_pressure.c @@ -0,0 +1,34 @@ +#include + +/* Enough simultaneously live temporaries that the va_list address + operands spill and rax/rcx/rdx carry live values across va_copy. */ +static long f(long m, ...) { + va_list ap, aq; + long t1 = m * 3; + long t2 = m + 11; + long t3 = m * 7; + long t4 = m - 2; + long t5 = m * 13; + long t6 = m + 29; + long t7 = m * 4; + long t8 = m + 41; + long t9 = m * 9; + long t10 = m + 53; + long t11 = m * 5; + long t12 = m + 61; + long t13 = m * 15; + long t14 = m + 3; + va_start(ap, m); + va_copy(aq, ap); + long a = va_arg(aq, long); + long b = va_arg(aq, long); + va_end(aq); + va_end(ap); + return t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8 + t9 + t10 + t11 + t12 + t13 + t14 + a + b; +} + +int main(void) { + long got = f(2, 10L, 20L); + long want = 6 + 13 + 14 + 0 + 26 + 31 + 8 + 43 + 18 + 55 + 10 + 63 + 30 + 5 + 10 + 20; + return got == want ? 0 : 1; +} From cc3494f510acae50bb44037d155e52f18a9b03db Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:56:47 -0700 Subject: [PATCH 31/67] x86_64: save rcx around a variable shift whenever it is allocated The rcx save in emit_shift_by_count_reg was gated on a def < shift < last-use pc-interval test, which misses a value live across the shift only on a loop back edge (the for-step block precedes the body in pc order). Save whenever any value is colored into rcx and the count does not already occupy it. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/x86_64/emit.rs | 15 ++++++++++----- src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + tests/fixtures/c/variable_shift_rcx_loop.c | 15 +++++++++++++++ 8 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 tests/fixtures/c/variable_shift_rcx_loop.c diff --git a/src/c5/codegen/x86_64/emit.rs b/src/c5/codegen/x86_64/emit.rs index b243ab054..2deec32ef 100644 --- a/src/c5/codegen/x86_64/emit.rs +++ b/src/c5/codegen/x86_64/emit.rs @@ -5020,12 +5020,17 @@ fn emit_shift_by_count_reg( spill_dst_to_slot(code, dst, rd, frame); return true; } + // Save rcx whenever any value is allocated there (unless the count + // already sits in rcx, in which case nothing below writes it). A + // `def < v < last_use` pc-interval test is not a liveness test: a + // value carried around a loop back edge is live at the shift while + // the shift's pc lies outside the interval. + let _ = v; let rcx_holds_live = count_reg.map(|r| r.0).unwrap_or(u8::MAX) != Reg::RCX.0 - && alloc.places.iter().enumerate().any(|(idx, p)| { - let i = idx as u32; - let last = alloc.last_use.get(idx).copied().unwrap_or(0); - matches!(p, Place::IntReg(r) if *r == Reg::RCX.0) && i < v && v < last - }); + && alloc + .places + .iter() + .any(|p| matches!(p, Place::IntReg(r) if *r == Reg::RCX.0)); if rcx_holds_live { emit_push_r(code, Reg::RCX); } diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index cba75cec4..d550c97aa 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1567,6 +1567,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("mixed_sse_int_aggregate_args.c", 0), ("variadic_agg_return_classes.c", 0), ("va_copy_under_pressure.c", 0), + ("variable_shift_rcx_loop.c", 0), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index b0817a194..e033d3d8a 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -941,6 +941,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("mixed_sse_int_aggregate_args.c", 0), ("variadic_agg_return_classes.c", 0), ("va_copy_under_pressure.c", 0), + ("variable_shift_rcx_loop.c", 0), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index e62c405b2..e5f672e55 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -717,6 +717,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("mixed_sse_int_aggregate_args.c", 0), ("variadic_agg_return_classes.c", 0), ("va_copy_under_pressure.c", 0), + ("variable_shift_rcx_loop.c", 0), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 9644c342e..49c693941 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -666,6 +666,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("mixed_sse_int_aggregate_args.c", 0), ("variadic_agg_return_classes.c", 0), ("va_copy_under_pressure.c", 0), + ("variable_shift_rcx_loop.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index 164c8e344..03e558b14 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -924,6 +924,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("mixed_sse_int_aggregate_args.c", 0), ("variadic_agg_return_classes.c", 0), ("va_copy_under_pressure.c", 0), + ("variable_shift_rcx_loop.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index da22401f4..893533760 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -942,6 +942,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("mixed_sse_int_aggregate_args.c", 0), ("variadic_agg_return_classes.c", 0), ("va_copy_under_pressure.c", 0), + ("variable_shift_rcx_loop.c", 0), ]; #[test] diff --git a/tests/fixtures/c/variable_shift_rcx_loop.c b/tests/fixtures/c/variable_shift_rcx_loop.c new file mode 100644 index 000000000..e1311bfd6 --- /dev/null +++ b/tests/fixtures/c/variable_shift_rcx_loop.c @@ -0,0 +1,15 @@ +/* The x86_64 variable-shift lowering borrows rcx for the count; a + loop-carried value colored into rcx is live across the shift via + the back edge while its pc interval excludes the shift, so the + save must not rely on a pc-interval liveness test. */ +long g(long n, long m, long c, long k) { + long acc = 0; + for (long i = 0; acc < n; i += (m << c)) { + acc = i + k; + } + return k; +} + +int main(void) { + return g(100, 2, 3, 1) == 1 ? 0 : 1; +} From e8792c3112ddfaab715db3a89126ba4a9708e970 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 19:58:50 -0700 Subject: [PATCH 32/67] aarch64: apply the AAPCS64 B.5 post-increment check in va_arg The register-save-area path tested only offs >= 0 before serving an argument; a multi-eightbyte composite whose span crosses the save area's high edge (offs + span > 0) spilled to the overflow stack at the call and must be read from there, with the incremented offset kept written back so later reads stay on the stack. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/aarch64/emit.rs | 10 +++++++ src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + tests/fixtures/c/va_arg_composite_straddle.c | 28 ++++++++++++++++++++ 8 files changed, 44 insertions(+) create mode 100644 tests/fixtures/c/va_arg_composite_straddle.c diff --git a/src/c5/codegen/aarch64/emit.rs b/src/c5/codegen/aarch64/emit.rs index 8ad4f02f4..a44c2763c 100644 --- a/src/c5/codegen/aarch64/emit.rs +++ b/src/c5/codegen/aarch64/emit.rs @@ -2678,6 +2678,13 @@ fn emit_va_arg_aapcs64( enc_add_imm(scratch.primary, scratch.primary, reg_advance), ); emit(code, enc_str32_imm(scratch.primary, ap, off_field)); + // AAPCS64 B.5 post-increment check: a composite whose span crosses + // the save area's high edge (offs + span > 0) spilled to the stack + // at the call; take the overflow path. The incremented offset stays + // written back, keeping later register-bank reads exhausted. + emit(code, enc_subs_imm(Reg(31), scratch.primary, 0)); + emit(code, enc_b_cond(Cond::Gt, 0)); + let to_stack_straddle = code.len() - 4; // Land the address uniformly in x16. emit_mov_reg(code, scratch.primary, borrow); emit(code, enc_b(0)); @@ -2686,6 +2693,9 @@ fn emit_va_arg_aapcs64( let stack_lbl = code.len(); let delta = ((stack_lbl - to_stack) / 4) as i32; code[to_stack..to_stack + 4].copy_from_slice(&enc_b_cond(Cond::Ge, delta).to_le_bytes()); + let delta = ((stack_lbl - to_stack_straddle) / 4) as i32; + code[to_stack_straddle..to_stack_straddle + 4] + .copy_from_slice(&enc_b_cond(Cond::Gt, delta).to_le_bytes()); // x16 = __stack ; borrow = __stack + advance (next cursor) ; write back. emit(code, enc_ldr_imm(scratch.primary, ap, 0)); emit(code, enc_add_imm(borrow, scratch.primary, stack_advance)); diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index d550c97aa..1d0e9721f 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1568,6 +1568,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("variadic_agg_return_classes.c", 0), ("va_copy_under_pressure.c", 0), ("variable_shift_rcx_loop.c", 0), + ("va_arg_composite_straddle.c", 0), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index e033d3d8a..7eafc3715 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -942,6 +942,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("variadic_agg_return_classes.c", 0), ("va_copy_under_pressure.c", 0), ("variable_shift_rcx_loop.c", 0), + ("va_arg_composite_straddle.c", 0), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index e5f672e55..827b5cb9f 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -718,6 +718,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("variadic_agg_return_classes.c", 0), ("va_copy_under_pressure.c", 0), ("variable_shift_rcx_loop.c", 0), + ("va_arg_composite_straddle.c", 0), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 49c693941..ce58b3202 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -667,6 +667,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("variadic_agg_return_classes.c", 0), ("va_copy_under_pressure.c", 0), ("variable_shift_rcx_loop.c", 0), + ("va_arg_composite_straddle.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index 03e558b14..dcc5f426d 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -925,6 +925,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("variadic_agg_return_classes.c", 0), ("va_copy_under_pressure.c", 0), ("variable_shift_rcx_loop.c", 0), + ("va_arg_composite_straddle.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index 893533760..baee360bc 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -943,6 +943,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("variadic_agg_return_classes.c", 0), ("va_copy_under_pressure.c", 0), ("variable_shift_rcx_loop.c", 0), + ("va_arg_composite_straddle.c", 0), ]; #[test] diff --git a/tests/fixtures/c/va_arg_composite_straddle.c b/tests/fixtures/c/va_arg_composite_straddle.c new file mode 100644 index 000000000..66906cbf2 --- /dev/null +++ b/tests/fixtures/c/va_arg_composite_straddle.c @@ -0,0 +1,28 @@ +#include +#include + +struct S { long x, y; }; + +/* Seven eightbyte-consuming named+leading variadic args leave one GPR + in the save area; the two-eightbyte struct then straddles and must + come from the overflow stack (AAPCS64 B.5), as must the tail. */ +static long take(int n, ...) { + va_list ap; + va_start(ap, n); + for (int i = 0; i < 6; i++) { + (void)va_arg(ap, long); + } + struct S s = va_arg(ap, struct S); + long tail = va_arg(ap, long); + va_end(ap); + if (s.x != 111 || s.y != 222) return 1; + if (tail != 777) return 2; + return 0; +} + +int main(void) { + struct S s; + s.x = 111; + s.y = 222; + return (int)take(1, 2L, 3L, 4L, 5L, 6L, 7L, s, 777L); +} From de156eaaea78845cf95bf30eb4e64e7fcfdf9b6d Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 20:04:48 -0700 Subject: [PATCH 33/67] codegen: pass windows-arm64 variadic composites in the integer bank The Microsoft ARM64 convention treats SIMD/FP registers as unavailable to variadic arguments: an anonymous composite <= 16 bytes rides x0-x7 then the stack, a larger one goes by reference. plan_call_args_aggs placed a variadic HFA in d-registers, which neither a badc nor an MSVC callee reads. The AAPCS64/SysV va_arg side still classes every aggregate as general-register; the HFA vector-area composition is a TODO. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/aarch64/emit.rs | 4 ++ src/c5/codegen/mod.rs | 49 ++++++++++++++++++++++ src/c5/tests/native.rs | 1 + src/c5/tests/native_pe_arm64.rs | 1 + tests/fixtures/c/variadic_hfa_struct_arg.c | 24 +++++++++++ 5 files changed, 79 insertions(+) create mode 100644 tests/fixtures/c/variadic_hfa_struct_arg.c diff --git a/src/c5/codegen/aarch64/emit.rs b/src/c5/codegen/aarch64/emit.rs index a44c2763c..6f98ba04c 100644 --- a/src/c5/codegen/aarch64/emit.rs +++ b/src/c5/codegen/aarch64/emit.rs @@ -2644,6 +2644,10 @@ fn emit_va_arg_aapcs64( // __vr_top (+16), 16-byte register stride. The overflow stack uses an // 8-byte stride for both classes (AAPCS64 rounds each variadic // argument to an eightbyte; a double overflow argument occupies one). + // TODO: an HFA composite argument rides the vector save area with + // one 16-byte slot per member (AAPCS64 B.5) and needs per-member + // composition into a contiguous temporary; the descriptor currently + // classes every aggregate as general-register. let (off_field, top_field, reg_step): (u32, u32, u32) = if is_fp { (28, 16, 16) } else { (24, 8, 8) }; // A by-value aggregate (integer class) spans `ceil(size/8)` eightbytes diff --git a/src/c5/codegen/mod.rs b/src/c5/codegen/mod.rs index d7c27e3b4..330f063a6 100644 --- a/src/c5/codegen/mod.rs +++ b/src/c5/codegen/mod.rs @@ -416,6 +416,55 @@ pub(super) fn plan_call_args_aggs( placements.push(placement); continue; } + // Windows aarch64 variadic convention: an anonymous composite + // is passed as if all SIMD/FP registers were unavailable -- a + // <= 16-byte composite (HFA or not) rides the integer bank + // x0-x7 then the stack, a larger one goes by reference. The + // callee's va_arg walks one 8-byte-stride region, so an FP + // bank placement would read garbage on both sides. + if i >= fixed_args && abi.variadic_int_only && matches!(abi.arch, Arch::Aarch64) { + let placement = if agg.size > 16 { + if int_idx < int_max { + let r = abi.int_arg_regs[int_idx]; + int_idx += 1; + ArgPlacement::StructByRefReg(r) + } else { + let off = stack_used; + stack_used += 8; + ArgPlacement::StructByRefStack(off) + } + } else { + let need = (aligned as usize / 8).max(1); + if int_idx + need <= int_max { + let mut regs = [ClassReg { + reg: 0, + is_fp: false, + }; 4]; + for (n, slot) in regs.iter_mut().enumerate().take(need) { + *slot = ClassReg { + reg: abi.int_arg_regs[int_idx], + is_fp: false, + }; + let _ = n; + int_idx += 1; + } + ArgPlacement::StructRegs { + regs, + n: need as u8, + } + } else { + int_idx = int_max; + let off = stack_used; + stack_used += aligned; + ArgPlacement::StructStack { + off, + size: agg.size, + } + } + }; + placements.push(placement); + continue; + } let placement = match &agg.class { AggClass::Regs(classes) => { let need_int = classes.iter().filter(|c| **c == RegClass::Integer).count(); diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index 7eafc3715..e62da8001 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -943,6 +943,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("va_copy_under_pressure.c", 0), ("variable_shift_rcx_loop.c", 0), ("va_arg_composite_straddle.c", 0), + ("variadic_hfa_struct_arg.c", 0), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index dcc5f426d..e780a1127 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -926,6 +926,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("va_copy_under_pressure.c", 0), ("variable_shift_rcx_loop.c", 0), ("va_arg_composite_straddle.c", 0), + ("variadic_hfa_struct_arg.c", 0), ]; #[test] diff --git a/tests/fixtures/c/variadic_hfa_struct_arg.c b/tests/fixtures/c/variadic_hfa_struct_arg.c new file mode 100644 index 000000000..5a84963f6 --- /dev/null +++ b/tests/fixtures/c/variadic_hfa_struct_arg.c @@ -0,0 +1,24 @@ +/* A variadic HFA composite: Windows aarch64 passes it in the integer + bank (SIMD/FP registers are unavailable to variadic composites). + TODO: the AAPCS64/SysV register-save va_arg reads every aggregate + from the general area; an HFA composite rides the vector area and + needs per-member composition, so this fixture is not yet registered + for the native_elf / native_elf_x64 lanes. */ +#include + +struct P { double x, y; }; + +static double sum(int n, ...) { + va_list ap; + va_start(ap, n); + struct P p = va_arg(ap, struct P); + va_end(ap); + return p.x + p.y; +} + +int main(void) { + struct P p; + p.x = 1.5; + p.y = 2.25; + return sum(1, p) == 3.75 ? 0 : 1; +} From 95ba77919bada1818fe52bbdd7d151328d6213cc Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 20:39:01 -0700 Subject: [PATCH 34/67] tests: snapshots for the call-ABI and allocator fixes Variadic marshalling, aggregate-return classification, va_arg composite handling, and the shift/fold liveness gates change the emitted shapes the affected fixtures pin; adds snapshots for the fourteen new regression fixtures. Co-Authored-By: Claude Fable 5 --- .../asm/aapcs64_variadic_host_abi.aarch64.asm | 18 ++ .../asm/aapcs64_variadic_host_abi.x64.asm | 15 +- ...atomic_operand_in_working_regs.aarch64.asm | 113 ++++++++++ .../atomic_operand_in_working_regs.x64.asm | 158 ++++++++++++++ ...k_scope_typedef_variadic_fnptr.aarch64.asm | 51 +++++ ...block_scope_typedef_variadic_fnptr.x64.asm | 47 ++++ .../asm/data_reloc_one_past_end.aarch64.asm | 35 +++ .../asm/data_reloc_one_past_end.x64.asm | 35 +++ .../asm/float_variadic_promotion.aarch64.asm | 2 + ...ine_multi_block_result_forward.aarch64.asm | 50 +++++ .../inline_multi_block_result_forward.x64.asm | 52 +++++ .../asm/integer_literal_suffix.x64.asm | 3 + .../mixed_sse_int_aggregate_args.aarch64.asm | 165 ++++++++++++++ .../asm/mixed_sse_int_aggregate_args.x64.asm | 203 ++++++++++++++++++ .../asm/mixed_struct_gpr_abi.x64.asm | 5 +- .../asm/rotate_variable_count.x64.asm | 3 + .../asm/setjmp_value_live_across.aarch64.asm | 72 +++++++ .../asm/setjmp_value_live_across.x64.asm | 66 ++++++ .../asm/shift_result_type_signedness.x64.asm | 4 + tests/snapshots/asm/sqlite_min.aarch64.asm | 18 +- tests/snapshots/asm/sqlite_min.x64.asm | 22 +- .../asm/ssa_call_result_spill.x64.asm | 4 + .../snapshots/asm/ssa_va_arg_loop.aarch64.asm | 4 + .../ssa_va_start_va_copy_aliasing.aarch64.asm | 8 + .../asm/ssa_va_start_va_copy_aliasing.x64.asm | 15 +- .../asm/struct_deref_va_arg.aarch64.asm | 2 + .../asm/sxtw_fold_source_liveness.aarch64.asm | 34 +++ .../asm/sxtw_fold_source_liveness.x64.asm | 36 ++++ .../asm/sys_addr_in_static_init.aarch64.asm | 18 +- .../asm/sys_addr_in_static_init.x64.asm | 21 +- .../asm/sysv_variadic_host_abi.aarch64.asm | 6 + .../asm/va_arg_composite_straddle.aarch64.asm | 192 +++++++++++++++++ .../asm/va_arg_composite_straddle.x64.asm | 162 ++++++++++++++ .../snapshots/asm/va_arg_int_seq.aarch64.asm | 2 + .../asm/va_arg_through_pointer.aarch64.asm | 6 + tests/snapshots/asm/va_copy.aarch64.asm | 2 + tests/snapshots/asm/va_copy.x64.asm | 15 +- .../asm/va_copy_under_pressure.aarch64.asm | 168 +++++++++++++++ .../asm/va_copy_under_pressure.x64.asm | 159 ++++++++++++++ .../asm/variable_shift_rcx_loop.aarch64.asm | 48 +++++ .../asm/variable_shift_rcx_loop.x64.asm | 55 +++++ .../variadic_agg_return_classes.aarch64.asm | 169 +++++++++++++++ .../asm/variadic_agg_return_classes.x64.asm | 185 ++++++++++++++++ .../asm/variadic_fn_ptr_init.aarch64.asm | 2 + .../variadic_fnptr_proto_erased.aarch64.asm | 2 + .../asm/variadic_hfa_struct_arg.aarch64.asm | 122 +++++++++++ .../asm/variadic_hfa_struct_arg.x64.asm | 107 +++++++++ ...ariadic_libc_fnptr_static_init.aarch64.asm | 58 +++++ .../variadic_libc_fnptr_static_init.x64.asm | 52 +++++ .../variadic_optimizer_survives.aarch64.asm | 4 + .../asm/variadic_struct_arg.aarch64.asm | 2 + .../asm/variadic_struct_arg_16b.aarch64.asm | 2 + .../variadic_struct_by_value_arg.aarch64.asm | 2 + .../asm/variadic_struct_return.aarch64.asm | 2 + .../variadic_union_struct_return.aarch64.asm | 4 + .../asm/variadic_via_fnptr.aarch64.asm | 6 + .../ssa/atomic_operand_in_working_regs.ssa | 160 ++++++++++++++ .../block_scope_typedef_variadic_fnptr.ssa | 84 ++++++++ .../snapshots/ssa/data_reloc_one_past_end.ssa | 87 ++++++++ .../ssa/inline_multi_block_result_forward.ssa | 128 +++++++++++ .../ssa/mixed_sse_int_aggregate_args.ssa | 201 +++++++++++++++++ .../ssa/setjmp_value_live_across.ssa | 110 ++++++++++ tests/snapshots/ssa/sqlite_min.ssa | 8 +- .../ssa/sxtw_fold_source_liveness.ssa | 92 ++++++++ .../snapshots/ssa/sys_addr_in_static_init.ssa | 8 +- .../ssa/va_arg_composite_straddle.ssa | 146 +++++++++++++ .../snapshots/ssa/va_copy_under_pressure.ssa | 189 ++++++++++++++++ .../snapshots/ssa/variable_shift_rcx_loop.ssa | 114 ++++++++++ .../ssa/variadic_agg_return_classes.ssa | 148 +++++++++++++ .../snapshots/ssa/variadic_hfa_struct_arg.ssa | 101 +++++++++ .../ssa/variadic_libc_fnptr_static_init.ssa | 87 ++++++++ 71 files changed, 4368 insertions(+), 108 deletions(-) create mode 100644 tests/snapshots/asm/atomic_operand_in_working_regs.aarch64.asm create mode 100644 tests/snapshots/asm/atomic_operand_in_working_regs.x64.asm create mode 100644 tests/snapshots/asm/block_scope_typedef_variadic_fnptr.aarch64.asm create mode 100644 tests/snapshots/asm/block_scope_typedef_variadic_fnptr.x64.asm create mode 100644 tests/snapshots/asm/data_reloc_one_past_end.aarch64.asm create mode 100644 tests/snapshots/asm/data_reloc_one_past_end.x64.asm create mode 100644 tests/snapshots/asm/inline_multi_block_result_forward.aarch64.asm create mode 100644 tests/snapshots/asm/inline_multi_block_result_forward.x64.asm create mode 100644 tests/snapshots/asm/mixed_sse_int_aggregate_args.aarch64.asm create mode 100644 tests/snapshots/asm/mixed_sse_int_aggregate_args.x64.asm create mode 100644 tests/snapshots/asm/setjmp_value_live_across.aarch64.asm create mode 100644 tests/snapshots/asm/setjmp_value_live_across.x64.asm create mode 100644 tests/snapshots/asm/sxtw_fold_source_liveness.aarch64.asm create mode 100644 tests/snapshots/asm/sxtw_fold_source_liveness.x64.asm create mode 100644 tests/snapshots/asm/va_arg_composite_straddle.aarch64.asm create mode 100644 tests/snapshots/asm/va_arg_composite_straddle.x64.asm create mode 100644 tests/snapshots/asm/va_copy_under_pressure.aarch64.asm create mode 100644 tests/snapshots/asm/va_copy_under_pressure.x64.asm create mode 100644 tests/snapshots/asm/variable_shift_rcx_loop.aarch64.asm create mode 100644 tests/snapshots/asm/variable_shift_rcx_loop.x64.asm create mode 100644 tests/snapshots/asm/variadic_agg_return_classes.aarch64.asm create mode 100644 tests/snapshots/asm/variadic_agg_return_classes.x64.asm create mode 100644 tests/snapshots/asm/variadic_hfa_struct_arg.aarch64.asm create mode 100644 tests/snapshots/asm/variadic_hfa_struct_arg.x64.asm create mode 100644 tests/snapshots/asm/variadic_libc_fnptr_static_init.aarch64.asm create mode 100644 tests/snapshots/asm/variadic_libc_fnptr_static_init.x64.asm create mode 100644 tests/snapshots/ssa/atomic_operand_in_working_regs.ssa create mode 100644 tests/snapshots/ssa/block_scope_typedef_variadic_fnptr.ssa create mode 100644 tests/snapshots/ssa/data_reloc_one_past_end.ssa create mode 100644 tests/snapshots/ssa/inline_multi_block_result_forward.ssa create mode 100644 tests/snapshots/ssa/mixed_sse_int_aggregate_args.ssa create mode 100644 tests/snapshots/ssa/setjmp_value_live_across.ssa create mode 100644 tests/snapshots/ssa/sxtw_fold_source_liveness.ssa create mode 100644 tests/snapshots/ssa/va_arg_composite_straddle.ssa create mode 100644 tests/snapshots/ssa/va_copy_under_pressure.ssa create mode 100644 tests/snapshots/ssa/variable_shift_rcx_loop.ssa create mode 100644 tests/snapshots/ssa/variadic_agg_return_classes.ssa create mode 100644 tests/snapshots/ssa/variadic_hfa_struct_arg.ssa create mode 100644 tests/snapshots/ssa/variadic_libc_fnptr_static_init.ssa diff --git a/tests/snapshots/asm/aapcs64_variadic_host_abi.aarch64.asm b/tests/snapshots/asm/aapcs64_variadic_host_abi.aarch64.asm index 7d208c2ba..30bce799a 100644 --- a/tests/snapshots/asm/aapcs64_variadic_host_abi.aarch64.asm +++ b/tests/snapshots/asm/aapcs64_variadic_host_abi.aarch64.asm @@ -70,6 +70,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -149,6 +151,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x10 str w16, [x17, #0x1c] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -238,6 +242,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x10 str w16, [x17, #0x1c] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -258,6 +264,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -343,6 +351,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -372,6 +382,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -458,6 +470,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -477,6 +491,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -496,6 +512,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/aapcs64_variadic_host_abi.x64.asm b/tests/snapshots/asm/aapcs64_variadic_host_abi.x64.asm index b4a1d93c4..51d48992c 100644 --- a/tests/snapshots/asm/aapcs64_variadic_host_abi.x64.asm +++ b/tests/snapshots/asm/aapcs64_variadic_host_abi.x64.asm @@ -233,12 +233,14 @@ Disassembly of section .text: movq %r10, 0x10(%rax) leaq -0x30(%rbp), %rax leaq -0x18(%rbp), %rcx - movq (%rcx), %r10 - movq %r10, (%rax) - movq 0x8(%rcx), %r10 - movq %r10, 0x8(%rax) - movq 0x10(%rcx), %r10 - movq %r10, 0x10(%rax) + pushq %rdx + movq (%rcx), %rdx + movq %rdx, (%rax) + movq 0x8(%rcx), %rdx + movq %rdx, 0x8(%rax) + movq 0x10(%rcx), %rdx + movq %rdx, 0x10(%rax) + popq %rdx movq %rdx, %rax movslq %edx, %rcx movslq -0xf0(%rbp), %rsi @@ -570,3 +572,4 @@ Disassembly of section .text: jmp jmp jmp + addb %al, (%rax) diff --git a/tests/snapshots/asm/atomic_operand_in_working_regs.aarch64.asm b/tests/snapshots/asm/atomic_operand_in_working_regs.aarch64.asm new file mode 100644 index 000000000..c1ab8d686 --- /dev/null +++ b/tests/snapshots/asm/atomic_operand_in_working_regs.aarch64.asm @@ -0,0 +1,113 @@ + +atomic_operand_in_working_regs.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x20 + mov x8, #0x64 // =100 + stur x8, [x29, #-0x8] + adrp x8, + add x8, x8, + sub x9, x29, #0x8 + mov x10, #0x5 // =5 + stp x9, x10, [sp, #-0x20]! + stp x11, x12, [sp, #0x10] + mov x9, x8 + ldr x10, [sp] + ldr x11, [sp, #0x8] + ldr x12, [x10] + ldaxr x16, [x9] + cmp x16, x12 + b.ne + stlxr w17, x11, [x9] + cbnz x17, + mov x16, #0x1 // =1 + b + str x16, [x10] + mov x16, #0x0 // =0 + ldp x11, x12, [sp, #0x10] + ldp x9, x10, [sp], #0x20 + mov x9, x16 + add x10, x0, x1 + stp x9, x10, [sp, #-0x20]! + stp x11, x12, [sp, #0x10] + mov x9, x8 + ldr x10, [sp, #0x8] + ldaxr x16, [x9] + add x11, x16, x10 + stlxr w12, x11, [x9] + cbnz x12, + ldp x11, x12, [sp, #0x10] + ldp x9, x10, [sp], #0x20 + mov x10, x16 + sxtw x9, w9 + cmp x9, #0x0 + b.eq + mov x0, #0x1 // =1 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + ldur x9, [x29, #-0x8] + cmp x9, #0x9 + b.eq + mov x0, #0x2 // =2 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + cmp x10, #0x9 + b.eq + mov x0, #0x3 // =3 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + ldr x8, [x8] + add x9, x0, #0x9 + add x9, x9, x1 + cmp x8, x9 + b.eq + mov x0, #0x4 // =4 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + add x0, x0, x1 + add x0, x0, x2 + add x0, x0, x3 + add x0, x0, x4 + add x0, x0, x5 + add x0, x0, x6 + add x0, x0, x7 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x50 + mov x0, #0x1 // =1 + mov x1, #0x2 // =2 + mov x2, #0x3 // =3 + mov x3, #0x4 // =4 + mov x4, #0x5 // =5 + mov x5, #0x6 // =6 + mov x6, #0x7 // =7 + mov x7, #0x8 // =8 + bl + cmp x0, #0x24 + b.ne + mov x1, #0x0 // =0 + b + sxtw x1, w0 + mov x0, x1 + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/atomic_operand_in_working_regs.x64.asm b/tests/snapshots/asm/atomic_operand_in_working_regs.x64.asm new file mode 100644 index 000000000..2c8e49c7d --- /dev/null +++ b/tests/snapshots/asm/atomic_operand_in_working_regs.x64.asm @@ -0,0 +1,158 @@ + +atomic_operand_in_working_regs.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + popq %r10 + subq $0x80, %rsp + movq 0x80(%rsp), %rax + movq %rax, 0x60(%rsp) + movq 0x88(%rsp), %rax + movq %rax, 0x70(%rsp) + pushq %r10 + pushq %rbp + movq %rsp, %rbp + subq $0x40, %rsp + movq %rbx, (%rsp) + movq %r12, 0x8(%rsp) + movq %r13, 0x10(%rsp) + movl $0x64, %eax + movq %rax, -0x8(%rbp) + leaq , %rax + leaq -0x8(%rbp), %rbx + movl $0x5, %r12d + pushq %rax + pushq %rcx + movq %rax, %r11 + movq %r12, %r10 + movq %rbx, %rcx + movq (%rcx), %rax + lock + cmpxchgq %r10, (%r11) + je + movq %rax, (%rcx) + sete %r11b + movzbq %r11b, %r11 + popq %rcx + popq %rax + movq %r11, %rbx + leaq (%rdi,%rsi), %r12 + pushq %rax + movq %rax, %r11 + movq %r12, %r10 + movq %r10, %rax + lock + xaddq %rax, (%r11) + movq %rax, %r10 + popq %rax + movq %r10, %r12 + movslq %ebx, %rbx + testq %rbx, %rbx + je + movl $0x1, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x40, %rsp + popq %rbp + popq %r11 + addq $0x80, %rsp + pushq %r11 + retq + movq -0x8(%rbp), %rbx + cmpq $0x9, %rbx + je + movl $0x2, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x40, %rsp + popq %rbp + popq %r11 + addq $0x80, %rsp + pushq %r11 + retq + cmpq $0x9, %r12 + je + movl $0x3, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x40, %rsp + popq %rbp + popq %r11 + addq $0x80, %rsp + pushq %r11 + retq + movq (%rax), %rax + leaq 0x9(%rdi), %rbx + addq %rsi, %rbx + cmpq %rbx, %rax + je + movl $0x4, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x40, %rsp + popq %rbp + popq %r11 + addq $0x80, %rsp + pushq %r11 + retq + leaq (%rdi,%rsi), %rax + addq %rdx, %rax + addq %rcx, %rax + addq %r8, %rax + addq %r9, %rax + movq 0x70(%rbp), %rcx + addq %rcx, %rax + movq 0x80(%rbp), %rcx + addq %rcx, %rax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + addq $0x40, %rsp + popq %rbp + popq %r11 + addq $0x80, %rsp + pushq %r11 + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x60, %rsp + movq %rbx, (%rsp) + movl $0x1, %edi + movl $0x2, %esi + movl $0x3, %edx + movl $0x4, %ecx + movl $0x5, %r8d + movl $0x6, %r9d + movl $0x7, %eax + movl $0x8, %ebx + subq $0x10, %rsp + movq %rax, (%rsp) + movq %rbx, 0x8(%rsp) + callq + addq $0x10, %rsp + cmpq $0x24, %rax + jne + xorq %rcx, %rcx + jmp + movslq %eax, %rcx + movq (%rsp), %rbx + movq %rcx, %rax + addq $0x60, %rsp + popq %rbp + retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/block_scope_typedef_variadic_fnptr.aarch64.asm b/tests/snapshots/asm/block_scope_typedef_variadic_fnptr.aarch64.asm new file mode 100644 index 000000000..2cff6e648 --- /dev/null +++ b/tests/snapshots/asm/block_scope_typedef_variadic_fnptr.aarch64.asm @@ -0,0 +1,51 @@ + +block_scope_typedef_variadic_fnptr.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x2b0 // =688 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x80 + str x19, [sp] + sub x0, x29, #0x40 + mov x1, #0x0 // =0 + strb w1, [x0] + sub x0, x29, #0x40 + mov x1, #0x40 // =64 + adrp x2, + add x2, x2, + mov x3, #0x7 // =7 + adrp x4, + add x4, x4, + adrp x5, + add x5, x5, + ldr x5, [x5] + mov x9, x5 + blr x9 + sub x0, x29, #0x40 + adrp x1, + add x1, x1, + bl + sxtw x0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x1 // =1 + ldr x19, [sp] + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldr x19, [sp] + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + +<__c5_sys_snprintf>: + b diff --git a/tests/snapshots/asm/block_scope_typedef_variadic_fnptr.x64.asm b/tests/snapshots/asm/block_scope_typedef_variadic_fnptr.x64.asm new file mode 100644 index 000000000..004f67e9e --- /dev/null +++ b/tests/snapshots/asm/block_scope_typedef_variadic_fnptr.x64.asm @@ -0,0 +1,47 @@ + +block_scope_typedef_variadic_fnptr.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x70, %rsp + leaq -0x40(%rbp), %rax + xorq %rcx, %rcx + movb %cl, (%rax) + leaq -0x40(%rbp), %rdi + movl $0x40, %esi + leaq , %rdx + movl $0x7, %ecx + leaq , %r8 + leaq , %rax + movq (%rax), %rax + movq %rax, %r9 + movb $0x0, %al + callq *%r9 + leaq -0x40(%rbp), %rdi + leaq , %rsi + xorl %eax, %eax + callq + movslq %eax, %rax + testq %rax, %rax + je + movl $0x1, %eax + addq $0x70, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x70, %rsp + popq %rbp + retq + +<__c5_sys_snprintf>: + jmp diff --git a/tests/snapshots/asm/data_reloc_one_past_end.aarch64.asm b/tests/snapshots/asm/data_reloc_one_past_end.aarch64.asm new file mode 100644 index 000000000..da8fa6471 --- /dev/null +++ b/tests/snapshots/asm/data_reloc_one_past_end.aarch64.asm @@ -0,0 +1,35 @@ + +data_reloc_one_past_end.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x10 + mov x2, #0x0 // =0 + adrp x1, + add x1, x1, + adrp x0, + add x0, x0, + ldr x0, [x0] + cmp x1, x0 + b.eq + ldr x0, [x1] + add x2, x2, x0 + add x1, x1, #0x8 + b + adrp x0, + add x0, x0, + ldr x0, [x0, #0x18] + add x0, x2, x0 + sxtw x0, w0 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/data_reloc_one_past_end.x64.asm b/tests/snapshots/asm/data_reloc_one_past_end.x64.asm new file mode 100644 index 000000000..55f3dc1eb --- /dev/null +++ b/tests/snapshots/asm/data_reloc_one_past_end.x64.asm @@ -0,0 +1,35 @@ + +data_reloc_one_past_end.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x10, %rsp + xorq %rdx, %rdx + leaq , %rcx + leaq , %rax + movq (%rax), %rax + cmpq %rax, %rcx + je + movq (%rcx), %rax + addq %rax, %rdx + addq $0x8, %rcx + jmp + leaq , %rax + movq 0x18(%rax), %rax + addq %rdx, %rax + movslq %eax, %rax + addq $0x10, %rsp + popq %rbp + retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/float_variadic_promotion.aarch64.asm b/tests/snapshots/asm/float_variadic_promotion.aarch64.asm index c9890d1d7..e0ea58670 100644 --- a/tests/snapshots/asm/float_variadic_promotion.aarch64.asm +++ b/tests/snapshots/asm/float_variadic_promotion.aarch64.asm @@ -93,6 +93,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x10 str w16, [x17, #0x1c] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/inline_multi_block_result_forward.aarch64.asm b/tests/snapshots/asm/inline_multi_block_result_forward.aarch64.asm new file mode 100644 index 000000000..d12ebbcef --- /dev/null +++ b/tests/snapshots/asm/inline_multi_block_result_forward.aarch64.asm @@ -0,0 +1,50 @@ + +inline_multi_block_result_forward.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + add x0, x0, x0 + sxtw x0, w0 + ret + +: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x10 + sxtw x0, w0 + lsl x0, x0, #1 + sxtw x0, w0 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + +: + sxtw x0, w0 + b + add x2, x0, x0 + cmp x0, #0x3 + b.le + sxtw x0, w1 + ret + add x0, x1, x2 + sxtw x0, w0 + ret + sxtw x1, w0 + lsl x1, x1, #1 + sxtw x1, w1 + b + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + mov x0, #0x5 // =5 + bl + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/inline_multi_block_result_forward.x64.asm b/tests/snapshots/asm/inline_multi_block_result_forward.x64.asm new file mode 100644 index 000000000..dfcc24e95 --- /dev/null +++ b/tests/snapshots/asm/inline_multi_block_result_forward.x64.asm @@ -0,0 +1,52 @@ + +inline_multi_block_result_forward.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + leaq (%rdi,%rdi), %rax + movslq %eax, %rax + retq + +: + pushq %rbp + movq %rsp, %rbp + subq $0x10, %rsp + movslq %edi, %rdi + movq %rdi, %rax + shlq $0x1, %rax + movslq %eax, %rax + addq $0x10, %rsp + popq %rbp + retq + +: + movslq %edi, %rdi + jmp + leaq (%rdi,%rdi), %rdx + cmpq $0x3, %rdi + jle + movslq %ecx, %rax + retq + leaq (%rcx,%rdx), %rax + movslq %eax, %rax + retq + movslq %edi, %rax + shlq $0x1, %rax + movslq %eax, %rcx + jmp + +
: + pushq %rbp + movq %rsp, %rbp + movl $0x5, %edi + popq %rbp + jmp + addb %al, (%rax) diff --git a/tests/snapshots/asm/integer_literal_suffix.x64.asm b/tests/snapshots/asm/integer_literal_suffix.x64.asm index 6420e91d4..9701c3d5b 100644 --- a/tests/snapshots/asm/integer_literal_suffix.x64.asm +++ b/tests/snapshots/asm/integer_literal_suffix.x64.asm @@ -26,8 +26,10 @@ Disassembly of section .text: movl $0x1, %ecx movq %rax, %r10 movq %rcx, %rax + pushq %rcx movq %r10, %rcx shlq %cl, %rax + popq %rcx decq %rax movabsq $0xfffffffff, %r11 # imm = 0xFFFFFFFFF cmpq %r11, %rax @@ -81,3 +83,4 @@ Disassembly of section .text: popq %rbp retq jmp + addb %al, (%rax) diff --git a/tests/snapshots/asm/mixed_sse_int_aggregate_args.aarch64.asm b/tests/snapshots/asm/mixed_sse_int_aggregate_args.aarch64.asm new file mode 100644 index 000000000..8f2a7c166 --- /dev/null +++ b/tests/snapshots/asm/mixed_sse_int_aggregate_args.aarch64.asm @@ -0,0 +1,165 @@ + +mixed_sse_int_aggregate_args.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x50 + sub x16, x29, #0x10 + str x0, [x16] + str x1, [x16, #0x8] + sub x16, x29, #0x20 + str x3, [x16] + str x4, [x16, #0x8] + sub x16, x29, #0x30 + str d1, [x16] + str d2, [x16, #0x8] + mov x1, x2 + sub x0, x29, #0x10 + ldr d1, [x0] + mov x0, #0x4004000000000000 // =4612811918334230528 + fmov d17, x0 + fcmp d1, d17 + cset x2, ne + cbnz x2, + sub x0, x29, #0x10 + ldr x0, [x0, #0x8] + cmp x0, #0x7 + cset x2, ne + cbz x2, + mov x0, #0x1 // =1 + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0x50 + ret + cmp x1, #0x4 + b.eq + mov x0, #0x2 // =2 + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0x50 + ret + sub x0, x29, #0x20 + ldr x0, [x0] + cmp x0, #0xb + cset x1, ne + cbnz x1, + sub x0, x29, #0x20 + add x0, x0, #0x8 + ldr d1, [x0] + mov x0, #0x3fe0000000000000 // =4602678819172646912 + fmov d17, x0 + fcmp d1, d17 + cset x1, ne + cbz x1, + mov x0, #0x3 // =3 + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0x50 + ret + mov x0, #0x3ff4000000000000 // =4608308318706860032 + fmov d17, x0 + fcmp d0, d17 + cset x0, ne + cbz x0, + mov x0, #0x4 // =4 + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0x50 + ret + sub x0, x29, #0x30 + ldr d0, [x0] + mov x0, #0x400c000000000000 // =4615063718147915776 + fmov d17, x0 + fcmp d0, d17 + cset x1, ne + cbnz x1, + sub x0, x29, #0x30 + add x0, x0, #0x8 + ldr d0, [x0] + mov x0, #0x4012000000000000 // =4616752568008179712 + fmov d17, x0 + fcmp d0, d17 + cset x1, ne + cbz x1, + mov x0, #0x5 // =5 + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0x50 + ret + mov x0, #0x0 // =0 + add sp, sp, #0x50 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0x50 + ret + b + b + b + +: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + ldr d1, [x3] + ldr d2, [x3, #0x8] + mov x3, x2 + mov x2, x0 + mov x0, x1 + ldr x1, [x0, #0x8] + ldr x0, [x0] + ldr x4, [x3, #0x8] + ldr x3, [x3] + bl + ldp x29, x30, [sp], #0x10 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x60 + sub x0, x29, #0x10 + mov x1, #0x4004000000000000 // =4612811918334230528 + fmov d16, x1 + str d16, [x0] + sub x0, x29, #0x10 + mov x1, #0x7 // =7 + str x1, [x0, #0x8] + sub x0, x29, #0x20 + mov x1, #0xb // =11 + str x1, [x0] + sub x0, x29, #0x20 + add x0, x0, #0x8 + mov x1, #0x3fe0000000000000 // =4602678819172646912 + fmov d16, x1 + str d16, [x0] + sub x0, x29, #0x30 + mov x1, #0x400c000000000000 // =4615063718147915776 + fmov d16, x1 + str d16, [x0] + sub x0, x29, #0x30 + add x0, x0, #0x8 + mov x1, #0x4012000000000000 // =4616752568008179712 + fmov d16, x1 + str d16, [x0] + mov x0, #0x4 // =4 + sub x1, x29, #0x10 + sub x2, x29, #0x20 + sub x3, x29, #0x30 + mov x4, #0x3ff4000000000000 // =4608308318706860032 + fmov d0, x4 + bl + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/mixed_sse_int_aggregate_args.x64.asm b/tests/snapshots/asm/mixed_sse_int_aggregate_args.x64.asm new file mode 100644 index 000000000..c820f2bb6 --- /dev/null +++ b/tests/snapshots/asm/mixed_sse_int_aggregate_args.x64.asm @@ -0,0 +1,203 @@ + +mixed_sse_int_aggregate_args.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + popq %r10 + subq $0x50, %rsp + pushq %r10 + pushq %rbp + movq %rsp, %rbp + subq $0x50, %rsp + movsd %xmm0, -0x10(%rbp,%riz) + movq %rdi, -0x8(%rbp) + movq %rdx, -0x20(%rbp) + movsd %xmm1, -0x18(%rbp,%riz) + movsd %xmm3, -0x30(%rbp,%riz) + movsd %xmm4, -0x28(%rbp,%riz) + movapd %xmm2, %xmm0 + leaq -0x10(%rbp), %rax + movsd (%rax,%riz), %xmm1 + movabsq $0x4004000000000000, %rax # imm = 0x4004000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm1 + setne %cl + movzbq %cl, %rcx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rcx + testq %rcx, %rcx + jne + leaq -0x10(%rbp), %rax + movq 0x8(%rax), %rax + cmpq $0x7, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x1, %eax + addq $0x50, %rsp + popq %rbp + popq %r11 + addq $0x50, %rsp + pushq %r11 + retq + cmpq $0x4, %rsi + je + movl $0x2, %eax + addq $0x50, %rsp + popq %rbp + popq %r11 + addq $0x50, %rsp + pushq %r11 + retq + leaq -0x20(%rbp), %rax + movq (%rax), %rax + cmpq $0xb, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + jne + leaq -0x20(%rbp), %rax + addq $0x8, %rax + movsd (%rax,%riz), %xmm1 + movabsq $0x3fe0000000000000, %rax # imm = 0x3FE0000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm1 + setne %cl + movzbq %cl, %rcx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rcx + testq %rcx, %rcx + je + movl $0x3, %eax + addq $0x50, %rsp + popq %rbp + popq %r11 + addq $0x50, %rsp + pushq %r11 + retq + movabsq $0x3ff4000000000000, %rax # imm = 0x3FF4000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %al + movzbq %al, %rax + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rax + testq %rax, %rax + je + movl $0x4, %eax + addq $0x50, %rsp + popq %rbp + popq %r11 + addq $0x50, %rsp + pushq %r11 + retq + leaq -0x30(%rbp), %rax + movsd (%rax,%riz), %xmm0 + movabsq $0x400c000000000000, %rax # imm = 0x400C000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %cl + movzbq %cl, %rcx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rcx + testq %rcx, %rcx + jne + leaq -0x30(%rbp), %rax + addq $0x8, %rax + movsd (%rax,%riz), %xmm0 + movabsq $0x4012000000000000, %rax # imm = 0x4012000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %cl + movzbq %cl, %rcx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rcx + testq %rcx, %rcx + je + movl $0x5, %eax + addq $0x50, %rsp + popq %rbp + popq %r11 + addq $0x50, %rsp + pushq %r11 + retq + xorq %rax, %rax + addq $0x50, %rsp + popq %rbp + popq %r11 + addq $0x50, %rsp + pushq %r11 + retq + jmp + jmp + jmp + +: + pushq %rbp + movq %rsp, %rbp + movapd %xmm0, %xmm2 + movq %rcx, %r10 + movsd (%r10,%riz), %xmm3 + movsd 0x8(%r10,%riz), %xmm4 + xchgq %rsi, %rdi + movsd (%rdi,%riz), %xmm0 + movq 0x8(%rdi), %rdi + movsd 0x8(%rdx,%riz), %xmm1 + movq (%rdx), %rdx + callq + popq %rbp + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x60, %rsp + leaq -0x10(%rbp), %rax + movabsq $0x4004000000000000, %rcx # imm = 0x4004000000000000 + movq %rcx, %xmm14 + movsd %xmm14, (%rax,%riz) + leaq -0x10(%rbp), %rax + movl $0x7, %ecx + movq %rcx, 0x8(%rax) + leaq -0x20(%rbp), %rax + movl $0xb, %ecx + movq %rcx, (%rax) + leaq -0x20(%rbp), %rax + addq $0x8, %rax + movabsq $0x3fe0000000000000, %rcx # imm = 0x3FE0000000000000 + movq %rcx, %xmm14 + movsd %xmm14, (%rax,%riz) + leaq -0x30(%rbp), %rax + movabsq $0x400c000000000000, %rcx # imm = 0x400C000000000000 + movq %rcx, %xmm14 + movsd %xmm14, (%rax,%riz) + leaq -0x30(%rbp), %rax + addq $0x8, %rax + movabsq $0x4012000000000000, %rcx # imm = 0x4012000000000000 + movq %rcx, %xmm14 + movsd %xmm14, (%rax,%riz) + movl $0x4, %edi + leaq -0x10(%rbp), %rsi + leaq -0x20(%rbp), %rdx + leaq -0x30(%rbp), %rcx + movabsq $0x3ff4000000000000, %r8 # imm = 0x3FF4000000000000 + movq %r8, %xmm0 + callq + addq $0x60, %rsp + popq %rbp + retq + addb %al, (%rax) diff --git a/tests/snapshots/asm/mixed_struct_gpr_abi.x64.asm b/tests/snapshots/asm/mixed_struct_gpr_abi.x64.asm index 453ed19b6..847596946 100644 --- a/tests/snapshots/asm/mixed_struct_gpr_abi.x64.asm +++ b/tests/snapshots/asm/mixed_struct_gpr_abi.x64.asm @@ -85,9 +85,8 @@ Disassembly of section .text: popq %rdx leaq -0x10(%rbp), %rdi movl $0x2, %esi - movq %rdi, %r10 - movq (%r10), %rdi - movsd 0x8(%r10,%riz), %xmm0 + movsd 0x8(%rdi,%riz), %xmm0 + movq (%rdi), %rdi callq cmpq $0xe, %rax je diff --git a/tests/snapshots/asm/rotate_variable_count.x64.asm b/tests/snapshots/asm/rotate_variable_count.x64.asm index e12af4e80..2df0f9e20 100644 --- a/tests/snapshots/asm/rotate_variable_count.x64.asm +++ b/tests/snapshots/asm/rotate_variable_count.x64.asm @@ -13,8 +13,10 @@ Disassembly of section .text: : movslq %esi, %rsi movq %rdi, %rax + pushq %rcx movq %rsi, %rcx rorq %cl, %rax + popq %rcx retq : @@ -151,3 +153,4 @@ Disassembly of section .text: addq $0x70, %rsp popq %rbp retq + addb %al, (%rax) diff --git a/tests/snapshots/asm/setjmp_value_live_across.aarch64.asm b/tests/snapshots/asm/setjmp_value_live_across.aarch64.asm new file mode 100644 index 000000000..75970a0c0 --- /dev/null +++ b/tests/snapshots/asm/setjmp_value_live_across.aarch64.asm @@ -0,0 +1,72 @@ + +setjmp_value_live_across.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x2b0 // =688 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x10 + str x19, [sp] + adrp x0, + add x0, x0, + mov x1, #0x1 // =1 + bl + uxtb w0, w0 + mov x0, #0x0 // =0 + ldr x19, [sp] + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + +: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x30 + str x20, [sp] + str x19, [sp, #0x10] + mov x17, #0x7 // =7 + mul x0, x0, x17 + add x0, x0, x1 + sxtw x20, w0 + adrp x0, + add x0, x0, + bl + sxtw x0, w0 + cbz x0, + mov x0, x20 + ldr x20, [sp] + ldr x19, [sp, #0x10] + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + bl + mov x0, #0x0 // =0 + ldr x20, [sp] + ldr x19, [sp, #0x10] + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x20 + mov x0, #0x5 // =5 + mov x1, #0x7 // =7 + bl + cmp x0, #0x2a + b.ne + mov x1, #0x0 // =0 + b + mov x1, #0x1 // =1 + mov x0, x1 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/setjmp_value_live_across.x64.asm b/tests/snapshots/asm/setjmp_value_live_across.x64.asm new file mode 100644 index 000000000..20238ed21 --- /dev/null +++ b/tests/snapshots/asm/setjmp_value_live_across.x64.asm @@ -0,0 +1,66 @@ + +setjmp_value_live_across.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + pushq %rbp + movq %rsp, %rbp + leaq , %rdi + movl $0x1, %esi + xorl %eax, %eax + callq + movzbq %al, %rax + xorq %rax, %rax + popq %rbp + retq + +: + pushq %rbp + movq %rsp, %rbp + subq $0x20, %rsp + movq %rbx, (%rsp) + imulq $0x7, %rdi, %rax + addq %rsi, %rax + movslq %eax, %rbx + leaq , %rdi + xorl %eax, %eax + callq + movslq %eax, %rax + testq %rax, %rax + je + movq %rbx, %rax + movq (%rsp), %rbx + addq $0x20, %rsp + popq %rbp + retq + callq + xorq %rax, %rax + movq (%rsp), %rbx + addq $0x20, %rsp + popq %rbp + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x20, %rsp + movl $0x5, %edi + movl $0x7, %esi + callq + cmpq $0x2a, %rax + jne + xorq %rcx, %rcx + jmp + movl $0x1, %ecx + movq %rcx, %rax + addq $0x20, %rsp + popq %rbp + retq diff --git a/tests/snapshots/asm/shift_result_type_signedness.x64.asm b/tests/snapshots/asm/shift_result_type_signedness.x64.asm index 149073ea7..57c1cf981 100644 --- a/tests/snapshots/asm/shift_result_type_signedness.x64.asm +++ b/tests/snapshots/asm/shift_result_type_signedness.x64.asm @@ -13,12 +13,16 @@ Disassembly of section .text: : movslq %esi, %rsi movl %edi, %eax + pushq %rcx movq %rsi, %rcx shlq %cl, %rax + popq %rcx movl %eax, %eax movslq %eax, %rax + pushq %rcx movq %rsi, %rcx sarq %cl, %rax + popq %rcx retq
: diff --git a/tests/snapshots/asm/sqlite_min.aarch64.asm b/tests/snapshots/asm/sqlite_min.aarch64.asm index 4696c0370..6cae7cd4a 100644 --- a/tests/snapshots/asm/sqlite_min.aarch64.asm +++ b/tests/snapshots/asm/sqlite_min.aarch64.asm @@ -129,23 +129,7 @@ Disassembly of section .text: ret <__c5_sys_open>: - str x2, [sp, #-0x10]! - str x1, [sp, #-0x10]! - str x0, [sp, #-0x10]! - stp x29, x30, [sp, #-0x10]! - mov x29, sp - sub sp, sp, #0x10 - str x19, [sp] - ldur x0, [x29, #0x10] - ldur x1, [x29, #0x20] - ldur x2, [x29, #0x30] - bl - sxtw x0, w0 - ldr x19, [sp] - add sp, sp, #0x10 - ldp x29, x30, [sp], #0x10 - add sp, sp, #0x30 - ret + b <__c5_sys_close>: str x0, [sp, #-0x10]! diff --git a/tests/snapshots/asm/sqlite_min.x64.asm b/tests/snapshots/asm/sqlite_min.x64.asm index 3243fb3a9..a8a0de6fd 100644 --- a/tests/snapshots/asm/sqlite_min.x64.asm +++ b/tests/snapshots/asm/sqlite_min.x64.asm @@ -106,25 +106,7 @@ Disassembly of section .text: retq <__c5_sys_open>: - popq %r10 - subq $0x30, %rsp - movq %rdi, (%rsp) - movq %rsi, 0x10(%rsp) - movq %rdx, 0x20(%rsp) - pushq %r10 - pushq %rbp - movq %rsp, %rbp - movq 0x10(%rbp), %rdi - movq 0x20(%rbp), %rsi - movq 0x30(%rbp), %rdx - movb $0x0, %al - callq - movslq %eax, %rax - popq %rbp - popq %r11 - addq $0x30, %rsp - pushq %r11 - retq + jmp <__c5_sys_close>: popq %r10 @@ -220,4 +202,4 @@ Disassembly of section .text: addq $0x20, %rsp pushq %r11 retq - addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/ssa_call_result_spill.x64.asm b/tests/snapshots/asm/ssa_call_result_spill.x64.asm index 1aa597829..d66f9a324 100644 --- a/tests/snapshots/asm/ssa_call_result_spill.x64.asm +++ b/tests/snapshots/asm/ssa_call_result_spill.x64.asm @@ -13,8 +13,10 @@ Disassembly of section .text: : movslq %esi, %rsi movq %rdi, %rax + pushq %rcx movq %rsi, %rcx rorq %cl, %rax + popq %rcx retq : @@ -31,8 +33,10 @@ Disassembly of section .text: movslq %eax, %rax movq %rax, %r10 movq %rdi, %rax + pushq %rcx movq %r10, %rcx rorq %cl, %rax + popq %rcx movl $0x12, %ecx movslq %ecx, %rcx movq %rcx, %r10 diff --git a/tests/snapshots/asm/ssa_va_arg_loop.aarch64.asm b/tests/snapshots/asm/ssa_va_arg_loop.aarch64.asm index 58746eeeb..ab94e97c1 100644 --- a/tests/snapshots/asm/ssa_va_arg_loop.aarch64.asm +++ b/tests/snapshots/asm/ssa_va_arg_loop.aarch64.asm @@ -70,6 +70,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -138,6 +140,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/ssa_va_start_va_copy_aliasing.aarch64.asm b/tests/snapshots/asm/ssa_va_start_va_copy_aliasing.aarch64.asm index 9a05fd0cc..d68375565 100644 --- a/tests/snapshots/asm/ssa_va_start_va_copy_aliasing.aarch64.asm +++ b/tests/snapshots/asm/ssa_va_start_va_copy_aliasing.aarch64.asm @@ -60,6 +60,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -78,6 +80,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -159,6 +163,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -177,6 +183,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/ssa_va_start_va_copy_aliasing.x64.asm b/tests/snapshots/asm/ssa_va_start_va_copy_aliasing.x64.asm index ab20b1bc9..f8ce235e9 100644 --- a/tests/snapshots/asm/ssa_va_start_va_copy_aliasing.x64.asm +++ b/tests/snapshots/asm/ssa_va_start_va_copy_aliasing.x64.asm @@ -99,12 +99,14 @@ Disassembly of section .text: movq %r10, 0x10(%rax) leaq -0x30(%rbp), %rax leaq -0x18(%rbp), %rcx - movq (%rcx), %r10 - movq %r10, (%rax) - movq 0x8(%rcx), %r10 - movq %r10, 0x8(%rax) - movq 0x10(%rcx), %r10 - movq %r10, 0x10(%rax) + pushq %rdx + movq (%rcx), %rdx + movq %rdx, (%rax) + movq 0x8(%rcx), %rdx + movq %rdx, 0x8(%rax) + movq 0x10(%rcx), %rdx + movq %rdx, 0x10(%rax) + popq %rdx leaq -0x18(%rbp), %rax movq %rax, %r11 movl (%r11), %r10d @@ -176,3 +178,4 @@ Disassembly of section .text: addq $0x20, %rsp popq %rbp retq + addb %al, (%rax) diff --git a/tests/snapshots/asm/struct_deref_va_arg.aarch64.asm b/tests/snapshots/asm/struct_deref_va_arg.aarch64.asm index 5d3f2c5e2..ae4927055 100644 --- a/tests/snapshots/asm/struct_deref_va_arg.aarch64.asm +++ b/tests/snapshots/asm/struct_deref_va_arg.aarch64.asm @@ -62,6 +62,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/sxtw_fold_source_liveness.aarch64.asm b/tests/snapshots/asm/sxtw_fold_source_liveness.aarch64.asm new file mode 100644 index 000000000..e812fb190 --- /dev/null +++ b/tests/snapshots/asm/sxtw_fold_source_liveness.aarch64.asm @@ -0,0 +1,34 @@ + +sxtw_fold_source_liveness.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x20 + lsl x2, x0, #32 + add x0, x0, x1 + asr x2, x2, #32 + add x0, x2, x0 + add x0, x0, x1 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + +
: + mov x0, #0x2 // =2 + mov x1, #0x7 // =7 + lsl x2, x0, #32 + add x0, x0, x1 + asr x2, x2, #32 + add x0, x2, x0 + add x0, x0, x1 + sxtw x0, w0 + ret diff --git a/tests/snapshots/asm/sxtw_fold_source_liveness.x64.asm b/tests/snapshots/asm/sxtw_fold_source_liveness.x64.asm new file mode 100644 index 000000000..635b6be10 --- /dev/null +++ b/tests/snapshots/asm/sxtw_fold_source_liveness.x64.asm @@ -0,0 +1,36 @@ + +sxtw_fold_source_liveness.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + pushq %rbp + movq %rsp, %rbp + subq $0x20, %rsp + leaq (%rdi,%rsi), %rcx + movslq %edi, %rax + addq %rcx, %rax + addq %rsi, %rax + addq $0x20, %rsp + popq %rbp + retq + +
: + movl $0x2, %eax + movl $0x7, %ecx + movq %rax, %rdx + shlq $0x20, %rdx + addq %rcx, %rax + sarq $0x20, %rdx + addq %rdx, %rax + addq %rcx, %rax + movslq %eax, %rax + retq + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/sys_addr_in_static_init.aarch64.asm b/tests/snapshots/asm/sys_addr_in_static_init.aarch64.asm index 98bd8dc9f..7c52e79d6 100644 --- a/tests/snapshots/asm/sys_addr_in_static_init.aarch64.asm +++ b/tests/snapshots/asm/sys_addr_in_static_init.aarch64.asm @@ -104,23 +104,7 @@ Disassembly of section .text: ret <__c5_sys_open>: - str x2, [sp, #-0x10]! - str x1, [sp, #-0x10]! - str x0, [sp, #-0x10]! - stp x29, x30, [sp, #-0x10]! - mov x29, sp - sub sp, sp, #0x10 - str x19, [sp] - ldur x0, [x29, #0x10] - ldur x1, [x29, #0x20] - ldur x2, [x29, #0x30] - bl - sxtw x0, w0 - ldr x19, [sp] - add sp, sp, #0x10 - ldp x29, x30, [sp], #0x10 - add sp, sp, #0x30 - ret + b <__c5_sys_read>: str x2, [sp, #-0x10]! diff --git a/tests/snapshots/asm/sys_addr_in_static_init.x64.asm b/tests/snapshots/asm/sys_addr_in_static_init.x64.asm index 5fe64bb1c..18d38fa39 100644 --- a/tests/snapshots/asm/sys_addr_in_static_init.x64.asm +++ b/tests/snapshots/asm/sys_addr_in_static_init.x64.asm @@ -74,25 +74,7 @@ Disassembly of section .text: retq <__c5_sys_open>: - popq %r10 - subq $0x30, %rsp - movq %rdi, (%rsp) - movq %rsi, 0x10(%rsp) - movq %rdx, 0x20(%rsp) - pushq %r10 - pushq %rbp - movq %rsp, %rbp - movq 0x10(%rbp), %rdi - movq 0x20(%rbp), %rsi - movq 0x30(%rbp), %rdx - movb $0x0, %al - callq - movslq %eax, %rax - popq %rbp - popq %r11 - addq $0x30, %rsp - pushq %r11 - retq + jmp <__c5_sys_read>: popq %r10 @@ -151,4 +133,3 @@ Disassembly of section .text: pushq %r11 retq addb %al, (%rax) - addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/sysv_variadic_host_abi.aarch64.asm b/tests/snapshots/asm/sysv_variadic_host_abi.aarch64.asm index 2221d8f27..2ba9142fd 100644 --- a/tests/snapshots/asm/sysv_variadic_host_abi.aarch64.asm +++ b/tests/snapshots/asm/sysv_variadic_host_abi.aarch64.asm @@ -89,6 +89,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -109,6 +111,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x10 str w16, [x17, #0x1c] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -182,6 +186,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x10 str w16, [x17, #0x1c] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/va_arg_composite_straddle.aarch64.asm b/tests/snapshots/asm/va_arg_composite_straddle.aarch64.asm new file mode 100644 index 000000000..ef52d20f8 --- /dev/null +++ b/tests/snapshots/asm/va_arg_composite_straddle.aarch64.asm @@ -0,0 +1,192 @@ + +va_arg_composite_straddle.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x230 // =560 + movk x1, #0x0, lsl #16 + b + brk #: + sub sp, sp, #0xc0 + str x0, [sp] + str x1, [sp, #0x8] + str x2, [sp, #0x10] + str x3, [sp, #0x18] + str x4, [sp, #0x20] + str x5, [sp, #0x28] + str x6, [sp, #0x30] + str x7, [sp, #0x38] + str d0, [sp, #0x40] + str d1, [sp, #0x50] + str d2, [sp, #0x60] + str d3, [sp, #0x70] + str d4, [sp, #0x80] + str d5, [sp, #0x90] + str d6, [sp, #0xa0] + str d7, [sp, #0xb0] + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x60 + str x19, [sp] + sub x0, x29, #0x20 + add x1, x29, #0x10 + mov x16, x0 + add x17, x29, #0xd0 + str x17, [x16] + add x17, x29, #0x50 + str x17, [x16, #0x8] + add x17, x29, #0xd0 + str x17, [x16, #0x10] + mov x17, #0xffc8 // =65480 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + str w17, [x16, #0x18] + mov x17, #0xff80 // =65408 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + str w17, [x16, #0x1c] + mov x1, #0x0 // =0 + sxtw x0, w1 + cmp x0, #0x6 + b.ge + b + sxtw x0, w1 + add x1, x0, #0x1 + b + sub x0, x29, #0x20 + mov x17, x0 + str x9, [sp, #-0x10]! + ldrsw x16, [x17, #0x18] + cmp x16, #0x0 + b.ge + ldr x9, [x17, #0x8] + add x9, x9, x16 + add x16, x16, #0x8 + str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt + mov x16, x9 + b + ldr x16, [x17] + add x9, x16, #0x8 + str x9, [x17] + ldr x9, [sp], #0x10 + mov x0, x16 + b + sub x0, x29, #0x20 + mov x17, x0 + str x9, [sp, #-0x10]! + ldrsw x16, [x17, #0x18] + cmp x16, #0x0 + b.ge + ldr x9, [x17, #0x8] + add x9, x9, x16 + add x16, x16, #0x10 + str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt + mov x16, x9 + b + ldr x16, [x17] + add x9, x16, #0x10 + str x9, [x17] + ldr x9, [sp], #0x10 + mov x0, x16 + sub x1, x29, #0x38 + str x10, [sp, #-0x10]! + ldr x10, [x0] + str x10, [x1] + ldr x10, [x0, #0x8] + str x10, [x1, #0x8] + ldr x10, [sp], #0x10 + mov x0, x1 + sub x0, x29, #0x20 + mov x17, x0 + str x9, [sp, #-0x10]! + ldrsw x16, [x17, #0x18] + cmp x16, #0x0 + b.ge + ldr x9, [x17, #0x8] + add x9, x9, x16 + add x16, x16, #0x8 + str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt + mov x16, x9 + b + ldr x16, [x17] + add x9, x16, #0x8 + str x9, [x17] + ldr x9, [sp], #0x10 + mov x0, x16 + ldr x0, [x0] + sub x1, x29, #0x20 + sub x1, x29, #0x38 + ldr x1, [x1] + cmp x1, #0x6f + cset x2, ne + cbnz x2, + sub x1, x29, #0x38 + ldr x1, [x1, #0x8] + cmp x1, #0xde + cset x2, ne + cbz x2, + mov x0, #0x1 // =1 + ldr x19, [sp] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0xc0 + ret + cmp x0, #0x309 + b.eq + mov x0, #0x2 // =2 + ldr x19, [sp] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0xc0 + ret + mov x0, #0x0 // =0 + ldr x19, [sp] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0xc0 + ret + b + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x60 + sub x0, x29, #0x10 + mov x1, #0x6f // =111 + str x1, [x0] + sub x0, x29, #0x10 + mov x1, #0xde // =222 + str x1, [x0, #0x8] + mov x0, #0x1 // =1 + mov x1, #0x2 // =2 + mov x2, #0x3 // =3 + mov x3, #0x4 // =4 + mov x4, #0x5 // =5 + mov x5, #0x6 // =6 + mov x6, #0x7 // =7 + sub x7, x29, #0x10 + mov x8, #0x309 // =777 + sub sp, sp, #0x20 + str x8, [sp, #0x10] + mov x16, x7 + ldr x17, [x16] + str x17, [sp] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8] + bl + add sp, sp, #0x20 + sxtw x0, w0 + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/va_arg_composite_straddle.x64.asm b/tests/snapshots/asm/va_arg_composite_straddle.x64.asm new file mode 100644 index 000000000..ca809d7fe --- /dev/null +++ b/tests/snapshots/asm/va_arg_composite_straddle.x64.asm @@ -0,0 +1,162 @@ + +va_arg_composite_straddle.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + pushq %rbp + movq %rsp, %rbp + subq $0xf0, %rsp + movq %rdi, -0xf0(%rbp) + movq %rsi, -0xe8(%rbp) + movq %rdx, -0xe0(%rbp) + movq %rcx, -0xd8(%rbp) + movq %r8, -0xd0(%rbp) + movq %r9, -0xc8(%rbp) + testb %al, %al + je + movsd %xmm0, -0xc0(%rbp,%riz) + movsd %xmm1, -0xb0(%rbp,%riz) + movsd %xmm2, -0xa0(%rbp,%riz) + movsd %xmm3, -0x90(%rbp,%riz) + movsd %xmm4, -0x80(%rbp,%riz) + movsd %xmm5, -0x70(%rbp,%riz) + movsd %xmm6, -0x60(%rbp,%riz) + movsd %xmm7, -0x50(%rbp,%riz) + leaq -0x18(%rbp), %rax + leaq -0xf0(%rbp), %rcx + movl $0x8, (%rax) + movl $0x30, 0x4(%rax) + leaq 0x10(%rbp), %r10 + movq %r10, 0x8(%rax) + leaq -0xf0(%rbp), %r10 + movq %r10, 0x10(%rax) + xorq %rcx, %rcx + movslq %ecx, %rax + cmpq $0x6, %rax + jge + jmp + movslq %ecx, %rax + leaq 0x1(%rax), %rcx + jmp + leaq -0x18(%rbp), %rax + movq %rax, %r11 + movl (%r11), %r10d + cmpq $0x30, %r10 + jae + addq 0x10(%r11), %r10 + addl $0x8, (%r11) + jmp + movq 0x8(%r11), %r10 + addq $0x8, 0x8(%r11) + movq %r10, %rax + jmp + leaq -0x18(%rbp), %rax + movq %rax, %r11 + movl (%r11), %r10d + cmpq $0x28, %r10 + jae + addq 0x10(%r11), %r10 + addl $0x10, (%r11) + jmp + movq 0x8(%r11), %r10 + addq $0x10, 0x8(%r11) + movq %r10, %rax + leaq -0x30(%rbp), %rcx + pushq %rdx + movq (%rax), %rdx + movq %rdx, (%rcx) + movq 0x8(%rax), %rdx + movq %rdx, 0x8(%rcx) + popq %rdx + movq %rcx, %rax + leaq -0x18(%rbp), %rax + movq %rax, %r11 + movl (%r11), %r10d + cmpq $0x30, %r10 + jae + addq 0x10(%r11), %r10 + addl $0x8, (%r11) + jmp + movq 0x8(%r11), %r10 + addq $0x8, 0x8(%r11) + movq %r10, %rax + movq (%rax), %rax + leaq -0x18(%rbp), %rcx + leaq -0x30(%rbp), %rcx + movq (%rcx), %rcx + cmpq $0x6f, %rcx + setne %dl + movzbq %dl, %rdx + testq %rdx, %rdx + jne + leaq -0x30(%rbp), %rcx + movq 0x8(%rcx), %rcx + cmpq $0xde, %rcx + setne %dl + movzbq %dl, %rdx + testq %rdx, %rdx + je + movl $0x1, %eax + addq $0xf0, %rsp + popq %rbp + retq + cmpq $0x309, %rax # imm = 0x309 + je + movl $0x2, %eax + addq $0xf0, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0xf0, %rsp + popq %rbp + retq + jmp + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x70, %rsp + movq %rbx, (%rsp) + movq %r12, 0x8(%rsp) + leaq -0x10(%rbp), %rax + movl $0x6f, %ecx + movq %rcx, (%rax) + leaq -0x10(%rbp), %rax + movl $0xde, %ecx + movq %rcx, 0x8(%rax) + movl $0x1, %edi + movl $0x2, %esi + movl $0x3, %edx + movl $0x4, %ecx + movl $0x5, %r8d + movl $0x6, %r9d + movl $0x7, %eax + leaq -0x10(%rbp), %rbx + movl $0x309, %r12d # imm = 0x309 + subq $0x20, %rsp + movq %rax, (%rsp) + movq %r12, 0x18(%rsp) + movq %rbx, %r10 + movq (%r10), %r11 + movq %r11, 0x8(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x10(%rsp) + movb $0x0, %al + callq + addq $0x20, %rsp + movslq %eax, %rax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + addq $0x70, %rsp + popq %rbp + retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/va_arg_int_seq.aarch64.asm b/tests/snapshots/asm/va_arg_int_seq.aarch64.asm index cd1a25cb4..9f9eb1889 100644 --- a/tests/snapshots/asm/va_arg_int_seq.aarch64.asm +++ b/tests/snapshots/asm/va_arg_int_seq.aarch64.asm @@ -76,6 +76,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/va_arg_through_pointer.aarch64.asm b/tests/snapshots/asm/va_arg_through_pointer.aarch64.asm index b3745f6fc..a922faf63 100644 --- a/tests/snapshots/asm/va_arg_through_pointer.aarch64.asm +++ b/tests/snapshots/asm/va_arg_through_pointer.aarch64.asm @@ -25,6 +25,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -45,6 +47,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -65,6 +69,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x10 str w16, [x17, #0x1c] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/va_copy.aarch64.asm b/tests/snapshots/asm/va_copy.aarch64.asm index d44b63c1a..aa1d2fe5d 100644 --- a/tests/snapshots/asm/va_copy.aarch64.asm +++ b/tests/snapshots/asm/va_copy.aarch64.asm @@ -78,6 +78,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/va_copy.x64.asm b/tests/snapshots/asm/va_copy.x64.asm index 52e9ac0a5..14ece69be 100644 --- a/tests/snapshots/asm/va_copy.x64.asm +++ b/tests/snapshots/asm/va_copy.x64.asm @@ -40,12 +40,14 @@ Disassembly of section .text: movq %r10, 0x10(%rax) leaq -0x30(%rbp), %rax leaq -0x18(%rbp), %rcx - movq (%rcx), %r10 - movq %r10, (%rax) - movq 0x8(%rcx), %r10 - movq %r10, 0x8(%rax) - movq 0x10(%rcx), %r10 - movq %r10, 0x10(%rax) + pushq %rdx + movq (%rcx), %rdx + movq %rdx, (%rax) + movq 0x8(%rcx), %rdx + movq %rdx, 0x8(%rax) + movq 0x10(%rcx), %rdx + movq %rdx, 0x10(%rax) + popq %rdx xorq %rcx, %rcx movq %rcx, %rax movslq %ecx, %rdx @@ -93,5 +95,4 @@ Disassembly of section .text: xorq %rax, %rax popq %rbp retq - addb %al, (%rax) addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/va_copy_under_pressure.aarch64.asm b/tests/snapshots/asm/va_copy_under_pressure.aarch64.asm new file mode 100644 index 000000000..8dcb6e4ae --- /dev/null +++ b/tests/snapshots/asm/va_copy_under_pressure.aarch64.asm @@ -0,0 +1,168 @@ + +va_copy_under_pressure.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + sub sp, sp, #0xc0 + str x0, [sp] + str x1, [sp, #0x8] + str x2, [sp, #0x10] + str x3, [sp, #0x18] + str x4, [sp, #0x20] + str x5, [sp, #0x28] + str x6, [sp, #0x30] + str x7, [sp, #0x38] + str d0, [sp, #0x40] + str d1, [sp, #0x50] + str d2, [sp, #0x60] + str d3, [sp, #0x70] + str d4, [sp, #0x80] + str d5, [sp, #0x90] + str d6, [sp, #0xa0] + str d7, [sp, #0xb0] + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0xe0 + str x20, [sp] + str x19, [sp, #0x10] + ldur x0, [x29, #0x10] + mov x17, #0x3 // =3 + mul x1, x0, x17 + add x2, x0, #0xb + mov x17, #0x7 // =7 + mul x3, x0, x17 + sub x4, x0, #0x2 + mov x17, #0xd // =13 + mul x5, x0, x17 + add x6, x0, #0x1d + lsl x7, x0, #2 + add x8, x0, #0x29 + mov x17, #0x9 // =9 + mul x9, x0, x17 + add x10, x0, #0x35 + mov x17, #0x5 // =5 + mul x11, x0, x17 + add x12, x0, #0x3d + mov x17, #0xf // =15 + mul x13, x0, x17 + add x0, x0, #0x3 + sub x14, x29, #0x20 + add x15, x29, #0x10 + mov x16, x14 + add x17, x29, #0xd0 + str x17, [x16] + add x17, x29, #0x50 + str x17, [x16, #0x8] + add x17, x29, #0xd0 + str x17, [x16, #0x10] + mov x17, #0xffc8 // =65480 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + str w17, [x16, #0x18] + mov x17, #0xff80 // =65408 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + str w17, [x16, #0x1c] + sub x14, x29, #0x40 + sub x15, x29, #0x20 + str x9, [sp, #-0x10]! + ldr x9, [x15] + str x9, [x14] + ldr x9, [x15, #0x8] + str x9, [x14, #0x8] + ldr x9, [x15, #0x10] + str x9, [x14, #0x10] + ldr x9, [x15, #0x18] + str x9, [x14, #0x18] + ldr x9, [sp], #0x10 + sub x14, x29, #0x40 + mov x17, x14 + str x9, [sp, #-0x10]! + ldrsw x16, [x17, #0x18] + cmp x16, #0x0 + b.ge + ldr x9, [x17, #0x8] + add x9, x9, x16 + add x16, x16, #0x8 + str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt + mov x16, x9 + b + ldr x16, [x17] + add x9, x16, #0x8 + str x9, [x17] + ldr x9, [sp], #0x10 + mov x14, x16 + ldr x14, [x14] + sub x15, x29, #0x40 + mov x17, x15 + str x9, [sp, #-0x10]! + ldrsw x16, [x17, #0x18] + cmp x16, #0x0 + b.ge + ldr x9, [x17, #0x8] + add x9, x9, x16 + add x16, x16, #0x8 + str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt + mov x16, x9 + b + ldr x16, [x17] + add x9, x16, #0x8 + str x9, [x17] + ldr x9, [sp], #0x10 + mov x15, x16 + ldr x15, [x15] + sub x20, x29, #0x40 + sub x20, x29, #0x20 + add x1, x1, x2 + add x1, x1, x3 + add x1, x1, x4 + add x1, x1, x5 + add x1, x1, x6 + add x1, x1, x7 + add x1, x1, x8 + add x1, x1, x9 + add x1, x1, x10 + add x1, x1, x11 + add x1, x1, x12 + add x1, x1, x13 + add x0, x1, x0 + add x0, x0, x14 + add x0, x0, x15 + ldr x20, [sp] + ldr x19, [sp, #0x10] + add sp, sp, #0xe0 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0xc0 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x30 + mov x0, #0x2 // =2 + mov x1, #0xa // =10 + mov x2, #0x14 // =20 + bl + mov x1, #0x160 // =352 + cmp x0, x1 + b.ne + mov x1, #0x0 // =0 + b + mov x1, #0x1 // =1 + mov x0, x1 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/va_copy_under_pressure.x64.asm b/tests/snapshots/asm/va_copy_under_pressure.x64.asm new file mode 100644 index 000000000..764d2443b --- /dev/null +++ b/tests/snapshots/asm/va_copy_under_pressure.x64.asm @@ -0,0 +1,159 @@ + +va_copy_under_pressure.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + pushq %rbp + movq %rsp, %rbp + subq $0x1c0, %rsp # imm = 0x1C0 + movq %rdi, -0x190(%rbp) + movq %rsi, -0x188(%rbp) + movq %rdx, -0x180(%rbp) + movq %rcx, -0x178(%rbp) + movq %r8, -0x170(%rbp) + movq %r9, -0x168(%rbp) + testb %al, %al + je + movsd %xmm0, -0x160(%rbp,%riz) + movsd %xmm1, -0x150(%rbp,%riz) + movsd %xmm2, -0x140(%rbp,%riz) + movsd %xmm3, -0x130(%rbp,%riz) + movsd %xmm4, -0x120(%rbp,%riz) + movsd %xmm5, -0x110(%rbp,%riz) + movsd %xmm6, -0x100(%rbp,%riz) + movsd %xmm7, -0xf0(%rbp,%riz) + movq %rbx, (%rsp) + movq %r12, 0x8(%rsp) + movq %r13, 0x10(%rsp) + movq %r14, 0x18(%rsp) + movq %r15, 0x20(%rsp) + movq -0x190(%rbp), %rax + leaq (%rax,%rax,2), %rcx + leaq 0xb(%rax), %rdx + imulq $0x7, %rax, %rsi + leaq -0x2(%rax), %rdi + imulq $0xd, %rax, %r8 + leaq 0x1d(%rax), %r9 + movq %rax, %rbx + shlq $0x2, %rbx + leaq 0x29(%rax), %r12 + leaq (%rax,%rax,8), %r13 + leaq 0x35(%rax), %r14 + leaq (%rax,%rax,4), %r15 + leaq 0x3d(%rax), %r10 + movq %r10, 0x108(%rsp) + imulq $0xf, %rax, %r10 + movq %r10, 0x100(%rsp) + addq $0x3, %rax + leaq -0x18(%rbp), %r10 + movq %r10, 0xf8(%rsp) + leaq -0x190(%rbp), %r10 + movq %r10, 0xf0(%rsp) + movq 0xf8(%rsp), %r11 + movl $0x8, (%r11) + movl $0x30, 0x4(%r11) + leaq 0x10(%rbp), %r10 + movq %r10, 0x8(%r11) + leaq -0x190(%rbp), %r10 + movq %r10, 0x10(%r11) + leaq -0x30(%rbp), %r10 + movq %r10, 0xf8(%rsp) + leaq -0x18(%rbp), %r10 + movq %r10, 0xf0(%rsp) + movq 0xf0(%rsp), %r11 + movq 0xf8(%rsp), %r10 + pushq %rax + movq (%r11), %rax + movq %rax, (%r10) + movq 0x8(%r11), %rax + movq %rax, 0x8(%r10) + movq 0x10(%r11), %rax + movq %rax, 0x10(%r10) + popq %rax + leaq -0x30(%rbp), %r10 + movq %r10, 0xf8(%rsp) + movq 0xf8(%rsp), %r11 + movl (%r11), %r10d + cmpq $0x30, %r10 + jae + addq 0x10(%r11), %r10 + addl $0x8, (%r11) + jmp + movq 0x8(%r11), %r10 + addq $0x8, 0x8(%r11) + movq %r10, 0xf8(%rsp) + movq 0xf8(%rsp), %r10 + movq (%r10), %r10 + movq %r10, 0xf8(%rsp) + leaq -0x30(%rbp), %r10 + movq %r10, 0xf0(%rsp) + movq 0xf0(%rsp), %r11 + movl (%r11), %r10d + cmpq $0x30, %r10 + jae + addq 0x10(%r11), %r10 + addl $0x8, (%r11) + jmp + movq 0x8(%r11), %r10 + addq $0x8, 0x8(%r11) + movq %r10, 0xf0(%rsp) + movq 0xf0(%rsp), %r10 + movq (%r10), %r10 + movq %r10, 0xf0(%rsp) + leaq -0x30(%rbp), %r10 + movq %r10, 0xe8(%rsp) + leaq -0x18(%rbp), %r10 + movq %r10, 0xe8(%rsp) + addq %rdx, %rcx + addq %rsi, %rcx + addq %rdi, %rcx + addq %r8, %rcx + addq %r9, %rcx + addq %rbx, %rcx + addq %r12, %rcx + addq %r13, %rcx + addq %r14, %rcx + addq %r15, %rcx + addq 0x108(%rsp), %rcx + addq 0x100(%rsp), %rcx + addq %rcx, %rax + addq 0xf8(%rsp), %rax + addq 0xf0(%rsp), %rax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + movq 0x18(%rsp), %r14 + movq 0x20(%rsp), %r15 + addq $0x1c0, %rsp # imm = 0x1C0 + popq %rbp + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x30, %rsp + movl $0x2, %edi + movl $0xa, %esi + movl $0x14, %edx + movb $0x0, %al + callq + movl $0x160, %ecx # imm = 0x160 + cmpq %rcx, %rax + jne + xorq %rcx, %rcx + jmp + movl $0x1, %ecx + movq %rcx, %rax + addq $0x30, %rsp + popq %rbp + retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/variable_shift_rcx_loop.aarch64.asm b/tests/snapshots/asm/variable_shift_rcx_loop.aarch64.asm new file mode 100644 index 000000000..0bab3eb2d --- /dev/null +++ b/tests/snapshots/asm/variable_shift_rcx_loop.aarch64.asm @@ -0,0 +1,48 @@ + +variable_shift_rcx_loop.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x10 + mov x5, #0x0 // =0 + mov x4, x5 + cmp x4, x0 + b.ge + b + lsl x6, x1, x2 + add x5, x5, x6 + b + add x4, x5, x3 + b + mov x0, x3 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x30 + mov x0, #0x64 // =100 + mov x1, #0x2 // =2 + mov x2, #0x3 // =3 + mov x3, #0x1 // =1 + bl + cmp x0, #0x1 + b.ne + mov x1, #0x0 // =0 + b + mov x1, #0x1 // =1 + mov x0, x1 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/variable_shift_rcx_loop.x64.asm b/tests/snapshots/asm/variable_shift_rcx_loop.x64.asm new file mode 100644 index 000000000..bd95a6d08 --- /dev/null +++ b/tests/snapshots/asm/variable_shift_rcx_loop.x64.asm @@ -0,0 +1,55 @@ + +variable_shift_rcx_loop.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + pushq %rbp + movq %rsp, %rbp + subq $0x10, %rsp + movq %rcx, %rax + xorq %r8, %r8 + movq %r8, %rcx + cmpq %rdi, %rcx + jge + jmp + movq %rsi, %r9 + pushq %rcx + movq %rdx, %rcx + shlq %cl, %r9 + popq %rcx + addq %r9, %r8 + jmp + leaq (%r8,%rax), %rcx + jmp + addq $0x10, %rsp + popq %rbp + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x30, %rsp + movl $0x64, %edi + movl $0x2, %esi + movl $0x3, %edx + movl $0x1, %ecx + callq + cmpq $0x1, %rax + jne + xorq %rcx, %rcx + jmp + movl $0x1, %ecx + movq %rcx, %rax + addq $0x30, %rsp + popq %rbp + retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/variadic_agg_return_classes.aarch64.asm b/tests/snapshots/asm/variadic_agg_return_classes.aarch64.asm new file mode 100644 index 000000000..c4b18b346 --- /dev/null +++ b/tests/snapshots/asm/variadic_agg_return_classes.aarch64.asm @@ -0,0 +1,169 @@ + +variadic_agg_return_classes.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + sub sp, sp, #0xc0 + str x0, [sp] + str x1, [sp, #0x8] + str x2, [sp, #0x10] + str x3, [sp, #0x18] + str x4, [sp, #0x20] + str x5, [sp, #0x28] + str x6, [sp, #0x30] + str x7, [sp, #0x38] + str d0, [sp, #0x40] + str d1, [sp, #0x50] + str d2, [sp, #0x60] + str d3, [sp, #0x70] + str d4, [sp, #0x80] + str d5, [sp, #0x90] + str d6, [sp, #0xa0] + str d7, [sp, #0xb0] + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x10 + sub x0, x29, #0x10 + mov x1, #0x3ff8000000000000 // =4609434218613702656 + ldursw x2, [x29, #0x10] + scvtf d0, x2 + fmov d16, x1 + fmul d0, d16, d0 + str d0, [x0] + sub x0, x29, #0x10 + add x0, x0, #0x8 + mov x1, #0x4002000000000000 // =4612248968380809216 + fmov d16, x1 + str d16, [x0] + sub x0, x29, #0x10 + mov x16, x0 + ldr d0, [x16] + ldr d1, [x16, #0x8] + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0xc0 + ret + +: + sub sp, sp, #0xc0 + str x0, [sp] + str x1, [sp, #0x8] + str x2, [sp, #0x10] + str x3, [sp, #0x18] + str x4, [sp, #0x20] + str x5, [sp, #0x28] + str x6, [sp, #0x30] + str x7, [sp, #0x38] + str d0, [sp, #0x40] + str d1, [sp, #0x50] + str d2, [sp, #0x60] + str d3, [sp, #0x70] + str d4, [sp, #0x80] + str d5, [sp, #0x90] + str d6, [sp, #0xa0] + str d7, [sp, #0xb0] + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x10 + sub x0, x29, #0x10 + mov x1, #0x3fe0000000000000 // =4602678819172646912 + fmov d16, x1 + str d16, [x0] + sub x0, x29, #0x10 + ldursw x1, [x29, #0x10] + add x1, x1, #0x29 + sxtw x1, w1 + str x1, [x0, #0x8] + sub x0, x29, #0x10 + mov x16, x0 + ldr x1, [x16, #0x8] + ldr x0, [x16] + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0xc0 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x90 + str x20, [sp] + mov x0, #0x2 // =2 + bl + sub x16, x29, #0x58 + str d0, [x16] + str d1, [x16, #0x8] + sub x0, x29, #0x58 + sub x1, x29, #0x10 + str x10, [sp, #-0x10]! + ldr x10, [x0] + str x10, [x1] + ldr x10, [x0, #0x8] + str x10, [x1, #0x8] + ldr x10, [sp], #0x10 + mov x0, x1 + sub x0, x29, #0x10 + ldr d0, [x0] + mov x0, #0x4008000000000000 // =4613937818241073152 + fmov d17, x0 + fcmp d0, d17 + cset x20, ne + cbnz x20, + sub x0, x29, #0x10 + add x0, x0, #0x8 + ldr d0, [x0] + mov x0, #0x4002000000000000 // =4612248968380809216 + fmov d17, x0 + fcmp d0, d17 + cset x20, ne + cbz x20, + mov x0, #0x1 // =1 + ldr x20, [sp] + add sp, sp, #0x90 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x1 // =1 + bl + sub x16, x29, #0x70 + str x0, [x16] + str x1, [x16, #0x8] + sub x0, x29, #0x70 + sub x1, x29, #0x30 + str x10, [sp, #-0x10]! + ldr x10, [x0] + str x10, [x1] + ldr x10, [x0, #0x8] + str x10, [x1, #0x8] + ldr x10, [sp], #0x10 + mov x0, x1 + sub x0, x29, #0x30 + ldr d0, [x0] + mov x0, #0x3fe0000000000000 // =4602678819172646912 + fmov d17, x0 + fcmp d0, d17 + cset x1, ne + cbnz x1, + sub x0, x29, #0x30 + ldr x0, [x0, #0x8] + cmp x0, #0x2a + cset x1, ne + cbz x1, + mov x0, #0x2 // =2 + ldr x20, [sp] + add sp, sp, #0x90 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldr x20, [sp] + add sp, sp, #0x90 + ldp x29, x30, [sp], #0x10 + ret + b + b diff --git a/tests/snapshots/asm/variadic_agg_return_classes.x64.asm b/tests/snapshots/asm/variadic_agg_return_classes.x64.asm new file mode 100644 index 000000000..9594d1014 --- /dev/null +++ b/tests/snapshots/asm/variadic_agg_return_classes.x64.asm @@ -0,0 +1,185 @@ + +variadic_agg_return_classes.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + pushq %rbp + movq %rsp, %rbp + subq $0xc0, %rsp + movq %rdi, -0xc0(%rbp) + movq %rsi, -0xb8(%rbp) + movq %rdx, -0xb0(%rbp) + movq %rcx, -0xa8(%rbp) + movq %r8, -0xa0(%rbp) + movq %r9, -0x98(%rbp) + testb %al, %al + je + movsd %xmm0, -0x90(%rbp,%riz) + movsd %xmm1, -0x80(%rbp,%riz) + movsd %xmm2, -0x70(%rbp,%riz) + movsd %xmm3, -0x60(%rbp,%riz) + movsd %xmm4, -0x50(%rbp,%riz) + movsd %xmm5, -0x40(%rbp,%riz) + movsd %xmm6, -0x30(%rbp,%riz) + movsd %xmm7, -0x20(%rbp,%riz) + leaq -0x10(%rbp), %rax + movabsq $0x3ff8000000000000, %rcx # imm = 0x3FF8000000000000 + movslq -0xc0(%rbp), %rdx + cvtsi2sd %rdx, %xmm0 + movapd %xmm0, %xmm15 + movq %rcx, %xmm0 + mulsd %xmm15, %xmm0 + movsd %xmm0, (%rax,%riz) + leaq -0x10(%rbp), %rax + addq $0x8, %rax + movabsq $0x4002000000000000, %rcx # imm = 0x4002000000000000 + movq %rcx, %xmm14 + movsd %xmm14, (%rax,%riz) + leaq -0x10(%rbp), %rax + movq %rax, %rcx + movsd (%rcx,%riz), %xmm0 + movsd 0x8(%rcx,%riz), %xmm1 + addq $0xc0, %rsp + popq %rbp + retq + +: + pushq %rbp + movq %rsp, %rbp + subq $0xc0, %rsp + movq %rdi, -0xc0(%rbp) + movq %rsi, -0xb8(%rbp) + movq %rdx, -0xb0(%rbp) + movq %rcx, -0xa8(%rbp) + movq %r8, -0xa0(%rbp) + movq %r9, -0x98(%rbp) + testb %al, %al + je + movsd %xmm0, -0x90(%rbp,%riz) + movsd %xmm1, -0x80(%rbp,%riz) + movsd %xmm2, -0x70(%rbp,%riz) + movsd %xmm3, -0x60(%rbp,%riz) + movsd %xmm4, -0x50(%rbp,%riz) + movsd %xmm5, -0x40(%rbp,%riz) + movsd %xmm6, -0x30(%rbp,%riz) + movsd %xmm7, -0x20(%rbp,%riz) + leaq -0x10(%rbp), %rax + movabsq $0x3fe0000000000000, %rcx # imm = 0x3FE0000000000000 + movq %rcx, %xmm14 + movsd %xmm14, (%rax,%riz) + leaq -0x10(%rbp), %rax + movslq -0xc0(%rbp), %rcx + addq $0x29, %rcx + movslq %ecx, %rcx + movq %rcx, 0x8(%rax) + leaq -0x10(%rbp), %rax + movq %rax, %rcx + movsd (%rcx,%riz), %xmm0 + movq 0x8(%rcx), %rax + addq $0xc0, %rsp + popq %rbp + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x90, %rsp + movq %rbx, (%rsp) + movl $0x2, %edi + movb $0x0, %al + callq + movsd %xmm0, -0x58(%rbp,%riz) + movsd %xmm1, -0x50(%rbp,%riz) + leaq -0x58(%rbp), %rax + leaq -0x10(%rbp), %rcx + pushq %rdx + movq (%rax), %rdx + movq %rdx, (%rcx) + movq 0x8(%rax), %rdx + movq %rdx, 0x8(%rcx) + popq %rdx + movq %rcx, %rax + leaq -0x10(%rbp), %rax + movsd (%rax,%riz), %xmm0 + movabsq $0x4008000000000000, %rax # imm = 0x4008000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %bl + movzbq %bl, %rbx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rbx + testq %rbx, %rbx + jne + leaq -0x10(%rbp), %rax + addq $0x8, %rax + movsd (%rax,%riz), %xmm0 + movabsq $0x4002000000000000, %rax # imm = 0x4002000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %bl + movzbq %bl, %rbx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rbx + testq %rbx, %rbx + je + movl $0x1, %eax + movq (%rsp), %rbx + addq $0x90, %rsp + popq %rbp + retq + movl $0x1, %edi + movb $0x0, %al + callq + movsd %xmm0, -0x70(%rbp,%riz) + movq %rax, -0x68(%rbp) + leaq -0x70(%rbp), %rax + leaq -0x30(%rbp), %rcx + pushq %rdx + movq (%rax), %rdx + movq %rdx, (%rcx) + movq 0x8(%rax), %rdx + movq %rdx, 0x8(%rcx) + popq %rdx + movq %rcx, %rax + leaq -0x30(%rbp), %rax + movsd (%rax,%riz), %xmm0 + movabsq $0x3fe0000000000000, %rax # imm = 0x3FE0000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %cl + movzbq %cl, %rcx + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rcx + testq %rcx, %rcx + jne + leaq -0x30(%rbp), %rax + movq 0x8(%rax), %rax + cmpq $0x2a, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x2, %eax + movq (%rsp), %rbx + addq $0x90, %rsp + popq %rbp + retq + xorq %rax, %rax + movq (%rsp), %rbx + addq $0x90, %rsp + popq %rbp + retq + jmp + jmp + addb %al, (%rax) diff --git a/tests/snapshots/asm/variadic_fn_ptr_init.aarch64.asm b/tests/snapshots/asm/variadic_fn_ptr_init.aarch64.asm index a168bb4d7..1e258a00a 100644 --- a/tests/snapshots/asm/variadic_fn_ptr_init.aarch64.asm +++ b/tests/snapshots/asm/variadic_fn_ptr_init.aarch64.asm @@ -70,6 +70,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/variadic_fnptr_proto_erased.aarch64.asm b/tests/snapshots/asm/variadic_fnptr_proto_erased.aarch64.asm index 7bb403366..173e31cd7 100644 --- a/tests/snapshots/asm/variadic_fnptr_proto_erased.aarch64.asm +++ b/tests/snapshots/asm/variadic_fnptr_proto_erased.aarch64.asm @@ -70,6 +70,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/variadic_hfa_struct_arg.aarch64.asm b/tests/snapshots/asm/variadic_hfa_struct_arg.aarch64.asm new file mode 100644 index 000000000..bd238b610 --- /dev/null +++ b/tests/snapshots/asm/variadic_hfa_struct_arg.aarch64.asm @@ -0,0 +1,122 @@ + +variadic_hfa_struct_arg.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + sub sp, sp, #0xc0 + str x0, [sp] + str x1, [sp, #0x8] + str x2, [sp, #0x10] + str x3, [sp, #0x18] + str x4, [sp, #0x20] + str x5, [sp, #0x28] + str x6, [sp, #0x30] + str x7, [sp, #0x38] + str d0, [sp, #0x40] + str d1, [sp, #0x50] + str d2, [sp, #0x60] + str d3, [sp, #0x70] + str d4, [sp, #0x80] + str d5, [sp, #0x90] + str d6, [sp, #0xa0] + str d7, [sp, #0xb0] + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x40 + str x19, [sp] + sub x0, x29, #0x20 + add x1, x29, #0x10 + mov x16, x0 + add x17, x29, #0xd0 + str x17, [x16] + add x17, x29, #0x50 + str x17, [x16, #0x8] + add x17, x29, #0xd0 + str x17, [x16, #0x10] + mov x17, #0xffc8 // =65480 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + str w17, [x16, #0x18] + mov x17, #0xff80 // =65408 + movk x17, #0xffff, lsl #16 + movk x17, #0xffff, lsl #32 + movk x17, #0xffff, lsl #48 + str w17, [x16, #0x1c] + sub x0, x29, #0x20 + mov x17, x0 + str x9, [sp, #-0x10]! + ldrsw x16, [x17, #0x18] + cmp x16, #0x0 + b.ge + ldr x9, [x17, #0x8] + add x9, x9, x16 + add x16, x16, #0x10 + str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt + mov x16, x9 + b + ldr x16, [x17] + add x9, x16, #0x10 + str x9, [x17] + ldr x9, [sp], #0x10 + mov x0, x16 + sub x1, x29, #0x30 + str x10, [sp, #-0x10]! + ldr x10, [x0] + str x10, [x1] + ldr x10, [x0, #0x8] + str x10, [x1, #0x8] + ldr x10, [sp], #0x10 + mov x0, x1 + sub x0, x29, #0x20 + sub x0, x29, #0x30 + ldr d0, [x0] + sub x0, x29, #0x30 + add x0, x0, #0x8 + ldr d1, [x0] + fadd d0, d0, d1 + ldr x19, [sp] + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0xc0 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x30 + sub x0, x29, #0x10 + mov x1, #0x3ff8000000000000 // =4609434218613702656 + fmov d16, x1 + str d16, [x0] + sub x0, x29, #0x10 + add x0, x0, #0x8 + mov x1, #0x4002000000000000 // =4612248968380809216 + fmov d16, x1 + str d16, [x0] + mov x0, #0x1 // =1 + sub x1, x29, #0x10 + ldr d0, [x1] + ldr d1, [x1, #0x8] + bl + mov x0, #0x400e000000000000 // =4615626668101337088 + fmov d17, x0 + fcmp d0, d17 + cset x0, eq + cbz x0, + mov x1, #0x0 // =0 + b + mov x1, #0x1 // =1 + mov x0, x1 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/variadic_hfa_struct_arg.x64.asm b/tests/snapshots/asm/variadic_hfa_struct_arg.x64.asm new file mode 100644 index 000000000..2aa76bfde --- /dev/null +++ b/tests/snapshots/asm/variadic_hfa_struct_arg.x64.asm @@ -0,0 +1,107 @@ + +variadic_hfa_struct_arg.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + pushq %rbp + movq %rsp, %rbp + subq $0xe0, %rsp + movq %rdi, -0xe0(%rbp) + movq %rsi, -0xd8(%rbp) + movq %rdx, -0xd0(%rbp) + movq %rcx, -0xc8(%rbp) + movq %r8, -0xc0(%rbp) + movq %r9, -0xb8(%rbp) + testb %al, %al + je + movsd %xmm0, -0xb0(%rbp,%riz) + movsd %xmm1, -0xa0(%rbp,%riz) + movsd %xmm2, -0x90(%rbp,%riz) + movsd %xmm3, -0x80(%rbp,%riz) + movsd %xmm4, -0x70(%rbp,%riz) + movsd %xmm5, -0x60(%rbp,%riz) + movsd %xmm6, -0x50(%rbp,%riz) + movsd %xmm7, -0x40(%rbp,%riz) + leaq -0x18(%rbp), %rax + leaq -0xe0(%rbp), %rcx + movl $0x8, (%rax) + movl $0x30, 0x4(%rax) + leaq 0x10(%rbp), %r10 + movq %r10, 0x8(%rax) + leaq -0xe0(%rbp), %r10 + movq %r10, 0x10(%rax) + leaq -0x18(%rbp), %rax + movq %rax, %r11 + movl (%r11), %r10d + cmpq $0x28, %r10 + jae + addq 0x10(%r11), %r10 + addl $0x10, (%r11) + jmp + movq 0x8(%r11), %r10 + addq $0x10, 0x8(%r11) + movq %r10, %rax + leaq -0x28(%rbp), %rcx + pushq %rdx + movq (%rax), %rdx + movq %rdx, (%rcx) + movq 0x8(%rax), %rdx + movq %rdx, 0x8(%rcx) + popq %rdx + movq %rcx, %rax + leaq -0x18(%rbp), %rax + leaq -0x28(%rbp), %rax + movsd (%rax,%riz), %xmm0 + leaq -0x28(%rbp), %rax + addq $0x8, %rax + movsd (%rax,%riz), %xmm1 + addsd %xmm1, %xmm0 + addq $0xe0, %rsp + popq %rbp + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x30, %rsp + leaq -0x10(%rbp), %rax + movabsq $0x3ff8000000000000, %rcx # imm = 0x3FF8000000000000 + movq %rcx, %xmm14 + movsd %xmm14, (%rax,%riz) + leaq -0x10(%rbp), %rax + addq $0x8, %rax + movabsq $0x4002000000000000, %rcx # imm = 0x4002000000000000 + movq %rcx, %xmm14 + movsd %xmm14, (%rax,%riz) + movl $0x1, %edi + leaq -0x10(%rbp), %rsi + movq %rsi, %r10 + movsd (%r10,%riz), %xmm0 + movsd 0x8(%r10,%riz), %xmm1 + movb $0x0, %al + callq + movabsq $0x400e000000000000, %rax # imm = 0x400E000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + sete %al + movzbq %al, %rax + setnp %r10b + movzbq %r10b, %r10 + andq %r10, %rax + testq %rax, %rax + je + xorq %rcx, %rcx + jmp + movl $0x1, %ecx + movq %rcx, %rax + addq $0x30, %rsp + popq %rbp + retq diff --git a/tests/snapshots/asm/variadic_libc_fnptr_static_init.aarch64.asm b/tests/snapshots/asm/variadic_libc_fnptr_static_init.aarch64.asm new file mode 100644 index 000000000..737edf560 --- /dev/null +++ b/tests/snapshots/asm/variadic_libc_fnptr_static_init.aarch64.asm @@ -0,0 +1,58 @@ + +variadic_libc_fnptr_static_init.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x2b0 // =688 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0xa0 + str x19, [sp] + sub x0, x29, #0x40 + mov x1, #0x0 // =0 + strb w1, [x0] + adrp x0, + add x0, x0, + ldr x0, [x0, #0x8] + sub x1, x29, #0x40 + mov x2, #0x40 // =64 + adrp x3, + add x3, x3, + mov x4, #0x2a // =42 + adrp x5, + add x5, x5, + mov x6, #0x63 // =99 + mov x9, x0 + mov x0, x1 + mov x1, x2 + mov x2, x3 + mov x3, x4 + mov x4, x5 + mov x5, x6 + blr x9 + sub x0, x29, #0x40 + adrp x1, + add x1, x1, + bl + sxtw x0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x1 // =1 + ldr x19, [sp] + add sp, sp, #0xa0 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldr x19, [sp] + add sp, sp, #0xa0 + ldp x29, x30, [sp], #0x10 + ret + +<__c5_sys_snprintf>: + b diff --git a/tests/snapshots/asm/variadic_libc_fnptr_static_init.x64.asm b/tests/snapshots/asm/variadic_libc_fnptr_static_init.x64.asm new file mode 100644 index 000000000..276d0c011 --- /dev/null +++ b/tests/snapshots/asm/variadic_libc_fnptr_static_init.x64.asm @@ -0,0 +1,52 @@ + +variadic_libc_fnptr_static_init.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x90, %rsp + leaq -0x40(%rbp), %rax + xorq %rcx, %rcx + movb %cl, (%rax) + leaq , %rax + movq 0x8(%rax), %rax + leaq -0x40(%rbp), %rdi + movl $0x40, %esi + leaq , %rdx + movl $0x2a, %ecx + leaq , %r8 + movl $0x63, %r9d + subq $0x10, %rsp + movq %rax, (%rsp) + movq (%rsp), %r10 + movb $0x0, %al + callq *%r10 + addq $0x10, %rsp + leaq -0x40(%rbp), %rdi + leaq , %rsi + xorl %eax, %eax + callq + movslq %eax, %rax + testq %rax, %rax + je + movl $0x1, %eax + addq $0x90, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x90, %rsp + popq %rbp + retq + +<__c5_sys_snprintf>: + jmp + addb %al, (%rax) diff --git a/tests/snapshots/asm/variadic_optimizer_survives.aarch64.asm b/tests/snapshots/asm/variadic_optimizer_survives.aarch64.asm index 7631c5ec5..e92d515c9 100644 --- a/tests/snapshots/asm/variadic_optimizer_survives.aarch64.asm +++ b/tests/snapshots/asm/variadic_optimizer_survives.aarch64.asm @@ -60,6 +60,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -78,6 +80,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/variadic_struct_arg.aarch64.asm b/tests/snapshots/asm/variadic_struct_arg.aarch64.asm index 71904e3d7..20d726a85 100644 --- a/tests/snapshots/asm/variadic_struct_arg.aarch64.asm +++ b/tests/snapshots/asm/variadic_struct_arg.aarch64.asm @@ -70,6 +70,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/variadic_struct_arg_16b.aarch64.asm b/tests/snapshots/asm/variadic_struct_arg_16b.aarch64.asm index 2263a2674..f12351cae 100644 --- a/tests/snapshots/asm/variadic_struct_arg_16b.aarch64.asm +++ b/tests/snapshots/asm/variadic_struct_arg_16b.aarch64.asm @@ -70,6 +70,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x10 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/variadic_struct_by_value_arg.aarch64.asm b/tests/snapshots/asm/variadic_struct_by_value_arg.aarch64.asm index 9fbc6eead..5f517247b 100644 --- a/tests/snapshots/asm/variadic_struct_by_value_arg.aarch64.asm +++ b/tests/snapshots/asm/variadic_struct_by_value_arg.aarch64.asm @@ -68,6 +68,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/variadic_struct_return.aarch64.asm b/tests/snapshots/asm/variadic_struct_return.aarch64.asm index ddf8c7c2e..149abb4d7 100644 --- a/tests/snapshots/asm/variadic_struct_return.aarch64.asm +++ b/tests/snapshots/asm/variadic_struct_return.aarch64.asm @@ -143,6 +143,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/variadic_union_struct_return.aarch64.asm b/tests/snapshots/asm/variadic_union_struct_return.aarch64.asm index 90b9acab4..e7c98fdca 100644 --- a/tests/snapshots/asm/variadic_union_struct_return.aarch64.asm +++ b/tests/snapshots/asm/variadic_union_struct_return.aarch64.asm @@ -60,6 +60,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -78,6 +80,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/asm/variadic_via_fnptr.aarch64.asm b/tests/snapshots/asm/variadic_via_fnptr.aarch64.asm index 00323c54a..b85a9317e 100644 --- a/tests/snapshots/asm/variadic_via_fnptr.aarch64.asm +++ b/tests/snapshots/asm/variadic_via_fnptr.aarch64.asm @@ -60,6 +60,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -78,6 +80,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] @@ -96,6 +100,8 @@ Disassembly of section .text: add x9, x9, x16 add x16, x16, #0x8 str w16, [x17, #0x18] + cmp x16, #0x0 + b.gt mov x16, x9 b ldr x16, [x17] diff --git a/tests/snapshots/ssa/atomic_operand_in_working_regs.ssa b/tests/snapshots/ssa/atomic_operand_in_working_regs.ssa new file mode 100644 index 000000000..e305ce019 --- /dev/null +++ b/tests/snapshots/ssa/atomic_operand_in_working_regs.ssa @@ -0,0 +1,160 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=f +fn ent_pc=0 n_params=8 variadic=false locals=3 + spill_count=0 gpr_used=[3, 12, 13] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 ParamRef(2, kind=I64) -> x2 + v6 Imm(0) -> x0 + v7 ParamRef(3, kind=I64) -> x1 + v8 Imm(0) -> x0 + v9 ParamRef(4, kind=I64) -> x8 + v10 Imm(0) -> x0 + v11 ParamRef(5, kind=I64) -> x9 + v12 Imm(0) -> x0 + v13 Imm(100) -> x0 + v14 StoreLocal { off=-1, value=v13, kind=I64 } -> - + v15 ImmData(8) -> x0 + v16 LocalAddr(-1) -> x3 + v17 Imm(5) -> x12 + v18 AtomicCas { addr=v15, expected_addr=v16, desired=v17, width=8 } -> x3 + v19 Imm(0) -> x12 + v20 LoadLocal { off=2, kind=I64 } -> x12 + v21 LoadLocal { off=3, kind=I64 } -> x12 + v22 Binop { op=add, lhs=v1, rhs=v3 } -> x12 + v23 AtomicRmw { op=Add, addr=v15, value=v22, width=8 } -> x12 + v24 Imm(0) -> x13 + v25 Extend { value=v18, kind=I32 } -> x3 + v26 BinopI { op=ne, lhs=v25, rhs_imm=0 } -> x3 + terminator Bz { cond=v26, target=b2, fall=b1 } (exit_acc=v26) + block 1 start_pc=0 + v27 Imm(1) -> x0 + terminator Return(v27) (exit_acc=v27) + block 2 start_pc=0 + v28 LoadLocal { off=-1, kind=I64 } -> x3 + v29 BinopI { op=ne, lhs=v28, rhs_imm=9 } -> x3 + terminator Bz { cond=v29, target=b4, fall=b3 } (exit_acc=v29) + block 3 start_pc=0 + v30 Imm(2) -> x0 + terminator Return(v30) (exit_acc=v30) + block 4 start_pc=0 + v31 LoadLocal { off=-3, kind=I64 } -> x3 + v32 BinopI { op=ne, lhs=v23, rhs_imm=9 } -> x3 + terminator Bz { cond=v32, target=b6, fall=b5 } (exit_acc=v32) + block 5 start_pc=0 + v33 Imm(3) -> x0 + terminator Return(v33) (exit_acc=v33) + block 6 start_pc=0 + v34 ImmData(8) -> x3 + v35 Load { addr=v15, disp=0, kind=I64 } -> x0 + v36 Imm(9) -> x3 + v37 LoadLocal { off=2, kind=I64 } -> x3 + v38 BinopI { op=add, lhs=v1, rhs_imm=9 } -> x3 + v39 LoadLocal { off=3, kind=I64 } -> x12 + v40 Binop { op=add, lhs=v38, rhs=v3 } -> x3 + v41 Binop { op=ne, lhs=v35, rhs=v40 } -> x0 + terminator Bz { cond=v41, target=b8, fall=b7 } (exit_acc=v41) + block 7 start_pc=0 + v42 Imm(4) -> x0 + terminator Return(v42) (exit_acc=v42) + block 8 start_pc=0 + v43 LoadLocal { off=2, kind=I64 } -> x0 + v44 LoadLocal { off=3, kind=I64 } -> x0 + v45 Binop { op=add, lhs=v1, rhs=v3 } -> x0 + v46 LoadLocal { off=4, kind=I64 } -> x6 + v47 Binop { op=add, lhs=v45, rhs=v5 } -> x0 + v48 LoadLocal { off=5, kind=I64 } -> x2 + v49 Binop { op=add, lhs=v47, rhs=v7 } -> x0 + v50 LoadLocal { off=6, kind=I64 } -> x1 + v51 Binop { op=add, lhs=v49, rhs=v9 } -> x0 + v52 LoadLocal { off=7, kind=I64 } -> x1 + v53 Binop { op=add, lhs=v51, rhs=v11 } -> x0 + v54 LoadLocal { off=8, kind=I64 } -> x1 + v55 Binop { op=add, lhs=v53, rhs=v54 } -> x0 + v56 LoadLocal { off=9, kind=I64 } -> x1 + v57 Binop { op=add, lhs=v55, rhs=v56 } -> x0 + terminator Return(v57) (exit_acc=v57) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=10 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(1) -> x7 + v2 Imm(2) -> x6 + v3 Imm(3) -> x2 + v4 Imm(4) -> x1 + v5 Imm(5) -> x8 + v6 Imm(6) -> x9 + v7 Imm(7) -> x0 + v8 Imm(8) -> x3 + v9 Call { target_pc=0, args=[v1, v2, v3, v4, v5, v6, v7, v8], fixed_args=8, fp_return=false, fp_arg_mask=0x0 } -> x0 + v10 Imm(0) -> x1 + v11 LoadLocal { off=-1, kind=I64 } -> x1 + v12 BinopI { op=eq, lhs=v9, rhs_imm=36 } -> x1 + terminator Bz { cond=v12, target=b2, fall=b1 } (exit_acc=v12) + block 1 start_pc=0 + v13 Imm(0) -> x1 + v14 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v13) + block 2 start_pc=0 + v15 LoadLocal { off=-1, kind=I64 } -> x1 + v16 BinopI { op=shl, lhs=v9, rhs_imm=32 } -> x1 + v17 Extend { value=v9, kind=I32 } -> x1 + v18 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v17) + block 3 start_pc=0 + v19 Phi { incoming=[b1:v13, b2:v17], kind=I64 } -> x1 + v20 LoadLocal { off=-10, kind=I64 } -> x0 + terminator Return(v19) (exit_acc=v19) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/block_scope_typedef_variadic_fnptr.ssa b/tests/snapshots/ssa/block_scope_typedef_variadic_fnptr.ssa new file mode 100644 index 000000000..958c2e6ae --- /dev/null +++ b/tests/snapshots/ssa/block_scope_typedef_variadic_fnptr.ssa @@ -0,0 +1,84 @@ +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=13 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-8) -> x0 + v2 Imm(0) -> x1 + v3 Store { addr=v1, disp=0, value=v2, kind=I8 } -> - + v4 LocalAddr(-8) -> x7 + v5 Imm(64) -> x6 + v6 ImmData(64) -> x2 + v7 Imm(7) -> x1 + v8 ImmData(70) -> x8 + v9 ImmData(56) -> x0 + v10 Load { addr=v9, disp=0, kind=I64 } -> x0 + v11 CallIndirect { target=v10, args=[v4, v5, v6, v7, v8], callee_variadic=true, fixed_args=3, fp_return=false, fp_arg_mask=0x0 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 LocalAddr(-8) -> x7 + v15 ImmData(75) -> x6 + v16 CallExt { binding_idx=62, args=[v14, v15], fp_arg_mask=0x0 } -> x0 + v17 BinopI { op=ne, lhs=v16, rhs_imm=0 } -> x0 + terminator Bz { cond=v17, target=b2, fall=b1 } (exit_acc=v17) + block 1 start_pc=0 + v18 Imm(1) -> x0 + terminator Return(v18) (exit_acc=v18) + block 2 start_pc=0 + v19 Imm(0) -> x0 + terminator Return(v19) (exit_acc=v19) +; --- SSA dump (ok=true) ent_pc=2 --- +; name=__c5_sys_snprintf +fn ent_pc=2 n_params=0 variadic=false locals=0 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + terminator TailExt(3) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/data_reloc_one_past_end.ssa b/tests/snapshots/ssa/data_reloc_one_past_end.ssa new file mode 100644 index 000000000..d78ef6ed1 --- /dev/null +++ b/tests/snapshots/ssa/data_reloc_one_past_end.ssa @@ -0,0 +1,87 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=2 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(0) -> x2 + v2 Imm(0) -> x0 + v3 ImmData(8) -> x1 + v4 Imm(0) -> x0 + terminator Jmp(b1) (exit_acc=v3) + block 1 start_pc=0 + v5 Phi { incoming=[b0:v3, b2:v16], kind=I64 } -> x1 + v6 Phi { incoming=[b0:v1, b2:v14], kind=I64 } -> x2 + v7 LoadLocal { off=-2, kind=I64 } -> x0 + v8 ImmData(40) -> x0 + v9 Load { addr=v8, disp=0, kind=I64 } -> x0 + v10 Binop { op=ne, lhs=v5, rhs=v9 } -> x0 + terminator Bz { cond=v10, target=b3, fall=b2 } (exit_acc=v10) + block 2 start_pc=0 + v11 LoadLocal { off=-1, kind=I64 } -> x0 + v12 LoadLocal { off=-2, kind=I64 } -> x0 + v13 Load { addr=v5, disp=0, kind=I64 } -> x0 + v14 Binop { op=add, lhs=v6, rhs=v13 } -> x2 + v15 Imm(0) -> x0 + v16 BinopI { op=add, lhs=v5, rhs_imm=8 } -> x1 + v17 Imm(0) -> x0 + terminator Jmp(b1) (exit_acc=v16) + block 3 start_pc=0 + v18 LoadLocal { off=-1, kind=I64 } -> x0 + v19 ImmData(56) -> x0 + v20 Imm(24) -> x1 + v21 BinopI { op=add, lhs=v19, rhs_imm=24 } -> x1 + v22 Load { addr=v19, disp=24, kind=I64 } -> x0 + v23 Binop { op=add, lhs=v6, rhs=v22 } -> x0 + v24 Imm(0) -> x1 + v25 LoadLocal { off=-1, kind=I64 } -> x1 + v26 BinopI { op=shl, lhs=v23, rhs_imm=32 } -> x1 + v27 Extend { value=v23, kind=I32 } -> x0 + terminator Return(v27) (exit_acc=v27) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/inline_multi_block_result_forward.ssa b/tests/snapshots/ssa/inline_multi_block_result_forward.ssa new file mode 100644 index 000000000..7556898d7 --- /dev/null +++ b/tests/snapshots/ssa/inline_multi_block_result_forward.ssa @@ -0,0 +1,128 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=helper_one +fn ent_pc=0 n_params=1 variadic=false locals=0 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 Binop { op=add, lhs=v1, rhs=v1 } -> x0 + v5 BinopI { op=shl, lhs=v4, rhs_imm=32 } -> x1 + v6 Extend { value=v4, kind=I32 } -> x0 + terminator Return(v6) (exit_acc=v6) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=helper_two +fn ent_pc=1 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + terminator Jmp(b1) (exit_acc=v1) + block 1 start_pc=0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 BinopI { op=shl, lhs=v1, rhs_imm=1 } -> x0 + v5 BinopI { op=shl, lhs=v4, rhs_imm=32 } -> x1 + v6 Extend { value=v4, kind=I32 } -> x0 + v7 Imm(0) -> x1 + v8 LoadLocal { off=-1, kind=I32 } -> x1 + terminator Return(v6) (exit_acc=v6) +; --- SSA dump (ok=true) ent_pc=2 --- +; name=test +fn ent_pc=2 n_params=1 variadic=false locals=3 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + terminator Jmp(b4) + block 1 start_pc=0 + v16 Imm(0) -> x0 + v17 LoadLocal { off=2, kind=I32 } -> x0 + v18 Extend { value=v1, kind=I32 } -> x0 + v19 Imm(0) -> x0 + v20 Binop { op=add, lhs=v1, rhs=v1 } -> x2 + v21 BinopI { op=shl, lhs=v20, rhs_imm=32 } -> x0 + v22 Extend { value=v20, kind=I32 } -> x6 + v23 Imm(0) -> x0 + v24 LoadLocal { off=2, kind=I32 } -> x0 + v25 BinopI { op=gt, lhs=v1, rhs_imm=3 } -> x0 + terminator Bz { cond=v25, target=b3, fall=b2 } (exit_acc=v25) + block 2 start_pc=0 + v4 Extend { value=v14, kind=I32 } -> x0 + terminator Return(v4) (exit_acc=v4) + block 3 start_pc=0 + v5 Extend { value=v14, kind=I32 } -> x0 + v6 Extend { value=v22, kind=I32 } -> x0 + v7 Binop { op=add, lhs=v14, rhs=v20 } -> x0 + v8 BinopI { op=shl, lhs=v7, rhs_imm=32 } -> x1 + v9 Extend { value=v7, kind=I32 } -> x0 + terminator Return(v9) (exit_acc=v9) + block 4 start_pc=0 + v10 Extend { value=v1, kind=I32 } -> x0 + v11 Imm(0) -> x1 + terminator Jmp(b5) (exit_acc=v10) + block 5 start_pc=0 + v12 BinopI { op=shl, lhs=v10, rhs_imm=1 } -> x0 + v13 BinopI { op=shl, lhs=v12, rhs_imm=32 } -> x1 + v14 Extend { value=v12, kind=I32 } -> x1 + v15 Imm(0) -> x0 + terminator Jmp(b1) (exit_acc=v14) +; --- SSA dump (ok=true) ent_pc=3 --- +; name=main +fn ent_pc=3 n_params=0 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(5) -> x7 + v2 Call { target_pc=2, args=[v1], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v2) (exit_acc=v2) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/mixed_sse_int_aggregate_args.ssa b/tests/snapshots/ssa/mixed_sse_int_aggregate_args.ssa new file mode 100644 index 000000000..04d4ed255 --- /dev/null +++ b/tests/snapshots/ssa/mixed_sse_int_aggregate_args.ssa @@ -0,0 +1,201 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=take3 +fn ent_pc=0 n_params=5 variadic=false locals=9 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(1, kind=I64) -> x6 + v2 Imm(0) -> x0 + v3 ParamRef(3, kind=F64) -> d0 + v4 Imm(0) -> x0 + v5 LocalAddr(-2) -> x0 + v6 Load { addr=v5, disp=0, kind=F64 } -> d1 + v7 Imm(4612811918334230528) -> x0 + v8 Binop { op=fne, lhs=v6, rhs=v7 } -> x1 + v9 Imm(0) -> x0 + terminator Bnz { cond=v8, target=b17, fall=b1 } (exit_acc=v8) + block 1 start_pc=0 + v10 LocalAddr(-2) -> x0 + v11 BinopI { op=add, lhs=v10, rhs_imm=8 } -> x1 + v12 Load { addr=v10, disp=8, kind=I64 } -> x0 + v13 BinopI { op=ne, lhs=v12, rhs_imm=7 } -> x1 + v14 Imm(0) -> x0 + terminator Jmp(b2) (exit_acc=v13) + block 2 start_pc=0 + v15 Phi { incoming=[b17:v8, b1:v13], kind=I64 } -> x1 + v16 LoadLocal { off=-7, kind=I64 } -> x0 + terminator Bz { cond=v15, target=b4, fall=b3 } (exit_acc=v15) + block 3 start_pc=0 + v17 Imm(1) -> x0 + terminator Return(v17) (exit_acc=v17) + block 4 start_pc=0 + v18 LoadLocal { off=3, kind=I64 } -> x0 + v19 BinopI { op=ne, lhs=v1, rhs_imm=4 } -> x0 + terminator Bz { cond=v19, target=b6, fall=b5 } (exit_acc=v19) + block 5 start_pc=0 + v20 Imm(2) -> x0 + terminator Return(v20) (exit_acc=v20) + block 6 start_pc=0 + v21 LocalAddr(-4) -> x0 + v22 Load { addr=v21, disp=0, kind=I64 } -> x0 + v23 BinopI { op=ne, lhs=v22, rhs_imm=11 } -> x1 + v24 Imm(0) -> x0 + terminator Bnz { cond=v23, target=b18, fall=b7 } (exit_acc=v23) + block 7 start_pc=0 + v25 LocalAddr(-4) -> x0 + v26 BinopI { op=add, lhs=v25, rhs_imm=8 } -> x0 + v27 Load { addr=v26, disp=0, kind=F64 } -> d1 + v28 Imm(4602678819172646912) -> x0 + v29 Binop { op=fne, lhs=v27, rhs=v28 } -> x1 + v30 Imm(0) -> x0 + terminator Jmp(b8) (exit_acc=v29) + block 8 start_pc=0 + v31 Phi { incoming=[b18:v23, b7:v29], kind=I64 } -> x1 + v32 LoadLocal { off=-8, kind=I64 } -> x0 + terminator Bz { cond=v31, target=b10, fall=b9 } (exit_acc=v31) + block 9 start_pc=0 + v33 Imm(3) -> x0 + terminator Return(v33) (exit_acc=v33) + block 10 start_pc=0 + v34 LoadLocal { off=5, kind=F64 } -> d1 + v35 Imm(4608308318706860032) -> x0 + v36 Binop { op=fne, lhs=v3, rhs=v35 } -> x0 + terminator Bz { cond=v36, target=b12, fall=b11 } (exit_acc=v36) + block 11 start_pc=0 + v37 Imm(4) -> x0 + terminator Return(v37) (exit_acc=v37) + block 12 start_pc=0 + v38 LocalAddr(-6) -> x0 + v39 Load { addr=v38, disp=0, kind=F64 } -> d0 + v40 Imm(4615063718147915776) -> x0 + v41 Binop { op=fne, lhs=v39, rhs=v40 } -> x1 + v42 Imm(0) -> x0 + terminator Bnz { cond=v41, target=b19, fall=b13 } (exit_acc=v41) + block 13 start_pc=0 + v43 LocalAddr(-6) -> x0 + v44 BinopI { op=add, lhs=v43, rhs_imm=8 } -> x0 + v45 Load { addr=v44, disp=0, kind=F64 } -> d0 + v46 Imm(4616752568008179712) -> x0 + v47 Binop { op=fne, lhs=v45, rhs=v46 } -> x1 + v48 Imm(0) -> x0 + terminator Jmp(b14) (exit_acc=v47) + block 14 start_pc=0 + v49 Phi { incoming=[b19:v41, b13:v47], kind=I64 } -> x1 + v50 LoadLocal { off=-9, kind=I64 } -> x0 + terminator Bz { cond=v49, target=b16, fall=b15 } (exit_acc=v49) + block 15 start_pc=0 + v51 Imm(5) -> x0 + terminator Return(v51) (exit_acc=v51) + block 16 start_pc=0 + v52 Imm(0) -> x0 + terminator Return(v52) (exit_acc=v52) + block 17 start_pc=0 + terminator Jmp(b2) + block 18 start_pc=0 + terminator Jmp(b8) + block 19 start_pc=0 + terminator Jmp(b14) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=docall +fn ent_pc=1 n_params=5 variadic=false locals=5 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 ParamRef(2, kind=I64) -> x2 + v6 Imm(0) -> x0 + v7 ParamRef(3, kind=I64) -> x1 + v8 Imm(0) -> x0 + v9 ParamRef(4, kind=F64) -> d0 + v10 Imm(0) -> x0 + v11 LoadLocal { off=3, kind=I64 } -> x0 + v12 LoadLocal { off=2, kind=I64 } -> x0 + v13 LoadLocal { off=4, kind=I64 } -> x0 + v14 LoadLocal { off=6, kind=F64 } -> d1 + v15 LoadLocal { off=5, kind=I64 } -> x0 + v16 Call { target_pc=0, args=[v3, v1, v5, v9, v7], fixed_args=5, fp_return=false, fp_arg_mask=0x8 } -> x0 + terminator Return(v16) (exit_acc=v16) +; --- SSA dump (ok=true) ent_pc=2 --- +; name=main +fn ent_pc=2 n_params=0 variadic=false locals=11 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-2) -> x0 + v2 Imm(4612811918334230528) -> x1 + v3 Store { addr=v1, disp=0, value=v2, kind=F64 } -> - + v4 LocalAddr(-2) -> x0 + v5 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x1 + v6 Imm(7) -> x1 + v7 Store { addr=v4, disp=8, value=v6, kind=I64 } -> - + v8 LocalAddr(-4) -> x0 + v9 Imm(11) -> x1 + v10 Store { addr=v8, disp=0, value=v9, kind=I64 } -> - + v11 LocalAddr(-4) -> x0 + v12 BinopI { op=add, lhs=v11, rhs_imm=8 } -> x0 + v13 Imm(4602678819172646912) -> x1 + v14 Store { addr=v12, disp=0, value=v13, kind=F64 } -> - + v15 LocalAddr(-6) -> x0 + v16 Imm(4615063718147915776) -> x1 + v17 Store { addr=v15, disp=0, value=v16, kind=F64 } -> - + v18 LocalAddr(-6) -> x0 + v19 BinopI { op=add, lhs=v18, rhs_imm=8 } -> x0 + v20 Imm(4616752568008179712) -> x1 + v21 Store { addr=v19, disp=0, value=v20, kind=F64 } -> - + v22 Imm(4) -> x7 + v23 LocalAddr(-2) -> x6 + v24 LocalAddr(-4) -> x2 + v25 LocalAddr(-6) -> x1 + v26 Imm(4608308318706860032) -> x8 + v27 Call { target_pc=1, args=[v22, v23, v24, v25, v26], fixed_args=5, fp_return=false, fp_arg_mask=0x10 } -> x0 + terminator Return(v27) (exit_acc=v27) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/setjmp_value_live_across.ssa b/tests/snapshots/ssa/setjmp_value_live_across.ssa new file mode 100644 index 000000000..9b18b1ed5 --- /dev/null +++ b/tests/snapshots/ssa/setjmp_value_live_across.ssa @@ -0,0 +1,110 @@ +; --- SSA dump (ok=true) ent_pc=5 --- +; name=h +fn ent_pc=5 n_params=0 variadic=false locals=2 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ImmData(24) -> x7 + v2 Imm(1) -> x6 + v3 CallExt { binding_idx=1, args=[v1, v2], fp_arg_mask=0x0 } -> x0 + v4 Imm(0) -> x0 + terminator Return(v4) (exit_acc=v4) +; --- SSA dump (ok=true) ent_pc=6 --- +; name=test +fn ent_pc=6 n_params=2 variadic=false locals=2 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I32) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=2, kind=I32 } -> x0 + v6 BinopI { op=mul, lhs=v1, rhs_imm=7 } -> x0 + v7 BinopI { op=shl, lhs=v6, rhs_imm=32 } -> x1 + v8 Extend { value=v6, kind=I32 } -> x1 + v9 LoadLocal { off=3, kind=I32 } -> x1 + v10 Binop { op=add, lhs=v6, rhs=v3 } -> x0 + v11 BinopI { op=shl, lhs=v10, rhs_imm=32 } -> x1 + v12 Extend { value=v10, kind=I32 } -> x3 + v13 Imm(0) -> x0 + v14 ImmData(24) -> x7 + v15 CallExt { binding_idx=0, args=[v14], fp_arg_mask=0x0 } -> x0 + terminator Bz { cond=v15, target=b2, fall=b1 } (exit_acc=v15) + block 1 start_pc=0 + v16 LoadLocal { off=-1, kind=I32 } -> x0 + terminator Return(v12) (exit_acc=v12) + block 2 start_pc=0 + v17 Call { target_pc=5, args=[], fixed_args=0, fp_return=false, fp_arg_mask=0x0 } -> x0 + v18 Imm(0) -> x0 + terminator Return(v18) (exit_acc=v18) +; --- SSA dump (ok=true) ent_pc=7 --- +; name=main +fn ent_pc=7 n_params=0 variadic=false locals=3 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(5) -> x7 + v2 Imm(7) -> x6 + v3 Call { target_pc=6, args=[v1, v2], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x0 + v4 BinopI { op=eq, lhs=v3, rhs_imm=42 } -> x0 + terminator Bz { cond=v4, target=b2, fall=b1 } (exit_acc=v4) + block 1 start_pc=0 + v5 Imm(0) -> x1 + v6 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v5) + block 2 start_pc=0 + v7 Imm(1) -> x1 + v8 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v7) + block 3 start_pc=0 + v9 Phi { incoming=[b1:v5, b2:v7], kind=I64 } -> x1 + v10 LoadLocal { off=-3, kind=I64 } -> x0 + terminator Return(v9) (exit_acc=v9) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/sqlite_min.ssa b/tests/snapshots/ssa/sqlite_min.ssa index 01acd8999..12870b06f 100644 --- a/tests/snapshots/ssa/sqlite_min.ssa +++ b/tests/snapshots/ssa/sqlite_min.ssa @@ -90,15 +90,11 @@ fn ent_pc=5 n_params=0 variadic=false locals=28 terminator Return(v66) (exit_acc=v66) ; --- SSA dump (ok=true) ent_pc=6 --- ; name=__c5_sys_open -fn ent_pc=6 n_params=3 variadic=false locals=0 +fn ent_pc=6 n_params=0 variadic=false locals=0 spill_count=0 gpr_used=[] fp_used=[] block 0 start_pc=0 v0 AllocaInit(0) -> - - v1 LoadLocal { off=2, kind=I64 } -> x7 - v2 LoadLocal { off=3, kind=I64 } -> x6 - v3 LoadLocal { off=4, kind=I64 } -> x2 - v4 CallExt { binding_idx=61, args=[v1, v2, v3], fp_arg_mask=0x0 } -> x0 - terminator Return(v4) (exit_acc=v4) + terminator TailExt(61) ; --- SSA dump (ok=true) ent_pc=7 --- ; name=__c5_sys_close fn ent_pc=7 n_params=1 variadic=false locals=0 diff --git a/tests/snapshots/ssa/sxtw_fold_source_liveness.ssa b/tests/snapshots/ssa/sxtw_fold_source_liveness.ssa new file mode 100644 index 000000000..cd0fb70af --- /dev/null +++ b/tests/snapshots/ssa/sxtw_fold_source_liveness.ssa @@ -0,0 +1,92 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=f +fn ent_pc=0 n_params=2 variadic=false locals=3 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=2, kind=I64 } -> x0 + v6 BinopI { op=shl, lhs=v1, rhs_imm=32 } -> x0 + v7 Imm(0) -> x1 + v8 LoadLocal { off=3, kind=I64 } -> x1 + v9 Binop { op=add, lhs=v1, rhs=v3 } -> x1 + v10 Imm(0) -> x2 + v11 LoadLocal { off=-1, kind=I64 } -> x2 + v12 BinopI { op=shr, lhs=v6, rhs_imm=32 } -> x0 + v13 Imm(0) -> x2 + v14 LoadLocal { off=-3, kind=I64 } -> x2 + v15 LoadLocal { off=-2, kind=I64 } -> x2 + v16 Binop { op=add, lhs=v12, rhs=v9 } -> x0 + v17 Binop { op=add, lhs=v16, rhs=v3 } -> x0 + terminator Return(v17) (exit_acc=v17) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=2 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(2) -> x0 + v2 Imm(7) -> x1 + v3 Imm(0) -> x2 + v4 Imm(0) -> x2 + v5 BinopI { op=shl, lhs=v1, rhs_imm=32 } -> x2 + v6 Imm(0) -> x6 + v7 Binop { op=add, lhs=v1, rhs=v2 } -> x0 + v8 Imm(0) -> x6 + v9 BinopI { op=shr, lhs=v5, rhs_imm=32 } -> x2 + v10 Imm(0) -> x6 + v11 Binop { op=add, lhs=v9, rhs=v7 } -> x0 + v12 Binop { op=add, lhs=v11, rhs=v2 } -> x0 + v13 BinopI { op=shl, lhs=v12, rhs_imm=32 } -> x1 + v14 Extend { value=v12, kind=I32 } -> x0 + terminator Return(v14) (exit_acc=v14) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/sys_addr_in_static_init.ssa b/tests/snapshots/ssa/sys_addr_in_static_init.ssa index 6915b04f8..90b7ec4a3 100644 --- a/tests/snapshots/ssa/sys_addr_in_static_init.ssa +++ b/tests/snapshots/ssa/sys_addr_in_static_init.ssa @@ -67,15 +67,11 @@ fn ent_pc=6 n_params=0 variadic=false locals=16 terminator Return(v48) (exit_acc=v48) ; --- SSA dump (ok=true) ent_pc=7 --- ; name=__c5_sys_open -fn ent_pc=7 n_params=3 variadic=false locals=0 +fn ent_pc=7 n_params=0 variadic=false locals=0 spill_count=0 gpr_used=[] fp_used=[] block 0 start_pc=0 v0 AllocaInit(0) -> - - v1 LoadLocal { off=2, kind=I64 } -> x7 - v2 LoadLocal { off=3, kind=I64 } -> x6 - v3 LoadLocal { off=4, kind=I64 } -> x2 - v4 CallExt { binding_idx=61, args=[v1, v2, v3], fp_arg_mask=0x0 } -> x0 - terminator Return(v4) (exit_acc=v4) + terminator TailExt(61) ; --- SSA dump (ok=true) ent_pc=8 --- ; name=__c5_sys_read fn ent_pc=8 n_params=3 variadic=false locals=0 diff --git a/tests/snapshots/ssa/va_arg_composite_straddle.ssa b/tests/snapshots/ssa/va_arg_composite_straddle.ssa new file mode 100644 index 000000000..117f77129 --- /dev/null +++ b/tests/snapshots/ssa/va_arg_composite_straddle.ssa @@ -0,0 +1,146 @@ +; --- SSA dump (ok=true) ent_pc=1 --- +; name=take +fn ent_pc=1 n_params=1 variadic=true locals=8 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-3) -> x0 + v2 LocalAddr(2) -> x1 + v3 Intrinsic { kind=4, args=[v1, v2] } -> x0 + v4 Imm(0) -> x1 + v5 Imm(0) -> x0 + terminator Jmp(b1) (exit_acc=v4) + block 1 start_pc=0 + v6 Phi { incoming=[b0:v4, b2:v10], kind=I64 } -> x1 + v7 Extend { value=v6, kind=I32 } -> x0 + v8 BinopI { op=lt, lhs=v7, rhs_imm=6 } -> x0 + terminator Bz { cond=v8, target=b4, fall=b3 } (exit_acc=v8) + block 2 start_pc=0 + v9 Extend { value=v6, kind=I32 } -> x0 + v10 BinopI { op=add, lhs=v9, rhs_imm=1 } -> x1 + v11 Imm(0) -> x0 + terminator Jmp(b1) (exit_acc=v10) + block 3 start_pc=0 + v12 LocalAddr(-3) -> x0 + v13 Imm(8) -> x2 + v14 Intrinsic { kind=5, args=[v12, v13] } -> x0 + v15 Load { addr=v14, disp=0, kind=I64 } -> x0 + v16 BinopI { op=and, lhs=v15, rhs_imm=255 } -> x0 + terminator Jmp(b2) (exit_acc=v16) + block 4 start_pc=0 + v17 LocalAddr(-3) -> x0 + v18 Imm(16) -> x1 + v19 Intrinsic { kind=5, args=[v17, v18] } -> x0 + v20 LocalAddr(-6) -> x1 + v21 Mcpy { dst=v20, src=v19, size=16 } -> x0 + v22 LocalAddr(-3) -> x0 + v23 Imm(8) -> x1 + v24 Intrinsic { kind=5, args=[v22, v23] } -> x0 + v25 Load { addr=v24, disp=0, kind=I64 } -> x0 + v26 Imm(0) -> x1 + v27 LocalAddr(-3) -> x1 + v28 Intrinsic { kind=6, args=[v27] } -> x1 + v29 LocalAddr(-6) -> x1 + v30 Load { addr=v29, disp=0, kind=I64 } -> x1 + v31 BinopI { op=ne, lhs=v30, rhs_imm=111 } -> x2 + v32 Imm(0) -> x1 + terminator Bnz { cond=v31, target=b11, fall=b5 } (exit_acc=v31) + block 5 start_pc=0 + v33 LocalAddr(-6) -> x1 + v34 BinopI { op=add, lhs=v33, rhs_imm=8 } -> x2 + v35 Load { addr=v33, disp=8, kind=I64 } -> x1 + v36 BinopI { op=ne, lhs=v35, rhs_imm=222 } -> x2 + v37 Imm(0) -> x1 + terminator Jmp(b6) (exit_acc=v36) + block 6 start_pc=0 + v38 Phi { incoming=[b11:v31, b5:v36], kind=I64 } -> x2 + v39 LoadLocal { off=-8, kind=I64 } -> x1 + terminator Bz { cond=v38, target=b8, fall=b7 } (exit_acc=v38) + block 7 start_pc=0 + v40 Imm(1) -> x0 + terminator Return(v40) (exit_acc=v40) + block 8 start_pc=0 + v41 LoadLocal { off=-7, kind=I64 } -> x1 + v42 BinopI { op=ne, lhs=v25, rhs_imm=777 } -> x0 + terminator Bz { cond=v42, target=b10, fall=b9 } (exit_acc=v42) + block 9 start_pc=0 + v43 Imm(2) -> x0 + terminator Return(v43) (exit_acc=v43) + block 10 start_pc=0 + v44 Imm(0) -> x0 + terminator Return(v44) (exit_acc=v44) + block 11 start_pc=0 + terminator Jmp(b6) +; --- SSA dump (ok=true) ent_pc=2 --- +; name=main +fn ent_pc=2 n_params=0 variadic=false locals=11 + spill_count=0 gpr_used=[3, 12] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-2) -> x0 + v2 Imm(111) -> x1 + v3 Store { addr=v1, disp=0, value=v2, kind=I64 } -> - + v4 LocalAddr(-2) -> x0 + v5 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x1 + v6 Imm(222) -> x1 + v7 Store { addr=v4, disp=8, value=v6, kind=I64 } -> - + v8 Imm(1) -> x7 + v9 Imm(2) -> x6 + v10 Imm(3) -> x2 + v11 Imm(4) -> x1 + v12 Imm(5) -> x8 + v13 Imm(6) -> x9 + v14 Imm(7) -> x0 + v15 LocalAddr(-2) -> x3 + v16 Imm(777) -> x12 + v17 Call { target_pc=1, args=[v8, v9, v10, v11, v12, v13, v14, v15, v16], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + v18 BinopI { op=shl, lhs=v17, rhs_imm=32 } -> x1 + v19 Extend { value=v17, kind=I32 } -> x0 + terminator Return(v19) (exit_acc=v19) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/va_copy_under_pressure.ssa b/tests/snapshots/ssa/va_copy_under_pressure.ssa new file mode 100644 index 000000000..0e05542da --- /dev/null +++ b/tests/snapshots/ssa/va_copy_under_pressure.ssa @@ -0,0 +1,189 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=f +fn ent_pc=0 n_params=1 variadic=true locals=22 + spill_count=5 gpr_used=[3, 12, 13, 14, 15] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LoadLocal { off=2, kind=I64 } -> x0 + v2 BinopI { op=mul, lhs=v1, rhs_imm=3 } -> x1 + v3 Imm(0) -> x2 + v4 BinopI { op=add, lhs=v1, rhs_imm=11 } -> x2 + v5 Imm(0) -> x6 + v6 BinopI { op=mul, lhs=v1, rhs_imm=7 } -> x6 + v7 Imm(0) -> x7 + v8 BinopI { op=sub, lhs=v1, rhs_imm=2 } -> x7 + v9 Imm(0) -> x8 + v10 BinopI { op=mul, lhs=v1, rhs_imm=13 } -> x8 + v11 Imm(0) -> x9 + v12 BinopI { op=add, lhs=v1, rhs_imm=29 } -> x9 + v13 Imm(0) -> x3 + v14 BinopI { op=shl, lhs=v1, rhs_imm=2 } -> x3 + v15 Imm(0) -> x12 + v16 BinopI { op=add, lhs=v1, rhs_imm=41 } -> x12 + v17 Imm(0) -> x13 + v18 BinopI { op=mul, lhs=v1, rhs_imm=9 } -> x13 + v19 Imm(0) -> x14 + v20 BinopI { op=add, lhs=v1, rhs_imm=53 } -> x14 + v21 Imm(0) -> x15 + v22 BinopI { op=mul, lhs=v1, rhs_imm=5 } -> x15 + v23 Imm(0) -> [spill 0] + v24 BinopI { op=add, lhs=v1, rhs_imm=61 } -> [spill 0] + v25 Imm(0) -> [spill 1] + v26 BinopI { op=mul, lhs=v1, rhs_imm=15 } -> [spill 1] + v27 Imm(0) -> [spill 2] + v28 BinopI { op=add, lhs=v1, rhs_imm=3 } -> x0 + v29 Imm(0) -> [spill 2] + v30 LocalAddr(-3) -> [spill 2] + v31 LocalAddr(2) -> [spill 3] + v32 Intrinsic { kind=4, args=[v30, v31] } -> [spill 2] + v33 LocalAddr(-6) -> [spill 2] + v34 LocalAddr(-3) -> [spill 3] + v35 Intrinsic { kind=7, args=[v33, v34] } -> [spill 2] + v36 LocalAddr(-6) -> [spill 2] + v37 Imm(8) -> [spill 3] + v38 Intrinsic { kind=5, args=[v36, v37] } -> [spill 2] + v39 Load { addr=v38, disp=0, kind=I64 } -> [spill 2] + v40 Imm(0) -> [spill 3] + v41 LocalAddr(-6) -> [spill 3] + v42 Intrinsic { kind=5, args=[v41, v37] } -> [spill 3] + v43 Load { addr=v42, disp=0, kind=I64 } -> [spill 3] + v44 Imm(0) -> [spill 4] + v45 LocalAddr(-6) -> [spill 4] + v46 Intrinsic { kind=6, args=[v45] } -> [spill 4] + v47 LocalAddr(-3) -> [spill 4] + v48 Intrinsic { kind=6, args=[v47] } -> [spill 4] + v49 LoadLocal { off=-7, kind=I64 } -> [spill 4] + v50 LoadLocal { off=-8, kind=I64 } -> [spill 4] + v51 Binop { op=add, lhs=v2, rhs=v4 } -> x1 + v52 LoadLocal { off=-9, kind=I64 } -> x2 + v53 Binop { op=add, lhs=v51, rhs=v6 } -> x1 + v54 LoadLocal { off=-10, kind=I64 } -> x2 + v55 Binop { op=add, lhs=v53, rhs=v8 } -> x1 + v56 LoadLocal { off=-11, kind=I64 } -> x2 + v57 Binop { op=add, lhs=v55, rhs=v10 } -> x1 + v58 LoadLocal { off=-12, kind=I64 } -> x2 + v59 Binop { op=add, lhs=v57, rhs=v12 } -> x1 + v60 LoadLocal { off=-13, kind=I64 } -> x2 + v61 Binop { op=add, lhs=v59, rhs=v14 } -> x1 + v62 LoadLocal { off=-14, kind=I64 } -> x2 + v63 Binop { op=add, lhs=v61, rhs=v16 } -> x1 + v64 LoadLocal { off=-15, kind=I64 } -> x2 + v65 Binop { op=add, lhs=v63, rhs=v18 } -> x1 + v66 LoadLocal { off=-16, kind=I64 } -> x2 + v67 Binop { op=add, lhs=v65, rhs=v20 } -> x1 + v68 LoadLocal { off=-17, kind=I64 } -> x2 + v69 Binop { op=add, lhs=v67, rhs=v22 } -> x1 + v70 LoadLocal { off=-18, kind=I64 } -> x2 + v71 Binop { op=add, lhs=v69, rhs=v24 } -> x1 + v72 LoadLocal { off=-19, kind=I64 } -> x2 + v73 Binop { op=add, lhs=v71, rhs=v26 } -> x1 + v74 LoadLocal { off=-20, kind=I64 } -> x2 + v75 Binop { op=add, lhs=v73, rhs=v28 } -> x0 + v76 LoadLocal { off=-21, kind=I64 } -> x1 + v77 Binop { op=add, lhs=v75, rhs=v39 } -> x0 + v78 LoadLocal { off=-22, kind=I64 } -> x1 + v79 Binop { op=add, lhs=v77, rhs=v43 } -> x0 + terminator Return(v79) (exit_acc=v79) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=5 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(2) -> x7 + v2 Imm(10) -> x6 + v3 Imm(20) -> x2 + v4 Call { target_pc=0, args=[v1, v2, v3], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x1 + v6 Imm(19) -> x1 + v7 Imm(81604378624) -> x1 + v8 Imm(33) -> x1 + v9 Imm(141733920768) -> x1 + v10 Imm(59) -> x1 + v11 Imm(253403070464) -> x1 + v12 Imm(90) -> x1 + v13 Imm(386547056640) -> x1 + v14 Imm(98) -> x1 + v15 Imm(420906795008) -> x1 + v16 Imm(141) -> x1 + v17 Imm(605590388736) -> x1 + v18 Imm(159) -> x1 + v19 Imm(682899800064) -> x1 + v20 Imm(214) -> x1 + v21 Imm(919123001344) -> x1 + v22 Imm(224) -> x1 + v23 Imm(962072674304) -> x1 + v24 Imm(287) -> x1 + v25 Imm(1232655613952) -> x1 + v26 Imm(317) -> x1 + v27 Imm(1361504632832) -> x1 + v28 Imm(322) -> x1 + v29 Imm(1382979469312) -> x1 + v30 Imm(332) -> x1 + v31 Imm(1425929142272) -> x1 + v32 Imm(352) -> x1 + v33 Imm(1511828488192) -> x2 + v34 Imm(0) -> x2 + v35 LoadLocal { off=-1, kind=I64 } -> x2 + v36 LoadLocal { off=-2, kind=I64 } -> x2 + v37 Binop { op=eq, lhs=v4, rhs=v32 } -> x0 + terminator Bz { cond=v37, target=b2, fall=b1 } (exit_acc=v37) + block 1 start_pc=0 + v38 Imm(0) -> x1 + v39 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v38) + block 2 start_pc=0 + v40 Imm(1) -> x1 + v41 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v40) + block 3 start_pc=0 + v42 Phi { incoming=[b1:v38, b2:v40], kind=I64 } -> x1 + v43 LoadLocal { off=-5, kind=I64 } -> x0 + terminator Return(v42) (exit_acc=v42) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/variable_shift_rcx_loop.ssa b/tests/snapshots/ssa/variable_shift_rcx_loop.ssa new file mode 100644 index 000000000..3907cb045 --- /dev/null +++ b/tests/snapshots/ssa/variable_shift_rcx_loop.ssa @@ -0,0 +1,114 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=g +fn ent_pc=0 n_params=4 variadic=false locals=2 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 ParamRef(2, kind=I64) -> x2 + v6 Imm(0) -> x0 + v7 ParamRef(3, kind=I64) -> x0 + v8 Imm(0) -> x1 + v9 Imm(0) -> x8 + v10 Imm(0) -> x1 + v11 Imm(0) -> x1 + terminator Jmp(b1) (exit_acc=v9) + block 1 start_pc=0 + v12 Phi { incoming=[b0:v9, b2:v21], kind=I64 } -> x8 + v13 Phi { incoming=[b0:v9, b2:v25], kind=I64 } -> x1 + v14 LoadLocal { off=-1, kind=I64 } -> x9 + v15 LoadLocal { off=2, kind=I64 } -> x9 + v16 Binop { op=lt, lhs=v13, rhs=v1 } -> x1 + terminator Bz { cond=v16, target=b4, fall=b3 } (exit_acc=v16) + block 2 start_pc=0 + v17 LoadLocal { off=-2, kind=I64 } -> x9 + v18 LoadLocal { off=3, kind=I64 } -> x9 + v19 LoadLocal { off=4, kind=I64 } -> x9 + v20 Binop { op=shl, lhs=v3, rhs=v5 } -> x9 + v21 Binop { op=add, lhs=v12, rhs=v20 } -> x8 + v22 Imm(0) -> x9 + terminator Jmp(b1) (exit_acc=v21) + block 3 start_pc=0 + v23 LoadLocal { off=-2, kind=I64 } -> x1 + v24 LoadLocal { off=5, kind=I64 } -> x1 + v25 Binop { op=add, lhs=v12, rhs=v7 } -> x1 + v26 Imm(0) -> x9 + terminator Jmp(b2) (exit_acc=v25) + block 4 start_pc=0 + v27 LoadLocal { off=5, kind=I64 } -> x1 + terminator Return(v7) (exit_acc=v7) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=5 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(100) -> x7 + v2 Imm(2) -> x6 + v3 Imm(3) -> x2 + v4 Imm(1) -> x1 + v5 Call { target_pc=0, args=[v1, v2, v3, v4], fixed_args=4, fp_return=false, fp_arg_mask=0x0 } -> x0 + v6 BinopI { op=eq, lhs=v5, rhs_imm=1 } -> x0 + terminator Bz { cond=v6, target=b2, fall=b1 } (exit_acc=v6) + block 1 start_pc=0 + v7 Imm(0) -> x1 + v8 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v7) + block 2 start_pc=0 + v9 Imm(1) -> x1 + v10 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v9) + block 3 start_pc=0 + v11 Phi { incoming=[b1:v7, b2:v9], kind=I64 } -> x1 + v12 LoadLocal { off=-5, kind=I64 } -> x0 + terminator Return(v11) (exit_acc=v11) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/variadic_agg_return_classes.ssa b/tests/snapshots/ssa/variadic_agg_return_classes.ssa new file mode 100644 index 000000000..71b34a066 --- /dev/null +++ b/tests/snapshots/ssa/variadic_agg_return_classes.ssa @@ -0,0 +1,148 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=mkp +fn ent_pc=0 n_params=1 variadic=true locals=2 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-2) -> x0 + v2 Imm(4609434218613702656) -> x1 + v3 LoadLocal { off=2, kind=I32 } -> x2 + v4 FpCast { kind=IntToFp, value=v3 } -> d0 + v5 Binop { op=fmul, lhs=v2, rhs=v4 } -> d0 + v6 Store { addr=v1, disp=0, value=v5, kind=F64 } -> - + v7 LocalAddr(-2) -> x0 + v8 BinopI { op=add, lhs=v7, rhs_imm=8 } -> x0 + v9 Imm(4612248968380809216) -> x1 + v10 Store { addr=v8, disp=0, value=v9, kind=F64 } -> - + v11 LocalAddr(-2) -> x0 + terminator Return(v11) (exit_acc=v11) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=mkm +fn ent_pc=1 n_params=1 variadic=true locals=2 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-2) -> x0 + v2 Imm(4602678819172646912) -> x1 + v3 Store { addr=v1, disp=0, value=v2, kind=F64 } -> - + v4 LocalAddr(-2) -> x0 + v5 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x1 + v6 LoadLocal { off=2, kind=I32 } -> x1 + v7 BinopI { op=add, lhs=v6, rhs_imm=41 } -> x1 + v8 BinopI { op=shl, lhs=v7, rhs_imm=32 } -> x2 + v9 Extend { value=v7, kind=I32 } -> x1 + v10 Store { addr=v4, disp=8, value=v9, kind=I64 } -> - + v11 LocalAddr(-2) -> x0 + terminator Return(v11) (exit_acc=v11) +; --- SSA dump (ok=true) ent_pc=2 --- +; name=main +fn ent_pc=2 n_params=0 variadic=false locals=15 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(2) -> x7 + v2 Call { target_pc=0, args=[v1], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + v3 LocalAddr(-11) -> x0 + v4 LocalAddr(-2) -> x1 + v5 Mcpy { dst=v4, src=v3, size=16 } -> x0 + v6 LocalAddr(-2) -> x0 + v7 Load { addr=v6, disp=0, kind=F64 } -> d0 + v8 Imm(4613937818241073152) -> x0 + v9 Binop { op=fne, lhs=v7, rhs=v8 } -> x3 + v10 Imm(0) -> x0 + terminator Bnz { cond=v9, target=b9, fall=b1 } (exit_acc=v9) + block 1 start_pc=0 + v11 LocalAddr(-2) -> x0 + v12 BinopI { op=add, lhs=v11, rhs_imm=8 } -> x0 + v13 Load { addr=v12, disp=0, kind=F64 } -> d0 + v14 Imm(4612248968380809216) -> x0 + v15 Binop { op=fne, lhs=v13, rhs=v14 } -> x3 + v16 Imm(0) -> x0 + terminator Jmp(b2) (exit_acc=v15) + block 2 start_pc=0 + v17 Phi { incoming=[b9:v9, b1:v15], kind=I64 } -> x3 + v18 LoadLocal { off=-12, kind=I64 } -> x0 + terminator Bz { cond=v17, target=b4, fall=b3 } (exit_acc=v17) + block 3 start_pc=0 + v19 Imm(1) -> x0 + terminator Return(v19) (exit_acc=v19) + block 4 start_pc=0 + v20 Imm(1) -> x7 + v21 Call { target_pc=1, args=[v20], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + v22 LocalAddr(-14) -> x0 + v23 LocalAddr(-6) -> x1 + v24 Mcpy { dst=v23, src=v22, size=16 } -> x0 + v25 LocalAddr(-6) -> x0 + v26 Load { addr=v25, disp=0, kind=F64 } -> d0 + v27 Imm(4602678819172646912) -> x0 + v28 Binop { op=fne, lhs=v26, rhs=v27 } -> x1 + v29 Imm(0) -> x0 + terminator Bnz { cond=v28, target=b10, fall=b5 } (exit_acc=v28) + block 5 start_pc=0 + v30 LocalAddr(-6) -> x0 + v31 BinopI { op=add, lhs=v30, rhs_imm=8 } -> x1 + v32 Load { addr=v30, disp=8, kind=I64 } -> x0 + v33 BinopI { op=ne, lhs=v32, rhs_imm=42 } -> x1 + v34 Imm(0) -> x0 + terminator Jmp(b6) (exit_acc=v33) + block 6 start_pc=0 + v35 Phi { incoming=[b10:v28, b5:v33], kind=I64 } -> x1 + v36 LoadLocal { off=-15, kind=I64 } -> x0 + terminator Bz { cond=v35, target=b8, fall=b7 } (exit_acc=v35) + block 7 start_pc=0 + v37 Imm(2) -> x0 + terminator Return(v37) (exit_acc=v37) + block 8 start_pc=0 + v38 Imm(0) -> x0 + terminator Return(v38) (exit_acc=v38) + block 9 start_pc=0 + terminator Jmp(b2) + block 10 start_pc=0 + terminator Jmp(b6) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/variadic_hfa_struct_arg.ssa b/tests/snapshots/ssa/variadic_hfa_struct_arg.ssa new file mode 100644 index 000000000..3bd2b0cf7 --- /dev/null +++ b/tests/snapshots/ssa/variadic_hfa_struct_arg.ssa @@ -0,0 +1,101 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=sum +fn ent_pc=0 n_params=1 variadic=true locals=5 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-3) -> x0 + v2 LocalAddr(2) -> x1 + v3 Intrinsic { kind=4, args=[v1, v2] } -> x0 + v4 LocalAddr(-3) -> x0 + v5 Imm(16) -> x1 + v6 Intrinsic { kind=5, args=[v4, v5] } -> x0 + v7 LocalAddr(-5) -> x1 + v8 Mcpy { dst=v7, src=v6, size=16 } -> x0 + v9 LocalAddr(-3) -> x0 + v10 Intrinsic { kind=6, args=[v9] } -> x0 + v11 LocalAddr(-5) -> x0 + v12 Load { addr=v11, disp=0, kind=F64 } -> d0 + v13 LocalAddr(-5) -> x0 + v14 BinopI { op=add, lhs=v13, rhs_imm=8 } -> x0 + v15 Load { addr=v14, disp=0, kind=F64 } -> d1 + v16 Binop { op=fadd, lhs=v12, rhs=v15 } -> d0 + terminator Return(v16) (exit_acc=v16) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=5 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-2) -> x0 + v2 Imm(4609434218613702656) -> x1 + v3 Store { addr=v1, disp=0, value=v2, kind=F64 } -> - + v4 LocalAddr(-2) -> x0 + v5 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x0 + v6 Imm(4612248968380809216) -> x1 + v7 Store { addr=v5, disp=0, value=v6, kind=F64 } -> - + v8 Imm(1) -> x7 + v9 LocalAddr(-2) -> x6 + v10 Call { target_pc=0, args=[v8, v9], fixed_args=1, fp_return=true, fp_arg_mask=0x0 } -> d0 + v11 Imm(4615626668101337088) -> x0 + v12 Binop { op=feq, lhs=v10, rhs=v11 } -> x0 + terminator Bz { cond=v12, target=b2, fall=b1 } (exit_acc=v12) + block 1 start_pc=0 + v13 Imm(0) -> x1 + v14 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v13) + block 2 start_pc=0 + v15 Imm(1) -> x1 + v16 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v15) + block 3 start_pc=0 + v17 Phi { incoming=[b1:v13, b2:v15], kind=I64 } -> x1 + v18 LoadLocal { off=-5, kind=I64 } -> x0 + terminator Return(v17) (exit_acc=v17) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/variadic_libc_fnptr_static_init.ssa b/tests/snapshots/ssa/variadic_libc_fnptr_static_init.ssa new file mode 100644 index 000000000..7ce591b93 --- /dev/null +++ b/tests/snapshots/ssa/variadic_libc_fnptr_static_init.ssa @@ -0,0 +1,87 @@ +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=17 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-8) -> x0 + v2 Imm(0) -> x1 + v3 Store { addr=v1, disp=0, value=v2, kind=I8 } -> - + v4 ImmData(40) -> x0 + v5 Imm(8) -> x1 + v6 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x1 + v7 Load { addr=v4, disp=8, kind=I64 } -> x0 + v8 LocalAddr(-8) -> x7 + v9 Imm(64) -> x6 + v10 ImmData(56) -> x2 + v11 Imm(42) -> x1 + v12 ImmData(65) -> x8 + v13 Imm(99) -> x9 + v14 CallIndirect { target=v7, args=[v8, v9, v10, v11, v12, v13], callee_variadic=true, fixed_args=3, fp_return=false, fp_arg_mask=0x0 } -> x0 + v15 BinopI { op=shl, lhs=v14, rhs_imm=32 } -> x1 + v16 Extend { value=v14, kind=I32 } -> x0 + v17 LocalAddr(-8) -> x7 + v18 ImmData(69) -> x6 + v19 CallExt { binding_idx=62, args=[v17, v18], fp_arg_mask=0x0 } -> x0 + v20 BinopI { op=ne, lhs=v19, rhs_imm=0 } -> x0 + terminator Bz { cond=v20, target=b2, fall=b1 } (exit_acc=v20) + block 1 start_pc=0 + v21 Imm(1) -> x0 + terminator Return(v21) (exit_acc=v21) + block 2 start_pc=0 + v22 Imm(0) -> x0 + terminator Return(v22) (exit_acc=v22) +; --- SSA dump (ok=true) ent_pc=2 --- +; name=__c5_sys_snprintf +fn ent_pc=2 n_params=0 variadic=false locals=0 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + terminator TailExt(3) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) From 32203e240a1f3ce5defaa279e45f33ab4c275ab4 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 20:56:14 -0700 Subject: [PATCH 35/67] compiler: record the prototype of a cast-to-fn-pointer callee A call through a cast pointer type uses the cast's prototype (C99 6.5.2.2p7), but the cast's abstract declarator skipped its (args) list, so `((int (*)(int, int, ...))table[0])(fd, cmd, &fl)` marshalled the tail as fixed register arguments -- the dispatch-table idiom broke once the sys trampolines became pass-through tail jumps. Parse the plain fn-pointer cast shape's parameter list and override the indirect-callee channel after the operand, narrowing arguments and splitting the variadic tail per the cast. Co-Authored-By: Claude Fable 5 --- src/c5/compiler/declarator.rs | 33 +++++++++++++++-- src/c5/compiler/expr.rs | 18 +++++++++- src/c5/tests/jit.rs | 1 + src/c5/tests/native.rs | 2 ++ src/c5/tests/native_elf.rs | 2 ++ src/c5/tests/native_elf_x64.rs | 2 ++ src/c5/tests/native_pe_arm64.rs | 1 + src/c5/tests/native_pe_x64.rs | 1 + tests/fixtures/c/fcntl_lock_via_cast_fnptr.c | 36 +++++++++++++++++++ .../fixtures/c/variadic_cast_fnptr_dispatch.c | 23 ++++++++++++ 10 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 tests/fixtures/c/fcntl_lock_via_cast_fnptr.c create mode 100644 tests/fixtures/c/variadic_cast_fnptr_dispatch.c diff --git a/src/c5/compiler/declarator.rs b/src/c5/compiler/declarator.rs index 8723f6fc5..5a43ec4b0 100644 --- a/src/c5/compiler/declarator.rs +++ b/src/c5/compiler/declarator.rs @@ -108,13 +108,31 @@ impl Compiler { /// (0 when the parentheses enclose no `*`). Used by both the cast /// operand parser and the `sizeof` type-name parser. pub(super) fn parse_abstract_ptr_declarator_levels(&mut self) -> Result { + self.parse_abstract_ptr_declarator(false) + .map(|(levels, _)| levels) + } + + /// As [`Self::parse_abstract_ptr_declarator_levels`], but with + /// `capture_proto` the plain fn-pointer shape's `(args)` list is + /// parsed and returned so a cast expression can record the pointee + /// prototype (parameter types, variadic split) for a following + /// call. Nested declarator shapes keep the skip behaviour. + pub(super) fn parse_abstract_ptr_declarator( + &mut self, + capture_proto: bool, + ) -> Result<(i64, Option), C5Error> { debug_assert!(self.lex.tk == '('); let mut depth: i64 = 1; self.next()?; let mut nested_ptrs: i64 = 0; + // The plain fn-pointer shape holds only `*`s (and qualifiers) + // inside one paren level; anything else is a nested declarator + // whose trailing `(args)` is not the pointee prototype. + let mut plain = true; while depth > 0 && self.lex.tk != 0 { if self.lex.tk == '(' { depth += 1; + plain = false; } else if self.lex.tk == ')' { depth -= 1; if depth == 0 { @@ -123,6 +141,8 @@ impl Compiler { } } else if self.lex.tk == Token::MulOp && depth == 1 { nested_ptrs += 1; + } else if self.lex.tk != Token::TypeQual { + plain = false; } self.next()?; } @@ -130,9 +150,18 @@ impl Compiler { // function-pointer / function-returning-fn shape, or one or more // `[N]` / `[]` suffixes for the pointer-to-array shape // (`T (*)[N][M]`). Both are no-ops at c5's type-tag granularity. + let mut proto = None; if self.lex.tk == '(' { self.next()?; - self.skip_balanced_parens_after_open()?; + if capture_proto && plain && nested_ptrs > 0 { + let pp = self.parse_function_params()?; + for &p in &pp.indices { + Self::restore_shadowed_symbol(&mut self.symbols[p]); + } + proto = Some(pp); + } else { + self.skip_balanced_parens_after_open()?; + } } while self.lex.tk == Token::Brak { self.next()?; @@ -143,7 +172,7 @@ impl Compiler { self.accept(']')?; } } - Ok(nested_ptrs) + Ok((nested_ptrs, proto)) } /// Parse a single declarator: zero-or-more `*` (pointer levels) diff --git a/src/c5/compiler/expr.rs b/src/c5/compiler/expr.rs index bb8f35d06..59d1cba68 100644 --- a/src/c5/compiler/expr.rs +++ b/src/c5/compiler/expr.rs @@ -1539,8 +1539,9 @@ impl Compiler { // as a no-op pointer level. Counted-parens scan // until the cast's outer `)` so even nested fp // shapes consume cleanly. + let mut cast_fn_proto = None; if self.lex.tk == '(' { - let nested_ptrs = self.parse_abstract_ptr_declarator_levels()?; + let (nested_ptrs, proto) = self.parse_abstract_ptr_declarator(true)?; t += nested_ptrs * (Ty::Ptr as i64); // Abstract fn-ptr declarator: the inner `*` // count IS the indirection from the cast's @@ -1549,6 +1550,7 @@ impl Compiler { if nested_ptrs > 0 { cast_fpi = Some(nested_ptrs); } + cast_fn_proto = proto; } if self.lex.tk == ')' { self.next()?; @@ -1650,6 +1652,20 @@ impl Compiler { { self.pending.fn_ptr_chain_depth = fpi - 1; } + // C99 6.5.2.2p7: a call through the cast pointer + // uses the cast's prototype. Override the operand's + // recorded callee channel so a following call + // narrows each argument and splits the variadic + // tail per the cast, whatever the operand's own + // declared type said. + if let Some(pp) = cast_fn_proto { + self.pending.indirect_callee_is_variadic = pp.is_variadic; + self.pending.indirect_callee_params = if pp.types.is_empty() { + None + } else { + Some(pp.types) + }; + } } } else { self.expr(Token::Assign as i64)?; diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index 1d0e9721f..d59f37dd5 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1569,6 +1569,7 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("va_copy_under_pressure.c", 0), ("variable_shift_rcx_loop.c", 0), ("va_arg_composite_straddle.c", 0), + ("variadic_cast_fnptr_dispatch.c", 0), ]; #[test] diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index e62da8001..1be2a7cf6 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -944,6 +944,8 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("variable_shift_rcx_loop.c", 0), ("va_arg_composite_straddle.c", 0), ("variadic_hfa_struct_arg.c", 0), + ("variadic_cast_fnptr_dispatch.c", 0), + ("fcntl_lock_via_cast_fnptr.c", 0), ]; /// Build a fixture, sign it, run it with the given args, and return diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index 827b5cb9f..cc168614e 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -719,6 +719,8 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("va_copy_under_pressure.c", 0), ("variable_shift_rcx_loop.c", 0), ("va_arg_composite_straddle.c", 0), + ("variadic_cast_fnptr_dispatch.c", 0), + ("fcntl_lock_via_cast_fnptr.c", 0), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index ce58b3202..dba830710 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -668,6 +668,8 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("va_copy_under_pressure.c", 0), ("variable_shift_rcx_loop.c", 0), ("va_arg_composite_straddle.c", 0), + ("variadic_cast_fnptr_dispatch.c", 0), + ("fcntl_lock_via_cast_fnptr.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index e780a1127..87a04eedf 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -927,6 +927,7 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("variable_shift_rcx_loop.c", 0), ("va_arg_composite_straddle.c", 0), ("variadic_hfa_struct_arg.c", 0), + ("variadic_cast_fnptr_dispatch.c", 0), ]; #[test] diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index baee360bc..a3c4c86dc 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -944,6 +944,7 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("va_copy_under_pressure.c", 0), ("variable_shift_rcx_loop.c", 0), ("va_arg_composite_straddle.c", 0), + ("variadic_cast_fnptr_dispatch.c", 0), ]; #[test] diff --git a/tests/fixtures/c/fcntl_lock_via_cast_fnptr.c b/tests/fixtures/c/fcntl_lock_via_cast_fnptr.c new file mode 100644 index 000000000..ec357684e --- /dev/null +++ b/tests/fixtures/c/fcntl_lock_via_cast_fnptr.c @@ -0,0 +1,36 @@ +/* fcntl(fd, F_SETLK, &fl) through a sqlite-style dispatch table: the + cast supplies the variadic prototype, so the struct-address tail + must reach libc per the host variadic convention. Verified by the + kernel's return codes. */ +#include +#include +#include +#include + +typedef void (*syscall_ptr)(void); +static syscall_ptr table[1] = { (syscall_ptr)fcntl }; +#define osFcntl ((int (*)(int, int, ...))table[0]) + +int main(void) { + char path[64]; + snprintf(path, sizeof path, "/tmp/badc_fcntl_%d", (int)getpid()); + int fd = open(path, O_RDWR | O_CREAT, 0644); + if (fd < 0) { + return 3; + } + struct flock fl; + memset(&fl, 0, sizeof fl); + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + int direct = fcntl(fd, F_SETLK, &fl); + fl.l_type = F_UNLCK; + int unlock = fcntl(fd, F_SETLK, &fl); + fl.l_type = F_WRLCK; + int viaptr = osFcntl(fd, F_SETLK, &fl); + close(fd); + unlink(path); + if (direct != 0 || unlock != 0) { + return 2; + } + return viaptr == 0 ? 0 : 1; +} diff --git a/tests/fixtures/c/variadic_cast_fnptr_dispatch.c b/tests/fixtures/c/variadic_cast_fnptr_dispatch.c new file mode 100644 index 000000000..a1f4e9755 --- /dev/null +++ b/tests/fixtures/c/variadic_cast_fnptr_dispatch.c @@ -0,0 +1,23 @@ +/* A call through a cast fn-pointer type uses the cast's prototype + (C99 6.5.2.2p7): the variadic tail must marshal per the host + variadic convention even when the pointer's declared type says + nothing (the sqlite-style syscall dispatch table shape). */ +#include +#include + +typedef void (*fnp)(void); +static fnp table[1] = { (fnp)snprintf }; + +int main(void) { + char buf[32]; + buf[0] = 0; + int n = ((int (*)(char *, unsigned long, const char *, ...))table[0])( + buf, sizeof buf, "%d %s %d", 4, "mid", 9); + if (n != 7) { + return 1; + } + if (strcmp(buf, "4 mid 9") != 0) { + return 2; + } + return 0; +} From 1c28dcc5630bc8132d19870d4413e36268160e07 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 21:04:16 -0700 Subject: [PATCH 36/67] tests: snapshots for the cast-prototype fixtures Co-Authored-By: Claude Fable 5 --- .../asm/fcntl_lock_via_cast_fnptr.aarch64.asm | 133 ++++++++++++++++ .../asm/fcntl_lock_via_cast_fnptr.x64.asm | 142 +++++++++++++++++ .../variadic_cast_fnptr_dispatch.aarch64.asm | 66 ++++++++ .../asm/variadic_cast_fnptr_dispatch.x64.asm | 59 +++++++ .../ssa/fcntl_lock_via_cast_fnptr.ssa | 149 ++++++++++++++++++ .../ssa/variadic_cast_fnptr_dispatch.ssa | 93 +++++++++++ 6 files changed, 642 insertions(+) create mode 100644 tests/snapshots/asm/fcntl_lock_via_cast_fnptr.aarch64.asm create mode 100644 tests/snapshots/asm/fcntl_lock_via_cast_fnptr.x64.asm create mode 100644 tests/snapshots/asm/variadic_cast_fnptr_dispatch.aarch64.asm create mode 100644 tests/snapshots/asm/variadic_cast_fnptr_dispatch.x64.asm create mode 100644 tests/snapshots/ssa/fcntl_lock_via_cast_fnptr.ssa create mode 100644 tests/snapshots/ssa/variadic_cast_fnptr_dispatch.ssa diff --git a/tests/snapshots/asm/fcntl_lock_via_cast_fnptr.aarch64.asm b/tests/snapshots/asm/fcntl_lock_via_cast_fnptr.aarch64.asm new file mode 100644 index 000000000..1985dd1b1 --- /dev/null +++ b/tests/snapshots/asm/fcntl_lock_via_cast_fnptr.aarch64.asm @@ -0,0 +1,133 @@ + +fcntl_lock_via_cast_fnptr.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x4d0 // =1232 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x140 + str x20, [sp] + str x21, [sp, #0x8] + str x22, [sp, #0x10] + str x23, [sp, #0x18] + str x24, [sp, #0x20] + str x19, [sp, #0x30] + sub x20, x29, #0x40 + mov x21, #0x40 // =64 + adrp x22, + add x22, x22, + bl + sxtw x0, w0 + mov x3, x0 + mov x0, x20 + mov x2, x22 + mov x1, x21 + bl + sxtw x0, w0 + sub x0, x29, #0x40 + mov x1, #0x42 // =66 + mov x2, #0x1a4 // =420 + bl + sxtw x0, w0 + mov x20, x0 + sxtw x0, w20 + cmp x0, #0x0 + b.ge + mov x0, #0x3 // =3 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + ldr x23, [sp, #0x18] + ldr x24, [sp, #0x20] + ldr x19, [sp, #0x30] + add sp, sp, #0x140 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0xa8 + mov x21, #0x0 // =0 + mov x2, #0x60 // =96 + mov x1, x21 + bl + sub x0, x29, #0xa8 + mov x22, #0x1 // =1 + strh w22, [x0] + sub x0, x29, #0xa8 + strh w21, [x0, #0x2] + sxtw x0, w20 + mov x21, #0x6 // =6 + sub x2, x29, #0xa8 + mov x1, x21 + bl + sxtw x0, w0 + mov x23, x0 + sub x0, x29, #0xa8 + mov x1, #0x2 // =2 + strh w1, [x0] + sxtw x0, w20 + sub x2, x29, #0xa8 + mov x1, x21 + bl + sxtw x0, w0 + mov x24, x0 + sub x0, x29, #0xa8 + strh w22, [x0] + adrp x0, + add x0, x0, + ldr x0, [x0] + sxtw x1, w20 + sub x2, x29, #0xa8 + mov x9, x0 + mov x0, x1 + mov x1, x21 + blr x9 + sxtw x21, w0 + sxtw x0, w20 + bl + sxtw x0, w0 + sub x0, x29, #0x40 + bl + sxtw x0, w0 + sxtw x0, w23 + cmp x0, #0x0 + cset x1, ne + cbnz x1, + sxtw x0, w24 + cmp x0, #0x0 + cset x1, ne + cbz x1, + mov x0, #0x2 // =2 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + ldr x23, [sp, #0x18] + ldr x24, [sp, #0x20] + ldr x19, [sp, #0x30] + add sp, sp, #0x140 + ldp x29, x30, [sp], #0x10 + ret + cmp x21, #0x0 + b.ne + mov x1, #0x0 // =0 + b + mov x1, #0x1 // =1 + mov x0, x1 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + ldr x23, [sp, #0x18] + ldr x24, [sp, #0x20] + ldr x19, [sp, #0x30] + add sp, sp, #0x140 + ldp x29, x30, [sp], #0x10 + ret + b + +<__c5_sys_fcntl>: + b diff --git a/tests/snapshots/asm/fcntl_lock_via_cast_fnptr.x64.asm b/tests/snapshots/asm/fcntl_lock_via_cast_fnptr.x64.asm new file mode 100644 index 000000000..a9a17c270 --- /dev/null +++ b/tests/snapshots/asm/fcntl_lock_via_cast_fnptr.x64.asm @@ -0,0 +1,142 @@ + +fcntl_lock_via_cast_fnptr.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x130, %rsp # imm = 0x130 + movq %rbx, (%rsp) + movq %r12, 0x8(%rsp) + movq %r13, 0x10(%rsp) + movq %r14, 0x18(%rsp) + movq %r15, 0x20(%rsp) + leaq -0x40(%rbp), %rbx + movl $0x40, %r12d + leaq , %r13 + xorl %eax, %eax + callq + movslq %eax, %rax + movq %rax, %rcx + movq %rbx, %rdi + movq %r13, %rdx + movq %r12, %rsi + movb $0x0, %al + callq + movslq %eax, %rax + leaq -0x40(%rbp), %rdi + movl $0x42, %esi + movl $0x1a4, %edx # imm = 0x1A4 + movb $0x0, %al + callq + movslq %eax, %rax + movq %rax, %rbx + movslq %ebx, %rax + testq %rax, %rax + jge + movl $0x3, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + movq 0x18(%rsp), %r14 + movq 0x20(%rsp), %r15 + addq $0x130, %rsp # imm = 0x130 + popq %rbp + retq + leaq -0xa8(%rbp), %rdi + xorq %r12, %r12 + movl $0x60, %edx + movq %r12, %rsi + xorl %eax, %eax + callq + leaq -0xa8(%rbp), %rax + movl $0x1, %r13d + movw %r13w, (%rax) + leaq -0xa8(%rbp), %rax + movw %r12w, 0x2(%rax) + movslq %ebx, %rdi + movl $0x6, %r12d + leaq -0xa8(%rbp), %rdx + movq %r12, %rsi + movb $0x0, %al + callq + movslq %eax, %rax + movq %rax, %r14 + leaq -0xa8(%rbp), %rax + movl $0x2, %ecx + movw %cx, (%rax) + movslq %ebx, %rdi + leaq -0xa8(%rbp), %rdx + movq %r12, %rsi + movb $0x0, %al + callq + movslq %eax, %rax + movq %rax, %r15 + leaq -0xa8(%rbp), %rax + movw %r13w, (%rax) + leaq , %rax + movq (%rax), %rax + movslq %ebx, %rdi + leaq -0xa8(%rbp), %rdx + movq %rax, %rcx + movq %r12, %rsi + movb $0x0, %al + callq *%rcx + movslq %eax, %r12 + movslq %ebx, %rdi + xorl %eax, %eax + callq + movslq %eax, %rax + leaq -0x40(%rbp), %rdi + xorl %eax, %eax + callq + movslq %eax, %rax + movslq %r14d, %rax + testq %rax, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + jne + movslq %r15d, %rax + testq %rax, %rax + setne %cl + movzbq %cl, %rcx + testq %rcx, %rcx + je + movl $0x2, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + movq 0x18(%rsp), %r14 + movq 0x20(%rsp), %r15 + addq $0x130, %rsp # imm = 0x130 + popq %rbp + retq + testq %r12, %r12 + jne + xorq %rcx, %rcx + jmp + movl $0x1, %ecx + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + movq 0x18(%rsp), %r14 + movq 0x20(%rsp), %r15 + movq %rcx, %rax + addq $0x130, %rsp # imm = 0x130 + popq %rbp + retq + jmp + +<__c5_sys_fcntl>: + jmp + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/variadic_cast_fnptr_dispatch.aarch64.asm b/tests/snapshots/asm/variadic_cast_fnptr_dispatch.aarch64.asm new file mode 100644 index 000000000..e2f561d40 --- /dev/null +++ b/tests/snapshots/asm/variadic_cast_fnptr_dispatch.aarch64.asm @@ -0,0 +1,66 @@ + +variadic_cast_fnptr_dispatch.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x2b0 // =688 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x80 + str x19, [sp] + sub x0, x29, #0x20 + mov x1, #0x0 // =0 + strb w1, [x0] + adrp x0, + add x0, x0, + ldr x0, [x0] + sub x1, x29, #0x20 + mov x2, #0x20 // =32 + adrp x3, + add x3, x3, + mov x4, #0x4 // =4 + adrp x5, + add x5, x5, + mov x6, #0x9 // =9 + mov x9, x0 + mov x0, x1 + mov x1, x2 + mov x2, x3 + mov x3, x4 + mov x4, x5 + mov x5, x6 + blr x9 + sxtw x0, w0 + cmp x0, #0x7 + b.eq + mov x0, #0x1 // =1 + ldr x19, [sp] + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x20 + adrp x1, + add x1, x1, + bl + sxtw x0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x2 // =2 + ldr x19, [sp] + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldr x19, [sp] + add sp, sp, #0x80 + ldp x29, x30, [sp], #0x10 + ret + +<__c5_sys_snprintf>: + b diff --git a/tests/snapshots/asm/variadic_cast_fnptr_dispatch.x64.asm b/tests/snapshots/asm/variadic_cast_fnptr_dispatch.x64.asm new file mode 100644 index 000000000..a442df15c --- /dev/null +++ b/tests/snapshots/asm/variadic_cast_fnptr_dispatch.x64.asm @@ -0,0 +1,59 @@ + +variadic_cast_fnptr_dispatch.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x70, %rsp + leaq -0x20(%rbp), %rax + xorq %rcx, %rcx + movb %cl, (%rax) + leaq , %rax + movq (%rax), %rax + leaq -0x20(%rbp), %rdi + movl $0x20, %esi + leaq , %rdx + movl $0x4, %ecx + leaq , %r8 + movl $0x9, %r9d + subq $0x10, %rsp + movq %rax, (%rsp) + movq (%rsp), %r10 + movb $0x0, %al + callq *%r10 + addq $0x10, %rsp + movslq %eax, %rax + cmpq $0x7, %rax + je + movl $0x1, %eax + addq $0x70, %rsp + popq %rbp + retq + leaq -0x20(%rbp), %rdi + leaq , %rsi + xorl %eax, %eax + callq + movslq %eax, %rax + testq %rax, %rax + je + movl $0x2, %eax + addq $0x70, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x70, %rsp + popq %rbp + retq + +<__c5_sys_snprintf>: + jmp + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/ssa/fcntl_lock_via_cast_fnptr.ssa b/tests/snapshots/ssa/fcntl_lock_via_cast_fnptr.ssa new file mode 100644 index 000000000..e4a767424 --- /dev/null +++ b/tests/snapshots/ssa/fcntl_lock_via_cast_fnptr.ssa @@ -0,0 +1,149 @@ +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=31 + spill_count=0 gpr_used=[3, 12, 13, 14, 15] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-8) -> x3 + v2 Imm(64) -> x12 + v3 ImmData(40) -> x13 + v4 CallExt { binding_idx=107, args=[], fp_arg_mask=0x0 } -> x1 + v5 CallExt { binding_idx=3, args=[v1, v2, v3, v4], fp_arg_mask=0x0 } -> x0 + v6 LocalAddr(-8) -> x7 + v7 Imm(66) -> x6 + v8 Imm(420) -> x2 + v9 CallExt { binding_idx=79, args=[v6, v7, v8], fp_arg_mask=0x0 } -> x3 + v10 Imm(0) -> x0 + v11 Extend { value=v9, kind=I32 } -> x0 + v12 BinopI { op=lt, lhs=v11, rhs_imm=0 } -> x0 + terminator Bz { cond=v12, target=b2, fall=b1 } (exit_acc=v12) + block 1 start_pc=0 + v13 Imm(3) -> x0 + terminator Return(v13) (exit_acc=v13) + block 2 start_pc=0 + v14 LocalAddr(-21) -> x7 + v15 Imm(0) -> x12 + v16 Imm(96) -> x2 + v17 CallExt { binding_idx=209, args=[v14, v15, v16], fp_arg_mask=0x0 } -> x0 + v18 LocalAddr(-21) -> x0 + v19 Imm(1) -> x13 + v20 Store { addr=v18, disp=0, value=v19, kind=I16 } -> - + v21 Imm(281474976710656) -> x0 + v22 LocalAddr(-21) -> x0 + v23 BinopI { op=add, lhs=v22, rhs_imm=2 } -> x1 + v24 Store { addr=v22, disp=2, value=v15, kind=I16 } -> - + v25 Extend { value=v9, kind=I32 } -> x7 + v26 Imm(6) -> x12 + v27 LocalAddr(-21) -> x2 + v28 CallExt { binding_idx=54, args=[v25, v26, v27], fp_arg_mask=0x0 } -> x14 + v29 Imm(0) -> x0 + v30 LocalAddr(-21) -> x0 + v31 Imm(2) -> x1 + v32 Store { addr=v30, disp=0, value=v31, kind=I16 } -> - + v33 Imm(562949953421312) -> x0 + v34 Extend { value=v9, kind=I32 } -> x7 + v35 LocalAddr(-21) -> x2 + v36 CallExt { binding_idx=54, args=[v34, v26, v35], fp_arg_mask=0x0 } -> x15 + v37 Imm(0) -> x0 + v38 LocalAddr(-21) -> x0 + v39 Store { addr=v38, disp=0, value=v19, kind=I16 } -> - + v40 ImmData(32) -> x0 + v41 Load { addr=v40, disp=0, kind=I64 } -> x0 + v42 Extend { value=v9, kind=I32 } -> x7 + v43 LocalAddr(-21) -> x2 + v44 CallIndirect { target=v41, args=[v42, v26, v43], callee_variadic=true, fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x0 + v45 BinopI { op=shl, lhs=v44, rhs_imm=32 } -> x1 + v46 Extend { value=v44, kind=I32 } -> x12 + v47 Imm(0) -> x0 + v48 Extend { value=v9, kind=I32 } -> x7 + v49 CallExt { binding_idx=83, args=[v48], fp_arg_mask=0x0 } -> x0 + v50 LocalAddr(-8) -> x7 + v51 CallExt { binding_idx=97, args=[v50], fp_arg_mask=0x0 } -> x0 + v52 Extend { value=v28, kind=I32 } -> x0 + v53 BinopI { op=ne, lhs=v52, rhs_imm=0 } -> x1 + v54 Imm(0) -> x0 + terminator Bnz { cond=v53, target=b10, fall=b3 } (exit_acc=v53) + block 3 start_pc=0 + v55 Extend { value=v36, kind=I32 } -> x0 + v56 BinopI { op=ne, lhs=v55, rhs_imm=0 } -> x1 + v57 Imm(0) -> x0 + terminator Jmp(b4) (exit_acc=v56) + block 4 start_pc=0 + v58 Phi { incoming=[b10:v53, b3:v56], kind=I64 } -> x1 + v59 LoadLocal { off=-30, kind=I64 } -> x0 + terminator Bz { cond=v58, target=b6, fall=b5 } (exit_acc=v58) + block 5 start_pc=0 + v60 Imm(2) -> x0 + terminator Return(v60) (exit_acc=v60) + block 6 start_pc=0 + v61 LoadLocal { off=-24, kind=I32 } -> x0 + v62 BinopI { op=eq, lhs=v46, rhs_imm=0 } -> x0 + terminator Bz { cond=v62, target=b8, fall=b7 } (exit_acc=v62) + block 7 start_pc=0 + v63 Imm(0) -> x1 + v64 Imm(0) -> x0 + terminator Jmp(b9) (exit_acc=v63) + block 8 start_pc=0 + v65 Imm(1) -> x1 + v66 Imm(0) -> x0 + terminator Jmp(b9) (exit_acc=v65) + block 9 start_pc=0 + v67 Phi { incoming=[b7:v63, b8:v65], kind=I64 } -> x1 + v68 LoadLocal { off=-31, kind=I64 } -> x0 + terminator Return(v67) (exit_acc=v67) + block 10 start_pc=0 + terminator Jmp(b4) +; --- SSA dump (ok=true) ent_pc=2 --- +; name=__c5_sys_fcntl +fn ent_pc=2 n_params=0 variadic=false locals=0 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + terminator TailExt(54) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/variadic_cast_fnptr_dispatch.ssa b/tests/snapshots/ssa/variadic_cast_fnptr_dispatch.ssa new file mode 100644 index 000000000..ab41c3498 --- /dev/null +++ b/tests/snapshots/ssa/variadic_cast_fnptr_dispatch.ssa @@ -0,0 +1,93 @@ +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=14 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-4) -> x0 + v2 Imm(0) -> x1 + v3 Store { addr=v1, disp=0, value=v2, kind=I8 } -> - + v4 ImmData(40) -> x0 + v5 Load { addr=v4, disp=0, kind=I64 } -> x0 + v6 LocalAddr(-4) -> x7 + v7 Imm(32) -> x6 + v8 ImmData(48) -> x2 + v9 Imm(4) -> x1 + v10 ImmData(57) -> x8 + v11 Imm(9) -> x9 + v12 CallIndirect { target=v5, args=[v6, v7, v8, v9, v10, v11], callee_variadic=true, fixed_args=3, fp_return=false, fp_arg_mask=0x0 } -> x0 + v13 BinopI { op=shl, lhs=v12, rhs_imm=32 } -> x1 + v14 Extend { value=v12, kind=I32 } -> x0 + v15 Imm(0) -> x1 + v16 LoadLocal { off=-5, kind=I32 } -> x1 + v17 BinopI { op=ne, lhs=v14, rhs_imm=7 } -> x0 + terminator Bz { cond=v17, target=b2, fall=b1 } (exit_acc=v17) + block 1 start_pc=0 + v18 Imm(1) -> x0 + terminator Return(v18) (exit_acc=v18) + block 2 start_pc=0 + v19 LocalAddr(-4) -> x7 + v20 ImmData(61) -> x6 + v21 CallExt { binding_idx=62, args=[v19, v20], fp_arg_mask=0x0 } -> x0 + v22 BinopI { op=ne, lhs=v21, rhs_imm=0 } -> x0 + terminator Bz { cond=v22, target=b4, fall=b3 } (exit_acc=v22) + block 3 start_pc=0 + v23 Imm(2) -> x0 + terminator Return(v23) (exit_acc=v23) + block 4 start_pc=0 + v24 Imm(0) -> x0 + terminator Return(v24) (exit_acc=v24) +; --- SSA dump (ok=true) ent_pc=2 --- +; name=__c5_sys_snprintf +fn ent_pc=2 n_params=0 variadic=false locals=0 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + terminator TailExt(3) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) From 819a49129c8ce330b918a9893461d9361d04ebdc Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 21:17:31 -0700 Subject: [PATCH 37/67] headers: POSIX variadic fcntl on Linux; fixture: LLP64-safe shift widths The Linux fcntl declaration's fixed int third parameter truncated pointer arguments once calls narrow to the prototype (F_SETLK EFAULT under the test prelude's include order; the fixture's own order let unistd.h's correct variadic shape win). The shift-fold fixture used long where the pattern needs 64 bits regardless of data model. Co-Authored-By: Claude Fable 5 --- headers/include/fcntl.h | 2 +- tests/fixtures/c/sxtw_fold_source_liveness.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/headers/include/fcntl.h b/headers/include/fcntl.h index 0e83890d1..4241a4f21 100644 --- a/headers/include/fcntl.h +++ b/headers/include/fcntl.h @@ -206,7 +206,7 @@ int openat(int dirfd, const char *path, int flags, ...); #pragma binding(libc::splice, "splice") #pragma binding(libc::posix_fadvise, "posix_fadvise") #pragma binding(libc::posix_fallocate, "posix_fallocate") -int fcntl(int fd, int cmd, int arg); +int fcntl(int fd, int cmd, ...); int openat(int dirfd, const char *path, int flags, ...); // Move data between two descriptors, one of which must be a pipe; the // `off_*` parameters are in/out file offsets or null. diff --git a/tests/fixtures/c/sxtw_fold_source_liveness.c b/tests/fixtures/c/sxtw_fold_source_liveness.c index 806a1bb6d..91b133719 100644 --- a/tests/fixtures/c/sxtw_fold_source_liveness.c +++ b/tests/fixtures/c/sxtw_fold_source_liveness.c @@ -1,10 +1,10 @@ /* The Shl/Shr sign-narrow fold reads the Shl source's register at the Shr; an intervening definition may reuse that register once the source's live range ends. The fold must verify the place survives. */ -long f(long x, long b) { - long t = x << 32; - long v = x + b; - long y = t >> 32; +long long f(long long x, long long b) { + long long t = x << 32; + long long v = x + b; + long long y = t >> 32; return y + v + b; } From d6c3858e64a558766e687a3d7b7cbfb93bd1cf81 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 21:33:41 -0700 Subject: [PATCH 38/67] vm, jit, compiler: fix execution-mode linkage and libc-shim defects One linkage model for undefined externs: the compiler always assigns placeholder ent_pcs to declared-but-undefined extern functions and clears extern-object storage; the linker resolves the references, and --interp / --jit refuse them with the linker's undefined-reference wording instead of dispatching to the function at the colliding ent_pc 0 or reading phantom zeroed storage. JIT: #pragma binding(data ...) references (environ, tzname) patch through the fake GOT like the AOT import path instead of faulting on the unpatched placeholder; intercepted atexit handlers run when the program exits via libc exit() (C99 7.20.4.3p2). Interpreter: printf covers the C99 7.19.6.1 conversion-spec grammar (flags, width, precision, length modifiers, f/e/g families); exit(N) terminates with status N instead of a runtime error; frame allocation is bounded by the stack region so deep recursion is a hard error rather than silent heap corruption. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/aarch64/encode.rs | 3 +- src/c5/codegen/jit.rs | 206 ++++++++-- src/c5/codegen/mod.rs | 10 +- src/c5/codegen/x86_64/encode.rs | 3 +- src/c5/compiler/mod.rs | 64 +--- src/c5/error.rs | 2 +- src/c5/tests/codegen.rs | 4 +- src/c5/tests/dwarf.rs | 34 +- src/c5/tests/jit.rs | 102 +++++ src/c5/tests/parser.rs | 31 +- src/c5/vm/mod.rs | 93 +++++ src/c5/vm/ssa.rs | 639 +++++++++++++++++++++++++++---- 12 files changed, 1016 insertions(+), 175 deletions(-) diff --git a/src/c5/codegen/aarch64/encode.rs b/src/c5/codegen/aarch64/encode.rs index b4b12be1e..5e219ad35 100644 --- a/src/c5/codegen/aarch64/encode.rs +++ b/src/c5/codegen/aarch64/encode.rs @@ -1707,8 +1707,7 @@ pub(crate) fn lower( // `apply_fixups` and re-emit them as // `Build::user_extern_call_sites` entries that the writer // surfaces as `R_AARCH64_CALL26` relocs against the - // callee's symbol. Empty for builds without - // `CompileOptions::no_entry_point`. + // callee's symbol. let extern_pc_lookup: alloc::collections::BTreeMap = program .extern_function_imports .iter() diff --git a/src/c5/codegen/jit.rs b/src/c5/codegen/jit.rs index 99fd980e4..353ce100e 100644 --- a/src/c5/codegen/jit.rs +++ b/src/c5/codegen/jit.rs @@ -125,7 +125,8 @@ mod jit_impl { use super::super::super::error::C5Error; use super::super::super::program::Program; use super::super::Target; - use super::super::{Build, NativeOptions, ResolvedImports, aarch64, x86_64}; + use super::super::{Build, GotFixup, NativeOptions, ResolvedImport, ResolvedImports}; + use super::super::{aarch64, x86_64}; use super::host_target; use alloc::format; use alloc::string::String; @@ -198,19 +199,34 @@ mod jit_impl { 0 } - /// Return the JIT-side thunk address for any libc atexit-shape - /// symbol, otherwise 0. The host's libc atexit registers - /// handler PCs into the host's own `__cxa_finalize` list, but - /// those PCs sit in the JIT mmap region that `JitRegion::drop` - /// unmaps before the host process exits -- so handing the - /// host's atexit address to JIT'd code yields a dangling - /// pointer at process teardown. Intercepting the binding at + /// Replacement for libc's `exit` when JIT'd code resolves the + /// symbol through `dlsym`. C99 7.20.4.3p2: `exit` runs the + /// registered atexit handlers first. `atexit` was intercepted + /// into the JIT-side chain, which the host's `exit` knows + /// nothing about, so drain the chain before terminating with + /// the given status. `_Exit` / `quick_exit` stay on the host + /// symbols -- neither runs atexit handlers (7.20.4.5). + extern "C" fn jit_exit_thunk(status: c_int) -> ! { + drain_jit_atexit_chain(); + std::process::exit(status); + } + + /// Return the JIT-side thunk address for a libc symbol whose + /// host implementation must not be handed to JIT'd code, + /// otherwise 0. The host's libc atexit registers handler PCs + /// into the host's own `__cxa_finalize` list, but those PCs + /// sit in the JIT mmap region that `JitRegion::drop` unmaps + /// before the host process exits -- so handing the host's + /// atexit address to JIT'd code yields a dangling pointer at + /// process teardown; the host's `exit` would skip the + /// intercepted handlers entirely. Intercepting the binding at /// JIT bind_imports time means every JIT'd `atexit` / - /// `__cxa_atexit` call lands on our thunk instead. + /// `__cxa_atexit` / `exit` call lands on our thunk instead. fn atexit_thunk_addr(name: &str) -> u64 { match name { "atexit" => jit_atexit_thunk as *const () as usize as u64, "__cxa_atexit" => jit_cxa_atexit_thunk as *const () as usize as u64, + "exit" => jit_exit_thunk as *const () as usize as u64, _ => 0, } } @@ -259,7 +275,18 @@ mod jit_impl { options: NativeOptions, ) -> Result { let target = host_target()?; - let build = lower_for_jit(program, target, options)?; + let mut build = lower_for_jit(program, target, options)?; + + // Undefined extern functions: the lowering partitioned each + // call / address site targeting a placeholder ent_pc into + // `user_extern_call_sites`, and there is no link step to + // resolve them. Executing such a site would branch to the + // zeroed placeholder, so refuse up front, mirroring the + // linker's diagnosis. + if let Some(site) = build.user_extern_call_sites.first() { + return Err(undefined_reference(&site.symbol_name)); + } + route_jit_data_imports(&mut build)?; // Allocate a writable data region, copy `build.data` in. The // page is RW (no exec permission); an attempt to execute @@ -307,6 +334,20 @@ mod jit_impl { // exactly the way the ELF loader's relocations would. let mut got_region = GotRegion::new(build.imports.imports.len())?; got_region.bind_imports(&build.imports)?; + // A data import's GOT slot must resolve: unlike a function + // import (whose 0 slot faults only if called), the patched + // code loads the slot's value as an object address and + // dereferences it. + for fx in &build.got_fixups { + if fx.is_data_load && got_region.slot_value(fx.import_index) == 0 { + return Err(C5Error::Compile(crate::c5::error::fmt_internal_err( + &format!( + "JIT: unresolved extern data symbol `{}`", + build.imports.imports[fx.import_index].real_symbol, + ), + ))); + } + } let got_vmaddr = got_region.as_ptr() as u64; // Allocate the code region. Patch fixups against the mmap'd @@ -588,6 +629,62 @@ mod jit_impl { Ok(exit_code as i32) } + /// Mirror the linker's undefined-symbol diagnostic wording. + fn undefined_reference(name: &str) -> C5Error { + C5Error::Compile(crate::c5::error::fmt_link_err(&format!( + "undefined reference to `{name}`" + ))) + } + + /// Route `#pragma binding(data ...)` references through the fake + /// GOT. The emitters record each extern-data site as a named + /// [`super::super::UserExternDataRef`]; register the binding's host + /// symbol as a flat-lookup import so `bind_imports` resolves it via + /// the loader and `apply_jit_fixups` rewrites the site into a + /// GOT-slot load -- the JIT equivalent of the loader-bound data + /// import an AOT image gets. A leftover reference has no binding + /// and no definition anywhere: refuse it like the linker would. + fn route_jit_data_imports(build: &mut Build) -> Result<(), C5Error> { + if build.user_extern_data_refs.is_empty() { + return Ok(()); + } + let hosts: alloc::collections::BTreeMap = build + .imports + .data_bindings + .iter() + .map(|(local, host, dylib)| (local.clone(), (host.clone(), *dylib))) + .collect(); + let mut import_for: alloc::collections::BTreeMap = + alloc::collections::BTreeMap::new(); + for r in core::mem::take(&mut build.user_extern_data_refs) { + let Some((host, dylib)) = hosts.get(&r.symbol_name) else { + return Err(undefined_reference(&r.symbol_name)); + }; + let idx = *import_for.entry(r.symbol_name.clone()).or_insert_with(|| { + let i = build.imports.imports.len(); + build.imports.imports.push(ResolvedImport { + binding_idx: i as i64, + local_name: r.symbol_name.clone(), + real_symbol: host.clone(), + dylib_index: *dylib, + flat_lookup: true, + is_variadic: false, + fixed_args: 0, + return_type_tag: 0, + returns_long_double: false, + param_types: alloc::vec::Vec::new(), + }); + i + }); + build.got_fixups.push(GotFixup { + adrp_offset: r.instr_offset, + import_index: idx, + is_data_load: true, + }); + } + Ok(()) + } + fn lower_for_jit( program: &Program, target: Target, @@ -1250,6 +1347,14 @@ mod jit_impl { self.ptr } + /// Read back the resolved address in slot `idx`; 0 means + /// `bind_imports` could not resolve the symbol. + fn slot_value(&self, idx: usize) -> u64 { + // SAFETY: `bind_imports` wrote slot `idx` within the + // region sized from the import count. + unsafe { std::ptr::read_unaligned(self.ptr.add(idx * 8) as *const u64) } + } + /// Resolve a symbol name to its runtime address through the /// loader handles bound by `bind_imports`. Used for /// pointer-to-extern-data initializers; 0 means unresolved. @@ -1343,14 +1448,26 @@ mod jit_impl { build: &Build, ) -> Result<(), C5Error> { for fx in &build.got_fixups { - patch_got_call( - target, - code, - code_vmaddr, - fx.adrp_offset as u64, - got_vmaddr + (fx.import_index as u64) * 8, - "GOT fixup", - )?; + let slot_vmaddr = got_vmaddr + (fx.import_index as u64) * 8; + if fx.is_data_load { + patch_got_data_load( + target, + code, + code_vmaddr, + fx.adrp_offset as u64, + slot_vmaddr, + "GOT data fixup", + )?; + } else { + patch_got_call( + target, + code, + code_vmaddr, + fx.adrp_offset as u64, + slot_vmaddr, + "GOT fixup", + )?; + } } for fx in &build.data_fixups { patch_addr_load( @@ -1398,8 +1515,11 @@ mod jit_impl { } /// aarch64 `adrp Xd, page; ldr Xd, [Xd, #imm12]` patcher. The - /// loaded value at `target_vmaddr` is the GOT slot's stored - /// libc address; the JIT'd `blr xd` then dispatches there. + /// value loaded from `target_vmaddr` is the GOT slot's stored + /// host address; a call site follows with `blr xd`, a data + /// site continues with the address in `xd`. The destination + /// register is recovered from the placeholder adrp (x16 at + /// call sites, the allocator's choice at data sites). fn patch_adrp_ldr( code: &mut [u8], code_vmaddr: u64, @@ -1424,17 +1544,51 @@ mod jit_impl { &format!("JIT: {label} slot offset {in_page:#x} not 8-aligned"), ))); } - let adrp_word = super::super::aarch64::enc_adrp(super::super::aarch64::Reg::X16, imm21); - let ldr_word = super::super::aarch64::enc_ldr_imm( - super::super::aarch64::Reg::X16, - super::super::aarch64::Reg::X16, - in_page, - ); + let prev_adrp = + u32::from_le_bytes([code[off], code[off + 1], code[off + 2], code[off + 3]]); + let rd = super::super::aarch64::Reg((prev_adrp & 0x1F) as u8); + let adrp_word = super::super::aarch64::enc_adrp(rd, imm21); + let ldr_word = super::super::aarch64::enc_ldr_imm(rd, rd, in_page); code[off..off + 4].copy_from_slice(&adrp_word.to_le_bytes()); code[off + 4..off + 8].copy_from_slice(&ldr_word.to_le_bytes()); Ok(()) } + /// Patch an extern-data reference so the register receives the + /// imported object's address from its GOT slot. aarch64 rewrites + /// the `adrp + add` placeholder into `adrp + ldr` (same shape as + /// a call's slot load); x86_64 flips the emitter's + /// `lea rd, [rip+disp32]` into `mov rd, [rip+disp32]` -- the + /// rewrite the PE writer's IAT data path applies. + fn patch_got_data_load( + target: Target, + code: &mut [u8], + code_vmaddr: u64, + instr_offset: u64, + target_vmaddr: u64, + label: &str, + ) -> Result<(), C5Error> { + match target { + Target::MacOSAarch64 | Target::LinuxAarch64 | Target::WindowsAarch64 => { + patch_adrp_ldr(code, code_vmaddr, instr_offset, target_vmaddr, label) + } + Target::LinuxX64 | Target::WindowsX64 => { + let op_off = instr_offset as usize + 1; + if code[op_off] != 0x8D { + return Err(C5Error::Compile(crate::c5::error::fmt_internal_err( + &format!( + "JIT: {label} expected lea opcode 0x8D at text+{op_off:#x}, \ + found {:#04x}", + code[op_off], + ), + ))); + } + code[op_off] = 0x8B; + patch_lea_rip32(code, code_vmaddr, instr_offset, target_vmaddr, label) + } + } + } + /// x86_64 `call qword [rip + disp32]` patcher. disp32 is /// measured from the byte just past the call (i.e. from /// `instr_vmaddr + CALL_QWORD_RIP32_LEN`). diff --git a/src/c5/codegen/mod.rs b/src/c5/codegen/mod.rs index 330f063a6..c8549331e 100644 --- a/src/c5/codegen/mod.rs +++ b/src/c5/codegen/mod.rs @@ -232,9 +232,7 @@ pub(super) fn pc_extent_for_lowering( // highest `end_pc`; the codegen's per-`Inst::Call` fixup // pass uses the same dense `pc_to_native` table to // recognise them as out-of-range, so the table has to - // cover the placeholder range too. `extern_function_imports` - // is empty for every build that didn't go through the - // relocatable -c path. + // cover the placeholder range too. let from_imports = program .extern_function_imports .iter() @@ -1287,9 +1285,9 @@ pub(crate) struct Build { /// resolution. The `OutputKind::Relocatable` writer emits one /// undefined-extern symbol per unique name plus one /// `R_AARCH64_CALL26` / `R_X86_64_PLT32` reloc per call site - /// in `.rela.text`. Final-image writers leave the field - /// untouched because no `extern_function_imports` ever land - /// in a single-TU compile path. + /// in `.rela.text`. The JIT refuses a build with entries here + /// (`undefined reference`); final-image writers leave the + /// field untouched. #[allow(dead_code)] // consumed only by the std-only elf_reloc writer pub user_extern_call_sites: Vec, /// Cross-TU data references. Populated by the SSA emitters diff --git a/src/c5/codegen/x86_64/encode.rs b/src/c5/codegen/x86_64/encode.rs index 218ee4a6a..1c351df36 100644 --- a/src/c5/codegen/x86_64/encode.rs +++ b/src/c5/codegen/x86_64/encode.rs @@ -2146,8 +2146,7 @@ pub(crate) fn lower( // `apply_fixups` and re-emit them as // `Build::user_extern_call_sites` entries that the writer // surfaces as `R_X86_64_PLT32` relocs against the - // callee's symbol. Empty for builds without - // `CompileOptions::no_entry_point`. + // callee's symbol. let extern_pc_lookup: alloc::collections::BTreeMap = program .extern_function_imports .iter() diff --git a/src/c5/compiler/mod.rs b/src/c5/compiler/mod.rs index 19d25c9a4..09951dfb2 100644 --- a/src/c5/compiler/mod.rs +++ b/src/c5/compiler/mod.rs @@ -1567,48 +1567,21 @@ impl Compiler { // `target_ent_pc`. self.emit_sys_trampolines(); self.resolve_code_relocs()?; - // macOS resolves a `#pragma binding(data ...)` import (e.g. - // environ) through the GOT -- a flat-namespace bind to the host - // data symbol -- not through a COPY-relocated local slot, so the - // symbol must stay undefined even in a self-contained image. The - // no_entry_point clear below does this for relocatable objects; - // do the same for a data binding's local here regardless of - // no_entry_point so `live_glo_addr` returns `GloAddr::Extern` and - // routes the reference through `imm_data_extern` to the GOT - // rather than an uninitialized `.data` slot. - if self.target == Target::MacOSAarch64 { - let data_locals: alloc::collections::BTreeSet = self - .dylibs - .iter() - .flat_map(|d| d.bindings.iter()) - .filter(|b| b.is_data) - .map(|b| b.local_name.clone()) - .collect(); - for sym in self.symbols.iter_mut() { - if sym.class == Token::Glo as i64 - && sym.is_extern_decl - && !sym.has_initializer - && data_locals.contains(&sym.name) - { - sym.defined_here = false; - sym.val = 0; - } - } - } - // Cross-TU function imports. Every extern-declared - // `Token::Fun` symbol with no body in this TU gets a - // unique placeholder ent_pc (past `text.len()`), then has - // `Symbol::val` rewritten to that PC. The walker reads - // `Symbol::val` through `live_fun_val` when lowering an - // `Inst::Call`, so the matching call site carries the - // placeholder as its `target_pc`. The native codegen - // detects the placeholder (outside `[0, text.len())`) - // and emits a `RelocCallSite` against the symbol's name - // instead of resolving in place. Single-TU compiles - // without `no_entry_point` never reach this branch with - // an unresolved call: `resolve_entry_and_dllmain_pcs` - // errors out first. - let extern_imports = if self.no_entry_point { + // Cross-TU / undefined extern linkage. One model for every + // consumer: the linker resolves the references, the VM and + // the JIT refuse the unresolved ones, and no mode falls + // back to phantom storage or a colliding pc. + // + // Every extern-declared `Token::Fun` symbol with no body in + // this TU gets a unique placeholder ent_pc (past + // `text.len()`), then has `Symbol::val` rewritten to that + // PC. The walker reads `Symbol::val` through `live_fun_val` + // when lowering an `Inst::Call`, so the matching call site + // carries the placeholder as its `target_pc`. The native + // codegen detects the placeholder (outside `[0, + // text.len())`) and emits a `RelocCallSite` against the + // symbol's name instead of resolving in place. + let extern_imports = { use crate::c5::symbol::Linkage; let mut imports: alloc::vec::Vec<(usize, String)> = alloc::vec::Vec::new(); let mut next_pc = self.next_ent_pc + 1; @@ -1634,7 +1607,10 @@ impl Compiler { // walker emits `Inst::ImmData(stale_offset)` and the // ET_REL writer lowers it as a `.data section symbol + // 0` reloc, losing the symbol identity needed for - // cross-TU resolution. + // cross-TU resolution. The same clear keeps a `#pragma + // binding(data ...)` local (e.g. environ) undefined so + // its references route through the GOT / loader import + // instead of an uninitialized local slot. for sym in self.symbols.iter_mut() { if sym.class == Token::Glo as i64 && sym.linkage == Linkage::External @@ -1671,8 +1647,6 @@ impl Compiler { } } imports - } else { - alloc::vec::Vec::new() }; let (entry_pc, dllmain_pc, resolved_entry_name) = self.resolve_entry_and_dllmain_pcs()?; let exports = self.resolve_exports()?; diff --git a/src/c5/error.rs b/src/c5/error.rs index 02b165e97..1df4f4572 100644 --- a/src/c5/error.rs +++ b/src/c5/error.rs @@ -67,7 +67,7 @@ pub(crate) fn fmt_internal_err(message: &str) -> String { /// live in the linker module and the final-image writers, so under /// `--no-default-features --lib` this helper would otherwise /// trip the dead-code lint. -#[cfg(feature = "native-emit")] +#[cfg(any(feature = "native-emit", feature = "std"))] pub(crate) fn fmt_link_err(message: &str) -> String { use alloc::format; format!("error: {message}") diff --git a/src/c5/tests/codegen.rs b/src/c5/tests/codegen.rs index 4e5ec4ec0..7b2942856 100644 --- a/src/c5/tests/codegen.rs +++ b/src/c5/tests/codegen.rs @@ -1819,7 +1819,9 @@ fn foreign_cst16_section_lands_sixteen_aligned_in_image() { // non-empty `.got` ahead of `.data` (the placement the alignment // rounding must correct). let program = super::compile_str_bare( - "int puts(const char *s); \ + "#pragma dylib(libc, \"libc.so.6\")\n\ + #pragma binding(libc::puts, \"puts\")\n\ + int puts(const char *s); \ int main(void) { return puts(\"x\"); }", ); let opts = NativeOptions { diff --git a/src/c5/tests/dwarf.rs b/src/c5/tests/dwarf.rs index 37f70cc8b..9c31afbfb 100644 --- a/src/c5/tests/dwarf.rs +++ b/src/c5/tests/dwarf.rs @@ -716,29 +716,35 @@ fn debug_line_has_per_statement_rows() { /// Locals that stay in the frame keep their fbreg location. #[test] fn promoted_local_has_empty_location() { - let src = "long f(long n){ long base = n + 100; long acc = 0; long i = 0;\ - while (i < 3) { acc = acc + base; i = i + 1; } return acc; }\ + let src = "long f(long n){ long base = n + 100; long keep = n; long *pk = &keep;\ + long acc = 0; long i = 0;\ + while (i < 3) { acc = acc + base + *pk; i = i + 1; } return acc; }\ int main(void){ return (int)f(5); }"; let path = build_signed_mach_o_opt(src, "promoted_local_loc", true); let Some(out) = dwarfdump_debug_info(&path) else { return; }; - // `base` is single-def and read across the loop -> promoted; its - // location is empty. `acc` and `i` are loop-carried (a join phi), - // so they stay in the frame with a real fbreg location. - let base_at = out - .find("(\"base\")") - .unwrap_or_else(|| panic!("no `base` variable in:\n{out}")); - let after_base = &out[base_at..]; - let base_loc_end = after_base.find("DW_TAG").unwrap_or(after_base.len()); + // `base` is address-free -> promoted; its location is empty. + // `keep` has its address taken (`pk`), so it stays in the frame + // with a real fbreg location. Both checks are scoped to the + // variable's own DIE so unrelated subprograms can't satisfy them. + let loc_of = |name: &str| { + let at = out + .find(&format!("(\"{name}\")")) + .unwrap_or_else(|| panic!("no `{name}` variable in:\n{out}")); + let after = &out[at..]; + let end = after.find("DW_TAG").unwrap_or(after.len()); + &after[..end] + }; assert!( - after_base[..base_loc_end].contains("DW_AT_location\t()"), + loc_of("base").contains("DW_AT_location\t()"), "promoted local `base` should have an empty location, got:\n{}", - &after_base[..base_loc_end] + loc_of("base"), ); assert!( - out.contains("(\"acc\")") && out.contains("DW_OP_fbreg"), - "non-promoted locals should keep an fbreg location:\n{out}" + loc_of("keep").contains("DW_OP_fbreg"), + "address-taken local `keep` should keep an fbreg location, got:\n{}", + loc_of("keep"), ); let _ = std::fs::remove_file(&path); } diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index d59f37dd5..2fad014b0 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1119,6 +1119,9 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("pthread_key_once_width.c", 0), ("dev_t_width.c", 0), ("libc_int_arith.c", 0), + // Data binding (environ) read through the fake GOT; the site + // patching is the JIT counterpart of the AOT flat-lookup import. + ("environ_single_tu.c", 0), ("switch_default_routing.c", 100), ("control_flow.c", 1), ("do_while.c", 5), @@ -1776,3 +1779,102 @@ fn jit_resolves_pointer_to_extern_data() { int main(void) { return (*p == 0) ? 1 : 0; }\n"; assert_eq!(jit_exit(src, &[]), 0); } + +// A `#pragma binding(data ...)` global read from code (not just a +// static initializer) must patch like the AOT path: the site loads +// the host cell's address from the fake GOT. Previously the +// UserExternDataRef sites were never patched and the read faulted. +#[cfg(unix)] +#[test] +fn jit_reads_binding_data_global() { + let src = "#include \n\ + int main(void) {\n\ + int n = 0;\n\ + for (char **e = environ; *e; e++) n++;\n\ + return n > 0 ? 0 : 1;\n\ + }\n"; + let program = Compiler::new(src.to_string()).compile().expect("compile"); + assert_eq!( + jit_run(&program, &["jit-environ".to_string()]).expect("jit_run"), + 0 + ); +} + +/// Mirror the linker: a call to a declared-but-undefined extern must +/// refuse to run instead of dispatching to whatever function sits at +/// the placeholder-colliding ent_pc. +#[test] +fn undefined_extern_call_is_a_link_error() { + let program = Compiler::new( + "int bar(int);\n\ + int helper(int x) { return x + 1; }\n\ + int main(void) { return bar(41); }" + .to_string(), + ) + .compile() + .expect("compile"); + let err = jit_run(&program, &["jit-undef-call".to_string()]).expect_err("must not run"); + let msg = err.to_string(); + assert!(msg.contains("undefined reference to `bar`"), "{msg}"); +} + +#[test] +fn undefined_extern_object_is_a_link_error() { + let program = Compiler::new( + "extern int missing_obj;\n\ + int main(void) { return missing_obj + 7; }" + .to_string(), + ) + .compile() + .expect("compile"); + let err = jit_run(&program, &["jit-undef-obj".to_string()]).expect_err("must not run"); + let msg = err.to_string(); + assert!( + msg.contains("undefined reference to `missing_obj`"), + "{msg}" + ); +} + +/// C99 7.20.4.3p2: `exit` runs the registered atexit handlers. The +/// JIT intercepts both `atexit` and `exit`, so the handler chain must +/// drain before the process terminates with the passed status. `exit` +/// ends the whole process, so the assertion drives a re-executed copy +/// of this test binary gated by the marker env var. +#[test] +fn atexit_handlers_run_on_libc_exit() { + if let Ok(marker) = std::env::var("BADC_JIT_EXIT_MARKER") { + let src = format!( + "#include \n\ + #include \n\ + static void h(void) {{\n\ + FILE *f = fopen(\"{marker}\", \"w\");\n\ + if (f) {{ fputs(\"ran\", f); fclose(f); }}\n\ + }}\n\ + int main(void) {{ atexit(h); exit(42); }}\n", + ); + let program = Compiler::new(src).compile().expect("compile"); + let _ = jit_run(&program, &["jit-exit".to_string()]); + unreachable!("exit(42) must terminate the process"); + } + let marker = std::env::temp_dir().join(format!("badc_jit_exit_{}", std::process::id())); + let _ = std::fs::remove_file(&marker); + // libtest names tests without the crate segment of module_path!. + let module = module_path!(); + let module = module.split_once("::").map_or(module, |(_, rest)| rest); + let test_name = format!("{module}::atexit_handlers_run_on_libc_exit"); + let out = std::process::Command::new(std::env::current_exe().expect("current_exe")) + .args(["--exact", &test_name, "--test-threads=1"]) + .env("BADC_JIT_EXIT_MARKER", &marker) + .output() + .expect("re-exec the test binary"); + assert_eq!( + out.status.code(), + Some(42), + "stdout: {}\nstderr: {}", + String::from_utf8_lossy(&out.stdout), + String::from_utf8_lossy(&out.stderr), + ); + let contents = std::fs::read_to_string(&marker).expect("atexit handler must write the marker"); + let _ = std::fs::remove_file(&marker); + assert_eq!(contents, "ran"); +} diff --git a/src/c5/tests/parser.rs b/src/c5/tests/parser.rs index 589676f9c..e7554d70d 100644 --- a/src/c5/tests/parser.rs +++ b/src/c5/tests/parser.rs @@ -422,22 +422,33 @@ fn field_access_on_opaque_struct_is_rejected() { #[test] fn extern_and_static_keywords_are_no_op_at_global_scope() { use super::run_str; - // `extern` and `static` may appear before the type prefix - // (with or without `_Thread_local`); both are accepted and - // ignored. The semantics of the resulting decl are - // identical to the no-prefix form -- the global lives in - // .data with zero init -- so the program runs the same - // way it would without the keywords. + // `static` (and the accepted `static extern` combination) + // before the type prefix produce a tentative definition (C99 + // 6.9.2p2): the global lives in .data with zero init. let src = " - extern int a; static int b; static extern int c; int main() { - a = 1; b = 2; c = 3; - return a + b + c; + b = 2; c = 3; + return b + c; } "; - assert_eq!(run_str(&super::with_prelude(src)), 6); + assert_eq!(run_str(src), 5); + // A file-scope `extern int a;` defines no storage (C99 6.2.2p4 + // / 6.9.2); with no defining TU anywhere, a program that uses + // it fails with the linker's undefined-reference diagnosis + // instead of reading phantom zeroed storage. + let src = " + extern int a; + int main() { a = 1; return a; } + "; + let err = crate::Vm::new(super::compile_str(src)) + .run() + .expect_err("undefined extern object must not run"); + assert!( + err.to_string().contains("undefined reference to `a`"), + "{err}" + ); } #[test] diff --git a/src/c5/vm/mod.rs b/src/c5/vm/mod.rs index 9a5e05af6..f5e667b19 100644 --- a/src/c5/vm/mod.rs +++ b/src/c5/vm/mod.rs @@ -57,6 +57,18 @@ pub struct Vm { /// (walker compile errors, etc.) are deferred to `run` /// because `with_host` doesn't return `Result`. ssa_funcs: Result, C5Error>, + /// Cross-TU placeholder ent_pc -> symbol name for every + /// declared-but-undefined extern function. `run` refuses any + /// reference to these, mirroring the linker. + extern_fn_names: alloc::collections::BTreeMap, + /// `(name, defined_here)` per parser symbol, indexed by the + /// sym idx the `FunctionSsa::extern_*_refs` tables carry. + symbol_defs: Vec<(String, bool)>, + /// Local names bound to host data (`#pragma binding(data ...)`). + data_binding_locals: alloc::collections::BTreeSet, + /// `target_ent_pc` of every static-initializer function + /// pointer, checked against `extern_fn_names` at `run`. + code_reloc_pcs: Vec, } /// `Vm::new` is only available with the `std` feature; it picks the @@ -86,6 +98,28 @@ impl Vm { .iter() .flat_map(|d| d.bindings.iter().map(|b| b.local_name.clone())) .collect(); + let extern_fn_names = program + .extern_function_imports + .iter() + .map(|(pc, name)| (*pc, name.clone())) + .collect(); + let symbol_defs = program + .symbols + .iter() + .map(|s| (s.name.clone(), s.defined_here)) + .collect(); + let data_binding_locals = program + .dylibs + .iter() + .flat_map(|d| d.bindings.iter()) + .filter(|b| b.is_data) + .map(|b| b.local_name.clone()) + .collect(); + let code_reloc_pcs = program + .code_relocs + .iter() + .map(|r| r.target_ent_pc as usize) + .collect(); // Concatenate the TLS block onto the data segment so // `Inst::TlsAddr` resolutions ride the existing data-side // access checks. The starting offset is captured before @@ -115,7 +149,65 @@ impl Vm { track_pointers: false, tls_base, ssa_funcs, + extern_fn_names, + symbol_defs, + data_binding_locals, + code_reloc_pcs, + } + } + + /// Refuse any reference to a symbol with no definition in + /// this unit before execution starts, mirroring the linker's + /// undefined-symbol diagnosis. Without this, a call whose + /// placeholder pc collides with a real `ent_pc` dispatches to + /// the wrong function and an extern object reads a zero slot. + fn check_extern_refs(&self, funcs: &[FunctionSsa]) -> Result<(), C5Error> { + use super::ir::Inst; + let undef = + |name: &str| C5Error::Runtime(alloc::format!("undefined reference to `{name}`")); + for f in funcs { + for inst in &f.insts { + let pc = match inst { + Inst::Call { target_pc, .. } => *target_pc, + Inst::ImmCode(pc) => *pc, + _ => continue, + }; + if let Some(name) = self.extern_fn_names.get(&pc) { + return Err(undef(name)); + } + } + // `target_pc == 0` call / code-address sites record the + // parser sym; the sentinel is ambiguous (the first + // function's ent_pc is also 0), so consult the symbol. + for &(_, sym) in f.extern_call_refs.iter().chain(&f.extern_imm_code_refs) { + if let Some((name, defined)) = self.symbol_defs.get(sym as usize) + && !defined + { + return Err(undef(name)); + } + } + for &(_, sym) in f.extern_imm_data_refs.iter().chain(&f.extern_tls_refs) { + let Some((name, defined)) = self.symbol_defs.get(sym as usize) else { + continue; + }; + if *defined { + continue; + } + if self.data_binding_locals.contains(name) { + return Err(C5Error::Runtime(alloc::format!( + "`{name}` is bound to host data; the interpreter cannot \ + reach host memory (use --jit or compile natively)" + ))); + } + return Err(undef(name)); + } + } + for pc in &self.code_reloc_pcs { + if let Some(name) = self.extern_fn_names.get(pc) { + return Err(undef(name)); + } } + Ok(()) } /// Enable per-instruction trace output. Mirrors @@ -164,6 +256,7 @@ impl Vm { if funcs.is_empty() { return Err(C5Error::Runtime("empty program".to_string())); } + self.check_extern_refs(funcs)?; ssa::run_program_with_args_tracked( funcs, &self.data, diff --git a/src/c5/vm/ssa.rs b/src/c5/vm/ssa.rs index 2dcd86182..5938c34d5 100644 --- a/src/c5/vm/ssa.rs +++ b/src/c5/vm/ssa.rs @@ -244,10 +244,13 @@ impl Memory { "vm_ssa: stack overflow allocating {frame_bytes} bytes from {base}", )) })?; - if next > self.bytes.len() { + // Frames must stay inside [stack_base, heap_base); a frame + // written past heap_base would zero live heap allocations. + if next > self.heap_base { return Err(C5Error::Runtime(format!( - "vm_ssa: stack overflow ({next} > {})", - self.bytes.len(), + "vm_ssa: stack overflow: frame of {frame_bytes} bytes exceeds the \ + {}-byte stack region", + self.heap_base - self.stack_base, ))); } // Zero the new frame's bytes so undefined reads observe @@ -512,7 +515,30 @@ pub(super) fn run_program_with_args_tracked( } else { &entry_args }; - run_func(&prog, &mut mem, host, entry, slice) + match run_func(&prog, &mut mem, host, entry, slice) { + Err(e) => match exit_status_of(&e) { + Some(status) => Ok(status), + None => Err(e), + }, + ok => ok, + } +} + +/// `exit(status)` unwinds the interpreter through the `Result` +/// channel. The sentinel stays private to this module: it is +/// produced only by the `exit` shim and consumed at the program +/// boundary above, so it never surfaces as a user-visible error. +const EXIT_SIGNAL_PREFIX: &str = "vm_ssa-exit-status:"; + +fn exit_signal(status: i64) -> C5Error { + C5Error::Runtime(format!("{EXIT_SIGNAL_PREFIX}{status}")) +} + +fn exit_status_of(e: &C5Error) -> Option { + match e { + C5Error::Runtime(msg) => msg.strip_prefix(EXIT_SIGNAL_PREFIX)?.parse().ok(), + _ => None, + } } /// Lay out the argv strings + the argv pointer array at the end @@ -1142,13 +1168,13 @@ fn dispatch_callext( host: &mut H, ) -> Result { match name { - // `exit(int code)` terminates the host process in libc; - // inside the SSA-VM we route it through a sentinel error - // that the outer driver can catch and convert to the - // overall return value. + // `exit(int code)` terminates the hosted program (C99 + // 7.20.4.3). The Err unwinds every interpreter frame; + // `run_program_with_args_tracked` converts the sentinel + // back into an Ok(status) at the program boundary. "exit" => { let code = args.first().copied().unwrap_or(0); - Err(C5Error::Runtime(format!("vm_ssa: exit({code})"))) + Err(exit_signal(code)) } // `void *memcpy(void *dst, const void *src, size_t n)`. // c5's cdecl pushes args right-to-left; the walker @@ -1282,12 +1308,10 @@ fn dispatch_callext( } Ok(0) } - // `int printf(const char *fmt, ...)` -- minimal subset - // (%d / %u / %x / %c / %s / %%). Walks the variadic - // tail in `args[1..]`, formats into a String, and writes - // it to stdout via the host. Returns 0 (printf returns - // bytes written; no caller depends on the exact value - // in the current fixture set). + // `int printf(const char *fmt, ...)` -- formats the + // variadic tail in `args[1..]` per C99 7.19.6.1 and + // writes the bytes to stdout via the host. Returns the + // number of bytes transmitted (7.19.6.3p3). "printf" => { let fmt_addr = *args .first() @@ -1300,7 +1324,7 @@ fn dispatch_callext( let fmt = read_cstring_bytes(mem, fmt_addr as usize)?; let out = format_printf(&fmt, &args[1..], mem)?; let _ = host.write(1, &out); - Ok(0) + Ok(out.len() as i64) } // `int putchar(int c)` -- write one byte to stdout, returns // the byte (or EOF on error; we return the byte unconditionally). @@ -1458,16 +1482,51 @@ fn read_cstring(mem: &Memory, addr: usize) -> Result Result, C5Error> { - use core::fmt::Write; +/// Argument-width selector from a conversion spec's length +/// modifier (C99 7.19.6.1p7). The variadic tail holds one i64 +/// per argument; the modifier decides how many low bits carry +/// the value. +#[derive(Clone, Copy, PartialEq, Eq)] +enum ArgLen { + Char, // hh + Short, // h + Int, // (none) + Long, // l / ll / j / z / t / L +} + +/// One parsed conversion specification (C99 7.19.6.1p4). +struct PrintfSpec { + minus: bool, + plus: bool, + space: bool, + alt: bool, + zero: bool, + width: Option, + precision: Option, + len: ArgLen, + conv: u8, +} + +/// printf formatter (C99 7.19.6.1). Parses the full spec grammar +/// -- flags, width (incl. `*`), precision (incl. `.*`), length +/// modifiers -- and pulls arguments from `args` as each +/// conversion requires. Returns the raw output bytes for the +/// caller to hand to `host.write`. An unrecognised conversion +/// emits its spec text verbatim without consuming an argument +/// (undefined per 7.19.6.1p9). +fn format_printf(fmt: &[u8], args: &[i64], mem: &mut Memory) -> Result, C5Error> { let mut out: Vec = Vec::new(); - let mut num = alloc::string::String::new(); let mut arg_idx = 0usize; + let next_arg = |arg_idx: &mut usize| -> Result { + let val = args.get(*arg_idx).copied().ok_or_else(|| { + C5Error::Runtime(format!( + "vm_ssa: printf: format wants arg #{arg_idx} but only {} supplied", + args.len(), + )) + })?; + *arg_idx += 1; + Ok(val) + }; let mut i = 0usize; while i < fmt.len() { let c = fmt[i]; @@ -1476,70 +1535,326 @@ fn format_printf(fmt: &[u8], args: &[i64], mem: &Memory) -> Result, C5Er out.push(c); continue; } - let Some(&spec) = fmt.get(i) else { - break; + let spec_start = i; + let mut s = PrintfSpec { + minus: false, + plus: false, + space: false, + alt: false, + zero: false, + width: None, + precision: None, + len: ArgLen::Int, + conv: 0, }; - i += 1; - if spec == b'%' { - out.push(b'%'); - continue; + while let Some(&f) = fmt.get(i) { + match f { + b'-' => s.minus = true, + b'+' => s.plus = true, + b' ' => s.space = true, + b'#' => s.alt = true, + b'0' => s.zero = true, + _ => break, + } + i += 1; + } + if fmt.get(i) == Some(&b'*') { + i += 1; + // A negative `*` width means `-` flag plus the + // absolute value (7.19.6.1p5). + let w = next_arg(&mut arg_idx)? as i32; + s.width = Some(w.unsigned_abs() as usize); + s.minus |= w < 0; + } else { + while let Some(d) = fmt.get(i).filter(|d| d.is_ascii_digit()) { + s.width = Some(s.width.unwrap_or(0) * 10 + (d - b'0') as usize); + i += 1; + } } - let Some(val) = args.get(arg_idx).copied() else { - return Err(C5Error::Runtime(format!( - "vm_ssa: printf: format wants arg #{arg_idx} but only {} supplied", - args.len(), - ))); - }; - arg_idx += 1; - match spec { - b'd' | b'i' => { - num.clear(); - let _ = write!(num, "{}", val as i32 as i64); - out.extend_from_slice(num.as_bytes()); + if fmt.get(i) == Some(&b'.') { + i += 1; + if fmt.get(i) == Some(&b'*') { + i += 1; + // A negative `*` precision reads as omitted (p5). + let p = next_arg(&mut arg_idx)? as i32; + s.precision = (p >= 0).then_some(p as usize); + } else { + s.precision = Some(0); + while let Some(d) = fmt.get(i).filter(|d| d.is_ascii_digit()) { + s.precision = Some(s.precision.unwrap_or(0) * 10 + (d - b'0') as usize); + i += 1; + } + } + } + match fmt.get(i) { + Some(b'h') => { + i += 1; + s.len = ArgLen::Short; + if fmt.get(i) == Some(&b'h') { + i += 1; + s.len = ArgLen::Char; + } + } + Some(b'l') => { + i += 1; + s.len = ArgLen::Long; + if fmt.get(i) == Some(&b'l') { + i += 1; + } } - b'u' => { - num.clear(); - let _ = write!(num, "{}", val as u32 as u64); - out.extend_from_slice(num.as_bytes()); + Some(b'j') | Some(b'z') | Some(b't') | Some(b'L') => { + i += 1; + s.len = ArgLen::Long; } - b'x' => { - num.clear(); - let _ = write!(num, "{:x}", val as u32); - out.extend_from_slice(num.as_bytes()); + _ => {} + } + let Some(&conv) = fmt.get(i) else { + // Incomplete trailing spec: emit verbatim. + out.push(b'%'); + out.extend_from_slice(&fmt[spec_start..]); + break; + }; + i += 1; + s.conv = conv; + match conv { + b'%' => out.push(b'%'), + b'd' | b'i' => { + let raw = next_arg(&mut arg_idx)?; + let v = match s.len { + ArgLen::Char => raw as i8 as i64, + ArgLen::Short => raw as i16 as i64, + ArgLen::Int => raw as i32 as i64, + ArgLen::Long => raw, + }; + let sign = if v < 0 { + "-" + } else if s.plus { + "+" + } else if s.space { + " " + } else { + "" + }; + let digits = format!("{}", v.unsigned_abs()); + push_int(&mut out, &s, sign, &digits, v == 0); } - b'X' => { - num.clear(); - let _ = write!(num, "{:X}", val as u32); - out.extend_from_slice(num.as_bytes()); + b'u' | b'o' | b'x' | b'X' => { + let raw = next_arg(&mut arg_idx)?; + let v = match s.len { + ArgLen::Char => raw as u8 as u64, + ArgLen::Short => raw as u16 as u64, + ArgLen::Int => raw as u32 as u64, + ArgLen::Long => raw as u64, + }; + let digits = match conv { + b'u' => format!("{v}"), + b'o' => format!("{v:o}"), + b'x' => format!("{v:x}"), + _ => format!("{v:X}"), + }; + // `#`: force a leading 0 on octal; prefix 0x / 0X + // on a nonzero hex value (7.19.6.1p6). + let (prefix, digits) = match conv { + b'o' if s.alt && !digits.starts_with('0') => ("", format!("0{digits}")), + b'x' if s.alt && v != 0 => ("0x", digits), + b'X' if s.alt && v != 0 => ("0X", digits), + _ => ("", digits), + }; + push_int(&mut out, &s, prefix, &digits, v == 0); } b'c' => { - out.push(val as u8); + let v = next_arg(&mut arg_idx)?; + push_padded(&mut out, &s, &[v as u8]); } b's' => { + let val = next_arg(&mut arg_idx)?; if val < 0 { return Err(C5Error::Runtime(format!( "vm_ssa: printf %s: bad ptr 0x{val:x}", ))); } - let s = read_cstring_bytes(mem, val as usize)?; - out.extend_from_slice(&s); + let mut bytes = read_cstring_bytes(mem, val as usize)?; + if let Some(p) = s.precision { + bytes.truncate(p); + } + push_padded(&mut out, &s, &bytes); } b'p' => { - num.clear(); - let _ = write!(num, "0x{:x}", val as u64); - out.extend_from_slice(num.as_bytes()); + let v = next_arg(&mut arg_idx)? as u64; + push_padded(&mut out, &s, format!("0x{v:x}").as_bytes()); + } + b'f' | b'F' | b'e' | b'E' | b'g' | b'G' => { + let v = f64::from_bits(next_arg(&mut arg_idx)? as u64); + let body = format_float(v, &s); + push_int( + &mut out, + &s, + if v.is_sign_negative() && !v.is_nan() { + "-" + } else if s.plus { + "+" + } else if s.space { + " " + } else { + "" + }, + &body, + false, + ); + } + b'n' => { + // Store the byte count written so far (7.19.6.1p8). + let addr = next_arg(&mut arg_idx)?; + if addr < 0 { + return Err(C5Error::Runtime(format!( + "vm_ssa: printf %n: bad ptr 0x{addr:x}", + ))); + } + let kind = match s.len { + ArgLen::Char => StoreKind::I8, + ArgLen::Short => StoreKind::I16, + ArgLen::Int => StoreKind::I32, + ArgLen::Long => StoreKind::I64, + }; + store_to_memory(mem, addr as usize, out.len() as i64, kind)?; } - other => { - // Unrecognised conversion: emit the literal - // `%X` so the caller sees what was wrong. + _ => { out.push(b'%'); - out.push(other); + out.extend_from_slice(&fmt[spec_start..i]); } } } Ok(out) } +/// Pad `body` to the spec's field width (7.19.6.1p5): spaces on +/// the left by default, on the right under `-`. +fn push_padded(out: &mut Vec, s: &PrintfSpec, body: &[u8]) { + let pad = s.width.unwrap_or(0).saturating_sub(body.len()); + if !s.minus { + out.resize(out.len() + pad, b' '); + } + out.extend_from_slice(body); + if s.minus { + out.resize(out.len() + pad, b' '); + } +} + +/// Assemble a numeric conversion: precision zero-extends the +/// digit string (and suppresses a zero value at precision 0); +/// the `0` flag zero-pads between the sign / base prefix and the +/// digits unless `-` or an explicit precision overrides it +/// (7.19.6.1p6). +fn push_int(out: &mut Vec, s: &PrintfSpec, prefix: &str, digits: &str, is_zero: bool) { + let mut digits = alloc::string::String::from(digits); + if let Some(p) = s.precision + && !matches!(s.conv, b'f' | b'F' | b'e' | b'E' | b'g' | b'G') + { + if is_zero && p == 0 { + digits.clear(); + } + while digits.len() < p { + digits.insert(0, '0'); + } + } + let body_len = prefix.len() + digits.len(); + let pad = s.width.unwrap_or(0).saturating_sub(body_len); + let zero_pad = s.zero + && !s.minus + && (matches!(s.conv, b'f' | b'F' | b'e' | b'E' | b'g' | b'G') || s.precision.is_none()); + if zero_pad { + out.extend_from_slice(prefix.as_bytes()); + out.resize(out.len() + pad, b'0'); + out.extend_from_slice(digits.as_bytes()); + return; + } + if !s.minus { + out.resize(out.len() + pad, b' '); + } + out.extend_from_slice(prefix.as_bytes()); + out.extend_from_slice(digits.as_bytes()); + if s.minus { + out.resize(out.len() + pad, b' '); + } +} + +/// Format `|v|` for the f / e / g conversion families +/// (7.19.6.1p8); the caller prepends the sign and applies the +/// field width. Uppercase conversions upper-case the result. +fn format_float(v: f64, s: &PrintfSpec) -> alloc::string::String { + let upper = matches!(s.conv, b'F' | b'E' | b'G'); + if v.is_nan() { + return if upper { "NAN".into() } else { "nan".into() }; + } + if v.is_infinite() { + return if upper { "INF".into() } else { "inf".into() }; + } + let av = v.abs(); + let p = s.precision.unwrap_or(6); + let body = match s.conv { + b'f' | b'F' => { + let mut b = format!("{av:.p$}"); + if s.alt && p == 0 { + b.push('.'); + } + b + } + b'e' | b'E' => format_exp(av, p, s.alt), + _ => { + // g/G: precision P counts significant digits (0 reads + // as 1). Style e when the exponent X < -4 or X >= P, + // else style f with precision P-1-X; trailing zeros + // drop unless `#`. + let pp = p.max(1); + let exp = decimal_exponent(av, pp - 1); + let mut b = if exp < -4 || exp >= pp as i32 { + format_exp(av, pp - 1, s.alt) + } else { + format!("{:.*}", (pp as i32 - 1 - exp).max(0) as usize, av) + }; + if !s.alt && b.contains('.') { + let frac_end = b.find(['e', 'E']).unwrap_or(b.len()); + let trimmed = b[..frac_end].trim_end_matches('0').trim_end_matches('.'); + b = format!("{}{}", trimmed, &b[frac_end..]); + } + b + } + }; + if upper { body.to_uppercase() } else { body } +} + +/// `d.dddde±dd` with `prec` fraction digits (7.19.6.1p8, the e +/// conversion). Rust's `{:e}` produces `d.ddddeN`; rewrite the +/// exponent into the sign + minimum-two-digit C form. +fn format_exp(av: f64, prec: usize, alt: bool) -> alloc::string::String { + let raw = format!("{av:.prec$e}"); + let (mantissa, exp) = raw.split_once('e').unwrap_or((raw.as_str(), "0")); + let exp: i32 = exp.parse().unwrap_or(0); + let mut mantissa = alloc::string::String::from(mantissa); + if alt && prec == 0 { + mantissa.push('.'); + } + format!( + "{mantissa}e{}{:02}", + if exp < 0 { '-' } else { '+' }, + exp.unsigned_abs(), + ) +} + +/// Decimal exponent of `av` after rounding to `prec` fraction +/// digits in e-style -- the X in C99 7.19.6.1p8's g rules. +/// Deriving it from the rounded e form keeps the boundary cases +/// (9.99... rounding up a decade) consistent with the output. +fn decimal_exponent(av: f64, prec: usize) -> i32 { + if av == 0.0 { + return 0; + } + let raw = format!("{av:.prec$e}"); + raw.split_once('e') + .and_then(|(_, e)| e.parse().ok()) + .unwrap_or(0) +} + /// Parse `(dst/buf, src/buf, n)` argument triples used by /// memcpy / memcmp. Validates the size argument and converts /// pointer args to `usize`. @@ -1989,18 +2304,85 @@ mod tests { // 0xC3 0xA9 (the UTF-8 encoding of U+00E9) must reach stdout as // those two raw bytes, not the 4-byte Latin-1 -> UTF-8 re-encoding // the old path produced. - let mem = Memory::new(b"\xC3\xA9\x00"); - let out = format_printf(b"%s", &[0], &mem).expect("format"); + let mut mem = Memory::new(b"\xC3\xA9\x00"); + let out = format_printf(b"%s", &[0], &mut mem).expect("format"); assert_eq!(out, alloc::vec![0xC3u8, 0xA9]); } #[test] fn printf_char_preserves_high_byte() { - let mem = Memory::new(b"\x00"); - let out = format_printf(b"%c", &[0x80], &mem).expect("format"); + let mut mem = Memory::new(b"\x00"); + let out = format_printf(b"%c", &[0x80], &mut mem).expect("format"); assert_eq!(out, alloc::vec![0x80u8]); } + fn fmt1(fmt: &[u8], args: &[i64]) -> alloc::string::String { + let mut mem = Memory::new(b"abcdef\x00"); + let out = format_printf(fmt, args, &mut mem).expect("format"); + alloc::string::String::from_utf8(out).expect("utf8") + } + + #[test] + fn printf_width_precision_flags() { + // C99 7.19.6.1p5-p6: field width, precision, and the + // -, +, 0, # flags across the integer conversions. + assert_eq!(fmt1(b"%5d", &[42]), " 42"); + assert_eq!(fmt1(b"%-5d|", &[42]), "42 |"); + assert_eq!(fmt1(b"%05d", &[-42]), "-0042"); + assert_eq!(fmt1(b"%+d %+d", &[7, -7]), "+7 -7"); + assert_eq!(fmt1(b"% d", &[7]), " 7"); + assert_eq!(fmt1(b"%.5d", &[42]), "00042"); + assert_eq!(fmt1(b"%8.5d", &[42]), " 00042"); + assert_eq!(fmt1(b"%.0d", &[0]), ""); + assert_eq!(fmt1(b"%#x %#o", &[255, 8]), "0xff 010"); + assert_eq!(fmt1(b"%08x", &[0xbeef]), "0000beef"); + assert_eq!(fmt1(b"%*d", &[5, 42]), " 42"); + assert_eq!(fmt1(b"%-*d|", &[5, 42]), "42 |"); + assert_eq!(fmt1(b"%.*d", &[4, 42]), "0042"); + assert_eq!(fmt1(b"%10.3s|", &[0]), " abc|"); + assert_eq!(fmt1(b"%-6.2s|", &[0]), "ab |"); + assert_eq!(fmt1(b"%3c|", &[b'z' as i64]), " z|"); + } + + #[test] + fn printf_length_modifiers() { + // C99 7.19.6.1p7: hh / h narrow, l / ll / z / j keep the + // full 64-bit value; the default int case truncates to 32. + assert_eq!(fmt1(b"%ld", &[0x1_0000_0001]), "4294967297"); + assert_eq!(fmt1(b"%lld", &[-1]), "-1"); + assert_eq!(fmt1(b"%d", &[0x1_0000_0001]), "1"); + assert_eq!(fmt1(b"%hhd", &[0x1ff]), "-1"); + assert_eq!(fmt1(b"%hu", &[0x1_0005]), "5"); + assert_eq!(fmt1(b"%zu", &[u64::MAX as i64]), "18446744073709551615"); + assert_eq!(fmt1(b"%lx", &[-1]), "ffffffffffffffff"); + } + + #[test] + fn printf_float_conversions() { + let b = |v: f64| v.to_bits() as i64; + assert_eq!(fmt1(b"%f", &[b(3.5)]), "3.500000"); + assert_eq!(fmt1(b"%.2f", &[b(6.54321)]), "6.54"); + assert_eq!(fmt1(b"%8.3f", &[b(-6.54321)]), " -6.543"); + assert_eq!(fmt1(b"%08.3f", &[b(-6.54321)]), "-006.543"); + assert_eq!(fmt1(b"%e", &[b(65432.1875)]), "6.543219e+04"); + assert_eq!(fmt1(b"%.2E", &[b(0.00123)]), "1.23E-03"); + assert_eq!(fmt1(b"%g", &[b(0.0001)]), "0.0001"); + assert_eq!(fmt1(b"%g", &[b(0.00001)]), "1e-05"); + assert_eq!(fmt1(b"%g", &[b(100.0)]), "100"); + assert_eq!(fmt1(b"%.3g", &[b(1234.5)]), "1.23e+03"); + assert_eq!(fmt1(b"%f", &[b(f64::NAN)]), "nan"); + assert_eq!(fmt1(b"%F", &[b(f64::INFINITY)]), "INF"); + } + + #[test] + fn printf_percent_n_stores_count() { + // C99 7.19.6.1p8: %n stores the bytes written so far. + let mut mem = Memory::new(&[0u8; 16]); + let out = format_printf(b"abc%nd", &[8], &mut mem).expect("format"); + assert_eq!(out, b"abcd".to_vec()); + assert_eq!(load_from_memory(&mem, 8, LoadKind::I32).unwrap(), 3); + } + fn ssa_main_of(src: &str) -> FunctionSsa { let program = Compiler::new(src.to_string()) .compile() @@ -2041,6 +2423,127 @@ mod tests { .expect("ssa run") } + #[test] + fn exit_terminates_with_status() { + // C99 7.20.4.3: `exit(status)` ends the program with that + // status; the interpreter reports it as the program result + // instead of a runtime error. + assert_eq!( + run_full_program( + "#include + int main(void) { exit(7); return 1; }", + ), + 7, + ); + } + + #[test] + fn frame_allocation_is_bounded_by_the_stack_region() { + // A frame past `heap_base` would zero live heap + // allocations; exhaustion must be a hard error instead. + let mut mem = Memory::new(&[]); + let heap = mem.heap_alloc(16); + mem.bytes[heap] = 7; + let stack_bytes = mem.heap_base - mem.stack_base; + let err = mem.alloc_frame(stack_bytes + 8).expect_err("must overflow"); + match err { + C5Error::Runtime(m) => assert!(m.contains("stack overflow"), "{m}"), + other => panic!("expected Runtime, got {other:?}"), + } + assert_eq!( + mem.bytes[heap], 7, + "heap byte must survive the failed frame" + ); + } + + #[test] + fn deep_recursion_errors_instead_of_corrupting_the_heap() { + // 40 frames x ~8 KiB exceeds the 256 KiB stack region but + // stays inside the old `bytes.len()` bound, which silently + // wiped heap allocations. + let program = Compiler::new( + "int f(int n) { char buf[8192]; buf[0] = (char)n; \ + if (n == 0) return buf[0]; return f(n - 1); } \ + int main(void) { return f(40); }" + .to_string(), + ) + .compile() + .expect("compile fixture"); + let funcs = super::super::super::codegen::ssa::shadow::produce_ssa_funcs( + &program, + super::super::super::Target::MacOSAarch64, + ) + .expect("ssa lift"); + let mut host = super::super::super::host::StdHost::default(); + let err = run_program(&funcs, &program.data, &[], program.entry_pc, &mut host) + .expect_err("recursion past the stack region must fail"); + match err { + crate::C5Error::Runtime(m) => assert!(m.contains("stack overflow"), "{m}"), + other => panic!("expected Runtime, got {other:?}"), + } + } + + fn expect_runtime_err(src: &str, needle: &str) { + let program = Compiler::new(src.to_string()) + .compile() + .expect("compile fixture"); + let err = crate::Vm::new(program).run().expect_err("run must fail"); + match err { + crate::C5Error::Runtime(m) => assert!(m.contains(needle), "`{m}` lacks `{needle}`"), + other => panic!("expected Runtime, got {other:?}"), + } + } + + #[test] + fn undefined_extern_call_is_undefined_reference() { + // A declared-but-undefined callee must not dispatch to the + // function whose ent_pc collides with the placeholder. + expect_runtime_err( + "int bar(int); int helper(int x) { return x + 1; } \ + int main(void) { return bar(41); }", + "undefined reference to `bar`", + ); + } + + #[test] + fn undefined_variadic_extern_call_is_undefined_reference() { + // main sits at ent_pc 0 here; the pre-fix sentinel made + // this call recurse into main until the host stack overflowed. + expect_runtime_err( + "int ghost(int, ...); int main(void) { return ghost(1, 2); }", + "undefined reference to `ghost`", + ); + } + + #[test] + fn undefined_extern_object_is_undefined_reference() { + // C99 6.9.2: `extern int x;` defines no storage; reading it + // with no defining TU is a link error, not a zero read. + expect_runtime_err( + "extern int missing_obj; int main(void) { return missing_obj + 7; }", + "undefined reference to `missing_obj`", + ); + } + + #[test] + fn undefined_extern_fn_pointer_is_undefined_reference() { + expect_runtime_err( + "int bar(int); int main(void) { int (*fp)(int) = bar; return fp(1); }", + "undefined reference to `bar`", + ); + } + + #[test] + fn bound_data_global_is_diagnosed_under_interp() { + // `environ` binds to host data; the interpreter's memory + // model cannot reach the host cell, so the reference is a + // clean diagnostic rather than a phantom NULL read. + expect_runtime_err( + "#include \nint main(void) { return environ != 0; }", + "bound to host data", + ); + } + #[test] fn return_constant() { // C99 5.1.2.2.3: `int main(void) { return 42; }` -- the From c6db534b1b764a0b8695d25223bcf86a2bba3a62 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 21:58:51 -0700 Subject: [PATCH 39/67] preprocessor: alias-chain blue paint, #if fixes, __has_include dirs Five conformance fixes plus one input-handling fix: * Object-like alias chains (`#define A B` / `#define B C` / `#define C B x`) paint every intermediate name for the rescan (C99 6.10.3.4p2); the chain walk previously painted only the head, so the rescan re-fired an intermediate and duplicated tokens. A revisited name now ends the walk instead of looping to the cap. * `__has_include("h")` resolves its quoted form against the including file's directory and `__has_include_next` resumes past the current file's search-path entry, exactly as the matching directives do (C99 6.10.2p2); both previously ran a plain angle-include search. * `#if` character constants decode hexadecimal and octal escape sequences (C99 6.4.4.4) and sign-extend a single-character constant on signed-plain-char targets, matching the lexer. * `#if` ternaries apply the usual arithmetic conversions across both arms (C99 6.5.15p5), so `(1 ? -1 : 0u) > 0` compares unsigned. * An `#elif` / `#else` / `#endif` met while joining macro-argument lines with no locally opened frame belongs to the conditional enclosing the macro call; it now updates the outer stack (shared helpers keep both walks identical) instead of being swallowed and leaving the block unterminated. * A UTF-8 byte-order mark opening a file is skipped, following gcc and clang. Co-Authored-By: Claude Fable 5 --- src/c5/preprocessor.rs | 464 +++++++++++++++++++++++++++++++---------- 1 file changed, 353 insertions(+), 111 deletions(-) diff --git a/src/c5/preprocessor.rs b/src/c5/preprocessor.rs index 16c4c9095..fd1cb3825 100644 --- a/src/c5/preprocessor.rs +++ b/src/c5/preprocessor.rs @@ -718,6 +718,9 @@ impl Preprocessor { /// about; the top-level call uses `""`, `#include`'d /// files use the header name (`"stdio.h"`). fn process_named(&mut self, source: &str, filename: &str) -> Result { + // A UTF-8 byte-order mark opening the file is accepted and + // skipped, following gcc and clang. + let source = source.strip_prefix('\u{feff}').unwrap_or(source); // c99 sec 5.1.1.2 phase 2: every `\\\n` joins lines. We do this // up-front so the line-by-line preprocessor never sees a // continuation. Line counts are preserved by emitting blank @@ -872,7 +875,7 @@ impl Preprocessor { active = taken; } Directive::If(expr) => { - let taken = active && self.eval_condition(expr, source_line)?; + let taken = active && self.eval_condition(expr, source_line, filename)?; cond_stack.push(CondFrame { parent_active: active, this_branch_taken: taken, @@ -882,73 +885,18 @@ impl Preprocessor { active = taken; } Directive::Else => { - let frame = cond_stack.last_mut().ok_or_else(|| { - C5Error::Compile(super::error::fmt_compile_err( - filename, - line_no, - "`#else` with no matching `#if`", - )) - })?; - if frame.saw_else { - return Err(C5Error::Compile(super::error::fmt_compile_err( - filename, - line_no, - "duplicate `#else` for the same `#if`", - ))); - } - frame.saw_else = true; - let taken = frame.parent_active && !frame.any_branch_taken; - frame.this_branch_taken = taken; - frame.any_branch_taken |= taken; - active = taken; + active = apply_else(&mut cond_stack, filename, line_no)?; } Directive::Elif(expr) => { - // The directive eval needs a `&Self`, but - // `cond_stack.last_mut()` borrows `self` for - // the frame -- evaluate the expression first - // and only then mutate the frame. - let parent_active = - cond_stack.last().map(|f| f.parent_active).ok_or_else(|| { - C5Error::Compile(super::error::fmt_compile_err( - filename, - line_no, - "`#elif` with no matching `#if`", - )) - })?; - let any_taken_so_far = cond_stack - .last() - .map(|f| f.any_branch_taken) - .unwrap_or(false); - let eligible = parent_active && !any_taken_so_far; - let cond = if eligible { - self.eval_condition(expr, source_line)? - } else { - false - }; - // Non-empty by the `parent_active` ok_or_else above. - let frame = cond_stack - .last_mut() - .expect("cond_stack non-empty after parent_active check"); - if frame.saw_else { - return Err(C5Error::Compile(super::error::fmt_compile_err( - filename, - line_no, - "`#elif` after `#else` for the same `#if`", - ))); - } - frame.this_branch_taken = cond; - frame.any_branch_taken |= cond; - active = cond; + // The directive eval needs a `&Self`, but the + // frame update borrows `cond_stack` -- check + // eligibility first, evaluate, then mutate. + let eligible = elif_eligible(&cond_stack, filename, line_no)?; + let cond = eligible && self.eval_condition(expr, source_line, filename)?; + active = apply_elif(&mut cond_stack, cond, filename, line_no)?; } Directive::Endif => { - let frame = cond_stack.pop().ok_or_else(|| { - C5Error::Compile(super::error::fmt_compile_err( - filename, - line_no, - "`#endif` with no matching `#if`", - )) - })?; - active = frame.parent_active; + active = apply_endif(&mut cond_stack, filename, line_no)?; } Directive::Pragma(args) => { if active { @@ -1238,8 +1186,8 @@ impl Preprocessor { join_active = taken; } Directive::If(expr) => { - let taken = - join_active && self.eval_condition(expr, source_line)?; + let taken = join_active + && self.eval_condition(expr, source_line, filename)?; join_stack.push(CondFrame { parent_active: join_active, this_branch_taken: taken, @@ -1248,37 +1196,45 @@ impl Preprocessor { }); join_active = taken; } + // An `#elif` / `#else` / `#endif` with no + // frame opened inside the argument list + // belongs to the conditional enclosing the + // macro call; apply it to the outer stack so + // argument gathering resumes in the right + // branch and the outer frame still closes. Directive::Elif(expr) => { - let parent_active = - join_stack.last().map(|f| f.parent_active).unwrap_or(false); - let any_taken = join_stack - .last() - .map(|f| f.any_branch_taken) - .unwrap_or(true); - let eligible = parent_active && !any_taken; - let cond = if eligible { - self.eval_condition(expr, source_line)? + let stack = if join_stack.is_empty() { + &mut cond_stack } else { - false + &mut join_stack }; - if let Some(frame) = join_stack.last_mut() { - frame.this_branch_taken = cond; - frame.any_branch_taken |= cond; + let eligible = elif_eligible(stack, filename, source_line)?; + let cond = + eligible && self.eval_condition(expr, source_line, filename)?; + let taken = apply_elif(stack, cond, filename, source_line)?; + if join_stack.is_empty() { + active = taken; } - join_active = cond; + join_active = taken; } Directive::Else => { - if let Some(frame) = join_stack.last_mut() { - let taken = frame.parent_active && !frame.any_branch_taken; - frame.saw_else = true; - frame.this_branch_taken = taken; - frame.any_branch_taken |= taken; - join_active = taken; + let stack = if join_stack.is_empty() { + &mut cond_stack + } else { + &mut join_stack + }; + let taken = apply_else(stack, filename, source_line)?; + if join_stack.is_empty() { + active = taken; } + join_active = taken; } Directive::Endif => { if let Some(frame) = join_stack.pop() { join_active = frame.parent_active; + } else { + active = apply_endif(&mut cond_stack, filename, source_line)?; + join_active = active; } } // Other directives inside a macro argument are @@ -1774,10 +1730,19 @@ impl Preprocessor { // INC(...) calls expanded too. Hot path is the // not-a-macro case -- the early `None` saves an // allocation per source identifier. - match self.expand(ident) { + match self.expand_chain(ident) { None => out.push_str(ident), - Some(expanded) => { - let nested = Blocklist::Cons(ident, blocklist); + Some((expanded, chain)) => { + // Paint the name and every chain intermediate + // (C99 6.10.3.4p2) so the rescan cannot re-fire + // a macro the walk already went through. + let mut painted: Vec<&str> = alloc::vec![ident]; + for c in &chain { + if !painted.contains(&c.as_str()) { + painted.push(c); + } + } + let nested = Blocklist::Many(&painted, blocklist); // Token-stream rescan (C99 6.10.3.4): if the // expansion is a single identifier and the // *source* token immediately after the @@ -1884,18 +1849,31 @@ impl Preprocessor { /// non-macro identifiers than macro hits) and lets callers skip /// allocating a String just to compare it back against the input. fn expand(&self, name: &str) -> Option { + self.expand_chain(name).map(|(body, _)| body) + } + + /// `expand` plus the chain of intermediate macro names the walk + /// passed through. C99 6.10.3.4p2 paints every name replaced + /// during the rescan, so the caller must add the chain to the + /// blocklist -- otherwise a terminal body that re-mentions an + /// intermediate (`#define B C` / `#define C B x`) re-fires it and + /// duplicates tokens. A revisited name ends the walk. + fn expand_chain(&self, name: &str) -> Option<(String, Vec)> { let first = self.macros.get(name)?; - // We've got at least one substitution. Follow the - // `#define A B` -> `#define B 5` chain up to a fixed depth so - // a `#define A A` self-loop doesn't spin forever. + let mut chain: Vec = Vec::new(); let mut current = first.clone(); - for _ in 0..32 { + while chain.len() < 32 { + if current == name || chain.iter().any(|c| c == ¤t) { + break; + } match self.macros.get(¤t) { - Some(next) if next != ¤t => current = next.clone(), - _ => break, + Some(next) => { + chain.push(core::mem::replace(&mut current, next.clone())); + } + None => break, } } - Some(current) + Some((current, chain)) } /// `expand` but with the original name returned (allocated as a @@ -1986,7 +1964,7 @@ impl Preprocessor { strip_c_comments(&substituted) } - fn eval_condition(&self, expr: &str, line_no: usize) -> Result { + fn eval_condition(&self, expr: &str, line_no: usize, filename: &str) -> Result { // Full c99 `#if` expression evaluator: integer constants, // identifiers (treated as 0 if undefined), `defined(X)`, // unary `!`, comparisons, and boolean operators with @@ -2003,7 +1981,7 @@ impl Preprocessor { // substitute would otherwise expand X away. let prepared = self.expand_for_if(expr, line_no); self.take_pending_error()?; - let mut p = IfExprParser::new(&prepared, self); + let mut p = IfExprParser::new(&prepared, self, filename); let v = p.parse_ternary()?; p.skip_ws(); if !p.at_end() { @@ -3410,6 +3388,89 @@ impl CondFrame { } } +/// `#else` state transition on the innermost frame; returns the new +/// active state. Shared by the main directive loop and the +/// macro-argument line joiner so both agree on the semantics. +fn apply_else(stack: &mut [CondFrame], filename: &str, line_no: usize) -> Result { + let frame = stack.last_mut().ok_or_else(|| { + C5Error::Compile(super::error::fmt_compile_err( + filename, + line_no, + "`#else` with no matching `#if`", + )) + })?; + if frame.saw_else { + return Err(C5Error::Compile(super::error::fmt_compile_err( + filename, + line_no, + "duplicate `#else` for the same `#if`", + ))); + } + frame.saw_else = true; + let taken = frame.parent_active && !frame.any_branch_taken; + frame.this_branch_taken = taken; + frame.any_branch_taken |= taken; + Ok(taken) +} + +/// Whether an `#elif` on the innermost frame is eligible to take +/// (parent branch active, no earlier arm taken). C99 6.10.1p3: the +/// controlling expression of an ineligible group is not evaluated, +/// so the caller evaluates only when this returns true. +fn elif_eligible(stack: &[CondFrame], filename: &str, line_no: usize) -> Result { + let frame = stack.last().ok_or_else(|| { + C5Error::Compile(super::error::fmt_compile_err( + filename, + line_no, + "`#elif` with no matching `#if`", + )) + })?; + Ok(frame.parent_active && !frame.any_branch_taken) +} + +/// `#elif` state transition with the already-evaluated condition; +/// returns the new active state. +fn apply_elif( + stack: &mut [CondFrame], + cond: bool, + filename: &str, + line_no: usize, +) -> Result { + let frame = stack.last_mut().ok_or_else(|| { + C5Error::Compile(super::error::fmt_compile_err( + filename, + line_no, + "`#elif` with no matching `#if`", + )) + })?; + if frame.saw_else { + return Err(C5Error::Compile(super::error::fmt_compile_err( + filename, + line_no, + "`#elif` after `#else` for the same `#if`", + ))); + } + frame.this_branch_taken = cond; + frame.any_branch_taken |= cond; + Ok(cond) +} + +/// `#endif` pops the innermost frame; returns the restored active state. +fn apply_endif( + stack: &mut Vec, + filename: &str, + line_no: usize, +) -> Result { + let frame = stack.pop().ok_or_else(|| { + C5Error::Compile(super::error::fmt_compile_err( + filename, + line_no, + "`#endif` with no matching `#if`", + )) + })?; + Ok(frame.parent_active) +} + enum Directive<'a> { /// Object-like macro: `#define NAME body`. Define(&'a str, &'a str), @@ -4009,6 +4070,11 @@ struct IfExprParser<'a> { src: &'a str, pos: usize, pp: &'a Preprocessor, + /// Path of the file whose `#if` is being evaluated; + /// `__has_include("h")` resolves its quoted form against this + /// file's directory, and `__has_include_next` resumes the search + /// past this file's search-path entry. + filename: &'a str, /// Recursion depth, bounded by [`MAX_IF_EXPR_DEPTH`]. Every recursive /// cycle in the grammar passes through `parse_unary`, so the bound is /// checked there. @@ -4021,11 +4087,12 @@ struct IfExprParser<'a> { } impl<'a> IfExprParser<'a> { - fn new(src: &'a str, pp: &'a Preprocessor) -> Self { + fn new(src: &'a str, pp: &'a Preprocessor, filename: &'a str) -> Self { Self { src, pos: 0, pp, + filename, depth: 0, live: true, } @@ -4109,7 +4176,15 @@ impl<'a> IfExprParser<'a> { self.live = saved && !cond.truthy(); let else_v = self.parse_ternary()?; self.live = saved; - Ok(if cond.truthy() { then_v } else { else_v }) + // C99 6.5.15p5: the arms undergo the usual arithmetic + // conversions, so either arm being unsigned makes the result + // unsigned regardless of which arm is picked. + let uns = then_v.is_unsigned() || else_v.is_unsigned(); + let picked = if cond.truthy() { then_v } else { else_v }; + Ok(match picked { + IfValue::Int { val, .. } => IfValue::with_sign(val, uns), + other => other, + }) } fn parse_and(&mut self) -> Result { @@ -4410,34 +4485,73 @@ impl<'a> IfExprParser<'a> { self.pos += 1; } if self.eat_byte(b'\'') { - // Character literal -- a single byte, optionally escaped. - // Multi-char (`'AB'`) is implementation-defined; we use - // the last byte, which matches gcc's choice. + // Character literal. Multi-char (`'AB'`) is + // implementation-defined; each byte shifts into the + // accumulator, matching gcc. let bytes = self.src.as_bytes(); let mut acc: i64 = 0; + let mut count = 0usize; while let Some(b) = self.peek_byte() { if b == b'\'' { self.pos += 1; + // C99 6.4.4.4p10: a single-character constant has + // the char's value as int -- sign-extended on + // signed-plain-char targets, matching the lexer. + if count == 1 && self.pp.target.plain_char_signed() && (0..=0xFF).contains(&acc) + { + acc = acc as u8 as i8 as i64; + } return Ok(IfValue::signed(acc)); } + count += 1; if b == b'\\' && self.pos + 1 < bytes.len() { self.pos += 2; let esc = bytes[self.pos - 1]; - let ch = match esc { + // C99 6.4.4.4: simple, octal (`\N` up to three + // digits), and hexadecimal (`\xN...`) escapes. + let ch: i64 = match esc { b'n' => 0x0A, b't' => 0x09, b'r' => 0x0D, - b'0' => 0x00, - b'\\' => b'\\', - b'\'' => b'\'', - b'"' => b'"', + b'\\' => b'\\' as i64, + b'\'' => b'\'' as i64, + b'"' => b'"' as i64, b'a' => 0x07, b'b' => 0x08, b'f' => 0x0C, b'v' => 0x0B, - other => other, + b'x' => { + let mut v: i64 = 0; + while let Some(&h) = bytes.get(self.pos) { + let d = match h { + b'0'..=b'9' => h - b'0', + b'a'..=b'f' => h - b'a' + 10, + b'A'..=b'F' => h - b'A' + 10, + _ => break, + }; + v = (v << 4) | d as i64; + self.pos += 1; + } + v & 0xFF + } + b'0'..=b'7' => { + let mut v = (esc - b'0') as i64; + let mut n = 1; + while n < 3 { + match bytes.get(self.pos) { + Some(&o @ b'0'..=b'7') => { + v = (v << 3) | (o - b'0') as i64; + self.pos += 1; + n += 1; + } + _ => break, + } + } + v + } + other => other as i64, }; - acc = (acc << 8) | (ch as i64); + acc = (acc << 8) | ch; } else { acc = (acc << 8) | (b as i64); self.pos += 1; @@ -4619,7 +4733,22 @@ impl<'a> IfExprParser<'a> { "preprocessor: missing `)` in `__has_include`".to_string(), )); } - let found = self.pp.find_include(&header, None).is_some(); + // Resolve exactly as the matching directive would: the + // quoted form probes the including file's directory first + // (C99 6.10.2p2), and `__has_include_next` resumes past + // the search-path entry that supplied the current file. + let found = if name == "__has_include_next" { + self.pp.find_include_next(&header, self.filename).is_some() + } else { + let source_dir = if close == b'"' { + include_parent_dir(self.filename) + } else { + None + }; + self.pp + .find_include(&header, source_dir.as_deref()) + .is_some() + }; return Ok(IfValue::signed(found as i64)); } // Identifier -- look up in the macro table. Function-like @@ -5877,6 +6006,119 @@ int x_2 = __COUNTER__; super::include_parent_dir("/abs/dir/src.c"), Some("/abs/dir".to_string()) ); + // The stdin label behaves like a bare filename: gcc resolves a + // quoted include in piped source against the working directory. + assert_eq!(super::include_parent_dir("-"), Some(String::new())); + } + + #[test] + fn object_like_alias_chain_blue_paints_intermediates() { + // C99 6.10.3.4p2: every name replaced on the way to the terminal + // body stays painted for the rescan. Without that, the rescan of + // `B x` re-fires B -> C -> `B x` and duplicates the tail. + let out = process("#define A B\n#define B C\n#define C B x\nA\n"); + let line = out.lines().rfind(|l| !l.trim().is_empty()).unwrap_or(""); + assert_eq!(line.trim(), "B x", "{out}"); + // Mutual recursion through an alias stops at the painted name. + let out = process("#define P Q\n#define Q P\nP\n"); + let line = out.lines().rfind(|l| !l.trim().is_empty()).unwrap_or(""); + assert_eq!(line.trim(), "P", "{out}"); + } + + #[test] + fn if_char_constant_decodes_hex_and_octal_escapes() { + for e in [ + "'\\x41' == 65", + "'\\101' == 65", + // Signed plain char on this target: '\xff' sign-extends. + "'\\xff' == -1", + "'\\x7f' == 127", + "'\\0' == 0", + "'\\11' == 9", + "'AB' == 0x4142", + ] { + let out = process(&format!("#if {e}\nTAKEN\n#else\nNOT\n#endif\n")); + assert!(out.contains("TAKEN"), "{e}: {out}"); + } + } + + #[test] + fn if_ternary_applies_usual_arithmetic_conversions() { + // C99 6.5.15p5: the arms convert to a common type, so an + // unsigned arm makes the picked signed arm's value unsigned. + for e in ["(1 ? -1 : 0u) > 0", "(0 ? 0u : -1) > 0"] { + let out = process(&format!("#if {e}\nTAKEN\n#else\nNOT\n#endif\n")); + assert!(out.contains("TAKEN"), "{e}: {out}"); + } + // Both arms signed: the value stays signed. + let out = process("#if (1 ? -1 : 0) < 0\nTAKEN\n#endif\n"); + assert!(out.contains("TAKEN"), "{out}"); + } + + #[test] + fn macro_args_split_across_an_enclosing_conditional() { + // An `#else` / `#endif` seen while joining macro-argument lines + // with no locally opened frame belongs to the enclosing + // conditional: the joiner must apply it to the outer stack, skip + // the inactive branch's lines, and leave the block terminated. + let src = "#define m(a,b) a+b\n#define A 1\n#if A\nint x = m(1,\n#else\nint x = m(2,\n#endif\n3);\n"; + let out = process(src); + assert!(out.contains("1+3"), "{out}"); + assert!(!out.contains("2+"), "{out}"); + // The not-taken arm joins the other branch's argument line. + let src = "#define m(a,b) a+b\n#if 0\nint x = m(1,\n#else\nint x = m(2,\n#endif\n3);\n"; + let out = process(src); + assert!(out.contains("2+3"), "{out}"); + } + + #[test] + fn has_include_quoted_form_searches_the_including_dir() { + // C99 6.10.2p2 via C23 6.10.1: the quoted `__has_include` form + // probes the including file's directory exactly as the matching + // `#include "h"` would. + let base = std::env::temp_dir().join(format!("badc-hasinc-{}", std::process::id())); + std::fs::create_dir_all(&base).unwrap(); + std::fs::write(base.join("inner.h"), "int inner;\n").unwrap(); + std::fs::write( + base.join("probe.h"), + "#if __has_include(\"inner.h\")\nint FOUND;\n#else\nint MISSING;\n#endif\n", + ) + .unwrap(); + let mut pp = Preprocessor::new("macos-aarch64", Target::MacOSAarch64, "0.1.0"); + pp.add_search_path(base.to_str().unwrap()); + let out = pp.process("#include \n").unwrap(); + std::fs::remove_dir_all(&base).ok(); + assert!(out.contains("FOUND"), "{out}"); + } + + #[test] + fn has_include_next_resumes_after_the_current_entry() { + // `__has_include_next` must answer what `#include_next` would + // resolve: found through a later search-path entry, not the + // probing shim's own file. + let base = std::env::temp_dir().join(format!("badc-hasincnext-{}", std::process::id())); + let d1 = base.join("d1"); + let d2 = base.join("d2"); + std::fs::create_dir_all(&d1).unwrap(); + std::fs::create_dir_all(&d2).unwrap(); + std::fs::write( + d1.join("foo.h"), + "#if __has_include_next()\nint NEXT_FOUND;\n#else\nint NEXT_MISSING;\n#endif\n", + ) + .unwrap(); + std::fs::write(d2.join("foo.h"), "int real;\n").unwrap(); + + let mut pp = Preprocessor::new("macos-aarch64", Target::MacOSAarch64, "0.1.0"); + pp.add_search_path(d1.to_str().unwrap()); + pp.add_search_path(d2.to_str().unwrap()); + let out = pp.process("#include \n").unwrap(); + assert!(out.contains("NEXT_FOUND"), "{out}"); + + let mut pp = Preprocessor::new("macos-aarch64", Target::MacOSAarch64, "0.1.0"); + pp.add_search_path(d1.to_str().unwrap()); + let out = pp.process("#include \n").unwrap(); + std::fs::remove_dir_all(&base).ok(); + assert!(out.contains("NEXT_MISSING"), "{out}"); } #[test] From fd78143b07bc2c63937b3698c156d7c805b6851d Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 21:59:13 -0700 Subject: [PATCH 40/67] lexer: diagnose bytes that cannot start a token A byte outside the token grammar (`$`, `@`, backtick, any non-ASCII byte outside a literal) was silently discarded, so the parse could re-synchronize into a different program (`*$p` compiled as `*p`). Such bytes are now a lex error quoting the offending byte. C99 6.4 white-space (VT, FF) and stray NULs stay ignored, following gcc. Co-Authored-By: Claude Fable 5 --- src/c5/lexer.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/src/c5/lexer.rs b/src/c5/lexer.rs index 95878dc4b..e81eb039c 100644 --- a/src/c5/lexer.rs +++ b/src/c5/lexer.rs @@ -1657,8 +1657,34 @@ impl Lexer { _ => { if "!~;{}()],:".contains(c) { self.tk = Tok(c as i64); - } else { + } else if matches!(c, ' ' | '\t' | '\r' | '\x0B' | '\x0C' | '\0') { + // C99 6.4p3 white-space characters separate + // tokens and are otherwise ignored. A NUL is + // ignored too, following gcc. + continue; + } else if c as u32 == 0xEF + && self.src.get(self.pos) == Some(&0xBB) + && self.src.get(self.pos + 1) == Some(&0xBF) + { + // UTF-8 byte-order mark; accepted and + // skipped, following gcc and clang. + self.pos += 2; continue; + } else { + // Any other byte cannot start a + // preprocessing token (C99 6.4); dropping + // it would let the parse re-synchronize + // into a different program. + let shown = if c.is_ascii_graphic() { + format!("`{c}`") + } else { + format!("byte 0x{:02X}", c as u32) + }; + return Err(C5Error::Compile(crate::c5::error::fmt_compile_err( + &self.file, + self.line, + &format!("unrecognized character {shown} in source"), + ))); } } } @@ -2070,6 +2096,40 @@ mod tests { lex.ival } + /// Drive the lexer over `src` until EOF or the first error. + fn lex_all(src: &str) -> Result<(), C5Error> { + let mut lex = Lexer::new(src.to_string()); + let mut symbols: Vec = Vec::new(); + let mut index = SymbolIndex::new(); + let mut data: Vec = Vec::new(); + loop { + lex.next(&mut symbols, &mut index, &mut data)?; + if lex.tk == Tok::EOF { + return Ok(()); + } + } + } + + #[test] + fn unrecognized_bytes_are_lex_errors() { + // A byte that cannot start a preprocessing token (C99 6.4) must + // be diagnosed, not dropped -- `*$p` re-synchronizing as `*p` + // compiles a different program. + for (src, shown) in [ + ("int b = *$p;", "`$`"), + ("int a = `3`;", "``"), + ("int a @ b;", "`@`"), + ("int caf\u{e9};", "byte 0xC3"), + ] { + let err = lex_all(src).expect_err(src); + assert!(format!("{err}").contains(shown), "{src}: {err}"); + } + // White-space characters and a leading UTF-8 BOM are not errors, + // and literals keep their bytes. + lex_all("\u{feff}int x;\x0C int \x0B y;").unwrap(); + lex_all("const char *s = \"caf\u{e9} $ @\";").unwrap(); + } + #[test] fn simple_escapes_decode_to_their_byte() { assert_eq!(lex_string_literal(r#""\n""#), vec![b'\n']); From 33ffad88e43dd0076169f8453358f316b4a2104c Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 22:01:05 -0700 Subject: [PATCH 41/67] link: per-entry prologue anchors, weak-undef to zero, section pads * `prologue_ends` is keyed by the function's merged entry offset instead of its bare name: two units' same-named static functions each keep their own post-prologue anchor, so Win-x64 .pdata and the DWARF CFA no longer describe a framed static as a frameless leaf copied from the first unit. * An unresolved STB_WEAK UNDEF with no dylib routing resolves to address 0 (ELF practice) instead of becoming a required import against dylib 0: branches become no-ops (the GNU linkers' AArch64 handling), address materializations produce 0 so the `if (fn) fn();` guard reads null, and `.data` pointer slots take 0 + addend. Unsupported instruction shapes are a diagnostic. * GNU version-name strings appended to `.dynstr` re-pad it to 8, so `.hash` / `.gnu.version` keep their claimed sh_addralign (gABI). * Unit bss bases and the merged file image pad to 16 so each object's compaction-preserved alignment residue survives the link. Co-Authored-By: Claude Fable 5 --- src/c5/linker/link.rs | 192 ++++++++++++++++++++++--- src/c5/linker/synth_build.rs | 4 +- src/c5/object/elf.rs | 6 + src/c5/tests/linker.rs | 265 +++++++++++++++++++++++++++++++++++ 4 files changed, 447 insertions(+), 20 deletions(-) diff --git a/src/c5/linker/link.rs b/src/c5/linker/link.rs index 17c632139..21698a92a 100644 --- a/src/c5/linker/link.rs +++ b/src/c5/linker/link.rs @@ -161,8 +161,10 @@ pub struct MergedNative { /// the result in little-endian over `width` bytes. pub debug_info_text_relocs: Vec, pub debug_line_text_relocs: Vec, - /// Per-function post-prologue byte offset in [`Self::text`]. - /// Sourced from the writer's synthetic + /// Post-prologue byte offset in [`Self::text`], keyed by the + /// function's merged entry offset (name-keying would collapse + /// same-named statics across units onto one anchor). Sourced + /// from the writer's synthetic /// `.Lc5_prologue_end_` STB_LOCAL STT_NOTYPE symbols /// (see `elf_reloc::PROLOGUE_END_PREFIX`), rebased by the /// per-unit text base. The synth path consults this to @@ -170,7 +172,7 @@ pub struct MergedNative { /// `dwarf::build_debug_frame` emits /// `DW_CFA_advance_loc ` ahead of the /// post-prologue CFA rule. - pub prologue_ends: BTreeMap, + pub prologue_ends: BTreeMap, /// Defined `STT_FUNC STB_LOCAL` (static) functions as /// `(name, merged_text_offset)`, rebased by the per-unit text base. /// Kept as a flat list separate from `defined` -- which is @@ -378,10 +380,19 @@ pub fn link_native_objects_with_options( data_align = data_align.max(obj.data_align); data_bases.push(data.len()); data.extend_from_slice(&obj.data); - bss_size = align_usize(bss_size, 8); + // Each unit's bss offsets carry an alignment residue modulo 16 + // (the `.bss` sh_addralign the per-unit writer claims); a + // 16-aligned unit base preserves it. + bss_size = align_usize(bss_size, 16); bss_bases.push(bss_size); bss_size += obj.bss_size; } + // The merged bss region begins at `data.len()` in the unified + // data-offset space; pad the file image so bss offsets keep their + // per-unit alignment residues in the final image. + if bss_size > 0 { + align_up(&mut data, data_align.max(16)); + } // Pass 2 -- defined symbols. Every `STB_GLOBAL` symbol that // lives in a `.text` / `.data` / `.bss` section in some @@ -447,10 +458,12 @@ pub fn link_native_objects_with_options( // STB_LOCAL STT_NOTYPE symbol per function at the post- // prologue native byte offset, named with the // `PROLOGUE_END_PREFIX` prefix; rebase its value by the - // unit's text base and key it on the source function name - // (the suffix). Duplicate names lose to the first writer - // (matches the `defined` rule for STB_GLOBAL above). - let mut prologue_ends: BTreeMap = BTreeMap::new(); + // unit's text base and key it on the *same unit's* function + // entry offset. Name-keying would hand a later unit's + // same-named static the first unit's anchor, describing a + // framed function as frameless in the Win-x64 .pdata / DWARF + // CFA output. + let mut prologue_ends: BTreeMap = BTreeMap::new(); for (i, obj) in objs.iter().enumerate() { for sym in &obj.symbols { if !matches!(sym.section, NativeSymSection::Text) { @@ -462,10 +475,16 @@ pub fn link_native_objects_with_options( if fn_name.is_empty() { continue; } - let merged_offset = text_bases[i] as u64 + sym.value; - prologue_ends - .entry(fn_name.to_string()) - .or_insert(merged_offset); + // STT_FUNC = 2. + let Some(fsym) = obj.symbols.iter().find(|s| { + s.kind == 2 && matches!(s.section, NativeSymSection::Text) && s.name == fn_name + }) else { + continue; + }; + prologue_ends.insert( + text_bases[i] as u64 + fsym.value, + text_bases[i] as u64 + sym.value, + ); } } @@ -551,6 +570,15 @@ pub fn link_native_objects_with_options( // (Mach-O). The PLT pass consults this to skip stub creation. let mut data_import_indices: alloc::collections::BTreeSet = alloc::collections::BTreeSet::new(); + // Names with dylib routing from any unit's binding map. The c5 `.o` + // writer emits its libc imports as STB_WEAK UNDEF paired with a map + // entry; a weak UNDEF *without* routing is a genuine unresolved weak + // reference (typically from a foreign object) and resolves to + // address 0 per ELF practice rather than becoming a required import. + let routed_import_names: alloc::collections::BTreeSet<&str> = objs + .iter() + .flat_map(|o| o.import_dylib_map.iter().map(|(n, _)| n.as_str())) + .collect(); let record_import = |name: &str, imports: &mut Vec, idx_for_name: &mut BTreeMap| @@ -697,6 +725,23 @@ pub fn link_native_objects_with_options( // so the writer binds the host symbol through the GOT, // rather than rejecting it as unresolved. let is_data_binding = data_binding_locals.contains(&sym.name); + // STB_WEAK = 2. An unresolved weak reference with + // no dylib routing resolves to address 0 (C + // practice; ELF leaves the symbol 0 so the + // `if (fn) fn();` guard idiom skips the call). + if sym.binding == 2 + && !is_data_binding + && !routed_import_names.contains(sym.name.as_str()) + { + resolve_weak_undef_to_zero( + machine, + &mut text, + patch_offset, + reloc, + &sym.name, + )?; + continue; + } if sym.binding == 1 && !allow_undefined && !is_data_binding { return Err(link_err(&format!( "undefined reference to `{}`", @@ -898,12 +943,33 @@ pub fn link_native_objects_with_options( // Pass 2.5 and join `defined` with section // == Bss; the lookup is the same as for an // Undef cross-unit reference. - defined.get(&sym.name).map(|d| d.section).ok_or_else(|| { - link_err(&format!( - "undefined reference to `{}` (data initializer)", - sym.name, - )) - })? + match defined.get(&sym.name) { + Some(d) => d.section, + // An unresolved weak reference in a data + // initializer takes the absolute value + // 0 + addend (ELF behavior); patch the + // slot now, no reloc survives. + None if sym.binding == 2 + && !routed_import_names.contains(sym.name.as_str()) => + { + let slot = slot_offset as usize; + if slot + 8 > data.len() { + return Err(err(&format!( + "weak data reloc slot 0x{slot:x} past end of data (len {})", + data.len(), + ))); + } + data[slot..slot + 8] + .copy_from_slice(&(reloc.addend as u64).to_le_bytes()); + continue; + } + None => { + return Err(link_err(&format!( + "undefined reference to `{}` (data initializer)", + sym.name, + ))); + } + } } NativeSymSection::Tls => { return Err(link_err(&format!( @@ -1575,6 +1641,96 @@ pub fn emit_aarch64_plt(merged: &mut MergedNative) -> Result, // ---- Reloc application ---- +/// Resolve a reference to an unresolved STB_WEAK UNDEF symbol to +/// address 0 (ELF behavior for a weak reference nothing on the link +/// line satisfies). A branch becomes a no-op, matching the GNU +/// linkers' AArch64 handling of branches to undefined weak symbols; +/// an address-materializing instruction is rewritten to produce the +/// constant 0 so the `if (fn) fn();` guard idiom reads a null +/// pointer. Instruction shapes outside the supported set are a +/// diagnostic, never a silent import. +fn resolve_weak_undef_to_zero( + machine: NativeMachine, + text: &mut [u8], + patch_offset: usize, + reloc: &NativeReloc, + name: &str, +) -> Result<(), C5Error> { + let unsupported = |what: &str| { + err(&format!( + "unresolved weak reference to `{name}`: cannot resolve {what} to address 0", + )) + }; + if patch_offset + .checked_add(4) + .is_none_or(|end| end > text.len()) + { + return Err(err(&format!( + "relocation patch offset 0x{patch_offset:x} past end of text (len {})", + text.len(), + ))); + } + const AARCH64_NOP: u32 = 0xd503_201f; + match (machine, reloc.rtype) { + (NativeMachine::Aarch64, R_AARCH64_CALL26) => { + text[patch_offset..patch_offset + 4].copy_from_slice(&AARCH64_NOP.to_le_bytes()); + Ok(()) + } + (NativeMachine::Aarch64, R_AARCH64_ADR_PREL_PG_HI21) => { + // `adrp xd, ` -> `movz xd, #0`. + let instr = + u32::from_le_bytes(text[patch_offset..patch_offset + 4].try_into().unwrap()); + let rd = instr & 0x1f; + let movz = 0xd280_0000 | rd; + text[patch_offset..patch_offset + 4].copy_from_slice(&movz.to_le_bytes()); + Ok(()) + } + (NativeMachine::Aarch64, R_AARCH64_ADD_ABS_LO12_NC) => { + // The pair's ADRP already produced 0 in `xn`; keep the + // destination 0 whether or not it aliases the source. + let instr = + u32::from_le_bytes(text[patch_offset..patch_offset + 4].try_into().unwrap()); + let rd = instr & 0x1f; + let rn = (instr >> 5) & 0x1f; + let repl = if rd == rn { + AARCH64_NOP + } else { + 0xd280_0000 | rd + }; + text[patch_offset..patch_offset + 4].copy_from_slice(&repl.to_le_bytes()); + Ok(()) + } + (NativeMachine::X86_64, R_X86_64_PLT32) | (NativeMachine::X86_64, R_X86_64_PC32) => { + // `r_offset` names the disp32 field; classify by the + // instruction bytes ahead of it. + if patch_offset >= 1 && text[patch_offset - 1] == 0xE8 { + // `call rel32` -> 5-byte NOP (0F 1F 44 00 00). + text[patch_offset - 1..patch_offset + 4] + .copy_from_slice(&[0x0F, 0x1F, 0x44, 0x00, 0x00]); + return Ok(()); + } + if patch_offset >= 3 + && (0x40..=0x4f).contains(&text[patch_offset - 3]) + && text[patch_offset - 2] == 0x8D + && text[patch_offset - 1] & 0xC7 == 0x05 + { + // `lea reg, [rip+disp32]` -> `mov reg, 0` (C7 /0 + // imm32). The modrm reg field moves to rm, so the + // REX.R bit becomes REX.B; REX.W carries over. + let rex = text[patch_offset - 3]; + let reg = (text[patch_offset - 1] >> 3) & 0x7; + text[patch_offset - 3] = 0x40 | (rex & 0x08) | ((rex & 0x04) >> 2); + text[patch_offset - 2] = 0xC7; + text[patch_offset - 1] = 0xC0 | reg; + text[patch_offset..patch_offset + 4].copy_from_slice(&[0, 0, 0, 0]); + return Ok(()); + } + Err(unsupported("the referencing instruction")) + } + _ => Err(unsupported(&format!("reloc type {}", reloc.rtype))), + } +} + fn apply_reloc( machine: NativeMachine, text: &mut [u8], diff --git a/src/c5/linker/synth_build.rs b/src/c5/linker/synth_build.rs index cddb77022..037c9f411 100644 --- a/src/c5/linker/synth_build.rs +++ b/src/c5/linker/synth_build.rs @@ -198,7 +198,7 @@ fn synth_program_and_build( pc_to_native.resize(pc + 1, usize::MAX); } pc_to_native[pc] = pc; - if let Some(&post_native) = merged.prologue_ends.get(name) { + if let Some(&post_native) = merged.prologue_ends.get(&(pc as u64)) { func_prologue_native.insert(pc, post_native as usize); } } @@ -213,7 +213,7 @@ fn synth_program_and_build( pc_to_native.resize(pc + 1, usize::MAX); } pc_to_native[pc] = pc; - if let Some(&post_native) = merged.prologue_ends.get(name) { + if let Some(&post_native) = merged.prologue_ends.get(&(pc as u64)) { func_prologue_native.insert(pc, post_native as usize); } } diff --git a/src/c5/object/elf.rs b/src/c5/object/elf.rs index ab02c8e0b..57a5df23a 100644 --- a/src/c5/object/elf.rs +++ b/src/c5/object/elf.rs @@ -1484,6 +1484,12 @@ pub(super) fn write( }; import_versym[i] = idx; } + // Version names extend `.dynstr` past `build_dynstr`'s pad; re-pad + // so the sections laid out from `dynstr.len()` (`.hash`, + // `.gnu.version`) stay congruent with their claimed sh_addralign. + while !dynstr.len().is_multiple_of(8) { + dynstr.push(0); + } let has_versions = !verneed_groups.is_empty(); // Two extra allocated sections (.gnu.version / .gnu.version_r) precede // .rela.dyn when has_versions, shifting .text onward by two. Symbols diff --git a/src/c5/tests/linker.rs b/src/c5/tests/linker.rs index 5b8adbba9..402830f48 100644 --- a/src/c5/tests/linker.rs +++ b/src/c5/tests/linker.rs @@ -1751,3 +1751,268 @@ fn cpuid_xgetbv_asm_emit_for_x86_64() { "push rbx (callee-saved, clobbered by cpuid) must be saved" ); } + +#[test] +fn same_named_statics_keep_their_own_prologue_anchor() { + // The post-prologue anchor map is keyed by the function's merged + // entry offset. Name-keying handed a later unit's same-named + // static the first unit's anchor, describing a framed function as + // frameless in the Win-x64 .pdata / DWARF CFA output. + use crate::c5::linker::{link_native_objects, parse_native_elf}; + use crate::c5::{CompileOptions, NativeOptions, OutputKind, Target, emit_native_with_options}; + let compile = |src: &str| { + let program = Compiler::with_options( + src.to_string(), + Target::LinuxX64, + CompileOptions::default().with_no_entry_point(true), + ) + .compile() + .expect("compile"); + let opts = NativeOptions { + output_kind: OutputKind::Relocatable, + ..Default::default() + }; + let bytes = emit_native_with_options(&program, Target::LinuxX64, opts).expect("emit"); + parse_native_elf(&bytes).expect("parse ET_REL") + }; + let a = compile( + "static int helper(int x) { int buf[16]; buf[0] = x; return buf[0] + 1; }\n\ + int call_a(int x) { return helper(x); }\n", + ); + let b = compile( + "static int helper(int x) { int buf[32]; buf[1] = x; return buf[1] + 2; }\n\ + int call_b(int x) { return helper(x); }\n", + ); + let merged = link_native_objects(&[a, b]).expect("link"); + let helpers: alloc::vec::Vec = merged + .local_funcs + .iter() + .filter(|(n, _)| n == "helper") + .map(|(_, off)| *off) + .collect(); + assert_eq!(helpers.len(), 2, "both statics survive: {helpers:?}"); + let mut posts = alloc::vec::Vec::new(); + for entry in &helpers { + let post = merged + .prologue_ends + .get(entry) + .unwrap_or_else(|| panic!("anchor for helper at 0x{entry:x} missing")); + assert!( + post > entry, + "post-prologue 0x{post:x} must lie past the entry 0x{entry:x}" + ); + posts.push(*post); + } + assert_ne!(posts[0], posts[1], "each static keeps its own anchor"); +} + +#[test] +fn unrouted_weak_undef_resolves_to_zero() { + // ELF behavior: a weak reference nothing on the link line + // satisfies resolves to address 0 -- not a required import + // against the first dylib. The call becomes a no-op, the + // address-of reads null, and a pointer initializer slot holds 0. + use crate::c5::linker::object::{NativeReloc, NativeSymbol}; + use crate::c5::linker::{NativeMachine, NativeSymSection, link_native_objects}; + let null_sym = || NativeSymbol { + name: String::new(), + section: NativeSymSection::Undef, + value: 0, + size: 0, + binding: 0, + kind: 0, + }; + let weak_undef = || NativeSymbol { + name: "hook".to_string(), + section: NativeSymSection::Undef, + value: 0, + size: 0, + binding: 2, // STB_WEAK + kind: 0, + }; + let mk = |machine: NativeMachine, + text: alloc::vec::Vec, + data: alloc::vec::Vec, + text_relocs: alloc::vec::Vec, + data_relocs: alloc::vec::Vec| { + crate::c5::linker::NativeObject { + machine, + text, + data, + data_align: 8, + bss_size: 0, + tls_data: alloc::vec::Vec::new(), + tls_bss_size: 0, + symbols: alloc::vec![null_sym(), weak_undef()], + text_relocs, + data_relocs, + dylibs: alloc::vec::Vec::new(), + import_dylib_map: alloc::vec::Vec::new(), + exports: alloc::vec::Vec::new(), + tls_index_fixups: alloc::vec::Vec::new(), + macho_tlv_descriptors: alloc::vec::Vec::new(), + macho_tlv_fixups: alloc::vec::Vec::new(), + tls_symbols: alloc::vec::Vec::new(), + macho_tlv_descriptor_syms: alloc::vec::Vec::new(), + elf_tpoff_fixups: alloc::vec::Vec::new(), + copy_relocs: alloc::vec::Vec::new(), + debug_info: alloc::vec::Vec::new(), + debug_abbrev: alloc::vec::Vec::new(), + debug_line: alloc::vec::Vec::new(), + debug_str: alloc::vec::Vec::new(), + debug_info_relocs: alloc::vec::Vec::new(), + debug_line_relocs: alloc::vec::Vec::new(), + } + }; + + // x86_64: `lea rax, [rip+hook]` (R_X86_64_PC32) then `call hook` + // (R_X86_64_PLT32), plus a `.data` pointer slot (R_X86_64_64). + let x64 = mk( + NativeMachine::X86_64, + alloc::vec![ + 0x48, 0x8D, 0x05, 0, 0, 0, 0, // lea rax, [rip+0] + 0xE8, 0, 0, 0, 0, // call rel32 + ], + alloc::vec![0u8; 8], + alloc::vec![ + NativeReloc { + offset: 3, + sym_idx: 1, + rtype: 2, // R_X86_64_PC32 + addend: -4, + }, + NativeReloc { + offset: 8, + sym_idx: 1, + rtype: 4, // R_X86_64_PLT32 + addend: -4, + }, + ], + alloc::vec![NativeReloc { + offset: 0, + sym_idx: 1, + rtype: 1, // R_X86_64_64 + addend: 0, + }], + ); + let merged = link_native_objects(&[x64]).expect("weak undef links"); + assert!( + merged.imports.is_empty(), + "no import for an unresolved weak ref: {:?}", + merged.imports + ); + assert_eq!( + &merged.text[0..7], + &[0x48, 0xC7, 0xC0, 0, 0, 0, 0], + "lea rewritten to mov rax, 0" + ); + assert_eq!( + &merged.text[7..12], + &[0x0F, 0x1F, 0x44, 0x00, 0x00], + "call rewritten to a 5-byte nop" + ); + assert_eq!(&merged.data[0..8], &[0u8; 8], "pointer slot holds null"); + + // aarch64: `adrp x0, hook` + `add x0, x0, :lo12:hook` + `bl hook`. + let a64 = mk( + NativeMachine::Aarch64, + alloc::vec![ + 0x00, 0x00, 0x00, 0x90, // adrp x0, 0 + 0x00, 0x00, 0x00, 0x91, // add x0, x0, #0 + 0x00, 0x00, 0x00, 0x94, // bl 0 + ], + alloc::vec::Vec::new(), + alloc::vec![ + NativeReloc { + offset: 0, + sym_idx: 1, + rtype: 275, // R_AARCH64_ADR_PREL_PG_HI21 + addend: 0, + }, + NativeReloc { + offset: 4, + sym_idx: 1, + rtype: 277, // R_AARCH64_ADD_ABS_LO12_NC + addend: 0, + }, + NativeReloc { + offset: 8, + sym_idx: 1, + rtype: 283, // R_AARCH64_CALL26 + addend: 0, + }, + ], + alloc::vec::Vec::new(), + ); + let merged = link_native_objects(&[a64]).expect("weak undef links"); + assert!(merged.imports.is_empty(), "{:?}", merged.imports); + let word = |i: usize| u32::from_le_bytes(merged.text[i..i + 4].try_into().unwrap()); + assert_eq!(word(0), 0xd280_0000, "adrp rewritten to movz x0, #0"); + assert_eq!(word(4), 0xd503_201f, "add pair half becomes a nop"); + assert_eq!(word(8), 0xd503_201f, "bl becomes a nop"); +} + +#[test] +fn elf_section_offsets_respect_their_claimed_alignment() { + // gABI: `sh_addr` (and the file offset for SHF_ALLOC sections) + // must be congruent to 0 modulo `sh_addralign`. Version-name + // strings appended to `.dynstr` after its pad used to leave + // `.hash` / `.gnu.version` misaligned; the check runs over every + // section so any future layout drift is caught. Version sections + // only appear when the build host's libc yields versioned imports. + use crate::c5::linker::{ + emit_aarch64_plt, link_native_objects, parse_native_elf, write_native_image_from_merged, + }; + use crate::c5::{NativeOptions, OutputKind, Target, emit_native_with_options}; + let program = Compiler::new(alloc::format!( + "{TEST_PRELUDE}\ + int main(void) {{ printf(\"x\"); return 0; }}\n" + )) + .compile() + .expect("compile"); + let opts = NativeOptions { + output_kind: OutputKind::Relocatable, + ..Default::default() + }; + let bytes = emit_native_with_options(&program, Target::LinuxAarch64, opts).expect("emit"); + let obj = parse_native_elf(&bytes).expect("parse ET_REL"); + let mut merged = link_native_objects(&[obj]).expect("link"); + let plt = emit_aarch64_plt(&mut merged).expect("plt"); + let exe = write_native_image_from_merged( + &merged, + &plt, + "main", + None, + OutputKind::Executable, + Target::LinuxAarch64, + None, + ) + .expect("write executable"); + let shoff = u64::from_le_bytes(exe[0x28..0x30].try_into().unwrap()) as usize; + let shentsize = u16::from_le_bytes(exe[0x3a..0x3c].try_into().unwrap()) as usize; + let shnum = u16::from_le_bytes(exe[0x3c..0x3e].try_into().unwrap()) as usize; + assert!(shnum > 0, "executable must carry section headers"); + const SHT_NOBITS: u32 = 8; + for i in 0..shnum { + let base = shoff + i * shentsize; + let sh_type = u32::from_le_bytes(exe[base + 4..base + 8].try_into().unwrap()); + let sh_addr = u64::from_le_bytes(exe[base + 16..base + 24].try_into().unwrap()); + let sh_offset = u64::from_le_bytes(exe[base + 24..base + 32].try_into().unwrap()); + let sh_addralign = u64::from_le_bytes(exe[base + 48..base + 56].try_into().unwrap()); + if sh_addralign <= 1 { + continue; + } + assert_eq!( + sh_addr % sh_addralign, + 0, + "section {i} sh_addr 0x{sh_addr:x} violates sh_addralign {sh_addralign}" + ); + if sh_type != SHT_NOBITS { + assert_eq!( + sh_offset % sh_addralign, + 0, + "section {i} sh_offset 0x{sh_offset:x} violates sh_addralign {sh_addralign}" + ); + } + } +} From 4931d3351fa3000f65892bc12f1a4e4afc3749d1 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 22:02:00 -0700 Subject: [PATCH 42/67] compiler: honor _Alignas up to 16, keep tentative defs over extern * `_Alignas(N)` / `__attribute__((aligned(N)))` / `__declspec (align(N))` on a file-scope or static block-scope object is honored up to 16: the object's data offset is padded, the unit records `data_align = 16` (threaded through `Program` into the writers and the ET_REL `.data` sh_addralign), and the compaction residue rules carry the placement into the final image. Larger requests, automatic objects above the 8-byte slot alignment, and member alignment above 8 are diagnostics -- never a silent drop (C11 6.7.5). * `int x; extern int x;` keeps the tentative definition (C99 6.2.2p4 / 6.9.2p2): an extern redeclaration after a file-scope definition -- tentative, initialized, or the array form -- no longer marks the symbol extern-only, so the TU still defines it and the link succeeds. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/aarch64/encode.rs | 2 +- src/c5/codegen/x86_64/encode.rs | 2 +- src/c5/compiler/aggregate.rs | 31 ++++++++ src/c5/compiler/decl_base.rs | 69 +++++++++++++++++ src/c5/compiler/emit.rs | 8 ++ src/c5/compiler/locals.rs | 16 ++++ src/c5/compiler/mod.rs | 13 ++++ src/c5/compiler/run_compile.rs | 57 +++++++++++++-- src/c5/linker/synth_build.rs | 1 + src/c5/object/elf.rs | 1 + src/c5/object/elf_reloc.rs | 9 ++- src/c5/object/mach_o.rs | 1 + src/c5/program.rs | 5 ++ src/c5/tests/linker.rs | 122 +++++++++++++++++++++++++++++++ 14 files changed, 325 insertions(+), 12 deletions(-) diff --git a/src/c5/codegen/aarch64/encode.rs b/src/c5/codegen/aarch64/encode.rs index 5e219ad35..c4e1b78a3 100644 --- a/src/c5/codegen/aarch64/encode.rs +++ b/src/c5/codegen/aarch64/encode.rs @@ -1865,7 +1865,7 @@ pub(crate) fn lower( copy_relocs: Vec::new(), text: code, data: program.data.clone(), - data_align: 8, + data_align: program.data_align, bss_size: 0, entry_offset, got_fixups, diff --git a/src/c5/codegen/x86_64/encode.rs b/src/c5/codegen/x86_64/encode.rs index 1c351df36..30c21dbde 100644 --- a/src/c5/codegen/x86_64/encode.rs +++ b/src/c5/codegen/x86_64/encode.rs @@ -2302,7 +2302,7 @@ pub(crate) fn lower( copy_relocs: Vec::new(), text: code, data: program.data.clone(), - data_align: 8, + data_align: program.data_align, bss_size: 0, entry_offset, got_fixups, diff --git a/src/c5/compiler/aggregate.rs b/src/c5/compiler/aggregate.rs index c1e4f5770..53619dce0 100644 --- a/src/c5/compiler/aggregate.rs +++ b/src/c5/compiler/aggregate.rs @@ -47,6 +47,22 @@ impl Compiler { name: &str, is_union: bool, packed: bool, + ) -> Result { + // An alignment request preceding the tag + // (`__declspec(align(16)) struct S { ... }`) belongs to the + // declaration, not to the first member; park it across the + // body parse so the member checks see only member attributes. + let decl_attr_align = core::mem::take(&mut self.pending.attr_align); + let r = self.parse_aggregate_body_inner(name, is_union, packed); + self.pending.attr_align = self.pending.attr_align.max(decl_attr_align); + r + } + + fn parse_aggregate_body_inner( + &mut self, + name: &str, + is_union: bool, + packed: bool, ) -> Result { // Pre-register or recycle a forward declaration so // self-referential pointer fields can find this aggregate @@ -149,6 +165,15 @@ impl Compiler { while is_decl_modifier(self.lex.tk) { if self.lex.tk == Token::Attribute { self.skip_attribute_specifiers()?; + // Member layout uses 8-byte alignment at most; a + // larger request would change the struct layout + // silently, so it is a diagnostic. + let m_align = core::mem::take(&mut self.pending.attr_align); + if m_align > 8 { + return Err(self.compile_err(format!( + "member alignment {m_align} is not supported (at most 8)" + ))); + } continue; } if self.lex.tk == Token::Atomic && self.lex.peek_after_whitespace(b'(') { @@ -502,6 +527,12 @@ impl Compiler { // A member may carry a trailing attribute // (`int x __attribute__((deprecated));`). self.skip_attribute_specifiers()?; + let m_align = core::mem::take(&mut self.pending.attr_align); + if m_align > 8 { + return Err(self.compile_err(format!( + "member alignment {m_align} is not supported (at most 8)" + ))); + } // A typedef whose alias is an array contributes // its dimension when the declarator stayed at the // typedef's element type (`jmp_buf b;` -> diff --git a/src/c5/compiler/decl_base.rs b/src/c5/compiler/decl_base.rs index b95db1e23..c5cd16ed2 100644 --- a/src/c5/compiler/decl_base.rs +++ b/src/c5/compiler/decl_base.rs @@ -291,6 +291,7 @@ impl Compiler { thread_local: &mut bool, noreturn: &mut bool, dllexport: &mut bool, + aligned: &mut bool, ) { if self.lex.tk == Token::Id { let n = self.symbols[self.lex.curr_id_idx].name.as_str(); @@ -309,6 +310,9 @@ impl Compiler { // MSVC `__declspec(dllexport)`: export the symbol, the // equivalent of `#pragma export(name)`. *dllexport = true; + } else if n == "aligned" || n == "__aligned__" || n == "align" { + // GNU `aligned(N)` / MSVC `__declspec(align(N))`. + *aligned = true; } } } @@ -328,15 +332,44 @@ impl Compiler { let mut thread_local = false; let mut noreturn = false; let mut dllexport = false; + let mut align: i64 = 0; loop { if self.lex.tk == Token::Attribute { // `__attribute__((...))`, `__declspec(...)`, // `_Alignas(...)`. Consume the balanced parenthesised // payload, recording the `packed` attribute. + let is_alignas = self.symbols[self.lex.curr_id_idx].name == "_Alignas"; self.next()?; if self.lex.tk != '(' { return Err(self.compile_err("`(` expected after attribute specifier")); } + // C11 6.7.5 `_Alignas(constant-expression)`. The + // type-name form's alignment never exceeds 8 in this + // dialect and stays advisory. + if is_alignas { + self.next()?; // ( + if self.lex.tk == Token::Num { + let n = self.parse_constant_int()?; + align = align.max(n); + if self.lex.tk != ')' { + return Err(self.compile_err("`)` expected after `_Alignas` operand")); + } + self.next()?; + } else { + let mut depth = 1i32; + while depth > 0 { + if self.lex.tk == '(' { + depth += 1; + } else if self.lex.tk == ')' { + depth -= 1; + } else if self.lex.tk == 0 { + return Err(self.compile_err("unterminated `_Alignas`")); + } + self.next()?; + } + } + continue; + } let mut depth = 0i32; loop { if self.lex.tk == '(' { @@ -351,14 +384,34 @@ impl Compiler { } else if self.lex.tk == 0 { return Err(self.compile_err("unterminated attribute specifier")); } else { + let mut saw_aligned = false; self.note_attribute_name( &mut packed, &mut maybe_unused, &mut thread_local, &mut noreturn, &mut dllexport, + &mut saw_aligned, ); self.next()?; + if saw_aligned { + if self.lex.tk == '(' { + self.next()?; + let n = self.parse_constant_int()?; + align = align.max(n); + if self.lex.tk != ')' { + return Err( + self.compile_err("`)` expected after `aligned` operand") + ); + } + self.next()?; + } else { + // Bare `aligned`: the target's largest + // fundamental alignment (16 on the + // supported targets). + align = align.max(16); + } + } } } } else if self.lex.tk == Token::Brak && self.lex.peek_after_whitespace(b'[') { @@ -389,14 +442,27 @@ impl Compiler { } else if self.lex.tk == 0 { return Err(self.compile_err("unterminated `[[` attribute")); } else { + let mut saw_aligned = false; self.note_attribute_name( &mut packed, &mut maybe_unused, &mut thread_local, &mut noreturn, &mut dllexport, + &mut saw_aligned, ); self.next()?; + if saw_aligned && self.lex.tk == '(' { + self.next()?; + let n = self.parse_constant_int()?; + align = align.max(n); + if self.lex.tk != ')' { + return Err( + self.compile_err("`)` expected after `aligned` operand") + ); + } + self.next()?; + } } } } else { @@ -415,6 +481,9 @@ impl Compiler { if dllexport { self.pending.attr_dllexport = true; } + if align > 0 { + self.pending.attr_align = self.pending.attr_align.max(align); + } Ok(packed) } diff --git a/src/c5/compiler/emit.rs b/src/c5/compiler/emit.rs index 2fd1ccb68..21eca4518 100644 --- a/src/c5/compiler/emit.rs +++ b/src/c5/compiler/emit.rs @@ -227,6 +227,14 @@ impl Compiler { } } + /// Pad `self.data` to `align` bytes -- the `_Alignas(16)` / + /// `aligned(16)` placement for a file-scope object. + pub(super) fn align_data_to(&mut self, align: usize) { + while !self.data.len().is_multiple_of(align.max(8)) { + self.data.push(0); + } + } + /// True when the most recently emitted instruction is `Imm 0` -- /// i.e. the expression that just finished compiling was the literal /// `0`. Used by [`Compiler::type_warning`] to suppress the NULL diff --git a/src/c5/compiler/locals.rs b/src/c5/compiler/locals.rs index 3e8bad31d..82c33a6a3 100644 --- a/src/c5/compiler/locals.rs +++ b/src/c5/compiler/locals.rs @@ -204,6 +204,18 @@ impl Compiler { self.shadow_symbol(loc_idx); + // C11 6.7.5 on block-scope objects: a static local's + // `.data` slot honors up to 16 like a file-scope object; + // an automatic object lives in 8-byte frame slots, so a + // larger request is a diagnostic, never a silent drop. + let req_align = core::mem::take(&mut self.pending.attr_align); + if req_align > 16 || (req_align > 8 && !is_static) { + return Err(self.compile_err(format!( + "requested alignment {req_align} is not supported here \ + (automatic objects align to 8, static objects to at most 16)" + ))); + } + if is_static { self.symbols[loc_idx].class = Token::Glo as i64; self.symbols[loc_idx].type_ = ty; @@ -213,6 +225,10 @@ impl Compiler { // object of the same name reappears. The `Loc`-gated // cleanup would skip it, so mark it for restore. self.symbols[loc_idx].is_scope_static = true; + if req_align > 8 { + self.align_data_to(req_align as usize); + self.data_align = 16; + } self.allocate_static_local(loc_idx, ty, array_size)?; self.ast_emit_static_local_decl(loc_idx as u32); } else { diff --git a/src/c5/compiler/mod.rs b/src/c5/compiler/mod.rs index 09951dfb2..50bbb0ced 100644 --- a/src/c5/compiler/mod.rs +++ b/src/c5/compiler/mod.rs @@ -580,6 +580,12 @@ pub(in crate::c5::compiler) struct Pending { /// skip to mark the declared locals so their unused-variable /// diagnostics are suppressed. pub attr_maybe_unused: bool, + /// Requested object alignment from `_Alignas(N)` / + /// `__attribute__((aligned(N)))` / `__declspec(align(N))`, 0 when + /// absent. The declaration parse takes it: file-scope objects + /// honor up to 16, anything larger (or an automatic object above + /// the 8-byte slot alignment) is a diagnostic, never silent. + pub attr_align: i64, /// A consumed `__declspec(thread)`. Read by the declaration parse to mark /// the declared object thread-local (the storage class `_Thread_local` /// reaches the same flag through the keyword path). @@ -625,6 +631,7 @@ impl Default for Pending { last_imm_was_zero: false, compound_lit_close_parens: 0, attr_maybe_unused: false, + attr_align: 0, attr_thread_local: false, attr_dllexport: false, } @@ -966,6 +973,10 @@ pub struct Compiler { /// `entry_name = None` if no entry symbol exists. no_entry_point: bool, + /// Base alignment the `.data` image requires, at least 8. Raised + /// to 16 when a file-scope object requests `_Alignas(16)`. + data_align: usize, + /// Mirror of [`CompileOptions::export_all_functions`]. When set, /// `resolve_exports` adds every non-static defined function to the /// export list so a `--shared` consumer can `dlsym` it. @@ -1317,6 +1328,7 @@ impl Compiler { pending_store_symbols: Vec::new(), warn_dead_store: opts.warn_dead_store, no_entry_point: opts.no_entry_point, + data_align: 8, export_all_functions: opts.export_all_functions, source_files: Vec::new(), source_label: opts.source_label.clone(), @@ -1652,6 +1664,7 @@ impl Compiler { let exports = self.resolve_exports()?; Ok(Program { data: self.data, + data_align: self.data_align, data_object_starts: self.data_object_starts, entry_pc, warnings: self.warnings, diff --git a/src/c5/compiler/run_compile.rs b/src/c5/compiler/run_compile.rs index d9a042708..650c48026 100644 --- a/src/c5/compiler/run_compile.rs +++ b/src/c5/compiler/run_compile.rs @@ -89,6 +89,7 @@ impl Compiler { self.pending_noreturn = false; self.pending.attr_thread_local = false; self.pending.attr_dllexport = false; + self.pending.attr_align = 0; self.pending_is_inline = false; loop { if self.lex.tk == Token::ThreadLocal { @@ -297,6 +298,7 @@ impl Compiler { array_size = typedef_dim; } self.ty = ty; + let prior_array_size = self.symbols[id_idx].array_size; self.symbols[id_idx].array_size = array_size; if fn_ptr_indirection > 0 { self.symbols[id_idx].fn_ptr_indirection = fn_ptr_indirection; @@ -1330,6 +1332,27 @@ impl Compiler { } else if self.symbols[id_idx].linkage != crate::c5::symbol::Linkage::Internal { self.symbols[id_idx].linkage = crate::c5::symbol::Linkage::External; } + // C11 6.7.5: a requested alignment up to 16 is + // honored on file-scope objects (the writers place + // `.data` at `Program::data_align`); anything + // larger is a diagnostic, never a silent drop. + let req_align = core::mem::take(&mut self.pending.attr_align); + if req_align > 16 { + return Err(self.compile_err(format!( + "requested alignment {req_align} exceeds the supported maximum of 16" + ))); + } + let decl_align: usize = if req_align > 8 { + if thread_local { + return Err(self.compile_err( + "alignment above 8 is not supported for `_Thread_local` objects", + )); + } + self.data_align = 16; + 16 + } else { + 8 + }; let was_extern_only_decl = extern_seen && self.lex.tk != Token::Assign && array_size != -1; // `extern struct S s;` while `struct S` is still @@ -1352,7 +1375,13 @@ impl Compiler { continue; } if was_extern_only_decl { - self.symbols[id_idx].is_extern_decl = true; + // C99 6.2.2p4 + 6.9.2p2: `extern T x;` after a + // prior file-scope definition (tentative or + // initialized) redeclares the same object; the + // definition stands. + if !self.symbols[id_idx].defined_here { + self.symbols[id_idx].is_extern_decl = true; + } } else { self.symbols[id_idx].is_extern_decl = false; // Default: a file-scope global declaration @@ -1378,8 +1407,16 @@ impl Compiler { // address against the defining TU's // storage. if extern_seen { - self.symbols[id_idx].is_extern_decl = true; - self.symbols[id_idx].defined_here = false; + // C99 6.2.2p4: after a prior definition, + // `extern T x[];` is a redeclaration of + // the same object -- the definition and + // its dimension stand. + if self.symbols[id_idx].defined_here { + self.symbols[id_idx].array_size = prior_array_size; + } else { + self.symbols[id_idx].is_extern_decl = true; + self.symbols[id_idx].defined_here = false; + } self.accept(',')?; continue; } @@ -1395,7 +1432,9 @@ impl Compiler { } let elem = self.size_of_type(ty) as i64; let aligned = ((elem + 7) / 8) * 8; - if self.size_of_type(ty) > 1 { + if decl_align > 8 { + self.align_data_to(decl_align); + } else if self.size_of_type(ty) > 1 { self.align_data_to_8(); } let off = self.data.len() as i64; @@ -1457,7 +1496,7 @@ impl Compiler { { self.symbols[id_idx].val } else { - self.align_data_to_8(); + self.align_data_to(decl_align); let fresh = self.data.len() as i64; self.symbols[id_idx].reserved_data_bytes = needed; for _ in 0..needed { @@ -1555,7 +1594,9 @@ impl Compiler { { self.symbols[id_idx].val } else { - if self.size_of_type(ty) > 1 { + if decl_align > 8 { + self.align_data_to(decl_align); + } else if self.size_of_type(ty) > 1 { self.align_data_to_8(); } let fresh = self.data.len() as i64; @@ -1629,7 +1670,9 @@ impl Compiler { } off } else { - if self.size_of_type(ty) > 1 { + if decl_align > 8 { + self.align_data_to(decl_align); + } else if self.size_of_type(ty) > 1 { self.align_data_to_8(); } let off = self.data.len() as i64; diff --git a/src/c5/linker/synth_build.rs b/src/c5/linker/synth_build.rs index 037c9f411..3e60512ad 100644 --- a/src/c5/linker/synth_build.rs +++ b/src/c5/linker/synth_build.rs @@ -138,6 +138,7 @@ fn synth_program_and_build( let program = Program { data: Vec::new(), + data_align: 8, data_object_starts: Vec::new(), entry_pc: 0, warnings: Vec::new(), diff --git a/src/c5/object/elf.rs b/src/c5/object/elf.rs index 57a5df23a..6f409ff12 100644 --- a/src/c5/object/elf.rs +++ b/src/c5/object/elf.rs @@ -2904,6 +2904,7 @@ mod tests { structs: Vec::new(), enums: Vec::new(), entry_name: None, + data_align: 8, subsystem: None, finished_functions: alloc::vec::Vec::new(), symbols: alloc::vec::Vec::new(), diff --git a/src/c5/object/elf_reloc.rs b/src/c5/object/elf_reloc.rs index 40ed64eae..19610b8b0 100644 --- a/src/c5/object/elf_reloc.rs +++ b/src/c5/object/elf_reloc.rs @@ -1032,8 +1032,10 @@ pub(super) fn write_relocatable( ..Default::default() }); - // .data - let data_off = round_up(out.len() as u64, 8); + // .data -- `sh_addralign` carries the unit's base data alignment + // so the linker places this unit's data at a multiple of it. + let data_align = build.data_align.max(8) as u64; + let data_off = round_up(out.len() as u64, data_align); out.resize(data_off as usize, 0); out.extend_from_slice(&build.data); sh.push(Elf64Shdr { @@ -1042,7 +1044,7 @@ pub(super) fn write_relocatable( sh_flags: SHF_ALLOC | SHF_WRITE, sh_offset: data_off, sh_size: build.data.len() as u64, - sh_addralign: 8, + sh_addralign: data_align, ..Default::default() }); @@ -1760,6 +1762,7 @@ mod tests { structs: Vec::new(), enums: Vec::new(), entry_name: None, + data_align: 8, subsystem: None, finished_functions: Vec::new(), symbols: Vec::new(), diff --git a/src/c5/object/mach_o.rs b/src/c5/object/mach_o.rs index 7a49e69cc..b52057089 100644 --- a/src/c5/object/mach_o.rs +++ b/src/c5/object/mach_o.rs @@ -2821,6 +2821,7 @@ mod tests { structs: Vec::new(), enums: Vec::new(), entry_name: None, + data_align: 8, subsystem: None, finished_functions: alloc::vec::Vec::new(), symbols: alloc::vec::Vec::new(), diff --git a/src/c5/program.rs b/src/c5/program.rs index e9698e208..82fb118d0 100644 --- a/src/c5/program.rs +++ b/src/c5/program.rs @@ -98,6 +98,11 @@ pub struct CodeReloc { #[derive(Debug, Clone)] pub struct Program { pub data: Vec, + /// Base alignment `data` requires in the image, at least 8; + /// raised to 16 when a file-scope object carries `_Alignas(16)` + /// (or the attribute equivalents). The native writers place the + /// data section at a multiple of it. + pub data_align: usize, /// Start offsets of anonymous data objects (string literals and the /// implicit `__func__` arrays of C99 6.4.2.2) within `data`. Named /// globals already carry their offset in `symbols[..].val`; these are diff --git a/src/c5/tests/linker.rs b/src/c5/tests/linker.rs index 402830f48..17281341a 100644 --- a/src/c5/tests/linker.rs +++ b/src/c5/tests/linker.rs @@ -2016,3 +2016,125 @@ fn elf_section_offsets_respect_their_claimed_alignment() { } } } + +#[test] +fn extern_redeclaration_keeps_the_tentative_definition() { + // C99 6.2.2p4 + 6.9.2p2: `int x; extern int x;` retains the + // tentative definition (the extern redeclaration refers to the + // same object), so the TU's object defines `x`. The same holds + // for the array form and for an initialized definition. + use crate::c5::linker::{NativeSymSection, parse_native_elf}; + use crate::c5::{CompileOptions, NativeOptions, OutputKind, Target, emit_native_with_options}; + let defined_sections = |src: &str, names: &[&str]| -> alloc::vec::Vec { + let program = Compiler::with_options( + src.to_string(), + Target::LinuxX64, + CompileOptions::default().with_no_entry_point(true), + ) + .compile() + .expect("compile"); + let opts = NativeOptions { + output_kind: OutputKind::Relocatable, + ..Default::default() + }; + let bytes = emit_native_with_options(&program, Target::LinuxX64, opts).expect("emit"); + let obj = parse_native_elf(&bytes).expect("parse ET_REL"); + names + .iter() + .map(|n| { + obj.symbols + .iter() + .any(|s| &s.name == n && s.section != NativeSymSection::Undef) + }) + .collect() + }; + let defined = defined_sections( + "int x;\nextern int x;\n\ + int a[4];\nextern int a[];\n\ + int y = 5;\nextern int y;\n\ + int use_all(void) { return x + a[0] + y; }\n", + &["x", "a", "y"], + ); + assert_eq!( + defined, + alloc::vec![true, true, true], + "the definitions must survive the extern redeclarations (x, a, y)" + ); + // A genuinely extern-only declaration still emits an UNDEF. + let defined = defined_sections("extern int z;\nint use_z(void) { return z; }\n", &["z"]); + assert_eq!(defined, alloc::vec![false], "extern-only stays undefined"); +} + +#[test] +fn alignas_sixteen_places_objects_and_raises_data_align() { + // C11 6.7.5: a 16-byte alignment request on a file-scope object + // is honored -- the object's section offset is 16-aligned through + // compaction and the unit records `data_align = 16` so the linker + // and the image writers keep the base congruent. Larger requests + // and unsupported positions are diagnostics, never silent drops. + use crate::c5::linker::{NativeSymSection, link_native_objects, parse_native_elf}; + use crate::c5::{CompileOptions, NativeOptions, OutputKind, Target, emit_native_with_options}; + let compile = |src: &str| { + let program = Compiler::with_options( + src.to_string(), + Target::LinuxX64, + CompileOptions::default().with_no_entry_point(true), + ) + .compile() + .expect("compile"); + let opts = NativeOptions { + output_kind: OutputKind::Relocatable, + ..Default::default() + }; + let bytes = emit_native_with_options(&program, Target::LinuxX64, opts).expect("emit"); + parse_native_elf(&bytes).expect("parse ET_REL") + }; + let aligned_unit = "\ + _Alignas(16) unsigned char pool[24];\n\ + char skew[3] = \"ab\";\n\ + __attribute__((aligned(16))) unsigned char pool2[8];\n\ + int use_all(void) { return pool[0] + skew[0] + pool2[0]; }\n"; + let obj = compile(aligned_unit); + assert_eq!(obj.data_align, 16, "unit must claim 16-byte data alignment"); + for name in ["pool", "pool2"] { + let sym = obj + .symbols + .iter() + .find(|s| s.name == name) + .unwrap_or_else(|| panic!("{name} missing")); + assert!( + sym.section != NativeSymSection::Undef && sym.value.is_multiple_of(16), + "{name} at {:?}+0x{:x} must be 16-aligned", + sym.section, + sym.value + ); + } + // Linked after a unit with an odd-sized data tail, the offsets + // stay 16-congruent (the unit base honors the claimed alignment) + // and the file image is padded so bss offsets keep their residue. + let odd = compile("char tail[5] = \"abcd\";\nint use_tail(void) { return tail[0]; }\n"); + let merged = link_native_objects(&[odd, compile(aligned_unit)]).expect("link"); + assert_eq!(merged.data_align, 16); + if merged.bss_size > 0 { + assert!(merged.data.len().is_multiple_of(16)); + } + for name in ["pool", "pool2"] { + let sym = merged.defined.get(name).unwrap_or_else(|| panic!("{name}")); + assert!( + sym.value.is_multiple_of(16), + "{name} merged offset 0x{:x} must stay 16-aligned", + sym.value + ); + } + // Diagnostics: above 16, automatic objects above 8, members above 8. + for src in [ + "_Alignas(64) static char big[8];\nint main(void) { return 0; }\n", + "int main(void) { _Alignas(16) char buf[8]; return buf[0]; }\n", + "struct S { _Alignas(16) int f; };\nint main(void) { struct S s; s.f = 0; return s.f; }\n", + ] { + assert!( + Compiler::new(src.to_string()).compile().is_err(), + "must be diagnosed: {src}" + ); + } +} From c7897fcda476e55ae2ca62cd935de7248ce67fb1 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 22:02:51 -0700 Subject: [PATCH 43/67] driver: on-demand archive members, link-preferred definitions, -c pragma warning * Static-archive members join the link on demand: a member is included iff it defines a symbol the link still leaves undefined, iterated to a fixpoint (matching the documented model and SysV ar practice). Unreferenced members no longer fail a valid link with their unrelated undefined or duplicate symbols. * The auto-include retry no longer overrides a user definition: when a multi-TU link defines a name the retry bound to a bundled-header libc binding, the referencing source is recompiled with the name as a C89 6.3.2.2 implicit `extern int name();` so the call resolves against the user's definition. Names nothing defines keep the auto-include. * `-c` and `--ar` warn when `#pragma subsystem` / `#pragma entrypoint` is dropped: the pragma rides the in-memory program of the invocation that links, and an ET_REL object carries neither, so a GUI TU compiled to an object no longer silently links as a console image. `Program::entry_pragma` carries the literal pragma value, distinct from the resolved `entry_name`. Co-Authored-By: Claude Fable 5 --- src/c5/compiler/expr.rs | 17 ++++ src/c5/compiler/mod.rs | 23 ++++++ src/c5/linker/synth_build.rs | 2 + src/c5/object/elf.rs | 2 + src/c5/object/elf_reloc.rs | 2 + src/c5/object/mach_o.rs | 2 + src/c5/program.rs | 12 +++ src/main.rs | 153 ++++++++++++++++++++++++++++++++-- tests/cli_linker_smoke.rs | 155 +++++++++++++++++++++++++++++++++++ 9 files changed, 363 insertions(+), 5 deletions(-) diff --git a/src/c5/compiler/expr.rs b/src/c5/compiler/expr.rs index 59d1cba68..c566fc3c0 100644 --- a/src/c5/compiler/expr.rs +++ b/src/c5/compiler/expr.rs @@ -542,6 +542,23 @@ impl Compiler { self.next()?; if self.lex.tk == '(' { self.next()?; + // C89 6.3.2.2 implicit declaration, restricted to the + // names the driver listed: the link set defines them, + // so the call binds `extern int name();` and resolves + // against the user's definition rather than through a + // header's library binding. + if self.symbols[id_idx].class == 0 + && !self.implicit_extern_fns.is_empty() + && self + .implicit_extern_fns + .iter() + .any(|n| n == &self.symbols[id_idx].name) + { + self.symbols[id_idx].class = Token::Fun as i64; + self.symbols[id_idx].type_ = Ty::Int as i64; + self.symbols[id_idx].linkage = crate::c5::symbol::Linkage::External; + self.symbols[id_idx].defined_here = false; + } // C11 7.17 atomic operations and the other compiler // builtins share the `#pragma intrinsic` registry // (`` declares the atomics). An atomic op is diff --git a/src/c5/compiler/mod.rs b/src/c5/compiler/mod.rs index 50bbb0ced..83d263e99 100644 --- a/src/c5/compiler/mod.rs +++ b/src/c5/compiler/mod.rs @@ -214,6 +214,12 @@ pub struct CompileOptions { /// most but not all of the GNU C surface, so it claims `__GNUC__` /// only when the caller opts in. pub gnu: bool, + /// Function names an undeclared call may bind as a C89 6.3.2.2 + /// implicit `extern int name();` instead of triggering the + /// auto-include retry. The driver fills this in a multi-TU build + /// for auto-included names another input defines, so the user's + /// definition wins over the header's library binding. + pub implicit_extern_fns: Vec, } impl CompileOptions { @@ -273,6 +279,12 @@ impl CompileOptions { self.no_entry_point = on; self } + /// Replace the implicit-extern function-name list. See + /// [`Self::implicit_extern_fns`]. + pub fn with_implicit_extern_fns(mut self, names: Vec) -> Self { + self.implicit_extern_fns = names; + self + } } /// Ephemeral side-channel state passed between parser layers -- @@ -977,6 +989,11 @@ pub struct Compiler { /// to 16 when a file-scope object requests `_Alignas(16)`. data_align: usize, + /// Mirror of [`CompileOptions::implicit_extern_fns`]. An + /// undeclared call to a listed name binds as a C89 6.3.2.2 + /// implicit `extern int name();` resolved at link time. + implicit_extern_fns: Vec, + /// Mirror of [`CompileOptions::export_all_functions`]. When set, /// `resolve_exports` adds every non-static defined function to the /// export list so a `--shared` consumer can `dlsym` it. @@ -1329,6 +1346,7 @@ impl Compiler { warn_dead_store: opts.warn_dead_store, no_entry_point: opts.no_entry_point, data_align: 8, + implicit_extern_fns: opts.implicit_extern_fns.clone(), export_all_functions: opts.export_all_functions, source_files: Vec::new(), source_label: opts.source_label.clone(), @@ -1520,6 +1538,7 @@ impl Compiler { // missing headers. The force-include set only grows, and a // header already in it ends the loop, so progress is monotone. let mut infos: Vec = Vec::new(); + let mut auto_names: Vec = Vec::new(); loop { let e = match result { Ok(mut prog) => { @@ -1530,6 +1549,7 @@ impl Compiler { for info in infos.into_iter().rev() { prog.warnings.insert(0, info); } + prog.auto_includes = auto_names; return Ok(prog); } Err(e) => e, @@ -1548,6 +1568,7 @@ impl Compiler { infos.push(format!( "info: auto-including <{header}> for undeclared `{name}`" )); + auto_names.push(name); result = Compiler::with_options_inner(source.clone(), target, opts.clone(), false) .compile_one_pass(); } @@ -1697,6 +1718,8 @@ impl Compiler { // CRT-recognised fallbacks (`wmain`, `WinMain`, // `wWinMain`) chosen when `main` is absent. entry_name: resolved_entry_name, + entry_pragma: self.pp_entrypoint.clone(), + auto_includes: Vec::new(), subsystem: self.pp_subsystem, // Compile output is pre-optimizer; only the explicit // `optimize()` step flips this on. diff --git a/src/c5/linker/synth_build.rs b/src/c5/linker/synth_build.rs index 3e60512ad..13a4f0e3d 100644 --- a/src/c5/linker/synth_build.rs +++ b/src/c5/linker/synth_build.rs @@ -156,6 +156,8 @@ fn synth_program_and_build( structs: Vec::new(), enums: Vec::new(), entry_name: Some(entry_name.to_string()), + entry_pragma: None, + auto_includes: Vec::new(), subsystem, finished_functions: Vec::new(), symbols: Vec::new(), diff --git a/src/c5/object/elf.rs b/src/c5/object/elf.rs index 6f409ff12..747d833fe 100644 --- a/src/c5/object/elf.rs +++ b/src/c5/object/elf.rs @@ -2904,6 +2904,8 @@ mod tests { structs: Vec::new(), enums: Vec::new(), entry_name: None, + entry_pragma: None, + auto_includes: Vec::new(), data_align: 8, subsystem: None, finished_functions: alloc::vec::Vec::new(), diff --git a/src/c5/object/elf_reloc.rs b/src/c5/object/elf_reloc.rs index 19610b8b0..c366066c5 100644 --- a/src/c5/object/elf_reloc.rs +++ b/src/c5/object/elf_reloc.rs @@ -1762,6 +1762,8 @@ mod tests { structs: Vec::new(), enums: Vec::new(), entry_name: None, + entry_pragma: None, + auto_includes: Vec::new(), data_align: 8, subsystem: None, finished_functions: Vec::new(), diff --git a/src/c5/object/mach_o.rs b/src/c5/object/mach_o.rs index b52057089..1eb1cc235 100644 --- a/src/c5/object/mach_o.rs +++ b/src/c5/object/mach_o.rs @@ -2821,6 +2821,8 @@ mod tests { structs: Vec::new(), enums: Vec::new(), entry_name: None, + entry_pragma: None, + auto_includes: Vec::new(), data_align: 8, subsystem: None, finished_functions: alloc::vec::Vec::new(), diff --git a/src/c5/program.rs b/src/c5/program.rs index 82fb118d0..63de93287 100644 --- a/src/c5/program.rs +++ b/src/c5/program.rs @@ -265,6 +265,18 @@ pub struct Program { /// `__getmainargs` for `__wgetmainargs`); other writers /// ignore it. pub entry_name: Option, + /// The literal `#pragma entrypoint()` value; `None` when + /// the source has no such pragma. Distinct from `entry_name`, + /// which also reflects the CRT fallbacks. The driver reads this + /// to warn when a relocatable emit drops the pragma (an object + /// file does not carry it). + pub entry_pragma: Option, + /// Function names the auto-include retry bound to a bundled + /// header during [`crate::c5::Compiler::compile`]. The driver + /// consults this in a multi-TU build: a name another input + /// defines is recompiled as an implicit extern so the user's + /// definition wins over the header's library binding. + pub auto_includes: Vec, /// Source-declared Windows subsystem. Set by /// `#pragma subsystem()`; `None` falls back to the /// PE writer's default (`Console`). Read only by the PE diff --git a/src/main.rs b/src/main.rs index 9d529a1da..ff84f51b5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -877,8 +877,14 @@ fn main() { // `.c` -> in-memory native ELF64 ET_REL: the source compiles // straight to ET_REL bytes that `parse_native_elf` reads back, // so no intermediate `.o` is written to disk. - let compile_one = |src_path: &str| -> (Vec, Option, Option) { - if multi_tu && !quiet { + type CompiledUnit = ( + Vec, + Option, + Option, + Vec, + ); + let compile_one = |src_path: &str, implicit_externs: &[String]| -> CompiledUnit { + if multi_tu && !quiet && implicit_externs.is_empty() { eprint_diagnostic(format!("info: compiling {src_path}")); } let src_bytes = if src_path == "-" { @@ -902,6 +908,7 @@ fn main() { .with_show_includes(show_includes) .with_warn_dead_store(warn_dead_store) .with_export_all_functions(export_all) + .with_implicit_extern_fns(implicit_externs.to_vec()) .with_no_entry_point(true); let mut compiler = Compiler::with_options(src_bytes, target, copts); if show_includes { @@ -921,8 +928,9 @@ fn main() { } let entry = program.entry_name.clone(); let subsystem = program.subsystem; + let auto_includes = program.auto_includes.clone(); match badc::emit_native_with_options(&program, target, reloc_opts) { - Ok(b) => (b, entry, subsystem), + Ok(b) => (b, entry, subsystem, auto_includes), Err(e) => { eprint_diagnostic(e); std::process::exit(1); @@ -979,14 +987,16 @@ fn main() { // it (the source-level pragma rides the in-memory `Program`, // not a section), then threaded to the PE writer. let mut subsystem_override: Option = None; + let mut source_auto_includes: Vec> = Vec::with_capacity(sources.len()); for src_path in &sources { - let (bytes, entry, subsystem) = compile_one(src_path); + let (bytes, entry, subsystem, auto_includes) = compile_one(src_path, &[]); if entry_override.is_none() { entry_override = entry; } if subsystem_override.is_none() { subsystem_override = subsystem; } + source_auto_includes.push(auto_includes); match badc::parse_native_elf(&bytes) { Ok(o) => native_objs.push(o), Err(e) => { @@ -1127,6 +1137,14 @@ fn main() { } } } + // Archive members join the link on demand: a member is + // included iff it defines a symbol some already-included + // object still leaves undefined, iterated to a fixpoint so a + // pulled member's own references can pull further members + // (from any archive). Unreferenced members stay out, so their + // unrelated undefined or duplicate symbols cannot fail a + // valid link. + let mut pending: Vec<(String, badc::NativeObject)> = Vec::new(); for a_path in &archives { let bytes = match std::fs::read(a_path) { Ok(b) => b, @@ -1151,7 +1169,7 @@ fn main() { std::process::exit(1); } match badc::parse_native_elf(&m.bytes) { - Ok(o) => native_objs.push(o), + Ok(o) => pending.push((format!("{a_path}({})", m.name), o)), Err(e) => { eprint_diagnostic(format!("badc: {a_path}({}): {e}", m.name)); std::process::exit(1); @@ -1159,6 +1177,108 @@ fn main() { } } } + // C89 6.3.2.2 link semantics: a definition anywhere in the + // link set satisfies an implicitly declared call, so a name + // the auto-include retry bound to a header's library binding + // is recompiled as an implicit extern when an input defines + // it -- the user's definition wins over the binding. + if source_auto_includes.iter().any(|a| !a.is_empty()) { + let mut defined_fns = std::collections::HashSet::::new(); + for o in native_objs.iter().chain(pending.iter().map(|(_, o)| o)) { + for s in &o.symbols { + // STB_GLOBAL STT_FUNC section-resident definitions. + if s.binding == 1 + && s.kind == 2 + && !matches!( + s.section, + badc::NativeSymSection::Undef | badc::NativeSymSection::Abs + ) + { + defined_fns.insert(s.name.clone()); + } + } + } + for (i, autos) in source_auto_includes.iter().enumerate() { + let redirect: Vec = autos + .iter() + .filter(|n| defined_fns.contains(n.as_str())) + .cloned() + .collect(); + if redirect.is_empty() { + continue; + } + if !quiet { + for n in &redirect { + eprint_diagnostic(format!( + "info: the link defines `{n}`; rebinding the call in {} to it", + sources[i] + )); + } + } + let (bytes, _, _, _) = compile_one(&sources[i], &redirect); + match badc::parse_native_elf(&bytes) { + Ok(o) => native_objs[i] = o, + Err(e) => { + eprint_diagnostic(format!("badc: {}: {e}", sources[i])); + std::process::exit(1); + } + } + } + } + if !pending.is_empty() { + let mut defined = std::collections::HashSet::::new(); + let mut undefined = std::collections::HashSet::::new(); + // A global or weak definition satisfies references; only a + // strong (STB_GLOBAL) undefined reference pulls a member, + // matching ELF archive practice (a weak reference left + // unresolved does not extract members). + let account = + |o: &badc::NativeObject, + defined: &mut std::collections::HashSet, + undefined: &mut std::collections::HashSet| { + for s in &o.symbols { + if s.binding == 0 { + continue; + } + if s.section == badc::NativeSymSection::Undef { + if s.binding == 1 && !defined.contains(&s.name) { + undefined.insert(s.name.clone()); + } + } else { + defined.insert(s.name.clone()); + undefined.remove(&s.name); + } + } + }; + for o in &native_objs { + account(o, &mut defined, &mut undefined); + } + // The archive symbol index lists strong section-resident + // definitions; a member is pulled on exactly those. + let mut progress = true; + while progress { + progress = false; + let mut i = 0; + while i < pending.len() { + let wanted = pending[i].1.symbols.iter().any(|s| { + s.binding == 1 + && !matches!( + s.section, + badc::NativeSymSection::Undef | badc::NativeSymSection::Abs + ) + && undefined.contains(&s.name) + }); + if wanted { + let (_, o) = pending.remove(i); + account(&o, &mut defined, &mut undefined); + native_objs.push(o); + progress = true; + } else { + i += 1; + } + } + } + } if native_objs.is_empty() { eprint_diagnostic("badc: error: no inputs"); std::process::exit(1); @@ -1323,6 +1443,7 @@ fn main() { for w in &program.warnings { eprintln!("{}", colorize_diagnostic(w, stderr_is_tty)); } + warn_dropped_link_pragmas(&program, src_path); match badc::emit_native_with_options(&program, target, reloc_opts) { Ok(b) => b, Err(e) => { @@ -1427,6 +1548,7 @@ fn main() { for w in &program.warnings { eprintln!("{}", colorize_diagnostic(w, stderr_is_tty)); } + warn_dropped_link_pragmas(&program, src_path); match badc::emit_native_with_options(&program, target, reloc_opts) { Ok(b) => b, Err(e) => { @@ -1525,6 +1647,27 @@ fn native_defined_globals(bytes: &[u8], path: &str) -> Vec { .collect() } +/// `#pragma entrypoint` / `#pragma subsystem` ride the in-memory +/// `Program` of the invocation that links; an ET_REL object carries +/// neither. Warn when a relocatable emit drops them so the TU is +/// recompiled in the link invocation instead of silently producing a +/// console-subsystem / default-entry image. +fn warn_dropped_link_pragmas(program: &badc::Program, src_path: &str) { + let mut dropped: Vec<&str> = Vec::new(); + if program.entry_pragma.is_some() { + dropped.push("entrypoint"); + } + if program.subsystem.is_some() { + dropped.push("subsystem"); + } + for p in dropped { + eprint_diagnostic(format!( + "{src_path}: warning: `#pragma {p}(...)` is not carried by an object \ + file; compile this source in the link invocation for it to take effect" + )); + } +} + fn eprint_diagnostic(msg: impl core::fmt::Display) { let stderr_is_tty = std::io::stderr().is_terminal(); let s = msg.to_string(); diff --git a/tests/cli_linker_smoke.rs b/tests/cli_linker_smoke.rs index 6b9b38f70..6b509b11b 100644 --- a/tests/cli_linker_smoke.rs +++ b/tests/cli_linker_smoke.rs @@ -128,6 +128,107 @@ fn archive_resolves_via_minus_l_search() { assert_eq!(out.status.code(), Some(38), "exit code mismatch"); } +#[test] +fn archive_members_are_pulled_on_demand() { + // Archive semantics (SysV ar / ELF linker practice): a member + // joins the link iff it defines a still-undefined symbol, + // iterated to a fixpoint. An unreferenced member must stay out + // even when it carries an unresolvable reference of its own or + // defines a name the program also defines. + let dir = tempdir("archive-on-demand"); + write_source( + &dir, + "m1.c", + "extern int chain(void);\nint used(void) { return 11 + chain(); }\n", + ); + // Pulled only through m1's reference (fixpoint). + write_source(&dir, "m2.c", "int chain(void) { return 20; }\n"); + // Never referenced: its undefined `never_defined` must not fail + // the link. + write_source( + &dir, + "m3.c", + "extern int never_defined(void);\nint unused_entry(void) { return never_defined(); }\n", + ); + // Never referenced: its `helper` must not collide with main.c's. + write_source(&dir, "m4.c", "int helper(void) { return 99; }\n"); + write_source( + &dir, + "main.c", + "extern int used(void);\nint helper(void) { return 1; }\n\ + int main(void) { return used() + helper(); }\n", + ); + run( + Command::new(badc()) + .arg("--ar") + .arg("-o") + .arg(dir.join("libt.a")) + .arg(dir.join("m1.c")) + .arg(dir.join("m2.c")) + .arg(dir.join("m3.c")) + .arg(dir.join("m4.c")) + .current_dir(&dir), + "build archive", + ); + let exe = dir.join("prog"); + run( + Command::new(badc()) + .arg("-o") + .arg(&exe) + .arg(dir.join("main.c")) + .arg(dir.join("libt.a")) + .current_dir(&dir), + "link against the archive", + ); + let out = Command::new(&exe).output().expect("run prog"); + // 11 + 20 + 1 = 32. + assert_eq!( + out.status.code(), + Some(32), + "exit code mismatch: stderr={:?}", + String::from_utf8_lossy(&out.stderr) + ); +} + +#[test] +fn compile_only_warns_when_link_pragmas_are_dropped() { + // `#pragma subsystem` / `#pragma entrypoint` ride the in-memory + // program of the invocation that links; an ET_REL object carries + // neither. `-c` must say so instead of silently emitting an + // object that later links as a console / default-entry image. + let dir = tempdir("compile-only-pragmas"); + write_source( + &dir, + "gui.c", + "#pragma subsystem(windows)\nint main(void) { return 0; }\n", + ); + write_source( + &dir, + "ep.c", + "#pragma entrypoint(my_entry)\nint my_entry(void) { return 0; }\n", + ); + write_source(&dir, "plain.c", "int main(void) { return 0; }\n"); + let compile = |name: &str| -> String { + let out = run( + Command::new(badc()) + .arg("--target=windows-x64") + .arg("-c") + .arg(dir.join(name)) + .arg("-o") + .arg(dir.join(name).with_extension("o")) + .current_dir(&dir), + "compile -c", + ); + String::from_utf8_lossy(&out.stderr).into_owned() + }; + let gui = compile("gui.c"); + assert!(gui.contains("#pragma subsystem"), "stderr: {gui}"); + let ep = compile("ep.c"); + assert!(ep.contains("#pragma entrypoint"), "stderr: {ep}"); + let plain = compile("plain.c"); + assert!(!plain.contains("warning"), "stderr: {plain}"); +} + #[test] fn unresolved_extern_function_fails_link() { let dir = tempdir("unresolved"); @@ -2731,3 +2832,57 @@ fn defining_c5_entry_without_flag_is_not_implicitly_freestanding() { "expected a duplicate-symbol error for __c5_entry; got: {stderr:?}" ); } + +#[test] +fn link_defined_symbol_wins_over_auto_included_binding() { + // C89 6.3.2.2 link semantics: an undeclared call binds to + // whatever the link defines. When a sibling TU defines a name + // that also exists as a bundled-header libc binding (getpid), + // the auto-include retry must not override the user's + // definition with the library import. + let dir = tempdir("auto-include-preference"); + write_source( + &dir, + "caller.c", + "int main(void) { return getpid() == 999 ? 0 : 1; }\n", + ); + write_source(&dir, "impl.c", "int getpid(void) { return 999; }\n"); + let exe = dir.join("prog"); + run( + Command::new(badc()) + .arg("-o") + .arg(&exe) + .arg(dir.join("caller.c")) + .arg(dir.join("impl.c")) + .current_dir(&dir), + "link with a user getpid", + ); + let out = Command::new(&exe).output().expect("run prog"); + assert_eq!( + out.status.code(), + Some(0), + "the user's getpid must win: stderr={:?}", + String::from_utf8_lossy(&out.stderr) + ); + // The auto-include still serves calls nothing in the link + // defines: an undeclared printf in a multi-TU build works. + write_source( + &dir, + "p1.c", + "int main(void) { printf(\"hi\\n\"); return 0; }\n", + ); + write_source(&dir, "p2.c", "int unrelated(void) { return 0; }\n"); + let exe2 = dir.join("prog2"); + run( + Command::new(badc()) + .arg("-o") + .arg(&exe2) + .arg(dir.join("p1.c")) + .arg(dir.join("p2.c")) + .current_dir(&dir), + "link with auto-included printf", + ); + let out = Command::new(&exe2).output().expect("run prog2"); + assert_eq!(out.status.code(), Some(0), "auto-included printf runs"); + assert_eq!(String::from_utf8_lossy(&out.stdout), "hi\n"); +} From 4066646e456e92c132bae365e99dc22f165a0e9c Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 22:03:17 -0700 Subject: [PATCH 44/67] headers, runtime: drop dead libc bindings, wire Windows tz outputs * Remove bindings whose target symbol the named library does not export, so a use fails loudly at link instead of aborting at load: macOS clock_nanosleep, fexecve, mremap, and the sched_setparam / sched_getparam / sched_setscheduler / sched_getscheduler / sched_rr_get_interval family (dlsym-verified against libSystem), and glibc ctermid_r. * Windows: CharLowerW / CharUpperW bind to user32.dll and UuidCreate / UuidCreateSequential to rpcrt4.dll (their documented homes; kernel32 fails at load). _ftelli64 and the _byteswap_* family bind to ucrtbase (absent from the legacy msvcrt.dll); ctime_s binds to the 64-bit-time_t export `_ctime64_s` like its localtime_s / gmtime_s neighbors; the `_getpid` spelling is arch-gated to ucrtbase on arm64 like unistd.h's getpid. * Windows x64 binds tzname / timezone / daylight as msvcrt data imports (the `environ` treatment), so a read after `tzset()` sees the CRT's values instead of dead zero slots; the runtime's local slots stay Linux-only (COPY-relocation targets). arm64 keeps safe local slots (empty names, zero offset) with a TODO until the msvcrt.dll surface is verified on an arm64 box. Co-Authored-By: Claude Fable 5 --- headers/include/sched.h | 8 ++-- headers/include/stdio.h | 18 ++++++-- headers/include/sys/mman.h | 2 +- headers/include/time.h | 14 +++++- headers/include/unistd.h | 4 +- headers/include/windows.h | 18 ++++---- lib/runtime.c | 12 ++++- src/c5/tests/linker.rs | 95 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 146 insertions(+), 25 deletions(-) diff --git a/headers/include/sched.h b/headers/include/sched.h index c6c6f896e..70368b0b9 100644 --- a/headers/include/sched.h +++ b/headers/include/sched.h @@ -30,11 +30,9 @@ struct sched_param { #pragma binding(libc::sched_yield, "_sched_yield") #pragma binding(libc::sched_get_priority_max, "_sched_get_priority_max") #pragma binding(libc::sched_get_priority_min, "_sched_get_priority_min") -#pragma binding(libc::sched_setscheduler, "_sched_setscheduler") -#pragma binding(libc::sched_getscheduler, "_sched_getscheduler") -#pragma binding(libc::sched_setparam, "_sched_setparam") -#pragma binding(libc::sched_getparam, "_sched_getparam") -#pragma binding(libc::sched_rr_get_interval, "_sched_rr_get_interval") +// libSystem exports none of sched_setscheduler / sched_getscheduler / +// sched_setparam / sched_getparam / sched_rr_get_interval; leaving +// them unbound makes a use fail at link rather than at load. #endif #ifdef __linux__ diff --git a/headers/include/stdio.h b/headers/include/stdio.h index dfa62c721..170b187f4 100644 --- a/headers/include/stdio.h +++ b/headers/include/stdio.h @@ -293,7 +293,9 @@ int vsnprintf(char *buf, int size, char *fmt, char *ap); #pragma binding(msvcrt::fseek, "fseek") #pragma binding(msvcrt::ftell, "ftell") #pragma binding(msvcrt::_fseeki64, "_fseeki64") -#pragma binding(msvcrt::_ftelli64, "_ftelli64") +// The legacy msvcrt.dll exports no _ftelli64 (unlike _fseeki64); UCRT does. +#pragma dylib(ucrtbase, "ucrtbase.dll") +#pragma binding(ucrtbase::_ftelli64, "_ftelli64") #pragma binding(msvcrt::fgetpos, "fgetpos") #pragma binding(msvcrt::fsetpos, "fsetpos") #pragma binding(msvcrt::rewind, "rewind") @@ -371,7 +373,7 @@ int vsnprintf(char *buf, int size, char *fmt, char *ap); // SDK macros. badc's time_t is 64-bit on Windows, so the ABI matches. #pragma binding(msvcrt::localtime_s, "_localtime64_s") #pragma binding(msvcrt::gmtime_s, "_gmtime64_s") -#pragma binding(msvcrt::ctime_s, "ctime_s") +#pragma binding(msvcrt::ctime_s, "_ctime64_s") #pragma binding(msvcrt::asctime_s, "asctime_s") #pragma binding(msvcrt::strerror_s, "strerror_s") #pragma binding(msvcrt::_strdup, "_strdup") @@ -404,7 +406,12 @@ int vsnprintf(char *buf, int size, char *fmt, char *ap); #pragma binding(msvcrt::_unlink, "_unlink") #pragma binding(msvcrt::_getcwd, "_getcwd") #pragma binding(msvcrt::_chdir, "_chdir") +// The legacy arm64 msvcrt.dll does not export `_getpid`; UCRT does. +#if defined(__aarch64__) +#pragma binding(ucrtbase::_getpid, "_getpid") +#else #pragma binding(msvcrt::_getpid, "_getpid") +#endif #pragma binding(msvcrt::_dup, "_dup") #pragma binding(msvcrt::_dup2, "_dup2") #pragma binding(msvcrt::_fdopen, "_fdopen") @@ -412,9 +419,10 @@ int vsnprintf(char *buf, int size, char *fmt, char *ap); // form, so the portable spelling binds to the same entry point. #pragma binding(msvcrt::fdopen, "_fdopen") #pragma binding(msvcrt::fileno, "_fileno") -#pragma binding(msvcrt::_byteswap_ulong, "_byteswap_ulong") -#pragma binding(msvcrt::_byteswap_uint64, "_byteswap_uint64") -#pragma binding(msvcrt::_byteswap_ushort, "_byteswap_ushort") +// The legacy msvcrt.dll exports no _byteswap_*; UCRT does. +#pragma binding(ucrtbase::_byteswap_ulong, "_byteswap_ulong") +#pragma binding(ucrtbase::_byteswap_uint64, "_byteswap_uint64") +#pragma binding(ucrtbase::_byteswap_ushort, "_byteswap_ushort") // `__acrt_iob_func(int)` is the CRT helper that returns a // FILE * to the requested standard stream (0=stdin, 1=stdout, // 2=stderr). Used by `__c5_lazy_stream` above to back the diff --git a/headers/include/sys/mman.h b/headers/include/sys/mman.h index 8d22a0a70..af6a31c04 100644 --- a/headers/include/sys/mman.h +++ b/headers/include/sys/mman.h @@ -43,7 +43,7 @@ #pragma dylib(libc, "/usr/lib/libSystem.B.dylib") #pragma binding(libc::mmap, "_mmap") #pragma binding(libc::munmap, "_munmap") -#pragma binding(libc::mremap, "_mremap") +// mremap is Linux-only; unbound here so a use fails at link. #pragma binding(libc::msync, "_msync") #pragma binding(libc::mprotect, "_mprotect") #pragma binding(libc::madvise, "_madvise") diff --git a/headers/include/time.h b/headers/include/time.h index d7689a1bb..52611f924 100644 --- a/headers/include/time.h +++ b/headers/include/time.h @@ -125,7 +125,7 @@ typedef long clock_t; #pragma binding(libc::clock_gettime, "_clock_gettime") #pragma binding(libc::clock_settime, "_clock_settime") #pragma binding(libc::clock_getres, "_clock_getres") -#pragma binding(libc::clock_nanosleep, "_clock_nanosleep") +// libSystem exports no clock_nanosleep; unbound so a use fails at link. #pragma binding(libc::gettimeofday, "_gettimeofday") #pragma binding(libc::difftime, "_difftime") #pragma binding(libc::mktime, "_mktime") @@ -179,6 +179,18 @@ typedef long clock_t; #pragma binding(msvcrt::gmtime, "gmtime") #pragma binding(msvcrt::strftime, "strftime") #pragma binding(msvcrt::tzset, "_tzset") +#if defined(__aarch64__) +// TODO: the arm64 msvcrt.dll tzset-output surface is unverified; +// the runtime defines safe local slots (empty names, zero offset) +// until the accessor route is validated on an arm64 box. +#else +// x64 msvcrt.dll exports the tzset outputs as data; bind each as a +// loader-filled import so a read after `tzset()` sees the CRT's +// values -- the same treatment as `environ` (see ). +#pragma binding(data msvcrt::tzname, "_tzname") +#pragma binding(data msvcrt::timezone, "_timezone") +#pragma binding(data msvcrt::daylight, "_daylight") +#endif // Windows doesn't ship POSIX `clock_gettime` / `gettimeofday`. SQLite // has its own Win32-specific code path that calls // `GetSystemTimeAsFileTime`; programs that want a portable shape diff --git a/headers/include/unistd.h b/headers/include/unistd.h index fe48dae81..b04d0ad0e 100644 --- a/headers/include/unistd.h +++ b/headers/include/unistd.h @@ -136,7 +136,7 @@ #pragma binding(libc::fpathconf, "_fpathconf") #pragma binding(libc::lockf, "_lockf") #pragma binding(libc::execv, "_execv") -#pragma binding(libc::fexecve, "_fexecve") +// libSystem exports no fexecve; unbound so a use fails at link. #pragma binding(libc::pathconf, "_pathconf") #pragma binding(libc::sysconf, "_sysconf") #pragma binding(libc::getpagesize, "_getpagesize") @@ -257,7 +257,7 @@ extern char **environ; #pragma binding(libc::ttyname, "ttyname") #pragma binding(libc::ttyname_r, "ttyname_r") #pragma binding(libc::ctermid, "ctermid") -#pragma binding(libc::ctermid_r, "ctermid_r") +// glibc exports no ctermid_r; unbound so a use fails at link. #pragma binding(libc::getlogin, "getlogin") #pragma binding(libc::getlogin_r,"getlogin_r") #pragma binding(libc::getgroups, "getgroups") diff --git a/headers/include/windows.h b/headers/include/windows.h index 7165c5fcd..ed14965aa 100644 --- a/headers/include/windows.h +++ b/headers/include/windows.h @@ -1676,8 +1676,10 @@ LONG RegSetValueExW(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType #pragma binding(kernel32::GetNativeSystemInfo, "GetNativeSystemInfo") #pragma binding(kernel32::GetProcessHeap, "GetProcessHeap") #pragma binding(kernel32::GetProcAddressA, "GetProcAddress") -#pragma binding(kernel32::CharLowerW, "CharLowerW") -#pragma binding(kernel32::CharUpperW, "CharUpperW") +// CharLowerW / CharUpperW are user32.dll exports (winuser.h). +#pragma dylib(user32, "user32.dll") +#pragma binding(user32::CharLowerW, "CharLowerW") +#pragma binding(user32::CharUpperW, "CharUpperW") #pragma binding(kernel32::CreateFileA, "CreateFileA") #pragma binding(kernel32::CreateFileTransactedA, "CreateFileTransactedA") #pragma binding(kernel32::CreateFileTransactedW, "CreateFileTransactedW") @@ -1848,13 +1850,11 @@ LONG RegSetValueExW(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType #pragma binding(kernel32::TzSpecificLocalTimeToSystemTime, "TzSpecificLocalTimeToSystemTime") #pragma binding(kernel32::GetLocalTime, "GetLocalTime") #pragma binding(kernel32::SetLastError, "SetLastError") -// rpcrt4-resident UUID helpers; sqlite gates these on -// `SQLITE_WIN32_USE_UUID`. The kernel32 dylib hosts the binding -// nominally -- runtime resolution still goes through the -// dispatch table -- but production-quality runs would bind these -// to rpcrt4.dll. -#pragma binding(kernel32::UuidCreate, "UuidCreate") -#pragma binding(kernel32::UuidCreateSequential, "UuidCreateSequential") +// UuidCreate / UuidCreateSequential are rpcrt4.dll exports (rpcdce.h); +// binding them to kernel32 fails at load. +#pragma dylib(rpcrt4, "rpcrt4.dll") +#pragma binding(rpcrt4::UuidCreate, "UuidCreate") +#pragma binding(rpcrt4::UuidCreateSequential, "UuidCreateSequential") // Prototypes mirror the Win32 API shapes documented on MSDN. Where // the real return type is `BOOL` (= int) we keep `int`; where it's diff --git a/lib/runtime.c b/lib/runtime.c index 5d756b968..b336c48de 100644 --- a/lib/runtime.c +++ b/lib/runtime.c @@ -91,14 +91,22 @@ int snprintf(char *buf, int size, char *fmt, ...) { #if !defined(__APPLE__) && !defined(_WIN32) char **environ; #endif -#ifndef __APPLE__ +#if defined(__linux__) // POSIX `tzset` outputs. Like `environ`, the Linux bindings route these // through a COPY relocation against the C library's symbols so a read // after `tzset()` sees what the library wrote; the local slots here are -// the relocation targets. +// the relocation targets. Windows x64 binds them as msvcrt data imports +// (see ), so the symbols must stay undefined there. char *tzname[2]; long timezone; int daylight; +#elif defined(_WIN32) && defined(__aarch64__) +// TODO: the arm64 msvcrt.dll tzset-output surface (data exports or +// accessors) is unverified; keep local slots with defined contents +// (empty names, zero offset, no DST) so reads cannot fault. +char *tzname[2] = { "", "" }; +long timezone; +int daylight; #endif // `__c5_exit` runs libc's `exit` so the atexit chain (including the diff --git a/src/c5/tests/linker.rs b/src/c5/tests/linker.rs index 17281341a..965a1ecf9 100644 --- a/src/c5/tests/linker.rs +++ b/src/c5/tests/linker.rs @@ -2138,3 +2138,98 @@ fn alignas_sixteen_places_objects_and_raises_data_align() { ); } } + +#[test] +fn windows_x64_tz_globals_bind_to_msvcrt_data_exports() { + // msvcrt's `_tzset` writes the DLL's own `_tzname` / `_timezone` / + // `_daylight`; the x64 image must import them as data (the + // `environ` treatment) instead of resolving the externs to local + // zero-filled slots `_tzset` never writes. + use crate::c5::{NativeOptions, OutputKind, Target, emit_native_with_options}; + let src = "#include \n\ + #include \n\ + #pragma export(use_tz)\n\ + long use_tz(void) { tzset(); return timezone + daylight + (tzname[0] != 0); }\n"; + let program = Compiler::with_target(src.to_string(), Target::WindowsX64) + .compile() + .expect("compile tz TU"); + let obj = emit_native_with_options( + &program, + Target::WindowsX64, + NativeOptions { + output_kind: OutputKind::Relocatable, + ..Default::default() + }, + ) + .expect("emit object"); + let contains = |needle: &[u8]| obj.windows(needle.len()).any(|w| w == needle); + for sym in [ + &b"\0_tzname\0"[..], + &b"\0_timezone\0"[..], + &b"\0_daylight\0"[..], + ] { + assert!( + contains(sym), + "x64 tz output {:?} must be a data import", + core::str::from_utf8(sym) + ); + } +} + +#[test] +fn dead_libc_bindings_fail_at_build_not_at_load() { + // libSystem exports none of these (dlsym-verified); the header must + // leave them unbound so a use fails the build loudly instead of + // producing an image that aborts at load with a dyld error. + let cases = [ + ( + "#include \nint main(void) { struct timespec t; t.tv_sec = 0; t.tv_nsec = 0; return clock_nanosleep(0, 0, &t, 0); }\n", + "clock_nanosleep", + ), + ( + "#include \nint main(void) { return mremap((void *)0, 0, 0, 0) != 0; }\n", + "mremap", + ), + ( + "#include \nint main(void) { return sched_getscheduler(0); }\n", + "sched_getscheduler", + ), + ( + "#include \nint main(void) { return fexecve(0, 0, 0); }\n", + "fexecve", + ), + ]; + use crate::c5::linker::{link_native_objects, parse_native_elf}; + use crate::c5::{CompileOptions, NativeOptions, OutputKind, Target, emit_native_with_options}; + let link_one = |src: &str| { + let program = Compiler::with_options( + src.to_string(), + Target::MacOSAarch64, + CompileOptions::default().with_no_entry_point(true), + ) + .compile() + .expect("compile"); + let opts = NativeOptions { + output_kind: OutputKind::Relocatable, + ..Default::default() + }; + let bytes = emit_native_with_options(&program, Target::MacOSAarch64, opts).expect("emit"); + link_native_objects(&[parse_native_elf(&bytes).expect("parse")]) + }; + for (src, name) in cases { + let err = link_one(src) + .err() + .unwrap_or_else(|| panic!("{name}: use of an unexported symbol must not link")); + assert!( + format!("{err}").contains(name), + "{name}: diagnostic must name the symbol: {err}" + ); + } + // The bound neighbors still link. + for src in [ + "#include \nint main(void) { struct timespec t; return clock_gettime(0, &t); }\n", + "#include \nint main(void) { return sched_yield(); }\n", + ] { + link_one(src).expect("bound libc call must link"); + } +} From 4a45c4065b0a6ec94441eba4ffb30e639e1a0fd8 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 22:11:54 -0700 Subject: [PATCH 45/67] headers, runtime: tz data imports on both Windows arches; ucrt byteswap Probing both boxes shows msvcrt.dll exports _tzname/_timezone/_daylight as data on arm64 as well as x64, so the arm64 fallback slots go away (they would now collide with the bindings), and the byte-swap trio lives in the UCRT on both architectures. tzset outputs verified live on kromyrzen and kromarm00. Co-Authored-By: Claude Fable 5 --- headers/include/intrin.h | 10 +++++---- headers/include/time.h | 13 ++++-------- lib/runtime.c | 12 +++-------- tests/snapshots/asm/sqlite_min.aarch64.asm | 18 +--------------- tests/snapshots/asm/sqlite_min.x64.asm | 21 +------------------ tests/snapshots/ssa/dlopen_atoi.ssa | 8 +++---- .../ssa/fcntl_lock_via_cast_fnptr.ssa | 2 +- tests/snapshots/ssa/libc_pread64_pwrite64.ssa | 12 +++++------ tests/snapshots/ssa/libc_struct_buf_size.ssa | 2 +- tests/snapshots/ssa/posix_os_headers.ssa | 4 ++-- tests/snapshots/ssa/pthread_create.ssa | 6 +++--- tests/snapshots/ssa/shm_open_mode_arg.ssa | 2 +- tests/snapshots/ssa/sqlite_min.ssa | 8 ++----- tests/snapshots/ssa/sysconf_pagesize.ssa | 12 +++++------ .../snapshots/ssa/thread_local_per_thread.ssa | 6 +++--- 15 files changed, 44 insertions(+), 92 deletions(-) diff --git a/headers/include/intrin.h b/headers/include/intrin.h index 617d2277e..d83d2abef 100644 --- a/headers/include/intrin.h +++ b/headers/include/intrin.h @@ -7,10 +7,12 @@ #ifdef _WIN32 -#pragma dylib(msvcrt, "msvcrt.dll") -#pragma binding(msvcrt::_byteswap_ushort, "_byteswap_ushort") -#pragma binding(msvcrt::_byteswap_ulong, "_byteswap_ulong") -#pragma binding(msvcrt::_byteswap_uint64, "_byteswap_uint64") +/* The byte-swap trio lives in the UCRT, not legacy msvcrt.dll +** (probed on both Windows boxes). */ +#pragma dylib(ucrtbase, "ucrtbase.dll") +#pragma binding(ucrtbase::_byteswap_ushort, "_byteswap_ushort") +#pragma binding(ucrtbase::_byteswap_ulong, "_byteswap_ulong") +#pragma binding(ucrtbase::_byteswap_uint64, "_byteswap_uint64") unsigned short _byteswap_ushort(unsigned short value); unsigned long _byteswap_ulong(unsigned long value); diff --git a/headers/include/time.h b/headers/include/time.h index 52611f924..0d8245186 100644 --- a/headers/include/time.h +++ b/headers/include/time.h @@ -179,18 +179,13 @@ typedef long clock_t; #pragma binding(msvcrt::gmtime, "gmtime") #pragma binding(msvcrt::strftime, "strftime") #pragma binding(msvcrt::tzset, "_tzset") -#if defined(__aarch64__) -// TODO: the arm64 msvcrt.dll tzset-output surface is unverified; -// the runtime defines safe local slots (empty names, zero offset) -// until the accessor route is validated on an arm64 box. -#else -// x64 msvcrt.dll exports the tzset outputs as data; bind each as a -// loader-filled import so a read after `tzset()` sees the CRT's -// values -- the same treatment as `environ` (see ). +// msvcrt.dll exports the tzset outputs as data on both x64 and +// arm64 (probed on the real boxes); bind each as a loader-filled +// import so a read after `tzset()` sees the CRT's values -- the +// same treatment as `environ` (see ). #pragma binding(data msvcrt::tzname, "_tzname") #pragma binding(data msvcrt::timezone, "_timezone") #pragma binding(data msvcrt::daylight, "_daylight") -#endif // Windows doesn't ship POSIX `clock_gettime` / `gettimeofday`. SQLite // has its own Win32-specific code path that calls // `GetSystemTimeAsFileTime`; programs that want a portable shape diff --git a/lib/runtime.c b/lib/runtime.c index b336c48de..6041f4a24 100644 --- a/lib/runtime.c +++ b/lib/runtime.c @@ -95,18 +95,12 @@ char **environ; // POSIX `tzset` outputs. Like `environ`, the Linux bindings route these // through a COPY relocation against the C library's symbols so a read // after `tzset()` sees what the library wrote; the local slots here are -// the relocation targets. Windows x64 binds them as msvcrt data imports -// (see ), so the symbols must stay undefined there. +// the relocation targets. Windows binds them as msvcrt data imports on +// both architectures (see ), so the symbols must stay +// undefined there. char *tzname[2]; long timezone; int daylight; -#elif defined(_WIN32) && defined(__aarch64__) -// TODO: the arm64 msvcrt.dll tzset-output surface (data exports or -// accessors) is unverified; keep local slots with defined contents -// (empty names, zero offset, no DST) so reads cannot fault. -char *tzname[2] = { "", "" }; -long timezone; -int daylight; #endif // `__c5_exit` runs libc's `exit` so the atexit chain (including the diff --git a/tests/snapshots/asm/sqlite_min.aarch64.asm b/tests/snapshots/asm/sqlite_min.aarch64.asm index 6cae7cd4a..1cb23980f 100644 --- a/tests/snapshots/asm/sqlite_min.aarch64.asm +++ b/tests/snapshots/asm/sqlite_min.aarch64.asm @@ -164,23 +164,7 @@ Disassembly of section .text: ret <__c5_sys_fcntl>: - str x2, [sp, #-0x10]! - str x1, [sp, #-0x10]! - str x0, [sp, #-0x10]! - stp x29, x30, [sp, #-0x10]! - mov x29, sp - sub sp, sp, #0x10 - str x19, [sp] - ldur x0, [x29, #0x10] - ldur x1, [x29, #0x20] - ldur x2, [x29, #0x30] - bl - sxtw x0, w0 - ldr x19, [sp] - add sp, sp, #0x10 - ldp x29, x30, [sp], #0x10 - add sp, sp, #0x30 - ret + b <__c5_sys_stat>: str x1, [sp, #-0x10]! diff --git a/tests/snapshots/asm/sqlite_min.x64.asm b/tests/snapshots/asm/sqlite_min.x64.asm index a8a0de6fd..0b510e664 100644 --- a/tests/snapshots/asm/sqlite_min.x64.asm +++ b/tests/snapshots/asm/sqlite_min.x64.asm @@ -145,25 +145,7 @@ Disassembly of section .text: retq <__c5_sys_fcntl>: - popq %r10 - subq $0x30, %rsp - movq %rdi, (%rsp) - movq %rsi, 0x10(%rsp) - movq %rdx, 0x20(%rsp) - pushq %r10 - pushq %rbp - movq %rsp, %rbp - movq 0x10(%rbp), %rdi - movq 0x20(%rbp), %rsi - movq 0x30(%rbp), %rdx - xorl %eax, %eax - callq - movslq %eax, %rax - popq %rbp - popq %r11 - addq $0x30, %rsp - pushq %r11 - retq + jmp <__c5_sys_stat>: popq %r10 @@ -202,4 +184,3 @@ Disassembly of section .text: addq $0x20, %rsp pushq %r11 retq - addb %al, 0x41(%rdx) diff --git a/tests/snapshots/ssa/dlopen_atoi.ssa b/tests/snapshots/ssa/dlopen_atoi.ssa index 46c2dc6c8..b01389618 100644 --- a/tests/snapshots/ssa/dlopen_atoi.ssa +++ b/tests/snapshots/ssa/dlopen_atoi.ssa @@ -6,7 +6,7 @@ fn ent_pc=5 n_params=0 variadic=false locals=5 v0 AllocaInit(0) -> - v1 Imm(0) -> x7 v2 Imm(2) -> x6 - v3 CallExt { binding_idx=222, args=[v1, v2], fp_arg_mask=0x0 } -> x3 + v3 CallExt { binding_idx=221, args=[v1, v2], fp_arg_mask=0x0 } -> x3 v4 Imm(0) -> x0 v5 LoadLocal { off=-1, kind=I64 } -> x0 v6 BinopI { op=eq, lhs=v3, rhs_imm=0 } -> x0 @@ -17,14 +17,14 @@ fn ent_pc=5 n_params=0 variadic=false locals=5 block 2 start_pc=0 v8 LoadLocal { off=-1, kind=I64 } -> x0 v9 ImmData(48) -> x6 - v10 CallExt { binding_idx=223, args=[v3, v9], fp_arg_mask=0x0 } -> x12 + v10 CallExt { binding_idx=222, args=[v3, v9], fp_arg_mask=0x0 } -> x12 v11 Imm(0) -> x0 v12 LoadLocal { off=-2, kind=I64 } -> x0 v13 BinopI { op=eq, lhs=v10, rhs_imm=0 } -> x0 terminator Bz { cond=v13, target=b4, fall=b3 } (exit_acc=v13) block 3 start_pc=0 v14 LoadLocal { off=-1, kind=I64 } -> x0 - v15 CallExt { binding_idx=224, args=[v3], fp_arg_mask=0x0 } -> x0 + v15 CallExt { binding_idx=223, args=[v3], fp_arg_mask=0x0 } -> x0 v16 Imm(2) -> x0 terminator Return(v16) (exit_acc=v16) block 4 start_pc=0 @@ -35,7 +35,7 @@ fn ent_pc=5 n_params=0 variadic=false locals=5 v21 Extend { value=v19, kind=I32 } -> x12 v22 Imm(0) -> x0 v23 LoadLocal { off=-1, kind=I64 } -> x0 - v24 CallExt { binding_idx=224, args=[v3], fp_arg_mask=0x0 } -> x0 + v24 CallExt { binding_idx=223, args=[v3], fp_arg_mask=0x0 } -> x0 v25 LoadLocal { off=-3, kind=I32 } -> x0 terminator Return(v21) (exit_acc=v21) ; --- SSA dump (ok=true) ent_pc=0 --- diff --git a/tests/snapshots/ssa/fcntl_lock_via_cast_fnptr.ssa b/tests/snapshots/ssa/fcntl_lock_via_cast_fnptr.ssa index e4a767424..da62f8815 100644 --- a/tests/snapshots/ssa/fcntl_lock_via_cast_fnptr.ssa +++ b/tests/snapshots/ssa/fcntl_lock_via_cast_fnptr.ssa @@ -24,7 +24,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=31 v14 LocalAddr(-21) -> x7 v15 Imm(0) -> x12 v16 Imm(96) -> x2 - v17 CallExt { binding_idx=209, args=[v14, v15, v16], fp_arg_mask=0x0 } -> x0 + v17 CallExt { binding_idx=208, args=[v14, v15, v16], fp_arg_mask=0x0 } -> x0 v18 LocalAddr(-21) -> x0 v19 Imm(1) -> x13 v20 Store { addr=v18, disp=0, value=v19, kind=I16 } -> - diff --git a/tests/snapshots/ssa/libc_pread64_pwrite64.ssa b/tests/snapshots/ssa/libc_pread64_pwrite64.ssa index 197925fdb..d08734651 100644 --- a/tests/snapshots/ssa/libc_pread64_pwrite64.ssa +++ b/tests/snapshots/ssa/libc_pread64_pwrite64.ssa @@ -7,7 +7,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=19 v1 LocalAddr(-8) -> x3 v2 ImmData(304) -> x12 v3 CallExt { binding_idx=48, args=[], fp_arg_mask=0x0 } -> x2 - v4 CallExt { binding_idx=186, args=[v1, v2, v3], fp_arg_mask=0x0 } -> x0 + v4 CallExt { binding_idx=185, args=[v1, v2, v3], fp_arg_mask=0x0 } -> x0 v5 LocalAddr(-8) -> x7 v6 Imm(66) -> x0 v7 Imm(578) -> x6 @@ -24,7 +24,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=19 v14 LocalAddr(-11) -> x7 v15 ImmData(320) -> x6 v16 Imm(16) -> x12 - v17 CallExt { binding_idx=157, args=[v14, v15, v16], fp_arg_mask=0x0 } -> x0 + v17 CallExt { binding_idx=156, args=[v14, v15, v16], fp_arg_mask=0x0 } -> x0 v18 Extend { value=v9, kind=I32 } -> x7 v19 LocalAddr(-11) -> x6 v20 Imm(0) -> x1 @@ -40,7 +40,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=19 v26 LocalAddr(-13) -> x7 v27 Imm(0) -> x12 v28 Imm(16) -> x13 - v29 CallExt { binding_idx=155, args=[v26, v27, v28], fp_arg_mask=0x0 } -> x0 + v29 CallExt { binding_idx=154, args=[v26, v27, v28], fp_arg_mask=0x0 } -> x0 v30 Extend { value=v9, kind=I32 } -> x7 v31 LocalAddr(-13) -> x6 v32 CallExt { binding_idx=23, args=[v30, v31, v28, v27], fp_arg_mask=0x0 } -> x0 @@ -55,7 +55,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=19 v37 LocalAddr(-11) -> x7 v38 LocalAddr(-13) -> x6 v39 Imm(16) -> x2 - v40 CallExt { binding_idx=156, args=[v37, v38, v39], fp_arg_mask=0x0 } -> x0 + v40 CallExt { binding_idx=155, args=[v37, v38, v39], fp_arg_mask=0x0 } -> x0 v41 BinopI { op=ne, lhs=v40, rhs_imm=0 } -> x0 terminator Bz { cond=v41, target=b8, fall=b7 } (exit_acc=v41) block 7 start_pc=0 @@ -92,7 +92,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=19 v66 LocalAddr(-13) -> x7 v67 Imm(0) -> x6 v68 Imm(16) -> x13 - v69 CallExt { binding_idx=155, args=[v66, v67, v68], fp_arg_mask=0x0 } -> x0 + v69 CallExt { binding_idx=154, args=[v66, v67, v68], fp_arg_mask=0x0 } -> x0 v70 Extend { value=v9, kind=I32 } -> x7 v71 LocalAddr(-13) -> x6 v72 Imm(8) -> x2 @@ -109,7 +109,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=19 v79 LocalAddr(-11) -> x7 v80 LocalAddr(-13) -> x6 v81 Imm(8) -> x2 - v82 CallExt { binding_idx=156, args=[v79, v80, v81], fp_arg_mask=0x0 } -> x0 + v82 CallExt { binding_idx=155, args=[v79, v80, v81], fp_arg_mask=0x0 } -> x0 v83 BinopI { op=ne, lhs=v82, rhs_imm=0 } -> x0 terminator Bz { cond=v83, target=b14, fall=b13 } (exit_acc=v83) block 13 start_pc=0 diff --git a/tests/snapshots/ssa/libc_struct_buf_size.ssa b/tests/snapshots/ssa/libc_struct_buf_size.ssa index 802a1d3b8..12bb2c90c 100644 --- a/tests/snapshots/ssa/libc_struct_buf_size.ssa +++ b/tests/snapshots/ssa/libc_struct_buf_size.ssa @@ -14,7 +14,7 @@ fn ent_pc=6 n_params=0 variadic=false locals=21 block 1 start_pc=0 v7 ImmData(81) -> x7 v8 Extend { value=v3, kind=I32 } -> x6 - v9 CallExt { binding_idx=193, args=[v7, v8], fp_arg_mask=0x0 } -> x0 + v9 CallExt { binding_idx=192, args=[v7, v8], fp_arg_mask=0x0 } -> x0 v10 Imm(1) -> x0 terminator Return(v10) (exit_acc=v10) block 2 start_pc=0 diff --git a/tests/snapshots/ssa/posix_os_headers.ssa b/tests/snapshots/ssa/posix_os_headers.ssa index b60fa06cf..ec531840c 100644 --- a/tests/snapshots/ssa/posix_os_headers.ssa +++ b/tests/snapshots/ssa/posix_os_headers.ssa @@ -84,10 +84,10 @@ fn ent_pc=0 n_params=0 variadic=false locals=17 v54 Load { addr=v51, disp=4, kind=I32 } -> x7 v55 CallExt { binding_idx=27, args=[v54], fp_arg_mask=0x0 } -> x0 v56 LocalAddr(-13) -> x6 - v57 CallExt { binding_idx=153, args=[v48, v56], fp_arg_mask=0x0 } -> x0 + v57 CallExt { binding_idx=152, args=[v48, v56], fp_arg_mask=0x0 } -> x0 v58 Imm(21523) -> x6 v59 LocalAddr(-14) -> x2 - v60 CallExt { binding_idx=164, args=[v48, v58, v59], fp_arg_mask=0x0 } -> x0 + v60 CallExt { binding_idx=163, args=[v48, v58, v59], fp_arg_mask=0x0 } -> x0 terminator Return(v48) (exit_acc=v48) ; --- SSA dump (ok=true) ent_pc=0 --- ; name=__c5_exit diff --git a/tests/snapshots/ssa/pthread_create.ssa b/tests/snapshots/ssa/pthread_create.ssa index fc5b555aa..d3a26f18e 100644 --- a/tests/snapshots/ssa/pthread_create.ssa +++ b/tests/snapshots/ssa/pthread_create.ssa @@ -19,15 +19,15 @@ fn ent_pc=1 n_params=0 variadic=false locals=9 v0 AllocaInit(0) -> - v1 Imm(0) -> x3 v2 Imm(2) -> x6 - v3 CallExt { binding_idx=179, args=[v1, v2], fp_arg_mask=0x0 } -> x12 + v3 CallExt { binding_idx=178, args=[v1, v2], fp_arg_mask=0x0 } -> x12 v4 Imm(0) -> x0 v5 LoadLocal { off=-1, kind=I64 } -> x0 v6 ImmData(48) -> x6 - v7 CallExt { binding_idx=180, args=[v3, v6], fp_arg_mask=0x0 } -> x13 + v7 CallExt { binding_idx=179, args=[v3, v6], fp_arg_mask=0x0 } -> x13 v8 Imm(0) -> x0 v9 LoadLocal { off=-1, kind=I64 } -> x0 v10 ImmData(63) -> x6 - v11 CallExt { binding_idx=180, args=[v3, v10], fp_arg_mask=0x0 } -> x12 + v11 CallExt { binding_idx=179, args=[v3, v10], fp_arg_mask=0x0 } -> x12 v12 Imm(0) -> x0 v13 LocalAddr(-4) -> x7 v14 ImmCode(ent_pc=0) -> x2 diff --git a/tests/snapshots/ssa/shm_open_mode_arg.ssa b/tests/snapshots/ssa/shm_open_mode_arg.ssa index dae7507dc..ca78edbf4 100644 --- a/tests/snapshots/ssa/shm_open_mode_arg.ssa +++ b/tests/snapshots/ssa/shm_open_mode_arg.ssa @@ -9,7 +9,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=31 v3 LocalAddr(-8) -> x3 v4 ImmData(76) -> x12 v5 CallExt { binding_idx=64, args=[], fp_arg_mask=0x0 } -> x2 - v6 CallExt { binding_idx=168, args=[v3, v4, v5], fp_arg_mask=0x0 } -> x0 + v6 CallExt { binding_idx=167, args=[v3, v4, v5], fp_arg_mask=0x0 } -> x0 v7 LocalAddr(-8) -> x7 v8 CallExt { binding_idx=7, args=[v7], fp_arg_mask=0x0 } -> x0 v9 LocalAddr(-8) -> x7 diff --git a/tests/snapshots/ssa/sqlite_min.ssa b/tests/snapshots/ssa/sqlite_min.ssa index 12870b06f..b7d423dac 100644 --- a/tests/snapshots/ssa/sqlite_min.ssa +++ b/tests/snapshots/ssa/sqlite_min.ssa @@ -116,15 +116,11 @@ fn ent_pc=8 n_params=2 variadic=false locals=0 terminator Return(v3) (exit_acc=v3) ; --- SSA dump (ok=true) ent_pc=9 --- ; name=__c5_sys_fcntl -fn ent_pc=9 n_params=3 variadic=false locals=0 +fn ent_pc=9 n_params=0 variadic=false locals=0 spill_count=0 gpr_used=[] fp_used=[] block 0 start_pc=0 v0 AllocaInit(0) -> - - v1 LoadLocal { off=2, kind=I64 } -> x7 - v2 LoadLocal { off=3, kind=I64 } -> x6 - v3 LoadLocal { off=4, kind=I64 } -> x2 - v4 CallExt { binding_idx=75, args=[v1, v2, v3], fp_arg_mask=0x0 } -> x0 - terminator Return(v4) (exit_acc=v4) + terminator TailExt(75) ; --- SSA dump (ok=true) ent_pc=10 --- ; name=__c5_sys_stat fn ent_pc=10 n_params=2 variadic=false locals=0 diff --git a/tests/snapshots/ssa/sysconf_pagesize.ssa b/tests/snapshots/ssa/sysconf_pagesize.ssa index ded40d79e..d92b71989 100644 --- a/tests/snapshots/ssa/sysconf_pagesize.ssa +++ b/tests/snapshots/ssa/sysconf_pagesize.ssa @@ -5,7 +5,7 @@ fn ent_pc=0 n_params=0 variadic=false locals=5 block 0 start_pc=0 v0 AllocaInit(0) -> - v1 Imm(30) -> x7 - v2 CallExt { binding_idx=135, args=[v1], fp_arg_mask=0x0 } -> x0 + v2 CallExt { binding_idx=134, args=[v1], fp_arg_mask=0x0 } -> x0 v3 Imm(0) -> x1 v4 LoadLocal { off=-1, kind=I64 } -> x1 v5 BinopI { op=le, lhs=v2, rhs_imm=0 } -> x1 @@ -41,7 +41,7 @@ fn ent_pc=0 n_params=0 variadic=false locals=5 terminator Return(v20) (exit_acc=v20) block 8 start_pc=0 v21 Imm(60) -> x7 - v22 CallExt { binding_idx=135, args=[v21], fp_arg_mask=0x0 } -> x0 + v22 CallExt { binding_idx=134, args=[v21], fp_arg_mask=0x0 } -> x0 v23 Imm(0) -> x1 v24 LoadLocal { off=-2, kind=I64 } -> x1 v25 BinopI { op=lt, lhs=v22, rhs_imm=16 } -> x0 @@ -51,7 +51,7 @@ fn ent_pc=0 n_params=0 variadic=false locals=5 terminator Return(v26) (exit_acc=v26) block 10 start_pc=0 v27 Imm(4) -> x7 - v28 CallExt { binding_idx=135, args=[v27], fp_arg_mask=0x0 } -> x0 + v28 CallExt { binding_idx=134, args=[v27], fp_arg_mask=0x0 } -> x0 v29 BinopI { op=le, lhs=v28, rhs_imm=0 } -> x0 terminator Bz { cond=v29, target=b12, fall=b11 } (exit_acc=v29) block 11 start_pc=0 @@ -59,7 +59,7 @@ fn ent_pc=0 n_params=0 variadic=false locals=5 terminator Return(v30) (exit_acc=v30) block 12 start_pc=0 v31 Imm(84) -> x7 - v32 CallExt { binding_idx=135, args=[v31], fp_arg_mask=0x0 } -> x0 + v32 CallExt { binding_idx=134, args=[v31], fp_arg_mask=0x0 } -> x0 v33 BinopI { op=le, lhs=v32, rhs_imm=0 } -> x0 terminator Bz { cond=v33, target=b14, fall=b13 } (exit_acc=v33) block 13 start_pc=0 @@ -67,7 +67,7 @@ fn ent_pc=0 n_params=0 variadic=false locals=5 terminator Return(v34) (exit_acc=v34) block 14 start_pc=0 v35 Imm(2) -> x7 - v36 CallExt { binding_idx=135, args=[v35], fp_arg_mask=0x0 } -> x0 + v36 CallExt { binding_idx=134, args=[v35], fp_arg_mask=0x0 } -> x0 v37 BinopI { op=le, lhs=v36, rhs_imm=0 } -> x0 terminator Bz { cond=v37, target=b16, fall=b15 } (exit_acc=v37) block 15 start_pc=0 @@ -76,7 +76,7 @@ fn ent_pc=0 n_params=0 variadic=false locals=5 block 16 start_pc=0 v39 ImmData(48) -> x7 v40 Imm(3) -> x6 - v41 CallExt { binding_idx=134, args=[v39, v40], fp_arg_mask=0x0 } -> x0 + v41 CallExt { binding_idx=133, args=[v39, v40], fp_arg_mask=0x0 } -> x0 v42 BinopI { op=le, lhs=v41, rhs_imm=0 } -> x0 terminator Bz { cond=v42, target=b18, fall=b17 } (exit_acc=v42) block 17 start_pc=0 diff --git a/tests/snapshots/ssa/thread_local_per_thread.ssa b/tests/snapshots/ssa/thread_local_per_thread.ssa index 7cd828504..3ed0563a3 100644 --- a/tests/snapshots/ssa/thread_local_per_thread.ssa +++ b/tests/snapshots/ssa/thread_local_per_thread.ssa @@ -42,15 +42,15 @@ fn ent_pc=6 n_params=0 variadic=false locals=9 v3 Store { addr=v1, disp=0, value=v2, kind=I32 } -> - v4 Imm(0) -> x12 v5 Imm(2) -> x6 - v6 CallExt { binding_idx=222, args=[v4, v5], fp_arg_mask=0x0 } -> x13 + v6 CallExt { binding_idx=221, args=[v4, v5], fp_arg_mask=0x0 } -> x13 v7 Imm(0) -> x0 v8 LoadLocal { off=-1, kind=I64 } -> x0 v9 ImmData(48) -> x6 - v10 CallExt { binding_idx=223, args=[v6, v9], fp_arg_mask=0x0 } -> x14 + v10 CallExt { binding_idx=222, args=[v6, v9], fp_arg_mask=0x0 } -> x14 v11 Imm(0) -> x0 v12 LoadLocal { off=-1, kind=I64 } -> x0 v13 ImmData(63) -> x6 - v14 CallExt { binding_idx=223, args=[v6, v13], fp_arg_mask=0x0 } -> x13 + v14 CallExt { binding_idx=222, args=[v6, v13], fp_arg_mask=0x0 } -> x13 v15 Imm(0) -> x0 v16 LocalAddr(-4) -> x7 v17 ImmCode(ent_pc=5) -> x2 From be4cb95ea1526666c844e03dadca0fb3586593bb Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 22:19:14 -0700 Subject: [PATCH 46/67] vm: pin the bound-data interp diagnostic test to an explicit target Compiler::new follows the host; the environ binding shape is per-OS (macOS GOT data import, Linux runtime definition, Windows per-arch), so the test compiled differently on a Windows host and failed before reaching the diagnostic under test. Co-Authored-By: Claude Fable 5 --- src/c5/vm/ssa.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/c5/vm/ssa.rs b/src/c5/vm/ssa.rs index 5938c34d5..9b6f03600 100644 --- a/src/c5/vm/ssa.rs +++ b/src/c5/vm/ssa.rs @@ -2537,11 +2537,24 @@ mod tests { fn bound_data_global_is_diagnosed_under_interp() { // `environ` binds to host data; the interpreter's memory // model cannot reach the host cell, so the reference is a - // clean diagnostic rather than a phantom NULL read. - expect_runtime_err( - "#include \nint main(void) { return environ != 0; }", - "bound to host data", - ); + // clean diagnostic rather than a phantom NULL read. Pinned + // to the macOS target: the Windows headers route `environ` + // per-arch and Linux defines it in the runtime, so the + // host-target shape varies. + let program = Compiler::with_options( + "#include \nint main(void) { return environ != 0; }".to_string(), + crate::Target::MacOSAarch64, + crate::CompileOptions::default(), + ) + .compile() + .expect("compile fixture"); + let err = crate::Vm::new(program).run().expect_err("run must fail"); + match err { + crate::C5Error::Runtime(m) => { + assert!(m.contains("bound to host data"), "{m}") + } + other => panic!("expected Runtime, got {other:?}"), + } } #[test] From 69150386b01e513818943eb3f513f6f577644e42 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 22:25:15 -0700 Subject: [PATCH 47/67] vm: ASCII-only comment in the e-conversion doc Co-Authored-By: Claude Fable 5 --- src/c5/vm/ssa.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/c5/vm/ssa.rs b/src/c5/vm/ssa.rs index 9b6f03600..554b85137 100644 --- a/src/c5/vm/ssa.rs +++ b/src/c5/vm/ssa.rs @@ -1823,7 +1823,7 @@ fn format_float(v: f64, s: &PrintfSpec) -> alloc::string::String { if upper { body.to_uppercase() } else { body } } -/// `d.dddde±dd` with `prec` fraction digits (7.19.6.1p8, the e +/// `d.dddde+/-dd` with `prec` fraction digits (7.19.6.1p8, the e /// conversion). Rust's `{:e}` produces `d.ddddeN`; rewrite the /// exponent into the sign + minimum-two-digit C form. fn format_exp(av: f64, prec: usize, alt: bool) -> alloc::string::String { From d3431354f68b19af671380c2b3628bcfe4351003 Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 23:48:21 -0700 Subject: [PATCH 48/67] headers: bundle the CI-corpus include surfaces (real, no coverage loss) The fatal missing-include diagnostic surfaced every silently-empty include across the tcl / cpython / curl lanes. Each is resolved by providing the platform-faithful surface -- sys/file.h flock, linux/{auxvec,fs,limits,memfd,sched,wait}.h and sys/{auxv,pidfd}.h subsets, net/ethernet.h, mach/* and sysctl, the Windows framework forwards -- never by turning a HAVE_ config claim off, so the demos exercise exactly what they did before. Adds the macOS deployment-target predefine and Annex-K memset_s. Co-Authored-By: Claude Fable 5 --- headers/include/AvailabilityMacros.h | 54 +++++++++++ headers/include/aclapi.h | 7 ++ headers/include/conio.h | 16 ++-- headers/include/crtdbg.h | 37 ++++++++ headers/include/linux/auxvec.h | 35 +++++++ headers/include/linux/fs.h | 22 +++++ headers/include/linux/limits.h | 29 ++++++ headers/include/linux/memfd.h | 30 ++++++ headers/include/linux/sched.h | 15 +++ headers/include/linux/wait.h | 12 +++ headers/include/lmcons.h | 12 +++ headers/include/mach-o/loader.h | 133 +++++++++++++++++++++++++++ headers/include/mach/mach.h | 7 +- headers/include/mach/task.h | 88 ++++++++++++++++++ headers/include/net/ethernet.h | 47 ++++++++++ headers/include/os/log.h | 42 +++++++++ headers/include/pathcch.h | 7 ++ headers/include/psapi.h | 27 ++++++ headers/include/sddl.h | 18 ++++ headers/include/shlwapi.h | 7 ++ headers/include/string.h | 8 ++ headers/include/sys/auxv.h | 14 +++ headers/include/sys/file.h | 26 ++++++ headers/include/sys/locking.h | 12 +++ headers/include/sys/mman.h | 6 +- headers/include/sys/pidfd.h | 21 +++++ headers/include/sys/sys_domain.h | 18 ++++ headers/include/sys/sysctl.h | 49 ++++++++++ headers/include/sys/utime.h | 24 +++++ headers/include/sysexits.h | 24 +++++ headers/include/versionhelpers.h | 53 +++++++++++ headers/include/winbase.h | 7 ++ headers/include/winioctl.h | 7 ++ src/c5/headers.rs | 86 +++++++++++++++++ src/c5/preprocessor.rs | 7 ++ 35 files changed, 992 insertions(+), 15 deletions(-) create mode 100644 headers/include/AvailabilityMacros.h create mode 100644 headers/include/aclapi.h create mode 100644 headers/include/crtdbg.h create mode 100644 headers/include/linux/auxvec.h create mode 100644 headers/include/linux/fs.h create mode 100644 headers/include/linux/limits.h create mode 100644 headers/include/linux/memfd.h create mode 100644 headers/include/linux/sched.h create mode 100644 headers/include/linux/wait.h create mode 100644 headers/include/lmcons.h create mode 100644 headers/include/mach-o/loader.h create mode 100644 headers/include/mach/task.h create mode 100644 headers/include/net/ethernet.h create mode 100644 headers/include/os/log.h create mode 100644 headers/include/pathcch.h create mode 100644 headers/include/psapi.h create mode 100644 headers/include/sddl.h create mode 100644 headers/include/shlwapi.h create mode 100644 headers/include/sys/auxv.h create mode 100644 headers/include/sys/file.h create mode 100644 headers/include/sys/locking.h create mode 100644 headers/include/sys/pidfd.h create mode 100644 headers/include/sys/sys_domain.h create mode 100644 headers/include/sys/sysctl.h create mode 100644 headers/include/sys/utime.h create mode 100644 headers/include/sysexits.h create mode 100644 headers/include/versionhelpers.h create mode 100644 headers/include/winbase.h create mode 100644 headers/include/winioctl.h diff --git a/headers/include/AvailabilityMacros.h b/headers/include/AvailabilityMacros.h new file mode 100644 index 000000000..d28233877 --- /dev/null +++ b/headers/include/AvailabilityMacros.h @@ -0,0 +1,54 @@ +// AvailabilityMacros.h -- macOS version gates. Version constants and +// the MIN_REQUIRED/MAX_ALLOWED derivation follow the SDK header; the +// compiler predefines __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +// to match the LC_BUILD_VERSION minimum it stamps. + +#pragma once + +#ifdef __APPLE__ + +#include + +// Encoded MMmm(pp): 10.x as 10x0 through 10.9, 10MM00/MM0000 after. +// Values from the SDK's . +#define MAC_OS_X_VERSION_10_0 1000 +#define MAC_OS_X_VERSION_10_1 1010 +#define MAC_OS_X_VERSION_10_2 1020 +#define MAC_OS_X_VERSION_10_3 1030 +#define MAC_OS_X_VERSION_10_4 1040 +#define MAC_OS_X_VERSION_10_5 1050 +#define MAC_OS_X_VERSION_10_6 1060 +#define MAC_OS_X_VERSION_10_7 1070 +#define MAC_OS_X_VERSION_10_8 1080 +#define MAC_OS_X_VERSION_10_9 1090 +#define MAC_OS_X_VERSION_10_10 101000 +#define MAC_OS_X_VERSION_10_11 101100 +#define MAC_OS_X_VERSION_10_12 101200 +#define MAC_OS_X_VERSION_10_13 101300 +#define MAC_OS_X_VERSION_10_14 101400 +#define MAC_OS_X_VERSION_10_15 101500 +#define MAC_OS_X_VERSION_10_16 101600 +#define MAC_OS_VERSION_11_0 110000 +#define MAC_OS_VERSION_12_0 120000 +#define MAC_OS_VERSION_13_0 130000 +#define MAC_OS_VERSION_14_0 140000 + +#ifndef MAC_OS_X_VERSION_MIN_REQUIRED +#ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +#else +#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_5 +#endif +#endif + +#ifndef MAC_OS_X_VERSION_MAX_ALLOWED +#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_VERSION_14_0 +#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_MIN_REQUIRED +#else +#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_VERSION_14_0 +#endif +#endif + +// TODO: AVAILABLE_MAC_OS_X_VERSION_* attribute decorators. + +#endif diff --git a/headers/include/aclapi.h b/headers/include/aclapi.h new file mode 100644 index 000000000..c3ea72f71 --- /dev/null +++ b/headers/include/aclapi.h @@ -0,0 +1,7 @@ +// aclapi.h -- access-control-list editing (advapi32). Consumers so far +// reach only the security types. TODO: SetEntriesInAclW, +// GetNamedSecurityInfoW, SetNamedSecurityInfoW. + +#pragma once + +#include diff --git a/headers/include/conio.h b/headers/include/conio.h index c2442b70d..c8a4ad798 100644 --- a/headers/include/conio.h +++ b/headers/include/conio.h @@ -1,7 +1,7 @@ #pragma once -// MSVC CRT direct-console I/O (`_getch` family) plus the `_locking` -// mode constants. These entry points live in msvcrt.dll; the -// underscore-prefixed names are the spellings the CRT exports. +// MSVC CRT direct-console I/O (`_getch` family). These entry points +// live in msvcrt.dll; the underscore-prefixed names are the spellings +// the CRT exports. #ifdef _WIN32 // `wchar_t` () and `wint_t` () back the wide // console entry points below. @@ -30,11 +30,7 @@ int _ungetch(int c); wint_t _ungetwch(wint_t c); int _kbhit(void); -// `_locking` mode argument (MSVC ). Values pinned by -// the CRT. -#define _LK_UNLCK 0 -#define _LK_LOCK 1 -#define _LK_NBLCK 2 -#define _LK_RLCK 3 -#define _LK_NBRLCK 4 +// Callers historically reached the `_locking` mode constants through +// this header; they live in their CRT home now. +#include #endif diff --git a/headers/include/crtdbg.h b/headers/include/crtdbg.h new file mode 100644 index 000000000..5ca655977 --- /dev/null +++ b/headers/include/crtdbg.h @@ -0,0 +1,37 @@ +// crtdbg.h -- CRT debug-heap and report interface. badc never defines +// _DEBUG, so this is the release shape of the UCRT header: report +// constants keep their values, entry points fold to the same no-op +// macros the UCRT uses. TODO: the _DEBUG report/heap entry points. + +#pragma once + +#ifdef _WIN32 +#include + +typedef void *_HFILE; + +#define _CRT_WARN 0 +#define _CRT_ERROR 1 +#define _CRT_ASSERT 2 +#define _CRT_ERRCNT 3 + +#define _CRTDBG_MODE_FILE 0x1 +#define _CRTDBG_MODE_DEBUG 0x2 +#define _CRTDBG_MODE_WNDW 0x4 +#define _CRTDBG_REPORT_MODE -1 + +#define _CRTDBG_INVALID_HFILE ((_HFILE)(intptr_t)-1) +#define _CRTDBG_HFILE_ERROR ((_HFILE)(intptr_t)-2) +#define _CRTDBG_FILE_STDOUT ((_HFILE)(intptr_t)-4) +#define _CRTDBG_FILE_STDERR ((_HFILE)(intptr_t)-5) +#define _CRTDBG_REPORT_FILE ((_HFILE)(intptr_t)-6) + +#define _CrtSetReportMode(t, f) ((int)0) +#define _CrtSetReportFile(t, f) ((_HFILE)0) +#define _CrtSetDbgFlag(f) ((int)0) +#define _CrtCheckMemory() ((int)1) +#define _CrtDumpMemoryLeaks() ((int)0) +#define _CrtDbgBreak() ((void)0) +#define _ASSERT(expr) ((void)0) +#define _ASSERTE(expr) ((void)0) +#endif diff --git a/headers/include/linux/auxvec.h b/headers/include/linux/auxvec.h new file mode 100644 index 000000000..d0c02409d --- /dev/null +++ b/headers/include/linux/auxvec.h @@ -0,0 +1,35 @@ +// linux/auxvec.h -- ELF auxiliary-vector entry types, from the kernel +// uapi header of the same name. + +#pragma once + +#ifdef __linux__ +#define AT_NULL 0 +#define AT_IGNORE 1 +#define AT_EXECFD 2 +#define AT_PHDR 3 +#define AT_PHENT 4 +#define AT_PHNUM 5 +#define AT_PAGESZ 6 +#define AT_BASE 7 +#define AT_FLAGS 8 +#define AT_ENTRY 9 +#define AT_NOTELF 10 +#define AT_UID 11 +#define AT_EUID 12 +#define AT_GID 13 +#define AT_EGID 14 +#define AT_PLATFORM 15 +#define AT_HWCAP 16 +#define AT_CLKTCK 17 +#define AT_SECURE 23 +#define AT_BASE_PLATFORM 24 +#define AT_RANDOM 25 +#define AT_HWCAP2 26 +#define AT_RSEQ_FEATURE_SIZE 27 +#define AT_RSEQ_ALIGN 28 +#define AT_HWCAP3 29 +#define AT_HWCAP4 30 +#define AT_EXECFN 31 +#define AT_MINSIGSTKSZ 51 +#endif diff --git a/headers/include/linux/fs.h b/headers/include/linux/fs.h new file mode 100644 index 000000000..567a7855c --- /dev/null +++ b/headers/include/linux/fs.h @@ -0,0 +1,22 @@ +// linux/fs.h -- filesystem ioctls from the kernel uapi header. The +// values expand the kernel's _IOW('\x94', nr, size) encoding: +// dir 1 (write) << 30 | size << 16 | 0x94 << 8 | nr. TODO: the +// FS_IOC_* attribute ioctls. + +#pragma once + +#ifdef __linux__ +#include + +struct file_clone_range { + int64_t src_fd; + uint64_t src_offset; + uint64_t src_length; + uint64_t dest_offset; +}; + +// _IOW(0x94, 9, int) +#define FICLONE 0x40049409 +// _IOW(0x94, 13, struct file_clone_range) +#define FICLONERANGE 0x4020940d +#endif diff --git a/headers/include/linux/limits.h b/headers/include/linux/limits.h new file mode 100644 index 000000000..526efa69c --- /dev/null +++ b/headers/include/linux/limits.h @@ -0,0 +1,29 @@ +// linux/limits.h -- kernel uapi limits. The names and +// also define are guarded so either include order +// holds. + +#pragma once + +#ifdef __linux__ +#define NR_OPEN 1024 +#ifndef NGROUPS_MAX +#define NGROUPS_MAX 65536 +#endif +#ifndef ARG_MAX +#define ARG_MAX 131072 +#endif +#define LINK_MAX 127 +#define MAX_CANON 255 +#define MAX_INPUT 255 +#ifndef NAME_MAX +#define NAME_MAX 255 +#endif +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif +#define PIPE_BUF 4096 +#define XATTR_NAME_MAX 255 +#define XATTR_SIZE_MAX 65536 +#define XATTR_LIST_MAX 65536 +#define RTSIG_MAX 32 +#endif diff --git a/headers/include/linux/memfd.h b/headers/include/linux/memfd.h new file mode 100644 index 000000000..0f3b73228 --- /dev/null +++ b/headers/include/linux/memfd.h @@ -0,0 +1,30 @@ +// linux/memfd.h -- memfd_create flags from the kernel uapi header; +// the entry point itself is bound in . The MFD_HUGE_* +// values encode log2(page size) in the top field, per the kernel's +// hugetlb_encode.h. + +#pragma once + +#ifdef __linux__ +#define MFD_CLOEXEC 0x0001U +#define MFD_ALLOW_SEALING 0x0002U +#define MFD_HUGETLB 0x0004U +#define MFD_NOEXEC_SEAL 0x0008U +#define MFD_EXEC 0x0010U + +#define MFD_HUGE_SHIFT 26 +#define MFD_HUGE_MASK 0x3f + +#define MFD_HUGE_64KB (16U << MFD_HUGE_SHIFT) +#define MFD_HUGE_512KB (19U << MFD_HUGE_SHIFT) +#define MFD_HUGE_1MB (20U << MFD_HUGE_SHIFT) +#define MFD_HUGE_2MB (21U << MFD_HUGE_SHIFT) +#define MFD_HUGE_8MB (23U << MFD_HUGE_SHIFT) +#define MFD_HUGE_16MB (24U << MFD_HUGE_SHIFT) +#define MFD_HUGE_32MB (25U << MFD_HUGE_SHIFT) +#define MFD_HUGE_256MB (28U << MFD_HUGE_SHIFT) +#define MFD_HUGE_512MB (29U << MFD_HUGE_SHIFT) +#define MFD_HUGE_1GB (30U << MFD_HUGE_SHIFT) +#define MFD_HUGE_2GB (31U << MFD_HUGE_SHIFT) +#define MFD_HUGE_16GB (34U << MFD_HUGE_SHIFT) +#endif diff --git a/headers/include/linux/sched.h b/headers/include/linux/sched.h new file mode 100644 index 000000000..513358c52 --- /dev/null +++ b/headers/include/linux/sched.h @@ -0,0 +1,15 @@ +// linux/sched.h -- scheduling policies from the kernel uapi header. +// The glibc-visible trio carries the same values as ; +// SCHED_NORMAL is the kernel spelling of SCHED_OTHER. TODO: the +// CLONE_* flags and struct clone_args. + +#pragma once + +#ifdef __linux__ +#define SCHED_NORMAL 0 +#define SCHED_FIFO 1 +#define SCHED_RR 2 +#define SCHED_BATCH 3 +#define SCHED_IDLE 5 +#define SCHED_DEADLINE 6 +#endif diff --git a/headers/include/linux/wait.h b/headers/include/linux/wait.h new file mode 100644 index 000000000..b5bbcab6d --- /dev/null +++ b/headers/include/linux/wait.h @@ -0,0 +1,12 @@ +// linux/wait.h -- the waitid id-type selectors from the kernel uapi +// header. P_PIDFD (Linux 5.4) has no glibc counterpart; +// the first three shadow the idtype_t enumerators with equal values. + +#pragma once + +#ifdef __linux__ +#define P_ALL 0 +#define P_PID 1 +#define P_PGID 2 +#define P_PIDFD 3 +#endif diff --git a/headers/include/lmcons.h b/headers/include/lmcons.h new file mode 100644 index 000000000..a05058c06 --- /dev/null +++ b/headers/include/lmcons.h @@ -0,0 +1,12 @@ +// lmcons.h -- LAN Manager name-length limits (character counts, +// excluding the terminator). + +#pragma once + +#ifdef _WIN32 +#define CNLEN 15 +#define DNLEN CNLEN +#define UNLEN 256 +#define GNLEN UNLEN +#define PWLEN 256 +#endif diff --git a/headers/include/mach-o/loader.h b/headers/include/mach-o/loader.h new file mode 100644 index 000000000..752623ad2 --- /dev/null +++ b/headers/include/mach-o/loader.h @@ -0,0 +1,133 @@ +// mach-o/loader.h -- Mach-O file-format structures and constants, the +// subset consumers reach for (headers, segment/section layout). Values +// match the macOS SDK's ; the format is fixed, so the +// definitions are usable on any host. No bindings -- data layout only. + +#pragma once + +#include + +// integer_t-based ids; protection bits. +typedef int cpu_type_t; +typedef int cpu_subtype_t; +typedef int vm_prot_t; + +struct mach_header { + uint32_t magic; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; + uint32_t flags; +}; + +#define MH_MAGIC 0xfeedface +#define MH_CIGAM 0xcefaedfe + +struct mach_header_64 { + uint32_t magic; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; + uint32_t flags; + uint32_t reserved; +}; + +#define MH_MAGIC_64 0xfeedfacf +#define MH_CIGAM_64 0xcffaedfe + +// mach_header filetype values. +#define MH_OBJECT 0x1 +#define MH_EXECUTE 0x2 +#define MH_DYLIB 0x6 +#define MH_DYLINKER 0x7 +#define MH_BUNDLE 0x8 +#define MH_DSYM 0xa + +struct load_command { + uint32_t cmd; + uint32_t cmdsize; +}; + +#define LC_SEGMENT 0x1 +#define LC_SYMTAB 0x2 +#define LC_UUID 0x1b +#define LC_SEGMENT_64 0x19 + +struct segment_command { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + uint32_t vmaddr; + uint32_t vmsize; + uint32_t fileoff; + uint32_t filesize; + vm_prot_t maxprot; + vm_prot_t initprot; + uint32_t nsects; + uint32_t flags; +}; + +struct segment_command_64 { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + uint64_t vmaddr; + uint64_t vmsize; + uint64_t fileoff; + uint64_t filesize; + vm_prot_t maxprot; + vm_prot_t initprot; + uint32_t nsects; + uint32_t flags; +}; + +struct section { + char sectname[16]; + char segname[16]; + uint32_t addr; + uint32_t size; + uint32_t offset; + uint32_t align; + uint32_t reloff; + uint32_t nreloc; + uint32_t flags; + uint32_t reserved1; + uint32_t reserved2; +}; + +struct section_64 { + char sectname[16]; + char segname[16]; + uint64_t addr; + uint64_t size; + uint32_t offset; + uint32_t align; + uint32_t reloff; + uint32_t nreloc; + uint32_t flags; + uint32_t reserved1; + uint32_t reserved2; + uint32_t reserved3; +}; + +struct symtab_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t symoff; + uint32_t nsyms; + uint32_t stroff; + uint32_t strsize; +}; + +#define SEG_PAGEZERO "__PAGEZERO" +#define SEG_TEXT "__TEXT" +#define SECT_TEXT "__text" +#define SEG_DATA "__DATA" +#define SECT_DATA "__data" +#define SECT_BSS "__bss" +#define SECT_COMMON "__common" +#define SEG_LINKEDIT "__LINKEDIT" diff --git a/headers/include/mach/mach.h b/headers/include/mach/mach.h index 02e497af9..8bffc96c4 100644 --- a/headers/include/mach/mach.h +++ b/headers/include/mach/mach.h @@ -4,12 +4,17 @@ #pragma once #ifdef __APPLE__ -// Mach kernel scalar types (all 32-bit on Darwin). +// Mach kernel scalar types (32-bit on Darwin; the mach_vm_* pair is +// 64-bit). typedef unsigned int mach_port_t; typedef mach_port_t task_t; typedef mach_port_t thread_t; typedef int kern_return_t; typedef unsigned int mach_msg_type_number_t; +typedef unsigned int natural_t; +typedef int integer_t; +typedef unsigned long long mach_vm_size_t; +typedef unsigned long long mach_vm_address_t; // An out-of-line array of thread ports returned by task_threads(). typedef thread_t *thread_array_t; diff --git a/headers/include/mach/task.h b/headers/include/mach/task.h new file mode 100644 index 000000000..a9a16f85f --- /dev/null +++ b/headers/include/mach/task.h @@ -0,0 +1,88 @@ +// mach/task.h -- task introspection: the task_info() flavor consumers +// reach for. Layouts and flavor values from the SDK's +// . TODO: the remaining flavors. + +#pragma once + +#ifdef __APPLE__ +#include +#include + +typedef natural_t task_flavor_t; +typedef integer_t *task_info_t; + +#define TASK_VM_INFO 22 + +// Mach info structs are 4-byte packed; the count encodes the struct +// revision in natural_t units. +#pragma pack(push, 4) +struct task_vm_info { + mach_vm_size_t virtual_size; + integer_t region_count; + integer_t page_size; + mach_vm_size_t resident_size; + mach_vm_size_t resident_size_peak; + mach_vm_size_t device; + mach_vm_size_t device_peak; + mach_vm_size_t internal; + mach_vm_size_t internal_peak; + mach_vm_size_t external; + mach_vm_size_t external_peak; + mach_vm_size_t reusable; + mach_vm_size_t reusable_peak; + mach_vm_size_t purgeable_volatile_pmap; + mach_vm_size_t purgeable_volatile_resident; + mach_vm_size_t purgeable_volatile_virtual; + mach_vm_size_t compressed; + mach_vm_size_t compressed_peak; + mach_vm_size_t compressed_lifetime; + // rev1 + mach_vm_size_t phys_footprint; + // rev2 + mach_vm_address_t min_address; + mach_vm_address_t max_address; + // rev3 + int64_t ledger_phys_footprint_peak; + int64_t ledger_purgeable_nonvolatile; + int64_t ledger_purgeable_novolatile_compressed; + int64_t ledger_purgeable_volatile; + int64_t ledger_purgeable_volatile_compressed; + int64_t ledger_tag_network_nonvolatile; + int64_t ledger_tag_network_nonvolatile_compressed; + int64_t ledger_tag_network_volatile; + int64_t ledger_tag_network_volatile_compressed; + int64_t ledger_tag_media_footprint; + int64_t ledger_tag_media_footprint_compressed; + int64_t ledger_tag_media_nofootprint; + int64_t ledger_tag_media_nofootprint_compressed; + int64_t ledger_tag_graphics_footprint; + int64_t ledger_tag_graphics_footprint_compressed; + int64_t ledger_tag_graphics_nofootprint; + int64_t ledger_tag_graphics_nofootprint_compressed; + int64_t ledger_tag_neural_footprint; + int64_t ledger_tag_neural_footprint_compressed; + int64_t ledger_tag_neural_nofootprint; + int64_t ledger_tag_neural_nofootprint_compressed; + // rev4 + uint64_t limit_bytes_remaining; + // rev5 + integer_t decompressions; + // rev6 + int64_t ledger_swapins; + // rev7 + int64_t ledger_tag_neural_nofootprint_total; + int64_t ledger_tag_neural_nofootprint_peak; +}; +#pragma pack(pop) + +typedef struct task_vm_info task_vm_info_data_t; +typedef struct task_vm_info *task_vm_info_t; + +#define TASK_VM_INFO_COUNT \ + ((mach_msg_type_number_t)(sizeof(task_vm_info_data_t) / sizeof(natural_t))) + +#pragma binding(libc::task_info, "_task_info") + +kern_return_t task_info(task_t task, task_flavor_t flavor, task_info_t info, + mach_msg_type_number_t *count); +#endif diff --git a/headers/include/net/ethernet.h b/headers/include/net/ethernet.h new file mode 100644 index 000000000..0080b02ee --- /dev/null +++ b/headers/include/net/ethernet.h @@ -0,0 +1,47 @@ +// net/ethernet.h -- Ethernet frame constants and address structures. + +#pragma once + +#if defined(__APPLE__) || defined(__linux__) + +#include + +// Octet counts and frame limits; identical in glibc +// (via ) and Darwin . +#define ETHER_ADDR_LEN 6 +#define ETHER_TYPE_LEN 2 +#define ETHER_CRC_LEN 4 +#define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) +#define ETHER_MIN_LEN 64 +#define ETHER_MAX_LEN 1518 + +#define ETHERTYPE_IP 0x0800 +#define ETHERTYPE_ARP 0x0806 +#define ETHERTYPE_REVARP 0x8035 +#define ETHERTYPE_VLAN 0x8100 +#define ETHERTYPE_IPV6 0x86dd + +struct ether_addr { + uint8_t ether_addr_octet[ETHER_ADDR_LEN]; +}; + +struct ether_header { + uint8_t ether_dhost[ETHER_ADDR_LEN]; + uint8_t ether_shost[ETHER_ADDR_LEN]; + uint16_t ether_type; +}; + +#ifdef __linux__ +// glibc's header pulls these from . +#define ETH_ALEN 6 +#define ETH_HLEN 14 +#define ETH_ZLEN 60 +#define ETH_DATA_LEN 1500 +#define ETH_FRAME_LEN 1514 +#define ETH_P_ALL 0x0003 +#define ETH_P_IP 0x0800 +#define ETH_P_ARP 0x0806 +#define ETH_P_IPV6 0x86dd +#endif + +#endif diff --git a/headers/include/os/log.h b/headers/include/os/log.h new file mode 100644 index 000000000..bb6320267 --- /dev/null +++ b/headers/include/os/log.h @@ -0,0 +1,42 @@ +// os/log.h -- unified logging. The SDK macro compiles the format via +// __builtin_os_log_format; badc routes through _os_log_internal, the +// exported variadic entry point older deployment targets use. Its +// first argument must be an address inside the calling image (sender +// attribution); a NULL faults in libtrace, so each including unit +// carries a static anchor byte. + +#pragma once + +#ifdef __APPLE__ +#include + +typedef struct os_log_s *os_log_t; +typedef uint8_t os_log_type_t; + +#define OS_LOG_TYPE_DEFAULT 0x00 +#define OS_LOG_TYPE_INFO 0x01 +#define OS_LOG_TYPE_DEBUG 0x02 +#define OS_LOG_TYPE_ERROR 0x10 +#define OS_LOG_TYPE_FAULT 0x11 + +#pragma dylib(libc, "/usr/lib/libSystem.B.dylib") +#pragma binding(libc::os_log_create, "_os_log_create") +#pragma binding(libc::_os_log_internal, "__os_log_internal") +#pragma binding(data libc::_os_log_default, "__os_log_default") + +extern struct os_log_s _os_log_default; +#define OS_LOG_DEFAULT (&_os_log_default) + +os_log_t os_log_create(const char *subsystem, const char *category); +void _os_log_internal(void *dso, os_log_t log, os_log_type_t type, const char *message, ...); + +static char __badc_os_log_anchor; + +#define os_log_with_type(log, type, ...) \ + _os_log_internal(&__badc_os_log_anchor, (log), (type), __VA_ARGS__) +#define os_log(log, ...) os_log_with_type((log), OS_LOG_TYPE_DEFAULT, __VA_ARGS__) +#define os_log_info(log, ...) os_log_with_type((log), OS_LOG_TYPE_INFO, __VA_ARGS__) +#define os_log_debug(log, ...) os_log_with_type((log), OS_LOG_TYPE_DEBUG, __VA_ARGS__) +#define os_log_error(log, ...) os_log_with_type((log), OS_LOG_TYPE_ERROR, __VA_ARGS__) +#define os_log_fault(log, ...) os_log_with_type((log), OS_LOG_TYPE_FAULT, __VA_ARGS__) +#endif diff --git a/headers/include/pathcch.h b/headers/include/pathcch.h new file mode 100644 index 000000000..8e77e7fb6 --- /dev/null +++ b/headers/include/pathcch.h @@ -0,0 +1,7 @@ +// pathcch.h -- wide path-combining API (api-ms-win-core-path). badc's +// carries the PathCch* prototypes, their bindings, and +// PATHCCH_ALLOW_LONG_PATHS. + +#pragma once + +#include diff --git a/headers/include/psapi.h b/headers/include/psapi.h new file mode 100644 index 000000000..1fc702e86 --- /dev/null +++ b/headers/include/psapi.h @@ -0,0 +1,27 @@ +// psapi.h -- process status API, the process-memory counters subset. +// Since PSAPI_VERSION 2 the SDK routes these through kernel32's K32* +// exports; the binding goes there directly. + +#pragma once + +#ifdef _WIN32 +#include + +typedef struct _PROCESS_MEMORY_COUNTERS { + DWORD cb; + DWORD PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; +} PROCESS_MEMORY_COUNTERS, *PPROCESS_MEMORY_COUNTERS; + +#pragma dylib(kernel32, "kernel32.dll") +#pragma binding(kernel32::GetProcessMemoryInfo, "K32GetProcessMemoryInfo") + +BOOL GetProcessMemoryInfo(HANDLE Process, PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb); +#endif diff --git a/headers/include/sddl.h b/headers/include/sddl.h new file mode 100644 index 000000000..b11942009 --- /dev/null +++ b/headers/include/sddl.h @@ -0,0 +1,18 @@ +// sddl.h -- security-descriptor string format (advapi32). TODO: the +// SID string conversions. + +#pragma once + +#ifdef _WIN32 +#include + +#define SDDL_REVISION_1 1 +#define SDDL_REVISION SDDL_REVISION_1 + +#pragma dylib(advapi32, "advapi32.dll") +#pragma binding(advapi32::ConvertStringSecurityDescriptorToSecurityDescriptorW, "ConvertStringSecurityDescriptorToSecurityDescriptorW") + +BOOL ConvertStringSecurityDescriptorToSecurityDescriptorW( + LPCWSTR StringSecurityDescriptor, DWORD StringSDRevision, + void **SecurityDescriptor, ULONG *SecurityDescriptorSize); +#endif diff --git a/headers/include/shlwapi.h b/headers/include/shlwapi.h new file mode 100644 index 000000000..522c5666e --- /dev/null +++ b/headers/include/shlwapi.h @@ -0,0 +1,7 @@ +// shlwapi.h -- shell light-weight path utilities. Consumers so far +// reach only the surface; the PathCch* replacements live +// in . TODO: the PathIsRelativeW family. + +#pragma once + +#include diff --git a/headers/include/string.h b/headers/include/string.h index a247effe6..057bfe5a8 100644 --- a/headers/include/string.h +++ b/headers/include/string.h @@ -181,6 +181,14 @@ char *strchrnul(const char *s, int c); char *memrchr(char *s, int c, int n); void explicit_bzero(void *s, size_t n); #endif +// C11 K.3.7.4.1, visible on the Annex-K opt-in like the platform +// header; libSystem exports it, glibc does not. +#if defined(__APPLE__) && defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ >= 1 +#pragma binding(libc::memset_s, "_memset_s") +typedef int errno_t; +typedef size_t rsize_t; +errno_t memset_s(void *s, rsize_t smax, int c, rsize_t n); +#endif #ifdef _WIN32 // Case-insensitive compares -- msvcrt-only, no POSIX equivalent // in the c5 surface. Names match the underscored entries diff --git a/headers/include/sys/auxv.h b/headers/include/sys/auxv.h new file mode 100644 index 000000000..d5f33f7ae --- /dev/null +++ b/headers/include/sys/auxv.h @@ -0,0 +1,14 @@ +// sys/auxv.h -- read entries from the ELF auxiliary vector (glibc). + +#pragma once + +#ifdef __linux__ +#include + +#pragma dylib(libc, "libc.so.6") +#pragma binding(libc::getauxval, "getauxval") + +// Value of the auxiliary-vector entry `type` (an AT_* constant), or 0 +// with errno ENOENT when the vector carries no such entry. +unsigned long getauxval(unsigned long type); +#endif diff --git a/headers/include/sys/file.h b/headers/include/sys/file.h new file mode 100644 index 000000000..297f81340 --- /dev/null +++ b/headers/include/sys/file.h @@ -0,0 +1,26 @@ +// sys/file.h -- BSD advisory whole-file locks (flock(2)). + +#pragma once + +#if defined(__APPLE__) || defined(__linux__) + +// Operation bits; identical in Darwin and glibc +// . +#define LOCK_SH 0x01 +#define LOCK_EX 0x02 +#define LOCK_NB 0x04 +#define LOCK_UN 0x08 + +#ifdef __APPLE__ +#pragma dylib(libc, "/usr/lib/libSystem.B.dylib") +#pragma binding(libc::flock, "_flock") +#endif +#ifdef __linux__ +#pragma dylib(libc, "libc.so.6") +#pragma binding(libc::flock, "flock") +#endif + +// Apply or remove an advisory lock on the open file `fd`; `operation` +// is LOCK_SH, LOCK_EX, or LOCK_UN, optionally or'ed with LOCK_NB. +int flock(int fd, int operation); +#endif diff --git a/headers/include/sys/locking.h b/headers/include/sys/locking.h new file mode 100644 index 000000000..b8b8e772c --- /dev/null +++ b/headers/include/sys/locking.h @@ -0,0 +1,12 @@ +// sys/locking.h -- mode argument of the CRT's `_locking` (declared in +// /). Values pinned by the CRT header of the same name. + +#pragma once + +#ifdef _WIN32 +#define _LK_UNLCK 0 +#define _LK_LOCK 1 +#define _LK_NBLCK 2 +#define _LK_RLCK 3 +#define _LK_NBRLCK 4 +#endif diff --git a/headers/include/sys/mman.h b/headers/include/sys/mman.h index af6a31c04..4a0dbb5a9 100644 --- a/headers/include/sys/mman.h +++ b/headers/include/sys/mman.h @@ -66,10 +66,8 @@ #pragma binding(libc::shm_open, "shm_open") #pragma binding(libc::shm_unlink, "shm_unlink") #pragma binding(libc::memfd_create, "memfd_create") -// memfd_create flags. -#define MFD_CLOEXEC 0x0001 -#define MFD_ALLOW_SEALING 0x0002 -#define MFD_HUGETLB 0x0004 +// The MFD_* flags live in their canonical kernel header. +#include int memfd_create(const char *name, unsigned int flags); #endif diff --git a/headers/include/sys/pidfd.h b/headers/include/sys/pidfd.h new file mode 100644 index 000000000..06a44f1cc --- /dev/null +++ b/headers/include/sys/pidfd.h @@ -0,0 +1,21 @@ +// sys/pidfd.h -- process file descriptors (glibc 2.36, Linux 5.3+). + +#pragma once + +#ifdef __linux__ +#include +#include +#include + +// Matches the kernel uapi definition: O_NONBLOCK on every arch. +#define PIDFD_NONBLOCK O_NONBLOCK + +#pragma dylib(libc, "libc.so.6") +#pragma binding(libc::pidfd_open, "pidfd_open") +#pragma binding(libc::pidfd_getfd, "pidfd_getfd") +#pragma binding(libc::pidfd_send_signal, "pidfd_send_signal") + +int pidfd_open(pid_t pid, unsigned int flags); +int pidfd_getfd(int pidfd, int targetfd, unsigned int flags); +int pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags); +#endif diff --git a/headers/include/sys/sys_domain.h b/headers/include/sys/sys_domain.h new file mode 100644 index 000000000..3010198a6 --- /dev/null +++ b/headers/include/sys/sys_domain.h @@ -0,0 +1,18 @@ +// sys/sys_domain.h -- Darwin AF_SYSTEM kernel-socket domain. + +#pragma once + +#ifdef __APPLE__ +#include + +#define SYSPROTO_EVENT 1 +#define SYSPROTO_CONTROL 2 +#define AF_SYS_CONTROL 2 + +struct sockaddr_sys { + unsigned char ss_len; + unsigned char ss_family; + uint16_t ss_sysaddr; + uint32_t ss_reserved[7]; +}; +#endif diff --git a/headers/include/sys/sysctl.h b/headers/include/sys/sysctl.h new file mode 100644 index 000000000..ffd438e8d --- /dev/null +++ b/headers/include/sys/sysctl.h @@ -0,0 +1,49 @@ +// sys/sysctl.h -- Darwin sysctl(3) MIB interface: the common CTL_KERN +// and CTL_HW names plus the three entry points. TODO: the per-subtree +// name tables. + +#pragma once + +#ifdef __APPLE__ +#include + +#define CTL_MAXNAME 12 +#define CTL_KERN 1 +#define CTL_VM 2 +#define CTL_NET 4 +#define CTL_HW 6 +#define CTL_MACHDEP 7 +#define CTL_USER 8 + +#define KERN_OSTYPE 1 +#define KERN_OSRELEASE 2 +#define KERN_OSREV 3 +#define KERN_VERSION 4 +#define KERN_MAXVNODES 5 +#define KERN_ARGMAX 8 +#define KERN_HOSTNAME 10 +#define KERN_PROC 14 +#define KERN_OSVERSION 65 + +#define HW_MACHINE 1 +#define HW_MODEL 2 +#define HW_NCPU 3 +#define HW_BYTEORDER 4 +#define HW_PHYSMEM 5 +#define HW_USERMEM 6 +#define HW_PAGESIZE 7 +#define HW_MACHINE_ARCH 12 +#define HW_MEMSIZE 24 +#define HW_AVAILCPU 25 + +#pragma dylib(libc, "/usr/lib/libSystem.B.dylib") +#pragma binding(libc::sysctl, "_sysctl") +#pragma binding(libc::sysctlbyname, "_sysctlbyname") +#pragma binding(libc::sysctlnametomib, "_sysctlnametomib") + +int sysctl(int *name, unsigned int namelen, void *oldp, size_t *oldlenp, + void *newp, size_t newlen); +int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp, + size_t newlen); +int sysctlnametomib(const char *name, int *mibp, size_t *sizep); +#endif diff --git a/headers/include/sys/utime.h b/headers/include/sys/utime.h new file mode 100644 index 000000000..b00d5e457 --- /dev/null +++ b/headers/include/sys/utime.h @@ -0,0 +1,24 @@ +// sys/utime.h -- the CRT home of the file-time interface; the POSIX +// spellings live in . The underscored CRT spellings are +// declared here on Windows. + +#pragma once + +#include + +#ifdef _WIN32 +// Same layout as `struct utimbuf`: two 8-byte time_t second counts. +struct _utimbuf { + time_t actime; + time_t modtime; +}; + +#pragma dylib(msvcrt, "msvcrt.dll") +#pragma binding(msvcrt::_utime, "_utime") +#pragma binding(msvcrt::_futime, "_futime") +#pragma binding(msvcrt::_wutime, "_wutime") + +int _utime(const char *path, struct _utimbuf *times); +int _futime(int fd, struct _utimbuf *times); +int _wutime(const unsigned short *path, struct _utimbuf *times); +#endif diff --git a/headers/include/sysexits.h b/headers/include/sysexits.h new file mode 100644 index 000000000..58665f947 --- /dev/null +++ b/headers/include/sysexits.h @@ -0,0 +1,24 @@ +// sysexits.h -- BSD exit-status codes (sysexits(3)). + +#pragma once + +#if defined(__APPLE__) || defined(__linux__) +#define EX_OK 0 +#define EX__BASE 64 +#define EX_USAGE 64 +#define EX_DATAERR 65 +#define EX_NOINPUT 66 +#define EX_NOUSER 67 +#define EX_NOHOST 68 +#define EX_UNAVAILABLE 69 +#define EX_SOFTWARE 70 +#define EX_OSERR 71 +#define EX_OSFILE 72 +#define EX_CANTCREAT 73 +#define EX_IOERR 74 +#define EX_TEMPFAIL 75 +#define EX_PROTOCOL 76 +#define EX_NOPERM 77 +#define EX_CONFIG 78 +#define EX__MAX 78 +#endif diff --git a/headers/include/versionhelpers.h b/headers/include/versionhelpers.h new file mode 100644 index 000000000..b7301b48d --- /dev/null +++ b/headers/include/versionhelpers.h @@ -0,0 +1,53 @@ +// versionhelpers.h -- OS version predicates, implemented over +// VerifyVersionInfoW exactly as the SDK header does. + +#pragma once + +#ifdef _WIN32 +#include +#include + +static inline BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, + WORD wServicePackMajor) { + OSVERSIONINFOEXW osvi = {0}; + DWORDLONG mask = 0; + VER_SET_CONDITION(mask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(mask, VER_MINORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); + osvi.dwOSVersionInfoSize = sizeof(osvi); + osvi.dwMajorVersion = wMajorVersion; + osvi.dwMinorVersion = wMinorVersion; + osvi.wServicePackMajor = wServicePackMajor; + return VerifyVersionInfoW(&osvi, + VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, + mask) != 0; +} + +static inline BOOL IsWindowsXPOrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0); +} + +static inline BOOL IsWindowsVistaOrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0); +} + +static inline BOOL IsWindows7OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0); +} + +static inline BOOL IsWindows7SP1OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1); +} + +static inline BOOL IsWindows8OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0); +} + +static inline BOOL IsWindows8Point1OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0); +} + +// TODO: IsWindows10OrGreater needs the manifest-gated +// RtlGetVersion/VerifyVersionInfo semantics change; IsWindowsServer +// needs VER_PRODUCT_TYPE. +#endif diff --git a/headers/include/winbase.h b/headers/include/winbase.h new file mode 100644 index 000000000..01505546a --- /dev/null +++ b/headers/include/winbase.h @@ -0,0 +1,7 @@ +// winbase.h -- in the SDK this is a sub-header, never +// included standalone; badc keeps the kernel32 surface in +// itself, so this name resolves to it. + +#pragma once + +#include diff --git a/headers/include/winioctl.h b/headers/include/winioctl.h new file mode 100644 index 000000000..f9870092f --- /dev/null +++ b/headers/include/winioctl.h @@ -0,0 +1,7 @@ +// winioctl.h -- device I/O control interface. badc's +// carries the FILE_DEVICE_*, FSCTL_*, and reparse-point constants the +// SDK defines here. + +#pragma once + +#include diff --git a/src/c5/headers.rs b/src/c5/headers.rs index 4e7475eee..0470f6028 100644 --- a/src/c5/headers.rs +++ b/src/c5/headers.rs @@ -90,6 +90,10 @@ pub(super) const EMBEDDED_HEADERS: &[(&str, &str)] = &[ ("assert.h", include_str!("../../headers/include/assert.h")), ("time.h", include_str!("../../headers/include/time.h")), ("utime.h", include_str!("../../headers/include/utime.h")), + ( + "sys/utime.h", + include_str!("../../headers/include/sys/utime.h"), + ), ("netdb.h", include_str!("../../headers/include/netdb.h")), ( "sys/utsname.h", @@ -130,6 +134,14 @@ pub(super) const EMBEDDED_HEADERS: &[(&str, &str)] = &[ ("sys/uio.h", include_str!("../../headers/include/sys/uio.h")), ("sys/un.h", include_str!("../../headers/include/sys/un.h")), ("net/if.h", include_str!("../../headers/include/net/if.h")), + ( + "net/ethernet.h", + include_str!("../../headers/include/net/ethernet.h"), + ), + ( + "sys/file.h", + include_str!("../../headers/include/sys/file.h"), + ), ( "sys/attr.h", include_str!("../../headers/include/sys/attr.h"), @@ -162,10 +174,30 @@ pub(super) const EMBEDDED_HEADERS: &[(&str, &str)] = &[ "mach/mach.h", include_str!("../../headers/include/mach/mach.h"), ), + ( + "mach/task.h", + include_str!("../../headers/include/mach/task.h"), + ), + ( + "sysexits.h", + include_str!("../../headers/include/sysexits.h"), + ), + ( + "sys/sys_domain.h", + include_str!("../../headers/include/sys/sys_domain.h"), + ), + ( + "sys/sysctl.h", + include_str!("../../headers/include/sys/sysctl.h"), + ), ( "mach-o/dyld.h", include_str!("../../headers/include/mach-o/dyld.h"), ), + ( + "mach-o/loader.h", + include_str!("../../headers/include/mach-o/loader.h"), + ), ( "sys/stat.h", include_str!("../../headers/include/sys/stat.h"), @@ -189,6 +221,35 @@ pub(super) const EMBEDDED_HEADERS: &[(&str, &str)] = &[ "linux/random.h", include_str!("../../headers/include/linux/random.h"), ), + ( + "linux/auxvec.h", + include_str!("../../headers/include/linux/auxvec.h"), + ), + ("linux/fs.h", include_str!("../../headers/include/linux/fs.h")), + ( + "linux/sched.h", + include_str!("../../headers/include/linux/sched.h"), + ), + ( + "linux/wait.h", + include_str!("../../headers/include/linux/wait.h"), + ), + ( + "linux/memfd.h", + include_str!("../../headers/include/linux/memfd.h"), + ), + ( + "linux/limits.h", + include_str!("../../headers/include/linux/limits.h"), + ), + ( + "sys/auxv.h", + include_str!("../../headers/include/sys/auxv.h"), + ), + ( + "sys/pidfd.h", + include_str!("../../headers/include/sys/pidfd.h"), + ), ("pty.h", include_str!("../../headers/include/pty.h")), ("utmp.h", include_str!("../../headers/include/utmp.h")), ( @@ -273,7 +334,32 @@ pub(super) const EMBEDDED_HEADERS: &[(&str, &str)] = &[ "TargetConditionals.h", include_str!("../../headers/include/TargetConditionals.h"), ), + ( + "AvailabilityMacros.h", + include_str!("../../headers/include/AvailabilityMacros.h"), + ), + ("os/log.h", include_str!("../../headers/include/os/log.h")), ("windows.h", include_str!("../../headers/include/windows.h")), + ("winbase.h", include_str!("../../headers/include/winbase.h")), + ( + "winioctl.h", + include_str!("../../headers/include/winioctl.h"), + ), + ("pathcch.h", include_str!("../../headers/include/pathcch.h")), + ("psapi.h", include_str!("../../headers/include/psapi.h")), + ( + "versionhelpers.h", + include_str!("../../headers/include/versionhelpers.h"), + ), + ("crtdbg.h", include_str!("../../headers/include/crtdbg.h")), + ("aclapi.h", include_str!("../../headers/include/aclapi.h")), + ("lmcons.h", include_str!("../../headers/include/lmcons.h")), + ("sddl.h", include_str!("../../headers/include/sddl.h")), + ("shlwapi.h", include_str!("../../headers/include/shlwapi.h")), + ( + "sys/locking.h", + include_str!("../../headers/include/sys/locking.h"), + ), ( "wincrypt.h", include_str!("../../headers/include/wincrypt.h"), diff --git a/src/c5/preprocessor.rs b/src/c5/preprocessor.rs index fd1cb3825..304bdcbfe 100644 --- a/src/c5/preprocessor.rs +++ b/src/c5/preprocessor.rs @@ -535,6 +535,13 @@ impl Preprocessor { Target::MacOSAarch64 => { macros.insert("__APPLE__".to_string(), "1".to_string()); macros.insert("__MACH__".to_string(), "1".to_string()); + // Deployment target, decimal MMmmpp. Matches the 11.0 + // minimum OS version stamped into LC_BUILD_VERSION; + // derives its version gates from it. + macros.insert( + "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__".to_string(), + "110000".to_string(), + ); } Target::LinuxAarch64 | Target::LinuxX64 => { macros.insert("__linux__".to_string(), "1".to_string()); From ec39a9def1d230c6374b819d74f2204663bc98fc Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 00:20:03 -0700 Subject: [PATCH 49/67] lexer: wrap the octal accumulator like the other bases The octal digit loop used checked multiply where the binary and hex paths already wrap, so the octal spelling of ULLONG_MAX panicked a debug build; wrap so debug and release agree and the type picker types the literal from the bit pattern (C99 6.4.4.1). Co-Authored-By: Claude Fable 5 --- src/c5/lexer.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/c5/lexer.rs b/src/c5/lexer.rs index e81eb039c..37c9ee851 100644 --- a/src/c5/lexer.rs +++ b/src/c5/lexer.rs @@ -1089,8 +1089,14 @@ impl Lexer { && self.pos < self.src.len() && (b'0'..=b'7').contains(&self.src[self.pos]) { + // Accumulate via wrapping_mul / wrapping_add so a + // full 64-bit octal pattern (the spelling of + // ULLONG_MAX) does not trip debug-build overflow + // detection; the type picker types it per C99 + // 6.4.4.1 from the wrapped bit pattern. while self.pos < self.src.len() && (b'0'..=b'7').contains(&self.src[self.pos]) { - val = val * 8 + (self.src[self.pos] - b'0') as i64; + let digit = (self.src[self.pos] - b'0') as i64; + val = val.wrapping_mul(8).wrapping_add(digit); self.pos += 1; } self.lex_int_suffix(); From 30fc6f7745ad80e9395dc120945c8231e33f7b7a Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 23:28:34 -0700 Subject: [PATCH 50/67] parser: bound recursion depth with a diagnostic The recursive-descent parser had no depth limit, so deeply nested parentheses, declarators, initializer braces, or blocks overflowed the native stack and aborted the compiler (SIGABRT at ~250 paren levels in a debug build). Every recursive entry point (statements, expressions, constant expressions, declarators, initializer lists) now runs through a shared counter bounded at 1024 levels -- well above the 63-level minimum of C99 5.2.4.1 -- and reports " nesting too deep". The CLI driver runs on a thread with a 256 MiB stack reservation so the diagnostic fires before the native stack runs out in debug builds, which spend tens of KiB of stack per nesting level. Co-Authored-By: Claude Fable 5 --- src/c5/compiler/const_expr.rs | 7 ++++ src/c5/compiler/declarator.rs | 4 ++ src/c5/compiler/diag.rs | 22 ++++++++++ src/c5/compiler/expr.rs | 4 ++ src/c5/compiler/global_init.rs | 11 +++++ src/c5/compiler/initializer.rs | 19 +++++++++ src/c5/compiler/mod.rs | 7 ++++ src/c5/compiler/stmt.rs | 4 ++ src/c5/tests/parser.rs | 76 ++++++++++++++++++++++++++++++++++ src/main.rs | 15 +++++++ 10 files changed, 169 insertions(+) diff --git a/src/c5/compiler/const_expr.rs b/src/c5/compiler/const_expr.rs index 3a8e7589c..ca6a2f99d 100644 --- a/src/c5/compiler/const_expr.rs +++ b/src/c5/compiler/const_expr.rs @@ -599,6 +599,13 @@ impl Compiler { } pub(super) fn parse_const_expr_unary_val(&mut self) -> Result { + // Every recursive cycle in the constant-expression grammar + // (parentheses, ternary arms, unary chains) passes through + // here, so this one guard bounds the whole cascade. + self.with_nesting("expression", |c| c.parse_const_expr_unary_val_inner()) + } + + fn parse_const_expr_unary_val_inner(&mut self) -> Result { if self.lex.tk == Token::SubOp { self.next()?; return Ok(match self.parse_const_expr_unary_val()? { diff --git a/src/c5/compiler/declarator.rs b/src/c5/compiler/declarator.rs index 5a43ec4b0..c1324b08c 100644 --- a/src/c5/compiler/declarator.rs +++ b/src/c5/compiler/declarator.rs @@ -189,6 +189,10 @@ impl Compiler { /// the decay happened, but for c5 today the equivalence is /// sufficient. pub(super) fn parse_declarator(&mut self, base: i64) -> Result<(usize, i64, i64), C5Error> { + self.with_nesting("declarator", |c| c.parse_declarator_inner(base)) + } + + fn parse_declarator_inner(&mut self, base: i64) -> Result<(usize, i64, i64), C5Error> { // Taken once so it scopes to this parameter's own declarator, not // any nested one (a function-pointer parameter's prototype). let param_ctx = core::mem::take(&mut self.pending.param_decl_context); diff --git a/src/c5/compiler/diag.rs b/src/c5/compiler/diag.rs index 8dd6f99e5..475107d0a 100644 --- a/src/c5/compiler/diag.rs +++ b/src/c5/compiler/diag.rs @@ -294,6 +294,28 @@ impl Compiler { } } + /// Bound one level of parser recursion. Every recursive cycle in + /// the grammar (expressions, constant expressions, declarators, + /// initializer lists, statements) passes through an entry wrapped + /// in this helper, so one counter bounds them all and + /// pathological nesting gets a diagnostic instead of exhausting + /// the native stack. C99 5.2.4.1 requires 63 nesting levels; the + /// bound stays well above any real source. + pub(super) fn with_nesting( + &mut self, + construct: &'static str, + f: impl FnOnce(&mut Self) -> Result, + ) -> Result { + const MAX_NEST_DEPTH: usize = 1024; + if self.nest_depth >= MAX_NEST_DEPTH { + return Err(self.compile_err(alloc::format!("{construct} nesting too deep"))); + } + self.nest_depth += 1; + let r = f(self); + self.nest_depth -= 1; + r + } + /// Build a `C5Error::Compile` whose message follows the /// gcc / clang-shape convention everything else in this codebase /// uses for diagnostics: diff --git a/src/c5/compiler/expr.rs b/src/c5/compiler/expr.rs index c566fc3c0..21a128c8b 100644 --- a/src/c5/compiler/expr.rs +++ b/src/c5/compiler/expr.rs @@ -433,6 +433,10 @@ impl Compiler { } pub(super) fn expr(&mut self, lev: i64) -> Result<(), C5Error> { + self.with_nesting("expression", |c| c.expr_inner(lev)) + } + + fn expr_inner(&mut self, lev: i64) -> Result<(), C5Error> { let mut t: i64; if self.lex.tk == 0 { diff --git a/src/c5/compiler/global_init.rs b/src/c5/compiler/global_init.rs index 3fe9480c4..d01a61ef1 100644 --- a/src/c5/compiler/global_init.rs +++ b/src/c5/compiler/global_init.rs @@ -76,6 +76,17 @@ impl Compiler { var_ty: i64, var_offset: i64, is_thread_local: bool, + ) -> Result<(), C5Error> { + self.with_nesting("initializer", |c| { + c.parse_global_initializer_inner(var_ty, var_offset, is_thread_local) + }) + } + + fn parse_global_initializer_inner( + &mut self, + var_ty: i64, + var_offset: i64, + is_thread_local: bool, ) -> Result<(), C5Error> { let line = self.lex.line; // C99 6.7.8p11 allows a scalar initializer to be enclosed diff --git a/src/c5/compiler/initializer.rs b/src/c5/compiler/initializer.rs index dabc51430..46ee6fd82 100644 --- a/src/c5/compiler/initializer.rs +++ b/src/c5/compiler/initializer.rs @@ -259,6 +259,15 @@ impl Compiler { pub(super) fn collect_array_initializer( &mut self, elem_ty: i64, + ) -> Result, C5Error> { + self.with_nesting("initializer", |c| { + c.collect_array_initializer_inner(elem_ty) + }) + } + + fn collect_array_initializer_inner( + &mut self, + elem_ty: i64, ) -> Result, C5Error> { // 2D inner-dim hint -- callers set this when the declarator // shape is `T xs[N][M]` so a nested `{ row }` that lists @@ -1503,6 +1512,16 @@ impl Compiler { &mut self, struct_id: usize, var_offset: i64, + ) -> Result<(), C5Error> { + self.with_nesting("initializer", |c| { + c.collect_struct_initializer_inner(struct_id, var_offset) + }) + } + + fn collect_struct_initializer_inner( + &mut self, + struct_id: usize, + var_offset: i64, ) -> Result<(), C5Error> { if self.lex.tk != '{' { return Err(self.compile_err("struct initializer must start with `{{`")); diff --git a/src/c5/compiler/mod.rs b/src/c5/compiler/mod.rs index 83d263e99..49aad6f48 100644 --- a/src/c5/compiler/mod.rs +++ b/src/c5/compiler/mod.rs @@ -801,6 +801,12 @@ pub struct Compiler { /// Number of currently-open `continue`-eligible scopes /// (loops only; `switch` doesn't open one). loop_continue_depth: usize, + /// Recursion depth shared by the recursive-descent entry points + /// (statements, expressions, constant expressions, declarators, + /// initializer lists). Bounded by `MAX_NEST_DEPTH` via + /// `with_nesting` so pathological nesting is diagnosed instead + /// of exhausting the native stack. + nest_depth: usize, /// Linear table of `(label_name, text_pc)`. Per-function (cleared /// at every function start), so it stays small -- typically 0-2 /// entries even in code that uses `goto`. Linear scan beats @@ -1321,6 +1327,7 @@ impl Compiler { pending_local_runtime_elements: Vec::new(), loop_break_depth: 0, loop_continue_depth: 0, + nest_depth: 0, labels: Vec::new(), unresolved_gotos: Vec::new(), switch_cases: Vec::new(), diff --git a/src/c5/compiler/stmt.rs b/src/c5/compiler/stmt.rs index 5e2f9fc8a..e6312f8e1 100644 --- a/src/c5/compiler/stmt.rs +++ b/src/c5/compiler/stmt.rs @@ -932,6 +932,10 @@ impl Compiler { } pub(super) fn stmt(&mut self) -> Result<(), C5Error> { + self.with_nesting("statement", |c| c.stmt_inner()) + } + + fn stmt_inner(&mut self) -> Result<(), C5Error> { // Function-pointer callee parameters captured for a postfix // indirect call never span a statement: drop any left set by a // producer whose call did not consume them so they cannot reach an diff --git a/src/c5/tests/parser.rs b/src/c5/tests/parser.rs index e7554d70d..1afc19198 100644 --- a/src/c5/tests/parser.rs +++ b/src/c5/tests/parser.rs @@ -812,3 +812,79 @@ fn constant_expression_llong_min_div_neg_one_folds() { .compile() .expect("LLONG_MIN / -1 must fold, not panic"); } + +/// Run on a thread with the same explicit stack reservation the CLI +/// driver uses: deeply nested source costs more native stack in debug +/// builds than the default test-thread allotment provides. +fn on_big_stack(f: impl FnOnce() + Send + 'static) { + std::thread::Builder::new() + .stack_size(256 * 1024 * 1024) + .spawn(f) + .expect("spawn compile thread") + .join() + .expect("join compile thread"); +} + +fn expect_compile_error_on_big_stack(src: String, needle: &'static str) { + on_big_stack(move || expect_compile_error(&src, needle)); +} + +#[test] +fn deep_expression_nesting_is_diagnosed() { + let n = 2000; + let src = format!( + "int main(void) {{ return {}1{}; }}", + "(".repeat(n), + ")".repeat(n) + ); + expect_compile_error_on_big_stack(src, "expression nesting too deep"); +} + +#[test] +fn deep_global_initializer_expression_nesting_is_diagnosed() { + let n = 2000; + let src = format!("int x = {}1{};", "(".repeat(n), ")".repeat(n)); + expect_compile_error_on_big_stack(src, "nesting too deep"); +} + +#[test] +fn deep_declarator_nesting_is_diagnosed() { + let n = 2000; + let src = format!("int {}x{};", "(".repeat(n), ")".repeat(n)); + expect_compile_error_on_big_stack(src, "declarator nesting too deep"); +} + +#[test] +fn deep_initializer_brace_nesting_is_diagnosed() { + let n = 2000; + let src = format!( + "int main(void) {{ int q[1] = {}1{}; return q[0]; }}", + "{".repeat(n), + "}".repeat(n) + ); + expect_compile_error_on_big_stack(src, "initializer nesting too deep"); +} + +#[test] +fn deep_statement_block_nesting_is_diagnosed() { + let n = 2000; + let src = format!( + "int main(void) {{ {}{} return 0; }}", + "{".repeat(n), + "}".repeat(n) + ); + expect_compile_error_on_big_stack(src, "statement nesting too deep"); +} + +#[test] +fn c99_minimum_expression_nesting_compiles() { + // C99 5.2.4.1: 63 nesting levels of parenthesized expressions + // must be accepted; the depth bound sits far above this. + let n = 63; + let src = format!( + "int main(void) {{ return {}0{}; }}", + "(".repeat(n), + ")".repeat(n) + ); + on_big_stack(move || assert_eq!(super::run_str(&src), 0)); +} diff --git a/src/main.rs b/src/main.rs index ff84f51b5..5ae2f0520 100644 --- a/src/main.rs +++ b/src/main.rs @@ -199,6 +199,21 @@ impl Mode { } fn main() { + // The recursive-descent parser bounds its nesting depth with a + // diagnostic, but debug builds spend tens of KiB of native stack + // per level, more than the platform default provides at the + // bound. Run the driver on a thread with an explicit reservation + // so the diagnostic always fires before the stack runs out. + let driver = std::thread::Builder::new() + .stack_size(256 * 1024 * 1024) + .spawn(run) + .expect("spawn driver thread"); + if let Err(e) = driver.join() { + std::panic::resume_unwind(e); + } +} + +fn run() { let raw: Vec = std::env::args().collect(); // Mode selection: at most one of the mode-picking flags From bab86583074beee1bc1bd46abd09e14fd4949b7b Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 23:40:50 -0700 Subject: [PATCH 51/67] c5: route the FP-typed ternary through the fused StoreLocal path The float arm of a conditional expression stored its result through LocalAddr + Store, which marked the synthetic merge slot address-taken and excluded it from mem2reg promotion. Both backends lower the fused StoreLocal / LoadLocal { F32 } in a single instruction (narrowing an f64 arm per C99 6.3.1.5), so the address-taken form was unnecessary. Use the fused ops for float as for double; the merge slot is now promoted and the single-precision value is preserved (C99 6.5.15). Co-Authored-By: Claude Fable 5 --- src/c5/ast/walk.rs | 42 +++++++++++++----------- src/c5/tests/programs.rs | 8 +++++ tests/fixtures/c/float_ternary_promote.c | 25 ++++++++++++++ 3 files changed, 55 insertions(+), 20 deletions(-) create mode 100644 tests/fixtures/c/float_ternary_promote.c diff --git a/src/c5/ast/walk.rs b/src/c5/ast/walk.rs index f71f6c552..fb7d10590 100644 --- a/src/c5/ast/walk.rs +++ b/src/c5/ast/walk.rs @@ -1850,7 +1850,7 @@ impl<'a> Walker<'a> { // substitute the `ShortCircuit` arm uses -- both // arms store the arm result and the merge block // loads it. Width is taken from the result type: - // FP-typed ternary uses `Store { kind: F32 }` / + // an FP-typed ternary uses `StoreLocal { kind: F32 }` / // `LoadLocal { kind: F32 }` so the codegen routes // through the FP register class; everything else // stays on the I64 `StoreLocal` / `LoadLocal` fast @@ -1863,23 +1863,24 @@ impl<'a> Walker<'a> { let slot = b.alloc_synthetic_local(); let load_kind = load_kind_for(*ty, self.target); let store_kind = store_kind_for(*ty, self.target); - // `float` keeps the value in an FP register but its - // 4-byte storage width forces the `LocalAddr` + `Store` - // path (the fused `StoreLocal { F32 }` is not lowered). - // `double` rides the FP register class at its full - // 8-byte width, so the fused `StoreLocal` / `LoadLocal` - // F64 path lowers it in a single `movsd` / `ldr d`. - let is_f32 = matches!(load_kind, super::super::ir::LoadKind::F32); - let is_f64 = matches!(load_kind, super::super::ir::LoadKind::F64); + // An FP-typed result rides the FP register class through + // the fused `StoreLocal` / `LoadLocal` path: the emit + // lowers `F32` (`movss` / `str s`, narrowing an f64 arm + // per C99 6.3.1.5) and `F64` (`movsd` / `ldr d`) each in + // a single instruction. The fused ops keep the synthetic + // merge slot mem2reg-promotable, unlike `LocalAddr` + + // `Store`. Everything else stays on the I64 fast path. + let is_fp = matches!( + load_kind, + super::super::ir::LoadKind::F32 | super::super::ir::LoadKind::F64 + ); let arm_store = |b: &mut super::super::codegen::ssa::build::SsaBuilder, v| { - if is_f32 { - let addr = b.local_addr(slot); - b.store(addr, v, store_kind); - } else if is_f64 { - b.store_local(slot, v, store_kind); + let kind = if is_fp { + store_kind } else { - b.store_local(slot, v, super::super::ir::StoreKind::I64); - } + super::super::ir::StoreKind::I64 + }; + b.store_local(slot, v, kind); }; b.switch_to(then_blk); let then_v = self.walk_expr_rvalue(b, *then_e)?; @@ -1890,11 +1891,12 @@ impl<'a> Walker<'a> { arm_store(b, else_v); b.jmp(after_blk); b.switch_to(after_blk); - if is_f32 || is_f64 { - Ok(b.load_local(slot, load_kind)) + let read_kind = if is_fp { + load_kind } else { - Ok(b.load_local(slot, super::super::ir::LoadKind::I64)) - } + super::super::ir::LoadKind::I64 + }; + Ok(b.load_local(slot, read_kind)) } Expr::Call { callee, args, ty } => { // Out-pointer-returning c5-internal callee: allocate a diff --git a/src/c5/tests/programs.rs b/src/c5/tests/programs.rs index f7aa2d084..2db15108f 100644 --- a/src/c5/tests/programs.rs +++ b/src/c5/tests/programs.rs @@ -104,6 +104,14 @@ fn fn_ptr_float_return() { assert_eq!(run_fixture("fn_ptr_float_return.c"), 0); } +#[test] +fn float_ternary_promote() { + // C99 6.5.15: an FP-typed conditional expression rides the fused + // StoreLocal / LoadLocal F32 path, keeping the synthetic merge slot + // mem2reg-promotable while preserving single-precision value. + assert_eq!(run_fixture("float_ternary_promote.c"), 0); +} + #[test] fn fn_ptr_float_arg() { // C99 6.5.2.2p7: a float argument through a function pointer is diff --git a/tests/fixtures/c/float_ternary_promote.c b/tests/fixtures/c/float_ternary_promote.c new file mode 100644 index 000000000..3d3c9bf01 --- /dev/null +++ b/tests/fixtures/c/float_ternary_promote.c @@ -0,0 +1,25 @@ +// C99 6.5.15: a float-typed conditional expression yields one arm's +// value at single precision. The lowering stores each arm through the +// fused StoreLocal / LoadLocal F32 path so the synthetic merge slot +// stays mem2reg-promotable; the value must round-trip exactly at +// 32-bit precision (all constants below are f32-representable). + +static float sel(int c, float a, float b) { + float r = c ? a : b; + return r; +} + +int main(void) { + if (sel(1, 1.5f, -2.5f) != 1.5f) return 1; + if (sel(0, 1.5f, -2.5f) != -2.5f) return 2; + + float x = 3.25f; + float y = (x > 0.0f ? x : -x) + (x < 0.0f ? -x : x); /* 2*|x| */ + if (y != 6.5f) return 3; + + int k = 2; + float z = k == 0 ? 0.0f : k == 1 ? 10.0f : 20.0f; + if (z != 20.0f) return 4; + + return 0; +} From ddcce6825f4adcc77fd20d950066957ef97af5ae Mon Sep 17 00:00:00 2001 From: kromych Date: Wed, 1 Jul 2026 23:41:20 -0700 Subject: [PATCH 52/67] c5: reconcile stale invariant comments with the code Correct comments that describe behavior the code has moved past: * x86_64 param_reg_stack_split: register/stack placements need not be contiguous (System V AMD64 MEMORY-class or Win64 overflow aggregates interleave them); no assertion gates this. * x86_64 detect_tail_call: callee-saved use is allowed (the caller-saved arg window is disjoint from gpr_used), and any LocalAddr, not only a negative slot, disqualifies the tail call. * aarch64 move_call_result: an FP scalar result rides d0 (AAPCS64 6.4.2), an integer result x0 (6.4.1); emit_return leaves it in d0. * reg_alloc last_use: document its live consumers (the call-spanning interval and coalescing tests), and add the GotoIndirect arm to the two terminator walks that lacked it -- redundant with the exit_acc bump but uniform with the liveness and use-count walks. * elf_reloc: .rela.text is emitted, so cross-TU calls link. * mach_o: __thread_data carries TLS init bytes once tls_init_size is non-zero; __DWARF is emitted for executables and dylibs at its own vmaddr slot. * pe: .reloc follows any absolute pointer (TLS directory and address-of-static relocations); the adrp+add pair is PC-relative and needs no base relocation. * pe / program / compiler: a _Thread_local initializer raises tls_init_size and lands in .tdata. * link / synth_build: multi-object TLS is resolved via per-unit TPOFF / descriptor rebasing; the Windows/aarch64 TEB path records a fixup for every access. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/aarch64/emit.rs | 14 ++++----- src/c5/codegen/ssa/reg_alloc.rs | 18 +++++++---- src/c5/codegen/x86_64/emit.rs | 39 +++++++++++------------ src/c5/compiler/mod.rs | 7 ++--- src/c5/linker/link.rs | 7 +++-- src/c5/linker/synth_build.rs | 13 ++++---- src/c5/object/elf_reloc.rs | 6 ++-- src/c5/object/mach_o.rs | 23 +++++++------- src/c5/object/pe.rs | 55 +++++++++++++++++---------------- src/c5/program.rs | 7 ++--- 10 files changed, 95 insertions(+), 94 deletions(-) diff --git a/src/c5/codegen/aarch64/emit.rs b/src/c5/codegen/aarch64/emit.rs index 6f98ba04c..3785a4a43 100644 --- a/src/c5/codegen/aarch64/emit.rs +++ b/src/c5/codegen/aarch64/emit.rs @@ -3786,13 +3786,13 @@ fn finish_call_result( } /// Common return-value bridge shared by `emit_call` and -/// `emit_call_indirect`. The c5-internal calling convention ferries -/// every return value -- including an f64 bit pattern -- through the -/// integer return register x0 (see `emit_return`, which moves an -/// FP-placed return value into x0 via `fmov x0, d`). When the callee -/// returns a floating-point scalar (`fp_return`) the call's result is -/// FP-classed, so the x0 bit pattern is reinterpreted into the FP -/// register file via `fmov d, x0`. +/// `emit_call_indirect`. An integer-classed result rides x0 (AAPCS64 +/// 6.4.1); a floating-point scalar rides d0, whose low 32 bits are the +/// s0 an f32 occupies (AAPCS64 6.4.2), which is where `emit_return` +/// leaves it. When the callee returns a floating-point scalar +/// (`fp_return`) this copies d0 into the FP-classed destination, or +/// bridges it to a GPR via `fmov x, d0` when the destination is +/// integer-classed. fn move_call_result(code: &mut Vec, dst: Place, frame: Frame, fp_return: bool) { if fp_return { // A floating-point scalar result arrives in d0 (C99 6.2.5p10 / diff --git a/src/c5/codegen/ssa/reg_alloc.rs b/src/c5/codegen/ssa/reg_alloc.rs index 42badc604..7378265df 100644 --- a/src/c5/codegen/ssa/reg_alloc.rs +++ b/src/c5/codegen/ssa/reg_alloc.rs @@ -104,12 +104,13 @@ pub(crate) struct Allocation { /// skip pure-with-no-uses insts (dead-code elimination). A value /// with zero uses and no side effects produces no machine code. pub use_counts: Vec, - /// Highest PC index that names each value as an operand. A - /// value defined at PC `i` is live throughout `[i, last_use[i]]` - /// and the emit pass queries this to compute the set of - /// registers carrying live SSA values at any given PC -- needed - /// when picking an intra-instruction scratch that must not - /// clobber a value the next instruction reads. + /// Highest PC index that names each value as an operand, raised + /// across back edges by `extend_last_use_across_blocks`. A value + /// defined at PC `i` is live throughout `[i, last_use[i]]`. The + /// allocator's interval tests read it: `class_last_use` feeds + /// `promote_calls_after_def_to_classes` so a value whose range + /// spans a call takes a callee-saved home, and the coalescing + /// hints avoid a caller-saved register such a call would clobber. pub last_use: Vec, /// For `BinopI(Shr, X, K)` insts the allocator recognised as /// the upper half of a sign-narrow `Shl K; Shr K` pair (K in @@ -1945,9 +1946,13 @@ fn compute_last_use(func: &FunctionSsa) -> Vec { } }; bump(b.exit_acc); + // A `GotoIndirect` sets `exit_acc` to its target, so the bump + // above already covers it; the explicit arm keeps this walk + // uniform with the liveness and use-count terminator walks. match &b.terminator { Terminator::Bz { cond, .. } | Terminator::Bnz { cond, .. } => bump(*cond), Terminator::Return(v) => bump(*v), + Terminator::GotoIndirect { target } => bump(*target), _ => {} } } @@ -2012,6 +2017,7 @@ fn extend_last_use_across_blocks(func: &FunctionSsa, last_use: &mut [u32]) { match &blk.terminator { Terminator::Bz { cond, .. } | Terminator::Bnz { cond, .. } => mark(*cond), Terminator::Return(v) if *v != NO_VALUE => mark(*v), + Terminator::GotoIndirect { target } if *target != NO_VALUE => mark(*target), _ => {} } } diff --git a/src/c5/codegen/x86_64/emit.rs b/src/c5/codegen/x86_64/emit.rs index 2deec32ef..4219be84f 100644 --- a/src/c5/codegen/x86_64/emit.rs +++ b/src/c5/codegen/x86_64/emit.rs @@ -334,14 +334,13 @@ fn param_placements(func: &FunctionSsa, abi: super::Abi) -> alloc::vec::Vec (usize, usize) { let placements = param_placements(func, abi); // The count of register-passed (non-stack) placements and the count @@ -7222,19 +7221,17 @@ fn emit_atomic_cas( /// own prologue, but the tail call site can't tell from here, so /// keep the tail conversion off when *this* function is variadic /// (its arg slots stay on the c5 stack rather than reg cells). -/// * The function has no `LocalAddr` to a negative slot: any such -/// address could have been passed to the callee in an earlier -/// call's argument, and tearing down our frame before the jmp -/// would invalidate it. -/// * The function records no callee-saved register use -/// (`alloc.gpr_used.is_empty()`): the epilogue would emit per-reg -/// restores between the arg marshal and the jmp, all of which -/// are callee-saved (rbx / r12 / r14 / r15 / rsi / rdi on Win64) -/// and so don't alias the caller-saved arg-register window the -/// tail call has just populated. Restricted on this first pass -/// for tractability; the more general path can drop this gate -/// once it is shown to be safe via an explicit save-before-marshal -/// sequence. +/// * The function takes no `LocalAddr`, whether to a user local +/// (negative `off`) or a c5 cdecl param cell (`off >= 2`): such an +/// address could have been passed to an earlier callee, and the +/// param cells are overwritten by the tail-callee's own prologue, +/// so tearing down the frame before the jmp would make it dangle. +/// +/// Callee-saved register use is allowed: the marshalled arguments ride +/// the caller-saved arg-register window, which is disjoint from +/// `alloc.gpr_used` (only callee-saved regs land there), so the +/// epilogue's per-reg restores cannot clobber them (see +/// `emit_tail_call`). fn detect_tail_call<'a>( func: &'a FunctionSsa, block: &super::super::ir::Block, diff --git a/src/c5/compiler/mod.rs b/src/c5/compiler/mod.rs index 49aad6f48..e15984660 100644 --- a/src/c5/compiler/mod.rs +++ b/src/c5/compiler/mod.rs @@ -880,10 +880,9 @@ pub struct Compiler { /// the .tls$ callback chain on Win64). Each `_Thread_local` /// global gets `slots_of_type(ty) * 8` bytes here, with /// `Symbol::val` holding the byte offset within `tls_data`. - /// Today we don't parse TLS initialisers, so the segment is - /// always zero-filled and goes entirely into .tbss; the layout - /// leaves room for a future "initialised TLS image -> .tdata" - /// path. + /// A `_Thread_local int x = 5;` initialiser fills its slice and + /// raises `tls_init_size` so its bytes go into .tdata; an + /// uninitialised variable stays zero-filled in .tbss. tls_data: Vec, /// Number of bytes at the start of [`Self::tls_data`] that /// are statically initialised by an explicit diff --git a/src/c5/linker/link.rs b/src/c5/linker/link.rs index 21698a92a..315c883b2 100644 --- a/src/c5/linker/link.rs +++ b/src/c5/linker/link.rs @@ -302,9 +302,10 @@ pub fn link_native_objects_with_options( // the same through `NT_BADC_ELF_TPOFF` fixups resolved in Pass 4.1 // below (x86_64 variant-2 `sub imm32`, Linux/aarch64 variant-1 `add // imm12`, Windows/aarch64 TEB-indexed `add imm12`), so a multi-unit - // link rebases each access against the merged layout. A same-unit - // access on the Windows TEB path with no cross-unit reference carries - // no fixup and keeps its baked single-unit offset. + // link rebases each access against the merged layout. On the + // Windows/aarch64 TEB path both a unit-local and an extern access + // record a fixup, so a unit-local offset is rebased by its unit's + // base in the merged block rather than kept as a baked offset. let uses_tlv = objs.iter().any(|o| { !o.macho_tlv_descriptors.is_empty() || !o.macho_tlv_fixups.is_empty() diff --git a/src/c5/linker/synth_build.rs b/src/c5/linker/synth_build.rs index 13a4f0e3d..af7491755 100644 --- a/src/c5/linker/synth_build.rs +++ b/src/c5/linker/synth_build.rs @@ -16,13 +16,6 @@ //! `is_variadic` / `fixed_args` / `param_types` across the ELF //! ET_REL roundtrip. The C99-motivated fix is a per-binding //! metadata note section. TODO. -//! * Multi-object `_Thread_local` storage. A single TLS-bearing -//! input is fully threaded: ELF PT_TLS via -//! [`MergedNative::tls_data`], the Win64 `_tls_index` fixups and -//! macOS TLV descriptors via the matching `.note.badc` records. -//! Merging two or more TLS objects still needs per-unit TPOFF / -//! descriptor-index relocations, so `link_native_objects` rejects -//! the multi-object case. TODO. //! * DWARF debug info. The merged image has no AST / function //! metadata to drive DWARF emit; debug sections are skipped, //! matching `write_executable_elf64`'s policy. TODO. @@ -30,6 +23,12 @@ //! Shared-library output is handled: the caller passes //! [`OutputKind::SharedLibrary`] and the `#pragma export` names ride //! the ET_REL `NT_BADC_EXPORTS` note into [`MergedNative::exports`]. +//! +//! `_Thread_local` storage is threaded for single- and multi-object +//! links: ELF PT_TLS via [`MergedNative::tls_data`], the Win64 +//! `_tls_index` fixups and macOS TLV descriptors via the matching +//! `.note.badc` records, with per-unit TPOFF / descriptor rebasing +//! resolved in `link_native_objects`. #![cfg(feature = "std")] diff --git a/src/c5/object/elf_reloc.rs b/src/c5/object/elf_reloc.rs index c366066c5..48068bde9 100644 --- a/src/c5/object/elf_reloc.rs +++ b/src/c5/object/elf_reloc.rs @@ -289,9 +289,9 @@ fn data_global_byte_size(sym: &crate::c5::symbol::Symbol) -> u64 { /// Emit a relocatable ELF64 object holding the contents of /// `build`. The result is a standard `.o` that `ld` / `lld` can -/// link (modulo missing relocations -- the writer doesn't yet -/// emit `.rela.text`, so a TU with cross-TU calls produces a -/// link error today). +/// link: the writer emits `.rela.text` (SHT_RELA, `sh_info` = the +/// `.text` section index) with one entry per call site, so a TU with +/// cross-TU calls resolves at link time. pub(super) fn write_relocatable( program: &Program, build: &Build, diff --git a/src/c5/object/mach_o.rs b/src/c5/object/mach_o.rs index 1eb1cc235..bb918cb79 100644 --- a/src/c5/object/mach_o.rs +++ b/src/c5/object/mach_o.rs @@ -238,12 +238,11 @@ const SEG_INDEX_DATA: u8 = 2; const S_ATTR_DEBUG: u32 = 0x0200_0000; /// Mach-O section type bits used by the TLV layout. See -/// `` for the full set; we only need -/// `__thread_bss` (zero-fill, the only flavour the c5 frontend -/// generates today since `_Thread_local` initialisers aren't -/// supported) and `__thread_vars` (descriptors). The matching -/// `__thread_data` (S_THREAD_LOCAL_REGULAR = 0x11) would be -/// emitted alongside if we ever support TLS initialisers. +/// `` for the full set. `__thread_vars` holds the +/// descriptors; the per-thread storage is `__thread_bss` (zero-fill) +/// when every `_Thread_local` starts zero, or `__thread_data` +/// (S_THREAD_LOCAL_REGULAR = 0x11, file-backed init template) once any +/// initialiser makes `build.tls_init_size` non-zero. #[allow(dead_code)] const S_ZEROFILL: u32 = 0x1; // __bss (zero-fill, no file backing) const S_THREAD_LOCAL_REGULAR: u32 = 0x11; // __thread_data (init data) @@ -2572,9 +2571,9 @@ pub(super) fn write(program: &Program, build: &Build) -> Result, C5Error // then dyld_info family, then symbol tables, then dylinker / // dylib / build_version / main (or LC_ID_DYLIB for shared libs). // Segment LC order: __PAGEZERO, __TEXT, __DATA, __DWARF - // (executables only), __LINKEDIT -- the layout - // `go build` produces for executables. __DWARF reuses - // __LINKEDIT's vmaddr with vmsize=0, so the loaded image's + // (present when debug info is emitted, for both executables and + // dylibs), __LINKEDIT. __DWARF occupies its own page-aligned + // vmaddr slot between __DATA and __LINKEDIT, so the loaded image's // address space stays monotonic non-decreasing. // File-resident order matches LC order. out.extend_from_slice(&pagezero); @@ -2746,9 +2745,9 @@ pub(super) fn write(program: &Program, build: &Build) -> Result, C5Error } out.resize((data_fileoff + data_filesize) as usize, 0); - // __DWARF contents (executables only -- dylibs skip phase - // 1 DWARF, see `emit_dwarf`). Order matches what - // `segment_dwarf` pointed each section at: info, abbrev, + // __DWARF contents, emitted whenever debug info is requested + // (executables and dylibs, gated by `emit_dwarf`). Order matches + // what `segment_dwarf` pointed each section at: info, abbrev, // line, str. Sits ahead of __LINKEDIT so codesign can grow // __LINKEDIT at the file tail without trampling debug // bytes. diff --git a/src/c5/object/pe.rs b/src/c5/object/pe.rs index 285d3b985..a819ecc37 100644 --- a/src/c5/object/pe.rs +++ b/src/c5/object/pe.rs @@ -177,11 +177,12 @@ const NUM_DATA_DIRS: u32 = 16; /// appears when the c5 program has initialized data -- string /// literals, globals, or `_Thread_local` storage -- because /// real Windows kernels reject images that list a zero-sized -/// section. The optional `.reloc` only appears when the -/// program declares any `_Thread_local` global; that's the -/// only path that puts absolute VAs into the image (the three -/// pointer fields of `IMAGE_TLS_DIRECTORY64`), which the -/// ASLR-aware loader needs to fix up after sliding. +/// section. The optional `.reloc` appears when the image holds +/// any absolute VA the ASLR-aware loader must fix up after +/// sliding: the three `IMAGE_TLS_DIRECTORY64` pointer fields +/// (when the program declares a `_Thread_local` global) and any +/// absolute pointer baked by an address-of-static data or code +/// relocation. /// /// `.pdata` is the Exception Directory, mandatory under the /// 64-bit Windows ABI: the loader looks up `RUNTIME_FUNCTION` @@ -191,13 +192,13 @@ const NUM_DATA_DIRS: u32 = 16; /// hosts can reject a missing entry, so we emit it on both /// arches. /// -/// `.reloc` is omitted for TLS-free images because every -/// cross-section reference the codegen emits is RIP-relative -/// (x86_64) or PC-relative (aarch64 ADRP+ADD), so the -/// DYNAMIC_BASE-flagged image can be slid to any address -/// without touching any absolute pointer in the file. The -/// only absolute pointers we ever emit live inside the TLS -/// directory, which is why `.reloc` follows TLS presence. +/// `.reloc` is omitted only when the image holds no absolute +/// pointer: most cross-section references are RIP-relative +/// (x86_64) or PC-relative (aarch64 ADRP+ADD), and a +/// DYNAMIC_BASE-flagged image slides freely without touching +/// them. Absolute VAs live in the TLS directory and in +/// address-of-static initializers, so `.reloc` follows their +/// presence. fn num_sections( data_section_present: bool, reloc_section_present: bool, @@ -1189,13 +1190,13 @@ pub(super) fn write( // subsequent `tls_array[0] + offset` then lands // inside another module's per-thread storage and // reads non-zero data, which trips - // `thread_local_basic.c`'s "counter != 0" check. - // The c5 frontend never produces non-zero TLS init - // bytes today (no `_Thread_local int x = 5;` - // syntax), so emitting the whole block as zero - // template bytes is byte-for-byte identical to the - // SizeOfZeroFill scheme but sidesteps the loader - // edge case. + // the "counter != 0" check in a per-thread test. + // The frontend may produce non-zero TLS init bytes + // (`_Thread_local int x = 5;`); `build.tls_data` + // already holds the init template followed by the + // zero-init tail, so emitting the whole block as + // template bytes carries both correctly and sidesteps + // the empty-template edge case. let tls_init_start_va = IMAGE_BASE + (data_rva + tls_layout.tls_init_offset_in_data) as u64; let tls_init_end_va = tls_init_start_va + build.tls_data.len() as u64; @@ -1207,10 +1208,9 @@ pub(super) fn write( out.extend_from_slice(&0u64.to_le_bytes()); // AddressOfCallBacks out.extend_from_slice(&zero_fill.to_le_bytes()); out.extend_from_slice(&0u32.to_le_bytes()); // Characteristics - // TLS template -- copied verbatim into each - // thread's per-thread region by the loader. The c5 - // frontend zero-initialises every TLS variable - // today, so this is effectively N bytes of zeros. + // TLS template -- copied verbatim into each thread's + // per-thread region by the loader. `tls_data` holds the + // initialised bytes followed by the zero-init tail. out.extend_from_slice(&build.tls_data); } } @@ -2861,10 +2861,11 @@ fn patch_aarch64_adrp_ldr( Ok(()) } -/// Patch an aarch64 `adrp xd, _; add xd, xd, #_` pair so the final -/// xd holds the absolute-address-mod-image-base equivalent of -/// `target_rva` (resolved by the loader at fixed image base since -/// we don't ship base relocations). +/// Patch an aarch64 `adrp xd, _; add xd, xd, #_` pair to point at +/// `target_rva`. The encoding is PC-relative: `adrp` takes the signed +/// 4 KiB page delta from its own page and `add` the 12-bit in-page +/// offset, so an ASLR slide moves the instruction and its target by +/// the same delta and the pair needs no base relocation. fn patch_aarch64_adrp_add( text: &mut [u8], adrp_offset_in_text: u32, diff --git a/src/c5/program.rs b/src/c5/program.rs index 63de93287..8833bbf32 100644 --- a/src/c5/program.rs +++ b/src/c5/program.rs @@ -119,10 +119,9 @@ pub struct Program { /// indexed by `Inst::TlsAddr`'s operand. The image writers copy /// this into `.tdata` (initialised slice = `tls_data[..tls_init_size]`) /// and `.tbss` (zero-fill remainder = `tls_data[tls_init_size..]`). - /// Today everything starts zero (no `_Thread_local int x = 5;` - /// initialiser syntax), so `tls_init_size == 0` and the whole - /// block lives in .tbss; the layout is structured for future - /// expansion. + /// A `_Thread_local int x = 5;` initialiser raises + /// `tls_init_size` so its bytes land in `.tdata`; an + /// uninitialised variable keeps its slice zero and in `.tbss`. pub tls_data: Vec, /// Number of bytes of `tls_data` that are statically initialised /// (i.e., emitted into `.tdata`). The remainder From 5b2902224785860206a16eed57ec28cced30bb86 Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 00:29:12 -0700 Subject: [PATCH 53/67] windows, driver: POSIX setenv overwrite, JIT handle unification, archive/freestanding input handling setenv now honors the POSIX overwrite flag via a runtime shim (msvcrt _putenv_s always overwrites); the Windows JIT resolves symbols through the same module-handle set bind_imports uses; the --freestanding entry check runs after inputs are parsed; and an archive-only invocation links its members instead of reporting no files. Co-Authored-By: Claude Fable 5 --- headers/include/stdlib.h | 8 +-- lib/runtime.c | 18 ++++++ src/c5/codegen/jit.rs | 45 ++++++++------- src/c5/tests/codegen.rs | 32 +++++++++++ src/c5/tests/native.rs | 1 + src/c5/tests/native_elf.rs | 1 + src/c5/tests/native_elf_x64.rs | 1 + src/c5/tests/native_pe_arm64.rs | 3 + src/c5/tests/native_pe_x64.rs | 3 + src/main.rs | 53 +++++++++++------ tests/cli_linker_smoke.rs | 88 +++++++++++++++++++++++++++++ tests/fixtures/c/setenv_overwrite.c | 16 ++++++ 12 files changed, 228 insertions(+), 41 deletions(-) create mode 100644 tests/fixtures/c/setenv_overwrite.c diff --git a/headers/include/stdlib.h b/headers/include/stdlib.h index d9f685f00..bb0b07962 100644 --- a/headers/include/stdlib.h +++ b/headers/include/stdlib.h @@ -168,11 +168,11 @@ #pragma binding(msvcrt::abort, "abort") #pragma binding(msvcrt::system, "system") #pragma binding(msvcrt::getenv, "getenv") -// POSIX putenv is msvcrt's underscored `_putenv`; msvcrt's `setenv` -// is `_putenv_s`. Same shapes: (string) -> int and -// (name, value, overwrite) -> int. +// POSIX putenv is msvcrt's underscored `_putenv` (a `(string) -> int` +// shape). POSIX setenv takes a third `overwrite` argument that msvcrt's +// 2-parameter `_putenv_s(name, value)` lacks, so it is left unbound and +// resolved by the runtime shim (see lib/runtime.c) that honors the flag. #pragma binding(msvcrt::putenv, "_putenv") -#pragma binding(msvcrt::setenv, "_putenv_s") #pragma binding(msvcrt::_wputenv_s, "_wputenv_s") #pragma binding(msvcrt::qsort, "qsort") #pragma binding(msvcrt::bsearch, "bsearch") diff --git a/lib/runtime.c b/lib/runtime.c index 6041f4a24..5536390ff 100644 --- a/lib/runtime.c +++ b/lib/runtime.c @@ -62,6 +62,24 @@ int snprintf(char *buf, int size, char *fmt, ...) { return len; } +// POSIX setenv (IEEE Std 1003.1): with overwrite == 0 an existing +// binding is left untouched and 0 is returned. msvcrt's +// `_putenv_s(name, value)` has no overwrite flag and always replaces, +// so probe `getenv` first and write only when the name is absent or a +// replacement is requested (`` leaves setenv unbound on +// Windows so this definition resolves it). +#pragma binding(libc::getenv, "getenv") +#pragma binding(libc::_putenv_s, "_putenv_s") +extern char *getenv(char *name); +extern int _putenv_s(char *name, char *value); + +int setenv(char *name, char *value, int overwrite) { + if (overwrite == 0 && getenv(name) != 0) { + return 0; + } + return _putenv_s(name, value); +} + #endif #endif diff --git a/src/c5/codegen/jit.rs b/src/c5/codegen/jit.rs index 353ce100e..613b4b94f 100644 --- a/src/c5/codegen/jit.rs +++ b/src/c5/codegen/jit.rs @@ -1123,10 +1123,14 @@ mod jit_impl { // with MEM_RELEASE requires size = 0. #[cfg_attr(target_os = "windows", allow(dead_code))] len: usize, - /// Library handles to release on drop. POSIX uses one - /// `dlopen(NULL)` handle (so this is at most one entry); - /// Windows uses one per declared dylib. - lib_handles: Vec<*mut c_void>, + /// Loader handles for both import binding and extern-data + /// resolution, paired with whether Drop must release the handle. + /// POSIX opens each with `dlopen` (owned). Windows takes a + /// non-owned `GetModuleHandleA` handle for an already-loaded + /// module and an owned `LoadLibraryA` handle otherwise; a + /// `GetModuleHandleA` handle carries no refcount, so it must not + /// be freed. Both bind and resolve search the full set. + lib_handles: Vec<(*mut c_void, bool)>, } impl GotRegion { @@ -1216,7 +1220,7 @@ mod jit_impl { "JIT: dlopen(NULL, RTLD_NOW) returned null -- can't resolve libc symbols", ))); } - self.lib_handles.push(handle); + self.lib_handles.push((handle, true)); // On Linux every declared dylib is its own .so (libc.so.6, // libm.so.6, libdl.so.2, ...) -- the Rust test binary @@ -1236,7 +1240,7 @@ mod jit_impl { if let Ok(cs) = CString::new(d.path.as_str()) { let h = unsafe { dlopen(cs.as_ptr(), RTLD_NOW) }; if !h.is_null() { - self.lib_handles.push(h); + self.lib_handles.push((h, true)); } } } @@ -1263,7 +1267,7 @@ mod jit_impl { Ok(cs) => cs, Err(_) => continue, // unreachable: symbol names are static ASCII }; - for h in &self.lib_handles { + for (h, _) in &self.lib_handles { let a = unsafe { dlsym(*h, cs.as_ptr()) } as u64; if a != 0 { addr = a; @@ -1319,10 +1323,10 @@ mod jit_impl { owned = true; } handles.push(h); - if owned { - // Track the handle so Drop releases it. - self.lib_handles.push(h); - } + // Every handle joins the shared set so extern-data + // resolution searches exactly what import binding used; + // `owned` gates release in Drop. + self.lib_handles.push((h, owned)); } for (i, imp) in imports.imports.iter().enumerate() { let mut addr = atexit_thunk_addr(imp.real_symbol.as_str()); @@ -1375,7 +1379,7 @@ mod jit_impl { Ok(cs) => cs, Err(_) => return 0, }; - for &h in &self.lib_handles { + for &(h, _) in &self.lib_handles { let a = unsafe { dlsym(h, cs.as_ptr()) } as u64; if a != 0 { return a; @@ -1384,16 +1388,17 @@ mod jit_impl { 0 } - /// Windows resolver: best-effort over the handles opened for - /// imports (`LoadLibraryA`). A data symbol in a module that was - /// not an import target won't resolve and the caller errors. + /// Windows resolver over the same handle set `bind_imports` + /// populated (both `GetModuleHandleA` and `LoadLibraryA`), so an + /// extern-data symbol in an already-loaded module resolves. 0 + /// means unresolved and the caller errors. #[cfg(target_os = "windows")] fn resolve_symbol(&self, name: &str) -> u64 { let cs = match CString::new(name) { Ok(cs) => cs, Err(_) => return 0, }; - for &h in &self.lib_handles { + for &(h, _) in &self.lib_handles { let a = unsafe { GetProcAddress(h, cs.as_ptr()) } as u64; if a != 0 { return a; @@ -1411,7 +1416,7 @@ mod jit_impl { fn munmap(addr: *mut c_void, len: usize) -> c_int; fn dlclose(handle: *mut c_void) -> c_int; } - for &h in &self.lib_handles { + for &(h, _) in &self.lib_handles { if !h.is_null() { dlclose(h); } @@ -1420,8 +1425,10 @@ mod jit_impl { } #[cfg(target_os = "windows")] unsafe { - for &h in &self.lib_handles { - if !h.is_null() { + // Release only owned handles; a `GetModuleHandleA` handle + // carries no refcount to drop. + for &(h, owned) in &self.lib_handles { + if owned && !h.is_null() { FreeLibrary(h); } } diff --git a/src/c5/tests/codegen.rs b/src/c5/tests/codegen.rs index 7b2942856..c83b5f7ee 100644 --- a/src/c5/tests/codegen.rs +++ b/src/c5/tests/codegen.rs @@ -231,6 +231,38 @@ fn environ_data_binding_records_copy_relocation() { ); } +/// POSIX `setenv` carries a third `overwrite` argument that msvcrt's +/// 2-parameter `_putenv_s` lacks, so `` must leave `setenv` +/// unbound on Windows -- resolved by the runtime shim that honors the +/// flag -- rather than binding it straight to `_putenv_s` (which drops +/// `overwrite`). The object for a `setenv`-calling TU must therefore +/// reference `setenv` as an undefined symbol and carry no `_putenv_s` +/// import of its own. +#[test] +fn setenv_left_unbound_for_runtime_shim_on_windows() { + use crate::{Compiler, NativeOptions, OutputKind, Target, emit_native_with_options}; + let program = Compiler::with_target( + "#include \nint main(void){ setenv(\"K\", \"V\", 0); return 0; }".to_string(), + Target::WindowsX64, + ) + .compile() + .expect("compile setenv TU for WindowsX64"); + let opts = NativeOptions { + output_kind: OutputKind::Relocatable, + ..NativeOptions::default() + }; + let obj = emit_native_with_options(&program, Target::WindowsX64, opts).expect("emit"); + let contains = |needle: &[u8]| obj.windows(needle.len()).any(|w| w == needle); + assert!( + contains(b"setenv"), + "setenv must reach the object as an undefined symbol for the runtime shim to satisfy" + ); + assert!( + !contains(b"_putenv_s"), + "setenv must not be bound directly to _putenv_s (the overwrite flag would be dropped)" + ); +} + /// A `#pragma binding(data lib::sym, ...)` import on the Windows /// x86-64 PE target must lower the data reference as a load of the /// import's IAT slot, not as the address of a `jmp [IAT]` call diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index 1be2a7cf6..42cc8b620 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -753,6 +753,7 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("type_warning_silenced_by_cast.c", 0), ("type_warning_arity.c", 0), ("setenv_then_get.c", 'Z' as i32), + ("setenv_overwrite.c", 0), // Runtime dynamic linking. Opens the global symbol table, // resolves libc atoi via dlsym, calls it through indirect call // (which loads args into x0..x7 in case the target is native), diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index cc168614e..ebae6e738 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -474,6 +474,7 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("type_warning_silenced_by_cast.c", 0), ("type_warning_arity.c", 0), ("setenv_then_get.c", 'Z' as i32), + ("setenv_overwrite.c", 0), // Runtime dynamic linking through libdl (libdl.so.2 + // libc.so.6 are both DT_NEEDED). dlopen+dlsym+blr finds // libc atoi and the indirect call passes "123" in x0. diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index dba830710..813dca53d 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -425,6 +425,7 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("type_warning_silenced_by_cast.c", 0), ("type_warning_arity.c", 0), ("setenv_then_get.c", 'Z' as i32), + ("setenv_overwrite.c", 0), ("dlopen_atoi.c", 123), ("dlopen_strlen.c", 13), // Multi-arg dlsym call path. glibc 2.34+ folded pthread into diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index 87a04eedf..84ffaf3f3 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -622,6 +622,9 @@ const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ ("arithmetic.c", 60), ("strtof_parses_float.c", 0), ("snprintf_truncation_c99.c", 0), + // Runtime CRT shim: POSIX setenv overwrite semantics over msvcrt's + // 2-parameter _putenv_s. + ("setenv_overwrite.c", 0), ("control_flow.c", 1), ("do_while.c", 5), ("break_continue.c", 4), diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index a3c4c86dc..82a2b967d 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -635,6 +635,9 @@ const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ ("arithmetic.c", 60), ("strtof_parses_float.c", 0), ("snprintf_truncation_c99.c", 0), + // Runtime CRT shim: POSIX setenv overwrite semantics over msvcrt's + // 2-parameter _putenv_s. + ("setenv_overwrite.c", 0), ("control_flow.c", 1), ("do_while.c", 5), ("break_continue.c", 4), diff --git a/src/main.rs b/src/main.rs index 5ae2f0520..5688468d4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -696,7 +696,7 @@ fn run() { { sources.push("-".to_string()); } - if sources.is_empty() && objects.is_empty() { + if sources.is_empty() && objects.is_empty() && archives.is_empty() { eprint_diagnostic("badc: error: no files"); std::process::exit(1); } @@ -1035,23 +1035,17 @@ fn run() { } // A freestanding image must supply its own entry symbol; the // embedded runtime that would otherwise define `__c5_entry` is - // not linked. Report a missing entry here rather than as a bare - // undefined-symbol relocation at link time. - if freestanding { - let entry = entry_override.as_deref().unwrap_or("__c5_entry"); - let defined = native_objs.iter().any(|o| { - o.symbols - .iter() - .any(|s| s.name == entry && s.section == badc::NativeSymSection::Text) - }); - if !defined { - eprint_diagnostic(format!( - "badc: error: --freestanding: image entry `{entry}` is not defined; \ - a freestanding image must provide its own entry point" - )); - std::process::exit(1); - } - } + // not linked. The entry may come from any input -- a compiled + // source, a `.o`, or an archive member -- so the defined-entry + // check runs below, after objects and archive members are + // parsed, rather than as a bare undefined-symbol relocation at + // link time. + let freestanding_entry = freestanding.then(|| { + entry_override + .as_deref() + .unwrap_or("__c5_entry") + .to_string() + }); // The runtime's CRT section (the C99 snprintf / vsnprintf // definitions on Windows) links into any image that may // import the user-mode C library -- hosted executables and @@ -1268,6 +1262,13 @@ fn run() { for o in &native_objs { account(o, &mut defined, &mut undefined); } + // A freestanding entry is a link root: seed it as undefined + // so an archive member that only defines the entry is pulled. + if let Some(entry) = &freestanding_entry { + if !defined.contains(entry) { + undefined.insert(entry.clone()); + } + } // The archive symbol index lists strong section-resident // definitions; a member is pulled on exactly those. let mut progress = true; @@ -1298,6 +1299,22 @@ fn run() { eprint_diagnostic("badc: error: no inputs"); std::process::exit(1); } + // With every source, object, and pulled archive member now + // parsed, a freestanding image's entry must be defined. + if let Some(entry) = &freestanding_entry { + let defined = native_objs.iter().any(|o| { + o.symbols + .iter() + .any(|s| s.name == *entry && s.section == badc::NativeSymSection::Text) + }); + if !defined { + eprint_diagnostic(format!( + "badc: error: --freestanding: image entry `{entry}` is not defined; \ + a freestanding image must provide its own entry point" + )); + std::process::exit(1); + } + } // Every supported target lays out `_Thread_local` storage // through the native path: ELF PT_TLS, the PE TLS directory + // `_tls_index` note, and the Mach-O TLV descriptors + fixups diff --git a/tests/cli_linker_smoke.rs b/tests/cli_linker_smoke.rs index 6b509b11b..c8a7277b7 100644 --- a/tests/cli_linker_smoke.rs +++ b/tests/cli_linker_smoke.rs @@ -190,6 +190,94 @@ fn archive_members_are_pulled_on_demand() { ); } +// An archive-only invocation is a valid link: the members supply the +// objects and `main` is pulled by the runtime's reference to it. The +// input-emptiness check must count archives, not just sources/objects. +#[cfg(target_os = "linux")] +#[test] +fn archive_only_invocation_links_and_pulls_main() { + let dir = tempdir("archive-only"); + write_source(&dir, "prog.c", "int main(void) { return 7; }\n"); + run( + Command::new(badc()) + .arg("--ar") + .arg("-o") + .arg(dir.join("libprog.a")) + .arg(dir.join("prog.c")) + .current_dir(&dir), + "build archive", + ); + let exe = dir.join("prog"); + run( + Command::new(badc()) + .arg("-o") + .arg(&exe) + .arg(dir.join("libprog.a")) + .current_dir(&dir), + "link archive-only", + ); + let out = Command::new(&exe).output().expect("run prog"); + assert_eq!(out.status.code(), Some(7), "exit code mismatch"); +} + +// A freestanding image's entry may live in a pre-compiled object; the +// defined-entry check must run after `.o` inputs are parsed, not before. +#[cfg(target_os = "linux")] +#[test] +fn freestanding_entry_defined_in_object_links() { + let dir = tempdir("freestanding-obj"); + write_source(&dir, "fs.c", "void __c5_entry(void) { }\n"); + run( + Command::new(badc()) + .arg("-c") + .arg(dir.join("fs.c")) + .arg("-o") + .arg(dir.join("fs.o")) + .current_dir(&dir), + "compile -c", + ); + let bin = dir.join("fs.bin"); + run( + Command::new(badc()) + .arg("--freestanding") + .arg(dir.join("fs.o")) + .arg("-o") + .arg(&bin) + .current_dir(&dir), + "freestanding link with entry in object", + ); + assert!(bin.exists(), "freestanding image was not produced"); +} + +// The freestanding entry is a link root: an archive member that only +// defines the entry must be pulled so the image links. +#[cfg(target_os = "linux")] +#[test] +fn freestanding_entry_from_archive_is_pulled() { + let dir = tempdir("freestanding-archive"); + write_source(&dir, "fs.c", "void __c5_entry(void) { }\n"); + run( + Command::new(badc()) + .arg("--ar") + .arg("-o") + .arg(dir.join("libfs.a")) + .arg(dir.join("fs.c")) + .current_dir(&dir), + "build archive", + ); + let bin = dir.join("fs.bin"); + run( + Command::new(badc()) + .arg("--freestanding") + .arg(dir.join("libfs.a")) + .arg("-o") + .arg(&bin) + .current_dir(&dir), + "freestanding link with entry in archive", + ); + assert!(bin.exists(), "freestanding image was not produced"); +} + #[test] fn compile_only_warns_when_link_pragmas_are_dropped() { // `#pragma subsystem` / `#pragma entrypoint` ride the in-memory diff --git a/tests/fixtures/c/setenv_overwrite.c b/tests/fixtures/c/setenv_overwrite.c new file mode 100644 index 000000000..0dc374c2e --- /dev/null +++ b/tests/fixtures/c/setenv_overwrite.c @@ -0,0 +1,16 @@ +#include + +// POSIX setenv (IEEE Std 1003.1): overwrite==0 leaves an existing +// binding untouched; overwrite!=0 replaces it. Verified through getenv. +int main(void) { + setenv("BADC_T_SETENV_OW", "first", 1); + setenv("BADC_T_SETENV_OW", "second", 0); /* must not clobber */ + if (getenv("BADC_T_SETENV_OW")[0] != 'f') { + return 1; + } + setenv("BADC_T_SETENV_OW", "third", 1); /* must clobber */ + if (getenv("BADC_T_SETENV_OW")[0] != 't') { + return 2; + } + return 0; +} From cffc32b691728c6e181c0ecf74e9d923a0604f52 Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 00:31:43 -0700 Subject: [PATCH 54/67] tests: snapshots for the M1/M5 medium fixes Co-Authored-By: Claude Fable 5 --- .../asm/float_ternary_promote.aarch64.asm | 150 +++++++++++++ .../asm/float_ternary_promote.x64.asm | 181 ++++++++++++++++ .../asm/fp_param_ternary.aarch64.asm | 27 +-- tests/snapshots/asm/fp_param_ternary.x64.asm | 24 +-- .../asm/setenv_overwrite.aarch64.asm | 70 +++++++ tests/snapshots/asm/setenv_overwrite.x64.asm | 55 +++++ tests/snapshots/ssa/float_ternary_promote.ssa | 197 ++++++++++++++++++ tests/snapshots/ssa/fp_param_ternary.ssa | 81 ++++--- tests/snapshots/ssa/setenv_overwrite.ssa | 86 ++++++++ 9 files changed, 791 insertions(+), 80 deletions(-) create mode 100644 tests/snapshots/asm/float_ternary_promote.aarch64.asm create mode 100644 tests/snapshots/asm/float_ternary_promote.x64.asm create mode 100644 tests/snapshots/asm/setenv_overwrite.aarch64.asm create mode 100644 tests/snapshots/asm/setenv_overwrite.x64.asm create mode 100644 tests/snapshots/ssa/float_ternary_promote.ssa create mode 100644 tests/snapshots/ssa/setenv_overwrite.ssa diff --git a/tests/snapshots/asm/float_ternary_promote.aarch64.asm b/tests/snapshots/asm/float_ternary_promote.aarch64.asm new file mode 100644 index 000000000..5000596d4 --- /dev/null +++ b/tests/snapshots/asm/float_ternary_promote.aarch64.asm @@ -0,0 +1,150 @@ + +float_ternary_promote.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x20 + sxtw x0, w0 + fmov d2, d0 + cbz x0, + b + fmov d2, d1 + fmov d0, d2 + add sp, sp, #0x20 + ldp x29, x30, [sp], #0x10 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x60 + str d8, [sp] + str x20, [sp, #0x10] + mov x0, #0x1 // =1 + mov x20, #0x3ff8000000000000 // =4609434218613702656 + fmov d16, x20 + fcvt s0, d16 + mov x1, #0x4004000000000000 // =4612811918334230528 + fmov d16, x1 + fneg d1, d16 + fcvt s1, d1 + bl + fcvt d0, s0 + fmov d17, x20 + fcmp d0, d17 + cset x0, ne + cbz x0, + mov x0, #0x1 // =1 + ldr x20, [sp, #0x10] + ldr d8, [sp] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + mov x1, #0x3ff8000000000000 // =4609434218613702656 + fmov d16, x1 + fcvt s0, d16 + mov x1, #0x4004000000000000 // =4612811918334230528 + fmov d16, x1 + fneg d8, d16 + fcvt s1, d8 + bl + fcvt d0, s0 + fcmp d0, d8 + cset x0, ne + cbz x0, + mov x0, #0x2 // =2 + ldr x20, [sp, #0x10] + ldr d8, [sp] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x400a000000000000 // =4614500768194494464 + fmov d16, x0 + fcvt s2, d16 + mov x0, #0x0 // =0 + fcvt d0, s2 + fmov d17, x0 + fcmp d0, d17 + cset x0, gt + cbz x0, + fmov d0, d2 + b + fneg s0, s2 + mov x0, #0x0 // =0 + fcvt d1, s2 + fmov d17, x0 + fcmp d1, d17 + cset x0, mi + cbz x0, + fneg s2, s2 + b + fadd s0, s0, s2 + mov x0, #0x401a000000000000 // =4619004367821864960 + fcvt d0, s0 + fmov d17, x0 + fcmp d0, d17 + cset x0, ne + cbz x0, + mov x0, #0x3 // =3 + ldr x20, [sp, #0x10] + ldr d8, [sp] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x2 // =2 + cmp x0, #0x0 + b.ne + mov x0, #0x0 // =0 + fmov d16, x0 + sub x17, x29, #0x38 + str d16, [x17] + b + cmp x0, #0x1 + b.ne + b + sub x16, x29, #0x38 + ldr d0, [x16] + fcvt s0, d0 + mov x0, #0x4034000000000000 // =4626322717216342016 + fcvt d0, s0 + fmov d17, x0 + fcmp d0, d17 + cset x0, ne + cbz x0, + b + mov x0, #0x4024000000000000 // =4621819117588971520 + fmov d16, x0 + sub x17, x29, #0x40 + str d16, [x17] + b + mov x0, #0x4034000000000000 // =4626322717216342016 + fmov d16, x0 + sub x17, x29, #0x40 + str d16, [x17] + sub x16, x29, #0x40 + ldr d0, [x16] + sub x17, x29, #0x38 + str d0, [x17] + b + mov x0, #0x4 // =4 + ldr x20, [sp, #0x10] + ldr d8, [sp] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldr x20, [sp, #0x10] + ldr d8, [sp] + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/float_ternary_promote.x64.asm b/tests/snapshots/asm/float_ternary_promote.x64.asm new file mode 100644 index 000000000..4baa9b1e4 --- /dev/null +++ b/tests/snapshots/asm/float_ternary_promote.x64.asm @@ -0,0 +1,181 @@ + +float_ternary_promote.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + pushq %rbp + movq %rsp, %rbp + subq $0x20, %rsp + movslq %edi, %rdi + movapd %xmm0, %xmm2 + testq %rdi, %rdi + je + jmp + movapd %xmm1, %xmm2 + movapd %xmm2, %xmm0 + addq $0x20, %rsp + popq %rbp + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x60, %rsp + movq %rbx, (%rsp) + movl $0x1, %edi + movabsq $0x3ff8000000000000, %rbx # imm = 0x3FF8000000000000 + movq %rbx, %xmm14 + cvtsd2ss %xmm14, %xmm0 + movabsq $0x4004000000000000, %rax # imm = 0x4004000000000000 + movq %rax, %xmm1 + movabsq $-0x8000000000000000, %r10 # imm = 0x8000000000000000 + movq %r10, %xmm15 + xorpd %xmm15, %xmm1 + cvtsd2ss %xmm1, %xmm1 + callq + cvtss2sd %xmm0, %xmm0 + movq %rbx, %xmm15 + ucomisd %xmm15, %xmm0 + setne %al + movzbq %al, %rax + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rax + testq %rax, %rax + je + movl $0x1, %eax + movq (%rsp), %rbx + addq $0x60, %rsp + popq %rbp + retq + xorq %rdi, %rdi + movabsq $0x3ff8000000000000, %rax # imm = 0x3FF8000000000000 + movq %rax, %xmm14 + cvtsd2ss %xmm14, %xmm0 + movabsq $0x4004000000000000, %rax # imm = 0x4004000000000000 + movq %rax, %xmm14 + movabsq $-0x8000000000000000, %r10 # imm = 0x8000000000000000 + movq %r10, %xmm15 + xorpd %xmm15, %xmm14 + movsd %xmm14, 0x18(%rsp) + movsd 0x18(%rsp), %xmm14 + cvtsd2ss %xmm14, %xmm1 + callq + cvtss2sd %xmm0, %xmm0 + movsd 0x18(%rsp), %xmm15 + ucomisd %xmm15, %xmm0 + setne %al + movzbq %al, %rax + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rax + testq %rax, %rax + je + movl $0x2, %eax + movq (%rsp), %rbx + addq $0x60, %rsp + popq %rbp + retq + movabsq $0x400a000000000000, %rax # imm = 0x400A000000000000 + movq %rax, %xmm14 + cvtsd2ss %xmm14, %xmm2 + xorq %rax, %rax + cvtss2sd %xmm2, %xmm0 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + seta %al + movzbq %al, %rax + testq %rax, %rax + je + movapd %xmm2, %xmm0 + jmp + movapd %xmm2, %xmm0 + movl $0x80000000, %r10d # imm = 0x80000000 + movq %r10, %xmm15 + xorpd %xmm15, %xmm0 + xorq %rax, %rax + cvtss2sd %xmm2, %xmm1 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm1 + setb %al + movzbq %al, %rax + setnp %r10b + movzbq %r10b, %r10 + andq %r10, %rax + testq %rax, %rax + je + movl $0x80000000, %r10d # imm = 0x80000000 + movq %r10, %xmm15 + xorpd %xmm15, %xmm2 + jmp + addss %xmm2, %xmm0 + movabsq $0x401a000000000000, %rax # imm = 0x401A000000000000 + cvtss2sd %xmm0, %xmm0 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %al + movzbq %al, %rax + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rax + testq %rax, %rax + je + movl $0x3, %eax + movq (%rsp), %rbx + addq $0x60, %rsp + popq %rbp + retq + movl $0x2, %eax + testq %rax, %rax + jne + xorq %rax, %rax + movq %rax, %xmm14 + movsd %xmm14, -0x38(%rbp,%riz) + jmp + cmpq $0x1, %rax + jne + jmp + movsd -0x38(%rbp,%riz), %xmm0 + cvtsd2ss %xmm0, %xmm0 + movabsq $0x4034000000000000, %rax # imm = 0x4034000000000000 + cvtss2sd %xmm0, %xmm0 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %al + movzbq %al, %rax + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rax + testq %rax, %rax + je + jmp + movabsq $0x4024000000000000, %rax # imm = 0x4024000000000000 + movq %rax, %xmm14 + movsd %xmm14, -0x40(%rbp,%riz) + jmp + movabsq $0x4034000000000000, %rax # imm = 0x4034000000000000 + movq %rax, %xmm14 + movsd %xmm14, -0x40(%rbp,%riz) + movsd -0x40(%rbp,%riz), %xmm0 + movsd %xmm0, -0x38(%rbp,%riz) + jmp + movl $0x4, %eax + movq (%rsp), %rbx + addq $0x60, %rsp + popq %rbp + retq + xorq %rax, %rax + movq (%rsp), %rbx + addq $0x60, %rsp + popq %rbp + retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/fp_param_ternary.aarch64.asm b/tests/snapshots/asm/fp_param_ternary.aarch64.asm index c4fdb65a7..f6301b43a 100644 --- a/tests/snapshots/asm/fp_param_ternary.aarch64.asm +++ b/tests/snapshots/asm/fp_param_ternary.aarch64.asm @@ -14,17 +14,13 @@ Disassembly of section .text: mov x29, sp sub sp, sp, #0x10 sxtw x0, w0 + fmov d1, d0 mov x17, #0x1 // =1 and x0, x0, x17 cbz x0, - sub x0, x29, #0x10 - str s0, [x0] b - fneg s0, s0 - sub x0, x29, #0x10 - str s0, [x0] - sub x16, x29, #0x10 - ldr s0, [x16] + fneg s1, s1 + fmov d0, d1 add sp, sp, #0x10 ldp x29, x30, [sp], #0x10 ret @@ -34,29 +30,18 @@ Disassembly of section .text: mov x29, sp sub sp, sp, #0x30 sxtw x0, w0 + fmov d2, d0 mov x17, #0x1 // =1 and x1, x0, x17 cbz x1, - sub x1, x29, #0x28 - str s0, [x1] b - fneg s0, s0 - sub x1, x29, #0x28 - str s0, [x1] - sub x16, x29, #0x28 - ldr s0, [x16] + fneg s2, s2 mov x17, #0x2 // =2 and x0, x0, x17 cbz x0, - sub x0, x29, #0x30 - str s1, [x0] b fneg s1, s1 - sub x0, x29, #0x30 - str s1, [x0] - sub x16, x29, #0x30 - ldr s1, [x16] - fadd s0, s0, s1 + fadd s0, s2, s1 add sp, sp, #0x30 ldp x29, x30, [sp], #0x10 ret diff --git a/tests/snapshots/asm/fp_param_ternary.x64.asm b/tests/snapshots/asm/fp_param_ternary.x64.asm index fba209ac9..69f2cee19 100644 --- a/tests/snapshots/asm/fp_param_ternary.x64.asm +++ b/tests/snapshots/asm/fp_param_ternary.x64.asm @@ -15,19 +15,16 @@ Disassembly of section .text: movq %rsp, %rbp subq $0x10, %rsp movslq %edi, %rdi + movapd %xmm0, %xmm1 movq %rdi, %rax andq $0x1, %rax testq %rax, %rax je - leaq -0x10(%rbp), %rax - movss %xmm0, (%rax,%riz) jmp movl $0x80000000, %r10d # imm = 0x80000000 movq %r10, %xmm15 - xorpd %xmm15, %xmm0 - leaq -0x10(%rbp), %rax - movss %xmm0, (%rax,%riz) - movss -0x10(%rbp,%riz), %xmm0 + xorpd %xmm15, %xmm1 + movapd %xmm1, %xmm0 addq $0x10, %rsp popq %rbp retq @@ -37,32 +34,24 @@ Disassembly of section .text: movq %rsp, %rbp subq $0x30, %rsp movslq %edi, %rdi + movapd %xmm0, %xmm2 movq %rdi, %rax andq $0x1, %rax testq %rax, %rax je - leaq -0x28(%rbp), %rax - movss %xmm0, (%rax,%riz) jmp movl $0x80000000, %r10d # imm = 0x80000000 movq %r10, %xmm15 - xorpd %xmm15, %xmm0 - leaq -0x28(%rbp), %rax - movss %xmm0, (%rax,%riz) - movss -0x28(%rbp,%riz), %xmm0 + xorpd %xmm15, %xmm2 movq %rdi, %rax andq $0x2, %rax testq %rax, %rax je - leaq -0x30(%rbp), %rax - movss %xmm1, (%rax,%riz) jmp movl $0x80000000, %r10d # imm = 0x80000000 movq %r10, %xmm15 xorpd %xmm15, %xmm1 - leaq -0x30(%rbp), %rax - movss %xmm1, (%rax,%riz) - movss -0x30(%rbp,%riz), %xmm1 + movapd %xmm2, %xmm0 addss %xmm1, %xmm0 addq $0x30, %rsp popq %rbp @@ -255,3 +244,4 @@ Disassembly of section .text: addq $0x10, %rsp popq %rbp retq + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/setenv_overwrite.aarch64.asm b/tests/snapshots/asm/setenv_overwrite.aarch64.asm new file mode 100644 index 000000000..af5842795 --- /dev/null +++ b/tests/snapshots/asm/setenv_overwrite.aarch64.asm @@ -0,0 +1,70 @@ + +setenv_overwrite.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x2b0 // =688 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x10 + str x19, [sp] + adrp x0, + add x0, x0, + adrp x1, + add x1, x1, + mov x2, #0x1 // =1 + bl + sxtw x0, w0 + adrp x0, + add x0, x0, + adrp x1, + add x1, x1, + mov x2, #0x0 // =0 + bl + sxtw x0, w0 + adrp x0, + add x0, x0, + bl + ldrb w0, [x0] + mov x17, #0x66 // =102 + eor x0, x0, x17 + mov w0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x1 // =1 + ldr x19, [sp] + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + adrp x0, + add x0, x0, + adrp x1, + add x1, x1, + mov x2, #0x1 // =1 + bl + sxtw x0, w0 + adrp x0, + add x0, x0, + bl + ldrb w0, [x0] + mov x17, #0x74 // =116 + eor x0, x0, x17 + mov w0, w0 + cmp x0, #0x0 + b.eq + mov x0, #0x2 // =2 + ldr x19, [sp] + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldr x19, [sp] + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/setenv_overwrite.x64.asm b/tests/snapshots/asm/setenv_overwrite.x64.asm new file mode 100644 index 000000000..0efbb701a --- /dev/null +++ b/tests/snapshots/asm/setenv_overwrite.x64.asm @@ -0,0 +1,55 @@ + +setenv_overwrite.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + leaq , %rdi + leaq , %rsi + movl $0x1, %edx + xorl %eax, %eax + callq + movslq %eax, %rax + leaq , %rdi + leaq , %rsi + xorq %rdx, %rdx + xorl %eax, %eax + callq + movslq %eax, %rax + leaq , %rdi + xorl %eax, %eax + callq + movsbq (%rax), %rax + cmpq $0x66, %rax + je + movl $0x1, %eax + popq %rbp + retq + leaq , %rdi + leaq , %rsi + movl $0x1, %edx + xorl %eax, %eax + callq + movslq %eax, %rax + leaq , %rdi + xorl %eax, %eax + callq + movsbq (%rax), %rax + cmpq $0x74, %rax + je + movl $0x2, %eax + popq %rbp + retq + xorq %rax, %rax + popq %rbp + retq + addb %al, (%rax) diff --git a/tests/snapshots/ssa/float_ternary_promote.ssa b/tests/snapshots/ssa/float_ternary_promote.ssa new file mode 100644 index 000000000..4d9fc570f --- /dev/null +++ b/tests/snapshots/ssa/float_ternary_promote.ssa @@ -0,0 +1,197 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=sel +fn ent_pc=0 n_params=3 variadic=false locals=4 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=F32) -> d2 [f32] + v4 Imm(0) -> x0 + v5 ParamRef(2, kind=F32) -> d1 [f32] + v6 Imm(0) -> x0 + v7 LoadLocal { off=2, kind=I32 } -> x0 + terminator Bz { cond=v1, target=b2, fall=b1 } (exit_acc=v1) + block 1 start_pc=0 + v8 LoadLocal { off=-1, kind=F32 } -> d0 [f32] + v9 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v3) + block 2 start_pc=0 + v10 LoadLocal { off=-2, kind=F32 } -> d0 [f32] + v11 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v5) + block 3 start_pc=0 + v12 Phi { incoming=[b1:v3, b2:v5], kind=F32 } -> d2 [f32] + v13 LoadLocal { off=-4, kind=F32 } -> d0 [f32] + v14 Imm(0) -> x0 + v15 LoadLocal { off=-3, kind=F32 } -> d0 [f32] + terminator Return(v12) (exit_acc=v12) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=8 + spill_count=1 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(1) -> x7 + v2 Imm(4609434218613702656) -> x3 + v3 FpCast { kind=F64ToF32, value=v2 } -> d0 [f32] + v4 Imm(4612811918334230528) -> x0 + v5 Fneg(v4) -> d1 + v6 FpCast { kind=F64ToF32, value=v5 } -> d1 [f32] + v7 Call { target_pc=0, args=[v1, v3, v6], fixed_args=3, fp_return=true, fp_arg_mask=0x6 } -> d0 [f32] + v8 FpCast { kind=F32ToF64, value=v7 } -> d0 + v9 Binop { op=fne, lhs=v8, rhs=v2 } -> x0 + terminator Bz { cond=v9, target=b2, fall=b1 } (exit_acc=v9) + block 1 start_pc=0 + v10 Imm(1) -> x0 + terminator Return(v10) (exit_acc=v10) + block 2 start_pc=0 + v11 Imm(0) -> x7 + v12 Imm(4609434218613702656) -> x0 + v13 FpCast { kind=F64ToF32, value=v12 } -> d0 [f32] + v14 Imm(4612811918334230528) -> x0 + v15 Fneg(v14) -> [spill 0] + v16 FpCast { kind=F64ToF32, value=v15 } -> d1 [f32] + v17 Call { target_pc=0, args=[v11, v13, v16], fixed_args=3, fp_return=true, fp_arg_mask=0x6 } -> d0 [f32] + v18 FpCast { kind=F32ToF64, value=v17 } -> d0 + v19 Binop { op=fne, lhs=v18, rhs=v15 } -> x0 + terminator Bz { cond=v19, target=b4, fall=b3 } (exit_acc=v19) + block 3 start_pc=0 + v20 Imm(2) -> x0 + terminator Return(v20) (exit_acc=v20) + block 4 start_pc=0 + v21 Imm(4614500768194494464) -> x0 + v22 FpCast { kind=F64ToF32, value=v21 } -> d2 [f32] + v23 Imm(0) -> x0 + v24 LoadLocal { off=-1, kind=F32 } -> d0 [f32] + v25 Imm(0) -> x0 + v26 FpCast { kind=F32ToF64, value=v22 } -> d0 + v27 Binop { op=fgt, lhs=v26, rhs=v25 } -> x0 + terminator Bz { cond=v27, target=b6, fall=b5 } (exit_acc=v27) + block 5 start_pc=0 + v28 LoadLocal { off=-1, kind=F32 } -> d0 [f32] + v29 Imm(0) -> x0 + terminator Jmp(b7) (exit_acc=v22) + block 6 start_pc=0 + v30 LoadLocal { off=-1, kind=F32 } -> d0 [f32] + v31 Fneg(v22) -> d0 [f32] + v32 Imm(0) -> x0 + terminator Jmp(b7) (exit_acc=v31) + block 7 start_pc=0 + v33 Phi { incoming=[b5:v22, b6:v31], kind=F32 } -> d0 [f32] + v34 LoadLocal { off=-5, kind=F32 } -> d1 [f32] + v35 LoadLocal { off=-1, kind=F32 } -> d1 [f32] + v36 Imm(0) -> x0 + v37 FpCast { kind=F32ToF64, value=v22 } -> d1 + v38 Binop { op=flt, lhs=v37, rhs=v36 } -> x0 + terminator Bz { cond=v38, target=b9, fall=b8 } (exit_acc=v38) + block 8 start_pc=0 + v39 LoadLocal { off=-1, kind=F32 } -> d1 [f32] + v40 Fneg(v22) -> d2 [f32] + v41 Imm(0) -> x0 + terminator Jmp(b10) (exit_acc=v40) + block 9 start_pc=0 + v42 LoadLocal { off=-1, kind=F32 } -> d1 [f32] + v43 Imm(0) -> x0 + terminator Jmp(b10) (exit_acc=v22) + block 10 start_pc=0 + v44 Phi { incoming=[b8:v40, b9:v22], kind=F32 } -> d2 [f32] + v45 LoadLocal { off=-6, kind=F32 } -> d1 [f32] + v46 Binop { op=fadd, lhs=v33, rhs=v44 } -> d0 [f32] + v47 Imm(0) -> x0 + v48 LoadLocal { off=-2, kind=F32 } -> d1 [f32] + v49 Imm(4619004367821864960) -> x0 + v50 FpCast { kind=F32ToF64, value=v46 } -> d0 + v51 Binop { op=fne, lhs=v50, rhs=v49 } -> x0 + terminator Bz { cond=v51, target=b12, fall=b11 } (exit_acc=v51) + block 11 start_pc=0 + v52 Imm(3) -> x0 + terminator Return(v52) (exit_acc=v52) + block 12 start_pc=0 + v53 Imm(2) -> x0 + v54 Imm(0) -> x1 + v55 LoadLocal { off=-3, kind=I32 } -> x1 + v56 BinopI { op=eq, lhs=v53, rhs_imm=0 } -> x1 + terminator Bz { cond=v56, target=b14, fall=b13 } (exit_acc=v56) + block 13 start_pc=0 + v57 Imm(0) -> x0 + v58 StoreLocal { off=-7, value=v57, kind=F64 } -> - + terminator Jmp(b15) (exit_acc=v58) + block 14 start_pc=0 + v59 LoadLocal { off=-3, kind=I32 } -> x1 + v60 BinopI { op=eq, lhs=v53, rhs_imm=1 } -> x0 + terminator Bz { cond=v60, target=b17, fall=b16 } (exit_acc=v60) + block 15 start_pc=0 + v61 LoadLocal { off=-7, kind=F64 } -> d0 + v62 FpCast { kind=F64ToF32, value=v61 } -> d0 [f32] + v63 Imm(0) -> x0 + v64 LoadLocal { off=-4, kind=F32 } -> d1 [f32] + v65 Imm(4626322717216342016) -> x0 + v66 FpCast { kind=F32ToF64, value=v62 } -> d0 + v67 Binop { op=fne, lhs=v66, rhs=v65 } -> x0 + terminator Bz { cond=v67, target=b20, fall=b19 } (exit_acc=v67) + block 16 start_pc=0 + v68 Imm(4621819117588971520) -> x0 + v69 StoreLocal { off=-8, value=v68, kind=F64 } -> - + terminator Jmp(b18) (exit_acc=v69) + block 17 start_pc=0 + v70 Imm(4626322717216342016) -> x0 + v71 StoreLocal { off=-8, value=v70, kind=F64 } -> - + terminator Jmp(b18) (exit_acc=v71) + block 18 start_pc=0 + v72 LoadLocal { off=-8, kind=F64 } -> d0 + v73 StoreLocal { off=-7, value=v72, kind=F64 } -> - + terminator Jmp(b15) (exit_acc=v73) + block 19 start_pc=0 + v74 Imm(4) -> x0 + terminator Return(v74) (exit_acc=v74) + block 20 start_pc=0 + v75 Imm(0) -> x0 + terminator Return(v75) (exit_acc=v75) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/fp_param_ternary.ssa b/tests/snapshots/ssa/fp_param_ternary.ssa index 744c939c7..c239b7da6 100644 --- a/tests/snapshots/ssa/fp_param_ternary.ssa +++ b/tests/snapshots/ssa/fp_param_ternary.ssa @@ -6,25 +6,24 @@ fn ent_pc=1 n_params=2 variadic=false locals=2 v0 AllocaInit(0) -> - v1 ParamRef(0, kind=I32) -> x7 v2 Imm(0) -> x0 - v3 ParamRef(1, kind=F32) -> d0 [f32] + v3 ParamRef(1, kind=F32) -> d1 [f32] v4 Imm(0) -> x0 v5 LoadLocal { off=2, kind=I32 } -> x0 v6 BinopI { op=and, lhs=v1, rhs_imm=1 } -> x0 terminator Bz { cond=v6, target=b2, fall=b1 } (exit_acc=v6) block 1 start_pc=0 - v7 LoadLocal { off=-1, kind=F32 } -> d1 [f32] - v8 LocalAddr(-2) -> x0 - v9 Store { addr=v8, disp=0, value=v3, kind=F32 } -> - - terminator Jmp(b3) (exit_acc=v9) + v7 LoadLocal { off=-1, kind=F32 } -> d0 [f32] + v8 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v3) block 2 start_pc=0 - v10 LoadLocal { off=-1, kind=F32 } -> d1 [f32] - v11 Fneg(v3) -> d0 [f32] - v12 LocalAddr(-2) -> x0 - v13 Store { addr=v12, disp=0, value=v11, kind=F32 } -> - - terminator Jmp(b3) (exit_acc=v13) + v9 LoadLocal { off=-1, kind=F32 } -> d0 [f32] + v10 Fneg(v3) -> d1 [f32] + v11 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v10) block 3 start_pc=0 - v14 LoadLocal { off=-2, kind=F32 } -> d0 [f32] - terminator Return(v14) (exit_acc=v14) + v12 Phi { incoming=[b1:v3, b2:v10], kind=F32 } -> d1 [f32] + v13 LoadLocal { off=-2, kind=F32 } -> d0 [f32] + terminator Return(v12) (exit_acc=v12) ; --- SSA dump (ok=true) ent_pc=2 --- ; name=grad_dot fn ent_pc=2 n_params=3 variadic=false locals=6 @@ -33,7 +32,7 @@ fn ent_pc=2 n_params=3 variadic=false locals=6 v0 AllocaInit(0) -> - v1 ParamRef(0, kind=I32) -> x7 v2 Imm(0) -> x0 - v3 ParamRef(1, kind=F32) -> d0 [f32] + v3 ParamRef(1, kind=F32) -> d2 [f32] v4 Imm(0) -> x0 v5 ParamRef(2, kind=F32) -> d1 [f32] v6 Imm(0) -> x0 @@ -41,40 +40,38 @@ fn ent_pc=2 n_params=3 variadic=false locals=6 v8 BinopI { op=and, lhs=v1, rhs_imm=1 } -> x0 terminator Bz { cond=v8, target=b2, fall=b1 } (exit_acc=v8) block 1 start_pc=0 - v9 LoadLocal { off=-1, kind=F32 } -> d2 [f32] - v10 LocalAddr(-5) -> x0 - v11 Store { addr=v10, disp=0, value=v3, kind=F32 } -> - - terminator Jmp(b3) (exit_acc=v11) + v9 LoadLocal { off=-1, kind=F32 } -> d0 [f32] + v10 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v3) block 2 start_pc=0 - v12 LoadLocal { off=-1, kind=F32 } -> d2 [f32] - v13 Fneg(v3) -> d0 [f32] - v14 LocalAddr(-5) -> x0 - v15 Store { addr=v14, disp=0, value=v13, kind=F32 } -> - - terminator Jmp(b3) (exit_acc=v15) + v11 LoadLocal { off=-1, kind=F32 } -> d0 [f32] + v12 Fneg(v3) -> d2 [f32] + v13 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v12) block 3 start_pc=0 - v16 LoadLocal { off=-5, kind=F32 } -> d0 [f32] - v17 Imm(0) -> x0 - v18 LoadLocal { off=2, kind=I32 } -> x0 - v19 BinopI { op=and, lhs=v1, rhs_imm=2 } -> x0 - terminator Bz { cond=v19, target=b5, fall=b4 } (exit_acc=v19) + v14 Phi { incoming=[b1:v3, b2:v12], kind=F32 } -> d2 [f32] + v15 LoadLocal { off=-5, kind=F32 } -> d0 [f32] + v16 Imm(0) -> x0 + v17 LoadLocal { off=2, kind=I32 } -> x0 + v18 BinopI { op=and, lhs=v1, rhs_imm=2 } -> x0 + terminator Bz { cond=v18, target=b5, fall=b4 } (exit_acc=v18) block 4 start_pc=0 - v20 LoadLocal { off=-2, kind=F32 } -> d2 [f32] - v21 LocalAddr(-6) -> x0 - v22 Store { addr=v21, disp=0, value=v5, kind=F32 } -> - - terminator Jmp(b6) (exit_acc=v22) + v19 LoadLocal { off=-2, kind=F32 } -> d0 [f32] + v20 Imm(0) -> x0 + terminator Jmp(b6) (exit_acc=v5) block 5 start_pc=0 - v23 LoadLocal { off=-2, kind=F32 } -> d2 [f32] - v24 Fneg(v5) -> d1 [f32] - v25 LocalAddr(-6) -> x0 - v26 Store { addr=v25, disp=0, value=v24, kind=F32 } -> - - terminator Jmp(b6) (exit_acc=v26) + v21 LoadLocal { off=-2, kind=F32 } -> d0 [f32] + v22 Fneg(v5) -> d1 [f32] + v23 Imm(0) -> x0 + terminator Jmp(b6) (exit_acc=v22) block 6 start_pc=0 - v27 LoadLocal { off=-6, kind=F32 } -> d1 [f32] - v28 Imm(0) -> x0 - v29 LoadLocal { off=-3, kind=F32 } -> d2 [f32] - v30 LoadLocal { off=-4, kind=F32 } -> d2 [f32] - v31 Binop { op=fadd, lhs=v16, rhs=v27 } -> d0 [f32] - terminator Return(v31) (exit_acc=v31) + v24 Phi { incoming=[b4:v5, b5:v22], kind=F32 } -> d1 [f32] + v25 LoadLocal { off=-6, kind=F32 } -> d0 [f32] + v26 Imm(0) -> x0 + v27 LoadLocal { off=-3, kind=F32 } -> d0 [f32] + v28 LoadLocal { off=-4, kind=F32 } -> d0 [f32] + v29 Binop { op=fadd, lhs=v14, rhs=v24 } -> d0 [f32] + terminator Return(v29) (exit_acc=v29) ; --- SSA dump (ok=true) ent_pc=3 --- ; name=main fn ent_pc=3 n_params=0 variadic=false locals=3 diff --git a/tests/snapshots/ssa/setenv_overwrite.ssa b/tests/snapshots/ssa/setenv_overwrite.ssa new file mode 100644 index 000000000..1553f500d --- /dev/null +++ b/tests/snapshots/ssa/setenv_overwrite.ssa @@ -0,0 +1,86 @@ +; --- SSA dump (ok=true) ent_pc=5 --- +; name=main +fn ent_pc=5 n_params=0 variadic=false locals=3 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ImmData(8) -> x7 + v2 ImmData(25) -> x6 + v3 Imm(1) -> x2 + v4 CallExt { binding_idx=18, args=[v1, v2, v3], fp_arg_mask=0x0 } -> x0 + v5 ImmData(31) -> x7 + v6 ImmData(48) -> x6 + v7 Imm(0) -> x2 + v8 CallExt { binding_idx=18, args=[v5, v6, v7], fp_arg_mask=0x0 } -> x0 + v9 ImmData(55) -> x7 + v10 CallExt { binding_idx=17, args=[v9], fp_arg_mask=0x0 } -> x0 + v11 Load { addr=v10, disp=0, kind=I8 } -> x0 + v12 BinopI { op=ne, lhs=v11, rhs_imm=102 } -> x0 + terminator Bz { cond=v12, target=b2, fall=b1 } (exit_acc=v12) + block 1 start_pc=0 + v13 Imm(1) -> x0 + terminator Return(v13) (exit_acc=v13) + block 2 start_pc=0 + v14 ImmData(72) -> x7 + v15 ImmData(89) -> x6 + v16 Imm(1) -> x2 + v17 CallExt { binding_idx=18, args=[v14, v15, v16], fp_arg_mask=0x0 } -> x0 + v18 ImmData(95) -> x7 + v19 CallExt { binding_idx=17, args=[v18], fp_arg_mask=0x0 } -> x0 + v20 Imm(0) -> x1 + v21 Load { addr=v19, disp=0, kind=I8 } -> x0 + v22 BinopI { op=ne, lhs=v21, rhs_imm=116 } -> x0 + terminator Bz { cond=v22, target=b4, fall=b3 } (exit_acc=v22) + block 3 start_pc=0 + v23 Imm(2) -> x0 + terminator Return(v23) (exit_acc=v23) + block 4 start_pc=0 + v24 Imm(0) -> x0 + terminator Return(v24) (exit_acc=v24) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) From ae64481224abd181e7110048aa3ed07c3f3295a7 Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 00:52:14 -0700 Subject: [PATCH 55/67] windows: setenv as an inline overwrite-honoring wrapper, not a runtime shim The runtime-shim setenv definition resolved only on the compiled path; under the interpreter and JIT the unbound symbol errored (a fixture's setenv roundtrip failed on Windows). Define setenv inline in so all three paths share one definition: probe getenv, then _putenv_s. Overwrite=0 leaves an existing binding untouched (verified on the Windows box). Co-Authored-By: Claude Fable 5 --- headers/include/stdlib.h | 20 +++++++++++++++++--- lib/runtime.c | 18 ------------------ src/c5/tests/codegen.rs | 21 ++++++++------------- 3 files changed, 25 insertions(+), 34 deletions(-) diff --git a/headers/include/stdlib.h b/headers/include/stdlib.h index bb0b07962..73453b7b6 100644 --- a/headers/include/stdlib.h +++ b/headers/include/stdlib.h @@ -169,10 +169,11 @@ #pragma binding(msvcrt::system, "system") #pragma binding(msvcrt::getenv, "getenv") // POSIX putenv is msvcrt's underscored `_putenv` (a `(string) -> int` -// shape). POSIX setenv takes a third `overwrite` argument that msvcrt's -// 2-parameter `_putenv_s(name, value)` lacks, so it is left unbound and -// resolved by the runtime shim (see lib/runtime.c) that honors the flag. +// shape). msvcrt's `_putenv_s(name, value)` has no overwrite flag and +// always replaces; setenv honors POSIX overwrite via the inline wrapper +// below (declared here, defined after getenv/_putenv_s are in scope). #pragma binding(msvcrt::putenv, "_putenv") +#pragma binding(msvcrt::_putenv_s, "_putenv_s") #pragma binding(msvcrt::_wputenv_s, "_wputenv_s") #pragma binding(msvcrt::qsort, "qsort") #pragma binding(msvcrt::bsearch, "bsearch") @@ -331,7 +332,20 @@ _Noreturn int abort(); _Noreturn int exit(int status); int system(char *cmd); char *getenv(char *name); +#ifdef _WIN32 +int _putenv_s(char *name, char *value); +// POSIX setenv (IEEE Std 1003.1): overwrite == 0 leaves an existing +// binding untouched and returns 0. Inline so the compiled, JIT, and +// interpreter paths share one definition without a runtime import. +static inline int setenv(char *name, char *value, int overwrite) { + if (overwrite == 0 && getenv(name) != 0) { + return 0; + } + return _putenv_s(name, value); +} +#else int setenv(char *name, char *value, int overwrite); +#endif int putenv(char *string); // Multibyte / wide-character string conversion (C99 7.20.8). `wchar_t` // and `size_t` come from . diff --git a/lib/runtime.c b/lib/runtime.c index 5536390ff..6041f4a24 100644 --- a/lib/runtime.c +++ b/lib/runtime.c @@ -62,24 +62,6 @@ int snprintf(char *buf, int size, char *fmt, ...) { return len; } -// POSIX setenv (IEEE Std 1003.1): with overwrite == 0 an existing -// binding is left untouched and 0 is returned. msvcrt's -// `_putenv_s(name, value)` has no overwrite flag and always replaces, -// so probe `getenv` first and write only when the name is absent or a -// replacement is requested (`` leaves setenv unbound on -// Windows so this definition resolves it). -#pragma binding(libc::getenv, "getenv") -#pragma binding(libc::_putenv_s, "_putenv_s") -extern char *getenv(char *name); -extern int _putenv_s(char *name, char *value); - -int setenv(char *name, char *value, int overwrite) { - if (overwrite == 0 && getenv(name) != 0) { - return 0; - } - return _putenv_s(name, value); -} - #endif #endif diff --git a/src/c5/tests/codegen.rs b/src/c5/tests/codegen.rs index c83b5f7ee..0790e7563 100644 --- a/src/c5/tests/codegen.rs +++ b/src/c5/tests/codegen.rs @@ -232,14 +232,13 @@ fn environ_data_binding_records_copy_relocation() { } /// POSIX `setenv` carries a third `overwrite` argument that msvcrt's -/// 2-parameter `_putenv_s` lacks, so `` must leave `setenv` -/// unbound on Windows -- resolved by the runtime shim that honors the -/// flag -- rather than binding it straight to `_putenv_s` (which drops -/// `overwrite`). The object for a `setenv`-calling TU must therefore -/// reference `setenv` as an undefined symbol and carry no `_putenv_s` -/// import of its own. +/// 2-parameter `_putenv_s` lacks, so `` defines `setenv` as +/// an inline wrapper that probes `getenv` before calling `_putenv_s`, +/// honoring the flag. The wrapper compiles in place -- the object +/// imports `_putenv_s` and carries no undefined `setenv` symbol -- and +/// the same definition serves the interpreter and JIT paths. #[test] -fn setenv_left_unbound_for_runtime_shim_on_windows() { +fn setenv_inline_wrapper_imports_putenv_s_on_windows() { use crate::{Compiler, NativeOptions, OutputKind, Target, emit_native_with_options}; let program = Compiler::with_target( "#include \nint main(void){ setenv(\"K\", \"V\", 0); return 0; }".to_string(), @@ -254,12 +253,8 @@ fn setenv_left_unbound_for_runtime_shim_on_windows() { let obj = emit_native_with_options(&program, Target::WindowsX64, opts).expect("emit"); let contains = |needle: &[u8]| obj.windows(needle.len()).any(|w| w == needle); assert!( - contains(b"setenv"), - "setenv must reach the object as an undefined symbol for the runtime shim to satisfy" - ); - assert!( - !contains(b"_putenv_s"), - "setenv must not be bound directly to _putenv_s (the overwrite flag would be dropped)" + contains(b"_putenv_s"), + "the inline setenv wrapper must import _putenv_s" ); } From ffa5f5135dcdb8fcab913d3d5dd91bc1eaad7c07 Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 00:58:15 -0700 Subject: [PATCH 56/67] vm: bridge _putenv_s so the Windows setenv wrapper runs under the interpreter The inline setenv wrapper calls _putenv_s, which the interpreter's libc bridge did not handle; a setenv roundtrip fixture failed under --interp on a Windows host. Dispatch _putenv_s to the host with force overwrite (its msvcrt semantics), matching the setenv arm. Co-Authored-By: Claude Fable 5 --- src/c5/vm/ssa.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/c5/vm/ssa.rs b/src/c5/vm/ssa.rs index 554b85137..bd0fc27fc 100644 --- a/src/c5/vm/ssa.rs +++ b/src/c5/vm/ssa.rs @@ -1397,6 +1397,28 @@ fn dispatch_callext( host.setenv(&env_name, &env_val, overwrite); Ok(0) } + // `int _putenv_s(const char *name, const char *value)` -- msvcrt's + // 2-argument setter, always replacing. The Windows `` + // setenv wrapper calls it after its own overwrite check, so the + // bridge forces the write. + "_putenv_s" => { + if args.len() < 2 { + return Err(C5Error::Runtime( + "vm_ssa: _putenv_s expects 2 args".to_string(), + )); + } + let name_addr = args[0]; + let val_addr = args[1]; + if name_addr < 0 || val_addr < 0 { + return Err(C5Error::Runtime(format!( + "vm_ssa: _putenv_s: bad addrs name=0x{name_addr:x} val=0x{val_addr:x}", + ))); + } + let env_name = read_cstring(mem, name_addr as usize)?; + let env_val = read_cstring(mem, val_addr as usize)?; + host.setenv(&env_name, &env_val, super::super::host::Overwrite::Force); + Ok(0) + } // `void *dlopen(const char *filename, int flags)` -- a NULL // filename maps to `Option::None` so the host can produce // dlopen(NULL, ...) (the global symbol table). From bc9a6126815c9fa39940924e0ce7e69c8724d98a Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 01:02:49 -0700 Subject: [PATCH 57/67] headers: rustfmt the bundled-header registry additions Co-Authored-By: Claude Fable 5 --- src/c5/headers.rs | 5 ++++- src/main.rs | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/c5/headers.rs b/src/c5/headers.rs index 0470f6028..ffa2e89a9 100644 --- a/src/c5/headers.rs +++ b/src/c5/headers.rs @@ -225,7 +225,10 @@ pub(super) const EMBEDDED_HEADERS: &[(&str, &str)] = &[ "linux/auxvec.h", include_str!("../../headers/include/linux/auxvec.h"), ), - ("linux/fs.h", include_str!("../../headers/include/linux/fs.h")), + ( + "linux/fs.h", + include_str!("../../headers/include/linux/fs.h"), + ), ( "linux/sched.h", include_str!("../../headers/include/linux/sched.h"), diff --git a/src/main.rs b/src/main.rs index 5688468d4..1dced89cd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1264,10 +1264,10 @@ fn run() { } // A freestanding entry is a link root: seed it as undefined // so an archive member that only defines the entry is pulled. - if let Some(entry) = &freestanding_entry { - if !defined.contains(entry) { - undefined.insert(entry.clone()); - } + if let Some(entry) = &freestanding_entry + && !defined.contains(entry) + { + undefined.insert(entry.clone()); } // The archive symbol index lists strong section-resident // definitions; a member is pulled on exactly those. From e74ecf3777cfad162728b83c35273bccd7cc6c23 Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 01:25:32 -0700 Subject: [PATCH 58/67] headers: bundle sys/cdefs.h and the CoreFoundation/SystemConfiguration surfaces The macOS CI lanes need three more real system headers the fatal missing-include diagnostic surfaced: sys/cdefs.h (the BSD declaration- decoration macros, tcl's unix port), plus the minimal CoreFoundation and SystemConfiguration surfaces curl's macos.c reaches for (SCDynamicStoreCopyProxies, CFRelease); framework symbols bind under their underscore-prefixed Mach-O names. Co-Authored-By: Claude Fable 5 --- .../include/CoreFoundation/CoreFoundation.h | 24 +++++++++++++++++++ .../SCDynamicStoreCopySpecific.h | 17 +++++++++++++ headers/include/sys/cdefs.h | 22 +++++++++++++++++ src/c5/headers.rs | 12 ++++++++++ 4 files changed, 75 insertions(+) create mode 100644 headers/include/CoreFoundation/CoreFoundation.h create mode 100644 headers/include/SystemConfiguration/SCDynamicStoreCopySpecific.h create mode 100644 headers/include/sys/cdefs.h diff --git a/headers/include/CoreFoundation/CoreFoundation.h b/headers/include/CoreFoundation/CoreFoundation.h new file mode 100644 index 000000000..49ea993c2 --- /dev/null +++ b/headers/include/CoreFoundation/CoreFoundation.h @@ -0,0 +1,24 @@ +/* Minimal Apple CoreFoundation surface (). +** Opaque CF*Ref handles are pointers; libSystem provides the runtime. +** Only the types and calls the bundled demos reference are declared. */ +#pragma once + +#ifdef __APPLE__ + +typedef const void *CFTypeRef; +typedef struct __CFString *CFStringRef; +typedef struct __CFDictionary *CFDictionaryRef; +typedef struct __CFAllocator *CFAllocatorRef; +typedef long CFIndex; +typedef unsigned long CFTypeID; + +#pragma dylib(corefoundation, "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation") +#pragma binding(corefoundation::CFRelease, "_CFRelease") +#pragma binding(corefoundation::CFRetain, "_CFRetain") +#pragma binding(corefoundation::CFGetTypeID, "_CFGetTypeID") + +void CFRelease(CFTypeRef cf); +CFTypeRef CFRetain(CFTypeRef cf); +CFTypeID CFGetTypeID(CFTypeRef cf); + +#endif diff --git a/headers/include/SystemConfiguration/SCDynamicStoreCopySpecific.h b/headers/include/SystemConfiguration/SCDynamicStoreCopySpecific.h new file mode 100644 index 000000000..d946acd61 --- /dev/null +++ b/headers/include/SystemConfiguration/SCDynamicStoreCopySpecific.h @@ -0,0 +1,17 @@ +/* Apple SystemConfiguration dynamic-store queries +** (). Declares the +** subset the bundled demos reach for; the framework supplies the code. */ +#pragma once + +#ifdef __APPLE__ + +#include + +typedef struct __SCDynamicStore *SCDynamicStoreRef; + +#pragma dylib(systemconfiguration, "/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration") +#pragma binding(systemconfiguration::SCDynamicStoreCopyProxies, "_SCDynamicStoreCopyProxies") + +CFDictionaryRef SCDynamicStoreCopyProxies(SCDynamicStoreRef store); + +#endif diff --git a/headers/include/sys/cdefs.h b/headers/include/sys/cdefs.h new file mode 100644 index 000000000..bd9264982 --- /dev/null +++ b/headers/include/sys/cdefs.h @@ -0,0 +1,22 @@ +/* BSD/Darwin : the decoration macros system headers wrap +** declarations in. For a plain C compiler they carry no effect. */ +#pragma once + +#define __BEGIN_DECLS +#define __END_DECLS +#define __THROW +#define __pure +#define __const const +#define __restrict restrict +#define __dead2 +#define __pure2 +#define __unused +#define __used +#define __deprecated +#define __restrict_arr +#define __P(protos) protos +#define __DARWIN_ALIAS(sym) +#define __DARWIN_ALIAS_C(sym) +#define __DARWIN_ALIAS_I(sym) +#define __DARWIN_INODE64(sym) +#define __GNUC_PREREQ(maj, min) 0 diff --git a/src/c5/headers.rs b/src/c5/headers.rs index ffa2e89a9..a39a4da05 100644 --- a/src/c5/headers.rs +++ b/src/c5/headers.rs @@ -142,6 +142,18 @@ pub(super) const EMBEDDED_HEADERS: &[(&str, &str)] = &[ "sys/file.h", include_str!("../../headers/include/sys/file.h"), ), + ( + "sys/cdefs.h", + include_str!("../../headers/include/sys/cdefs.h"), + ), + ( + "CoreFoundation/CoreFoundation.h", + include_str!("../../headers/include/CoreFoundation/CoreFoundation.h"), + ), + ( + "SystemConfiguration/SCDynamicStoreCopySpecific.h", + include_str!("../../headers/include/SystemConfiguration/SCDynamicStoreCopySpecific.h"), + ), ( "sys/attr.h", include_str!("../../headers/include/sys/attr.h"), From 55a7b0dbec97d7904b4864b0e5a41dd64ad853f3 Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 01:19:38 -0700 Subject: [PATCH 59/67] aarch64: honor folded FP displacement; widen call-site SP adjust emit_load hard-coded offset 0 for the F32/F64 arms while emit_store passed the folded displacement to the immediate-offset encoders. index fold declined the floating kinds, so disp was always 0 there and the drop stayed masked; extend the constant-offset fold to F32/F64 (the scaled-index fold stays integer-only) and route disp through the FP load encoders. The four FP ldr/str encoders now share enc_ldst_scaled, so an out-of-range or misaligned immediate is caught uniformly. Call-site SP adjustments used the raw 12-bit enc_add_imm/enc_sub_imm on plan.scratch_bytes and the 16-byte-stride push total; an outgoing area past 4095 bytes shifted the immediate into the LSL#12 bit and adjusted SP by the wrong multiple. Route every call-site adjustment through emit_sub_sp_imm/emit_add_sp_imm, the 24-bit split the prologue already uses. Two consequences the wide-argument fixtures surfaced: the argument planner's fp_arg_mask shift overflowed for arguments past 31 (the walker only sets the mask for the first 32), and emit_call_indirect blindly fell back to x9 for the target pointer when every scratch held a live arg source. Guard the shift and stage the pointer in a reserved stack cell (host-ABI branch) or capture it after the pushes consume the sources (c5-stack branch). Fixtures fp_load_folded_disp.c, call_sp_adjust_imm12_overflow.c, and indirect_call_target_scratch_exhausted.c registered in the jit, native, and both native_elf lanes; two byte-scan codegen tests lock the folded FP encoding and the shifted-12 SP split. Co-Authored-By: Claude Fable 5 --- src/c5/codegen/aarch64/emit.rs | 133 ++++--- src/c5/codegen/aarch64/encode.rs | 25 +- src/c5/codegen/mod.rs | 7 +- src/c5/codegen/passes/index_fold.rs | 153 ++++---- src/c5/tests/codegen.rs | 154 ++++++++ src/c5/tests/jit.rs | 3 + src/c5/tests/native.rs | 3 + src/c5/tests/native_elf.rs | 3 + src/c5/tests/native_elf_x64.rs | 3 + .../c/call_sp_adjust_imm12_overflow.c | 348 ++++++++++++++++++ tests/fixtures/c/fp_load_folded_disp.c | 40 ++ .../indirect_call_target_scratch_exhausted.c | 52 +++ 12 files changed, 780 insertions(+), 144 deletions(-) create mode 100644 tests/fixtures/c/call_sp_adjust_imm12_overflow.c create mode 100644 tests/fixtures/c/fp_load_folded_disp.c create mode 100644 tests/fixtures/c/indirect_call_target_scratch_exhausted.c diff --git a/src/c5/codegen/aarch64/emit.rs b/src/c5/codegen/aarch64/emit.rs index 3785a4a43..301c504d1 100644 --- a/src/c5/codegen/aarch64/emit.rs +++ b/src/c5/codegen/aarch64/emit.rs @@ -3427,9 +3427,7 @@ fn emit_call_ext( // argument-register packing. let aggs = build_arg_aggs(arg_aggs, agg_descs, abi); let plan = super::plan_call_args_aggs(args.len(), fixed, fp_arg_mask, abi, &aggs, false); - if plan.scratch_bytes > 0 { - emit(code, enc_sub_imm(Reg(31), Reg(31), plan.scratch_bytes)); - } + emit_sub_sp_imm(code, plan.scratch_bytes); if !marshal_args( code, &plan, args, alloc, scratch, frame, arg_aggs, agg_descs, ) { @@ -3481,9 +3479,7 @@ fn emit_call_ext( }); emit(code, enc_bl(0)); } - if plan.scratch_bytes > 0 { - emit(code, enc_add_imm(Reg(31), Reg(31), plan.scratch_bytes)); - } + emit_add_sp_imm(code, plan.scratch_bytes); if ret_agg.is_some() { finish_call_result( code, @@ -3632,9 +3628,7 @@ fn emit_call( // the areas then the overflow stack. let plan = super::plan_call_args_aggs(args.len(), fixed_args, fp_arg_mask, abi, &aggs, false); - if plan.scratch_bytes > 0 { - emit(code, enc_sub_imm(Reg(31), Reg(31), plan.scratch_bytes)); - } + emit_sub_sp_imm(code, plan.scratch_bytes); if !marshal_args( code, &plan, args, alloc, scratch, frame, arg_aggs, agg_descs, ) { @@ -3652,9 +3646,7 @@ fn emit_call( kind: BranchKind::Bl, }); emit(code, enc_bl(0)); - if plan.scratch_bytes > 0 { - emit(code, enc_add_imm(Reg(31), Reg(31), plan.scratch_bytes)); - } + emit_add_sp_imm(code, plan.scratch_bytes); finish_call_result( code, ret_agg, @@ -3683,9 +3675,7 @@ fn emit_call( // integer register as its `Imm` bit pattern. Feeding the mask to // the planner routes the FP args to d0..d7 instead of x0..x7. let plan = super::plan_call_args_aggs(args.len(), args.len(), fp_arg_mask, abi, &aggs, false); - if plan.scratch_bytes > 0 { - emit(code, enc_sub_imm(Reg(31), Reg(31), plan.scratch_bytes)); - } + emit_sub_sp_imm(code, plan.scratch_bytes); if !marshal_args( code, &plan, args, alloc, scratch, frame, arg_aggs, agg_descs, ) { @@ -3701,9 +3691,7 @@ fn emit_call( kind: BranchKind::Bl, }); emit(code, enc_bl(0)); - if plan.scratch_bytes > 0 { - emit(code, enc_add_imm(Reg(31), Reg(31), plan.scratch_bytes)); - } + emit_add_sp_imm(code, plan.scratch_bytes); finish_call_result( code, ret_agg, @@ -3871,10 +3859,8 @@ fn emit_call_indirect( // for this call. AAPCS64 doesn't assign these scratch // registers to int-arg slots, but the SSA allocator's // caller-saved pool includes them and may park an arg's - // source value in one. The target stage must avoid that - // register; otherwise the materialise below overwrites the - // arg's source before the marshal can push it onto the - // c5-stride stack. + // source value in one. The target stage must avoid those + // registers while the marshal still reads them. let mut arg_source_regs: alloc::vec::Vec = alloc::vec::Vec::with_capacity(args.len()); for &a in args { if let Some(Place::IntReg(r)) = alloc.places.get(a as usize) { @@ -3884,24 +3870,17 @@ fn emit_call_indirect( // Capture the function pointer into a caller-saved scratch // disjoint from the arg sources. Prefer x9, then x10..x15 -- // none are arg-passing registers per AAPCS64, so they are - // safe to clobber via the blr. The blr happens before the - // callee can observe the scratch, so the value reaches the - // indirect branch intact regardless of which scratch holds - // it. + // safe to clobber via the blr. When every candidate holds an + // arg source the marshal still reads, the host-ABI branch + // stages the pointer in a reserved stack cell instead, and the + // c5-stack branch captures after its pushes have consumed the + // sources; a blind fallback here overwrote a live source. const TARGET_SCRATCH_CANDIDATES: &[u8] = &[9, 10, 11, 12, 13, 14, 15]; - let target_reg_idx = TARGET_SCRATCH_CANDIDATES + let free_target_reg = TARGET_SCRATCH_CANDIDATES .iter() .copied() .find(|r| !arg_source_regs.contains(r)) - .unwrap_or(9); - let target_reg = Reg(target_reg_idx); - let target_r = match materialize_int(code, target_place, scratch.primary, frame) { - Some(r) => r, - None => return false, - }; - if target_r.0 != target_reg.0 { - emit_mov_reg(code, target_reg, target_r); - } + .map(Reg); if (callee_variadic && (abi.variadic_on_stack || abi.variadic_int_only || abi.aarch64_host_variadic())) || !aggs.is_empty() @@ -3917,13 +3896,41 @@ fn emit_call_indirect( // stack (Windows arm64, `variadic_int_only`), or both banks then // the stack (Linux aarch64, `aarch64_host_variadic`) -- the same // placement `emit_call` uses for a direct variadic call. The - // target pointer is already captured in `target_reg` (a - // non-arg-passing scratch), so `marshal_args` will not clobber - // it. `blr` through the captured register. - let plan = + // target pointer rides a non-arg-passing scratch that + // `marshal_args` will not clobber, or a reserved stack cell + // above the argument slots when no such scratch is free. + let mut plan = super::plan_call_args_aggs(args.len(), fixed_args, fp_arg_mask, abi, &aggs, false); - if plan.scratch_bytes > 0 { - emit(code, enc_sub_imm(Reg(31), Reg(31), plan.scratch_bytes)); + let staged_off = match free_target_reg { + Some(_) => None, + None => { + // One 16-byte cell keeps SP 16-aligned; the argument + // slots stay below the original scratch_bytes. + plan.scratch_bytes += 16; + Some(plan.scratch_bytes - 16) + } + }; + let target_r = match materialize_int(code, target_place, scratch.primary, frame) { + Some(r) => r, + None => return false, + }; + let target_reg = match free_target_reg { + Some(r) => { + if target_r.0 != r.0 { + emit_mov_reg(code, r, target_r); + } + r + } + None => { + if target_r.0 != scratch.primary.0 { + emit_mov_reg(code, scratch.primary, target_r); + } + scratch.primary + } + }; + emit_sub_sp_imm(code, plan.scratch_bytes); + if let Some(off) = staged_off { + emit_sp_str_x_auto(code, target_reg, off); } if !marshal_args( code, &plan, args, alloc, scratch, frame, arg_aggs, agg_descs, @@ -3931,10 +3938,17 @@ fn emit_call_indirect( return false; } setup_indirect_result(code, ret_agg, ret_slot_off, agg_descs, frame); - emit(code, enc_blr(target_reg)); - if plan.scratch_bytes > 0 { - emit(code, enc_add_imm(Reg(31), Reg(31), plan.scratch_bytes)); - } + // The marshal consumed every argument source, so x9 is free + // to carry the staged pointer to the blr. + let call_reg = match staged_off { + Some(off) => { + emit_sp_ldr_x(code, Reg(9), off); + Reg(9) + } + None => target_reg, + }; + emit(code, enc_blr(call_reg)); + emit_add_sp_imm(code, plan.scratch_bytes); finish_call_result( code, ret_agg, @@ -3984,6 +3998,17 @@ fn emit_call_indirect( emit(code, enc_str_pre(src, Reg(31), -16)); } let pushed_bytes = (args.len() as u32) * 16; + // The pushes consumed every argument source, so x9 holds no live + // value; capture the pointer here, with SP shifted by the pushes. + let target_reg = Reg(9); + let target_r = + match materialize_int_shifted(code, target_place, target_reg, frame, pushed_bytes) { + Some(r) => r, + None => return false, + }; + if target_r.0 != target_reg.0 { + emit_mov_reg(code, target_reg, target_r); + } // Load the prefix into host arg regs from the c5-stride // stack we just laid down. Non-variadic callees expect this // shape; variadic callees ignore the host arg regs but read @@ -3992,9 +4017,7 @@ fn emit_call_indirect( // past 8) stays on the c5 stack at `[sp + i*16]`, which the // callee prologue's overflow restripe loop also reads from. let plan = super::plan_call_args_aggs(args.len(), args.len(), fp_arg_mask, abi, &aggs, false); - if plan.scratch_bytes > 0 { - emit(code, enc_sub_imm(Reg(31), Reg(31), plan.scratch_bytes)); - } + emit_sub_sp_imm(code, plan.scratch_bytes); for (i, &placement) in plan.placements.iter().enumerate() { match placement { super::ArgPlacement::IntReg(r) => { @@ -4021,13 +4044,9 @@ fn emit_call_indirect( } } emit(code, enc_blr(target_reg)); - if plan.scratch_bytes > 0 { - emit(code, enc_add_imm(Reg(31), Reg(31), plan.scratch_bytes)); - } + emit_add_sp_imm(code, plan.scratch_bytes); // Drop the 16-byte-stride argument pushes. - if pushed_bytes > 0 { - emit(code, enc_add_imm(Reg(31), Reg(31), pushed_bytes)); - } + emit_add_sp_imm(code, pushed_bytes); move_call_result(code, dst, frame, fp_return); true } @@ -4578,7 +4597,7 @@ fn emit_load( return false; } }; - emit(code, enc_ldr_s_imm(dd, rn, 0)); + emit(code, enc_ldr_s_imm(dd, rn, disp)); if !keep_f32 { emit(code, enc_fcvt_d_s(dd, dd)); } @@ -4598,7 +4617,7 @@ fn emit_load( return false; } }; - emit(code, enc_ldr_d_imm(dd, rn, 0)); + emit(code, enc_ldr_d_imm(dd, rn, disp)); if let Place::Spill(slot) = dst { let sp_off = spill_off(frame, slot); emit_sp_str_d_auto(code, dd, sp_off); diff --git a/src/c5/codegen/aarch64/encode.rs b/src/c5/codegen/aarch64/encode.rs index c4e1b78a3..7bcb1c3fc 100644 --- a/src/c5/codegen/aarch64/encode.rs +++ b/src/c5/codegen/aarch64/encode.rs @@ -695,24 +695,18 @@ pub(crate) fn enc_mrs_tpidr_el0(rt: Reg) -> u32 { /// `LDR
, [, #imm]` -- 64-bit unsigned-offset FP/SIMD /// load. The offset is byte-addressed but encoded as `imm/8`; the -/// caller passes raw bytes (must be multiple of 8 in 0..32760). -/// Used by the variadic-FP packer to pull a c5-stack slot -/// straight into a `dN` register before a libc call. +/// caller passes raw bytes (a multiple of 8, up to 32760). pub(crate) fn enc_ldr_d_imm(dt: u8, rn: Reg, imm: u32) -> u32 { debug_assert!(dt < 32); - debug_assert!(imm.is_multiple_of(8) && imm < 32760); - 0xFD40_0000 | ((imm / 8) << 10) | ((rn.0 as u32) << 5) | (dt as u32) + enc_ldst_scaled(0xFD40_0000, 3, Reg(dt), rn, imm) } /// `LDR , [, #imm]` -- 32-bit unsigned-offset FP/SIMD -/// load. The offset is byte-addressed but encoded as `imm/4`; -/// caller passes raw bytes (must be multiple of 4 in 0..16380). -/// Used by [`LoadKind::F32`] to load a `float`-typed lvalue's storage -/// directly into the `sN` half of `dN` before the widening fcvt. +/// load. The offset is byte-addressed but encoded as `imm/4`; the +/// caller passes raw bytes (a multiple of 4, up to 16380). pub(crate) fn enc_ldr_s_imm(st: u8, rn: Reg, imm: u32) -> u32 { debug_assert!(st < 32); - debug_assert!(imm.is_multiple_of(4) && imm < 16380); - 0xBD40_0000 | ((imm / 4) << 10) | ((rn.0 as u32) << 5) | (st as u32) + enc_ldst_scaled(0xBD40_0000, 2, Reg(st), rn, imm) } /// `STR , [, #imm]` -- 32-bit unsigned-offset FP/SIMD @@ -720,17 +714,14 @@ pub(crate) fn enc_ldr_s_imm(st: u8, rn: Reg, imm: u32) -> u32 { /// to the `StoreKind::F32` lowering. pub(crate) fn enc_str_s_imm(st: u8, rn: Reg, imm: u32) -> u32 { debug_assert!(st < 32); - debug_assert!(imm.is_multiple_of(4) && imm < 16380); - 0xBD00_0000 | ((imm / 4) << 10) | ((rn.0 as u32) << 5) | (st as u32) + enc_ldst_scaled(0xBD00_0000, 2, Reg(st), rn, imm) } /// `STR
, [, #imm]` -- 64-bit unsigned-offset FP/SIMD -/// store, the partner of [`enc_ldr_d_imm`]. Used by the AArch64 -/// setjmp intrinsic to spill d8-d15 into the user's `jmp_buf`. +/// store, the partner of [`enc_ldr_d_imm`]. pub(crate) fn enc_str_d_imm(dt: u8, rn: Reg, imm: u32) -> u32 { debug_assert!(dt < 32); - debug_assert!(imm.is_multiple_of(8) && imm < 32760); - 0xFD00_0000 | ((imm / 8) << 10) | ((rn.0 as u32) << 5) | (dt as u32) + enc_ldst_scaled(0xFD00_0000, 3, Reg(dt), rn, imm) } /// `ADR , label` -- compute a PC-relative byte address (signed diff --git a/src/c5/codegen/mod.rs b/src/c5/codegen/mod.rs index c8549331e..3b3fb6600 100644 --- a/src/c5/codegen/mod.rs +++ b/src/c5/codegen/mod.rs @@ -43,7 +43,7 @@ pub(crate) mod aarch64; #[allow(dead_code)] pub(crate) mod abi_classify; mod jit; -mod passes; +pub(crate) mod passes; pub(crate) mod ssa; pub(crate) mod x86_64; @@ -551,7 +551,10 @@ pub(super) fn plan_call_args_aggs( placements.push(placement); continue; } - let is_fp = (fp_arg_mask & (1u32 << i)) != 0; + // The walker's mask covers the first 32 arguments; later + // positions read as integer-classed, matching the producer's + // bound (an unguarded shift by i >= 32 overflows). + let is_fp = i < 32 && (fp_arg_mask & (1u32 << i)) != 0; let is_variadic = i >= fixed_args; let force_stack = is_variadic && abi.variadic_on_stack; let allow_fp_reg = !is_variadic || !abi.variadic_int_only; diff --git a/src/c5/codegen/passes/index_fold.rs b/src/c5/codegen/passes/index_fold.rs index 2904b7d63..358367735 100644 --- a/src/c5/codegen/passes/index_fold.rs +++ b/src/c5/codegen/passes/index_fold.rs @@ -26,6 +26,7 @@ //! The same pass folds a constant pointer offset (a struct field offset) //! into the load/store displacement: a `BinopI(Add, base, c)` address //! with an aligned, in-range `c` becomes `Load { addr=base, disp=c }`. +//! Unlike the scaled-index fold this covers the floating kinds too. //! As with the scaled-index case this fires for a shared address too -- //! the load and store of a read-modify-write of one field fold the //! offset into both accesses, provided every use is a same-width access. @@ -34,27 +35,43 @@ use alloc::vec::Vec; use crate::c5::ir::{BinOp, FunctionSsa, Inst, LoadKind, NO_VALUE, StoreKind, Terminator, ValueId}; -/// Access width in bytes for a load kind, or `None` for the floating -/// kinds (the indexed emit handles integers only). -fn load_width(kind: LoadKind) -> Option { +/// Access width in bytes for a load kind. Used by the displacement +/// fold, which applies to integer and floating accesses alike (the +/// immediate-offset emit honors `disp` for every kind on both targets). +fn load_width(kind: LoadKind) -> u8 { + match kind { + LoadKind::I64 | LoadKind::F64 => 8, + LoadKind::I32 | LoadKind::U32 | LoadKind::F32 => 4, + LoadKind::I16 | LoadKind::U16 => 2, + LoadKind::I8 | LoadKind::U8 => 1, + } +} + +/// Access width in bytes for a store kind. See [`load_width`]. +fn store_width(kind: StoreKind) -> u8 { + match kind { + StoreKind::I64 | StoreKind::F64 => 8, + StoreKind::I32 | StoreKind::F32 => 4, + StoreKind::I16 => 2, + StoreKind::I8 => 1, + } +} + +/// [`load_width`] restricted to the integer kinds, `None` for the +/// floating kinds (the indexed emit handles integers only). +fn int_load_width(kind: LoadKind) -> Option { match kind { - LoadKind::I64 => Some(8), - LoadKind::I32 | LoadKind::U32 => Some(4), - LoadKind::I16 | LoadKind::U16 => Some(2), - LoadKind::I8 | LoadKind::U8 => Some(1), LoadKind::F32 | LoadKind::F64 => None, + k => Some(load_width(k)), } } -/// Access width in bytes for a store kind, or `None` for the floating -/// kinds. -fn store_width(kind: StoreKind) -> Option { +/// [`store_width`] restricted to the integer kinds; the scaled-index +/// emit and the narrowing-store rewrite apply to integer values only. +fn int_store_width(kind: StoreKind) -> Option { match kind { - StoreKind::I64 => Some(8), - StoreKind::I32 => Some(4), - StoreKind::I16 => Some(2), - StoreKind::I8 => Some(1), StoreKind::F32 | StoreKind::F64 => None, + k => Some(store_width(k)), } } @@ -134,14 +151,14 @@ fn foldable_scaled_addresses( disp: 0, kind, volatile: false, - } => (*addr, load_width(*kind)), + } => (*addr, int_load_width(*kind)), Inst::Store { addr, disp: 0, kind, volatile: false, .. - } => (*addr, store_width(*kind)), + } => (*addr, int_store_width(*kind)), _ => continue, }; if let Some(&(_, _, scale)) = cand.get(&addr) @@ -199,7 +216,7 @@ fn foldable_displaced_addresses( alloc::collections::BTreeMap::new(); let mut valid: alloc::collections::BTreeMap = alloc::collections::BTreeMap::new(); for inst in &func.insts { - let (addr, width) = match inst { + let (addr, w) = match inst { Inst::Load { addr, disp: 0, @@ -215,9 +232,9 @@ fn foldable_displaced_addresses( } => (*addr, store_width(*kind)), _ => continue, }; - let (Some(w), true) = (width, cand.contains_key(&addr)) else { + if !cand.contains_key(&addr) { continue; - }; + } let seen = width_seen.entry(addr).or_insert(0); *seen = if *seen == 0 || *seen == w { w } else { 0xff }; *valid.entry(addr).or_insert(0) += 1; @@ -292,7 +309,7 @@ fn narrow_store_values(func: &mut FunctionSsa) { let n = func.insts.len(); for idx in 0..n { let (value, width) = match &func.insts[idx] { - Inst::Store { value, kind, .. } => match store_width(*kind) { + Inst::Store { value, kind, .. } => match int_store_width(*kind) { Some(w) => (*value, w), None => continue, }, @@ -324,29 +341,29 @@ pub(crate) fn run(funcs: &mut [FunctionSsa]) { kind, volatile: false, } => { - if let Some(width) = load_width(*kind) { - if let Some(&(base, index, scale)) = scaled.get(addr) { - debug_assert_eq!(scale, width); - rewrites.push(( - idx, - Inst::LoadIndexed { - base, - index, - scale, - kind: *kind, - }, - )); - } else if let Some(&(base, disp)) = displaced.get(addr) { - rewrites.push(( - idx, - Inst::Load { - addr: base, - disp, - kind: *kind, - volatile: false, - }, - )); - } + if let (Some(width), Some(&(base, index, scale))) = + (int_load_width(*kind), scaled.get(addr)) + { + debug_assert_eq!(scale, width); + rewrites.push(( + idx, + Inst::LoadIndexed { + base, + index, + scale, + kind: *kind, + }, + )); + } else if let Some(&(base, disp)) = displaced.get(addr) { + rewrites.push(( + idx, + Inst::Load { + addr: base, + disp, + kind: *kind, + volatile: false, + }, + )); } } Inst::Store { @@ -356,31 +373,31 @@ pub(crate) fn run(funcs: &mut [FunctionSsa]) { kind, volatile: false, } => { - if let Some(width) = store_width(*kind) { - if let Some(&(base, index, scale)) = scaled.get(addr) { - debug_assert_eq!(scale, width); - rewrites.push(( - idx, - Inst::StoreIndexed { - base, - index, - scale, - value: *value, - kind: *kind, - }, - )); - } else if let Some(&(base, disp)) = displaced.get(addr) { - rewrites.push(( - idx, - Inst::Store { - addr: base, - disp, - value: *value, - kind: *kind, - volatile: false, - }, - )); - } + if let (Some(width), Some(&(base, index, scale))) = + (int_store_width(*kind), scaled.get(addr)) + { + debug_assert_eq!(scale, width); + rewrites.push(( + idx, + Inst::StoreIndexed { + base, + index, + scale, + value: *value, + kind: *kind, + }, + )); + } else if let Some(&(base, disp)) = displaced.get(addr) { + rewrites.push(( + idx, + Inst::Store { + addr: base, + disp, + value: *value, + kind: *kind, + volatile: false, + }, + )); } } _ => {} diff --git a/src/c5/tests/codegen.rs b/src/c5/tests/codegen.rs index 0790e7563..8ee583462 100644 --- a/src/c5/tests/codegen.rs +++ b/src/c5/tests/codegen.rs @@ -1889,3 +1889,157 @@ fn foreign_cst16_section_lands_sixteen_aligned_in_image() { "the constant's bytes must land at the placed offset" ); } + +/// A constant struct-field offset folds into the displacement of a +/// floating-point load and store, and the AArch64 emit carries that +/// displacement into the immediate-offset encoding. The load side used +/// to hard-code offset 0 while the store side honored it, masked only +/// by the fold declining FP kinds. +#[test] +fn aarch64_fp_access_folds_constant_displacement() { + use crate::c5::ir::{Inst, LoadKind, StoreKind}; + use crate::{Compiler, NativeOptions, OutputKind, Target, emit_native_with_options}; + let target = Target::LinuxAarch64; + let program = Compiler::with_target( + "struct s { long tag; float f; double d; }; \ + float rf(struct s *p) { return p->f; } \ + double rd(struct s *p) { return p->d; } \ + void wd(struct s *p) { p->d = p->d + 0.5; } \ + int main(void) { return 0; }" + .to_string(), + target, + ) + .compile() + .expect("compile"); + let mut funcs = + crate::c5::codegen::ssa::shadow::produce_ssa_funcs(&program, target).expect("ssa"); + crate::c5::codegen::passes::index_fold::run(&mut funcs); + let mut f32_load = false; + let mut f64_load = false; + let mut f64_store = false; + for inst in funcs.iter().flat_map(|f| f.insts.iter()) { + match inst { + Inst::Load { + disp: 8, + kind: LoadKind::F32, + .. + } => f32_load = true, + Inst::Load { + disp: 16, + kind: LoadKind::F64, + .. + } => f64_load = true, + Inst::Store { + disp: 16, + kind: StoreKind::F64, + .. + } => f64_store = true, + _ => {} + } + } + assert!(f32_load, "p->f must fold to Load {{ disp: 8, F32 }}"); + assert!(f64_load, "p->d must fold to Load {{ disp: 16, F64 }}"); + assert!( + f64_store, + "p->d = ... must fold to Store {{ disp: 16, F64 }}" + ); + let obj = emit_native_with_options( + &program, + target, + NativeOptions { + output_kind: OutputKind::Relocatable, + ..NativeOptions::new().with_optimize() + }, + ) + .expect("emit relocatable"); + let text = elf64_section(&obj, ".text").expect(".text"); + let words = || { + text.chunks_exact(4) + .map(|c| u32::from_le_bytes([c[0], c[1], c[2], c[3]])) + }; + // Unsigned-offset FP loads/stores scale the immediate by the access + // width, so #8 (F32) and #16 (F64) both encode imm12 = 2. Register + // fields are masked out. + let imm2 = |w: u32, class: u32| (w & 0xFFC0_0000) == class && (w >> 10) & 0xFFF == 2; + assert!( + words().any(|w| imm2(w, 0xBD40_0000)), + "expected `ldr s, [xN, #8]` for the folded F32 load" + ); + assert!( + words().any(|w| imm2(w, 0xFD40_0000)), + "expected `ldr d, [xN, #16]` for the folded F64 load" + ); + assert!( + words().any(|w| imm2(w, 0xFD00_0000)), + "expected `str d, [xN, #16]` for the folded F64 store" + ); +} + +/// A call whose outgoing-argument area exceeds the 12-bit add/sub +/// immediate must split the call-site SP adjustment into the +/// shifted-12 + remainder pair, as the prologue path does. 261 +/// by-value 16-byte structs leave 257 on the AAPCS64 stack: 257 * 16 = +/// 4112 = 4096 + 16 bytes. The raw encoder used to fold 4112 into the +/// `lsl #12` bit and adjust SP by 65536 instead. +#[test] +fn aarch64_call_sp_adjust_covers_wide_outgoing_area() { + use crate::{Compiler, NativeOptions, OutputKind, Target, emit_native_with_options}; + let mut src = String::from("struct pair { long a; long b; };\nstatic struct pair g[261];\n"); + src.push_str("long take("); + for i in 0..261 { + src.push_str(&format!("struct pair p{i}")); + src.push_str(if i < 260 { ", " } else { ");\n" }); + } + src.push_str("long caller(void) { return take("); + for i in 0..261 { + src.push_str(&format!("g[{i}]")); + src.push_str(if i < 260 { ", " } else { "); }\n" }); + } + src.push_str("int main(void) { return (int)caller(); }\n"); + let program = Compiler::with_target(src, Target::LinuxAarch64) + .compile() + .expect("compile"); + let obj = emit_native_with_options( + &program, + Target::LinuxAarch64, + NativeOptions { + output_kind: OutputKind::Relocatable, + ..NativeOptions::new() + }, + ) + .expect("emit relocatable"); + let text = elf64_section(&obj, ".text").expect(".text"); + let entry = elf_func_value(&obj, "caller").expect("caller symbol") as usize; + let size = elf_func_symbols(&obj) + .into_iter() + .find(|(n, _)| n == "caller") + .map(|(_, s)| s as usize) + .expect("caller size"); + let body = &text[entry..(entry + size).min(text.len())]; + let words: alloc::vec::Vec = body + .chunks_exact(4) + .map(|c| u32::from_le_bytes([c[0], c[1], c[2], c[3]])) + .collect(); + // 4112 bytes split as `sub sp, sp, #1, lsl #12` + `sub sp, sp, #16` + // and restore with the matching adds. The caller's own frame stays + // below 4096, so only the call site produces the shifted forms. + for (word, what) in [ + (0xD140_07FFu32, "sub sp, sp, #1, lsl #12"), + (0xD100_43FF, "sub sp, sp, #16"), + (0x9140_07FF, "add sp, sp, #1, lsl #12"), + (0x9100_43FF, "add sp, sp, #16"), + ] { + assert!( + words.contains(&word), + "caller must contain `{what}` ({word:#010x}) for the 4112-byte outgoing area" + ); + } + // The raw-encoder overflow artifact: 4112 << 10 sets the shift bit + // and leaves imm12 = 16, i.e. a 65536-byte adjustment. + for word in [0xD140_43FFu32, 0x9140_43FF] { + assert!( + !words.contains(&word), + "caller must not adjust SP by 65536 (mis-encoded 4112): {word:#010x}" + ); + } +} diff --git a/src/c5/tests/jit.rs b/src/c5/tests/jit.rs index 2fad014b0..487e119ed 100644 --- a/src/c5/tests/jit.rs +++ b/src/c5/tests/jit.rs @@ -1108,6 +1108,9 @@ const JIT_FIXTURES: &[(&str, i32)] = &[ ("inline_two_reg_struct_param.c", 0), ("struct_param_stack_spill.c", 0), ("struct_stack_arg_then_scalar.c", 0), + ("call_sp_adjust_imm12_overflow.c", 0), + ("indirect_call_target_scratch_exhausted.c", 0), + ("fp_load_folded_disp.c", 0), ("mixed_struct_gpr_abi.c", 0), ("unary_plus_preserves_type.c", 0), ("local_multidim_aggregate_array_init.c", 0), diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index 42cc8b620..7d4283a29 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -417,6 +417,9 @@ const NATIVE_FIXTURES: &[(&str, i32)] = &[ ("inline_two_reg_struct_param.c", 0), ("struct_param_stack_spill.c", 0), ("struct_stack_arg_then_scalar.c", 0), + ("call_sp_adjust_imm12_overflow.c", 0), + ("indirect_call_target_scratch_exhausted.c", 0), + ("fp_load_folded_disp.c", 0), ("mixed_struct_gpr_abi.c", 0), ("unary_plus_preserves_type.c", 0), ("local_multidim_aggregate_array_init.c", 0), diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index ebae6e738..29fd3fba5 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -722,6 +722,9 @@ const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ ("va_arg_composite_straddle.c", 0), ("variadic_cast_fnptr_dispatch.c", 0), ("fcntl_lock_via_cast_fnptr.c", 0), + ("call_sp_adjust_imm12_overflow.c", 0), + ("indirect_call_target_scratch_exhausted.c", 0), + ("fp_load_folded_disp.c", 0), ]; #[test] diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 813dca53d..8b4ebd042 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -671,6 +671,9 @@ const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ ("va_arg_composite_straddle.c", 0), ("variadic_cast_fnptr_dispatch.c", 0), ("fcntl_lock_via_cast_fnptr.c", 0), + ("call_sp_adjust_imm12_overflow.c", 0), + ("indirect_call_target_scratch_exhausted.c", 0), + ("fp_load_folded_disp.c", 0), ]; #[test] diff --git a/tests/fixtures/c/call_sp_adjust_imm12_overflow.c b/tests/fixtures/c/call_sp_adjust_imm12_overflow.c new file mode 100644 index 000000000..d8ed16913 --- /dev/null +++ b/tests/fixtures/c/call_sp_adjust_imm12_overflow.c @@ -0,0 +1,348 @@ +/* Call-site SP adjustments must cover an outgoing-argument area past + the 12-bit add/sub immediate: 261 by-value 16-byte structs leave 257 + on the AAPCS64 stack (257 * 16 = 4112 bytes), and the indirect call + pushes 260 scalar arguments at the 16-byte stride (4160 bytes). + Both calls run direct and through a function pointer. */ +struct pair { + long a; + long b; +}; + +static struct pair g[261]; + +static long sum_pairs( + struct pair p0, struct pair p1, struct pair p2, struct pair p3, struct pair p4, struct pair p5, + struct pair p6, struct pair p7, struct pair p8, struct pair p9, struct pair p10, struct pair p11, + struct pair p12, struct pair p13, struct pair p14, struct pair p15, struct pair p16, struct pair p17, + struct pair p18, struct pair p19, struct pair p20, struct pair p21, struct pair p22, struct pair p23, + struct pair p24, struct pair p25, struct pair p26, struct pair p27, struct pair p28, struct pair p29, + struct pair p30, struct pair p31, struct pair p32, struct pair p33, struct pair p34, struct pair p35, + struct pair p36, struct pair p37, struct pair p38, struct pair p39, struct pair p40, struct pair p41, + struct pair p42, struct pair p43, struct pair p44, struct pair p45, struct pair p46, struct pair p47, + struct pair p48, struct pair p49, struct pair p50, struct pair p51, struct pair p52, struct pair p53, + struct pair p54, struct pair p55, struct pair p56, struct pair p57, struct pair p58, struct pair p59, + struct pair p60, struct pair p61, struct pair p62, struct pair p63, struct pair p64, struct pair p65, + struct pair p66, struct pair p67, struct pair p68, struct pair p69, struct pair p70, struct pair p71, + struct pair p72, struct pair p73, struct pair p74, struct pair p75, struct pair p76, struct pair p77, + struct pair p78, struct pair p79, struct pair p80, struct pair p81, struct pair p82, struct pair p83, + struct pair p84, struct pair p85, struct pair p86, struct pair p87, struct pair p88, struct pair p89, + struct pair p90, struct pair p91, struct pair p92, struct pair p93, struct pair p94, struct pair p95, + struct pair p96, struct pair p97, struct pair p98, struct pair p99, struct pair p100, struct pair p101, + struct pair p102, struct pair p103, struct pair p104, struct pair p105, struct pair p106, struct pair p107, + struct pair p108, struct pair p109, struct pair p110, struct pair p111, struct pair p112, struct pair p113, + struct pair p114, struct pair p115, struct pair p116, struct pair p117, struct pair p118, struct pair p119, + struct pair p120, struct pair p121, struct pair p122, struct pair p123, struct pair p124, struct pair p125, + struct pair p126, struct pair p127, struct pair p128, struct pair p129, struct pair p130, struct pair p131, + struct pair p132, struct pair p133, struct pair p134, struct pair p135, struct pair p136, struct pair p137, + struct pair p138, struct pair p139, struct pair p140, struct pair p141, struct pair p142, struct pair p143, + struct pair p144, struct pair p145, struct pair p146, struct pair p147, struct pair p148, struct pair p149, + struct pair p150, struct pair p151, struct pair p152, struct pair p153, struct pair p154, struct pair p155, + struct pair p156, struct pair p157, struct pair p158, struct pair p159, struct pair p160, struct pair p161, + struct pair p162, struct pair p163, struct pair p164, struct pair p165, struct pair p166, struct pair p167, + struct pair p168, struct pair p169, struct pair p170, struct pair p171, struct pair p172, struct pair p173, + struct pair p174, struct pair p175, struct pair p176, struct pair p177, struct pair p178, struct pair p179, + struct pair p180, struct pair p181, struct pair p182, struct pair p183, struct pair p184, struct pair p185, + struct pair p186, struct pair p187, struct pair p188, struct pair p189, struct pair p190, struct pair p191, + struct pair p192, struct pair p193, struct pair p194, struct pair p195, struct pair p196, struct pair p197, + struct pair p198, struct pair p199, struct pair p200, struct pair p201, struct pair p202, struct pair p203, + struct pair p204, struct pair p205, struct pair p206, struct pair p207, struct pair p208, struct pair p209, + struct pair p210, struct pair p211, struct pair p212, struct pair p213, struct pair p214, struct pair p215, + struct pair p216, struct pair p217, struct pair p218, struct pair p219, struct pair p220, struct pair p221, + struct pair p222, struct pair p223, struct pair p224, struct pair p225, struct pair p226, struct pair p227, + struct pair p228, struct pair p229, struct pair p230, struct pair p231, struct pair p232, struct pair p233, + struct pair p234, struct pair p235, struct pair p236, struct pair p237, struct pair p238, struct pair p239, + struct pair p240, struct pair p241, struct pair p242, struct pair p243, struct pair p244, struct pair p245, + struct pair p246, struct pair p247, struct pair p248, struct pair p249, struct pair p250, struct pair p251, + struct pair p252, struct pair p253, struct pair p254, struct pair p255, struct pair p256, struct pair p257, + struct pair p258, struct pair p259, struct pair p260) +{ + long s = 0; + s += p0.a + p0.b; s += p1.a + p1.b; s += p2.a + p2.b; s += p3.a + p3.b; + s += p4.a + p4.b; s += p5.a + p5.b; s += p6.a + p6.b; s += p7.a + p7.b; + s += p8.a + p8.b; s += p9.a + p9.b; s += p10.a + p10.b; s += p11.a + p11.b; + s += p12.a + p12.b; s += p13.a + p13.b; s += p14.a + p14.b; s += p15.a + p15.b; + s += p16.a + p16.b; s += p17.a + p17.b; s += p18.a + p18.b; s += p19.a + p19.b; + s += p20.a + p20.b; s += p21.a + p21.b; s += p22.a + p22.b; s += p23.a + p23.b; + s += p24.a + p24.b; s += p25.a + p25.b; s += p26.a + p26.b; s += p27.a + p27.b; + s += p28.a + p28.b; s += p29.a + p29.b; s += p30.a + p30.b; s += p31.a + p31.b; + s += p32.a + p32.b; s += p33.a + p33.b; s += p34.a + p34.b; s += p35.a + p35.b; + s += p36.a + p36.b; s += p37.a + p37.b; s += p38.a + p38.b; s += p39.a + p39.b; + s += p40.a + p40.b; s += p41.a + p41.b; s += p42.a + p42.b; s += p43.a + p43.b; + s += p44.a + p44.b; s += p45.a + p45.b; s += p46.a + p46.b; s += p47.a + p47.b; + s += p48.a + p48.b; s += p49.a + p49.b; s += p50.a + p50.b; s += p51.a + p51.b; + s += p52.a + p52.b; s += p53.a + p53.b; s += p54.a + p54.b; s += p55.a + p55.b; + s += p56.a + p56.b; s += p57.a + p57.b; s += p58.a + p58.b; s += p59.a + p59.b; + s += p60.a + p60.b; s += p61.a + p61.b; s += p62.a + p62.b; s += p63.a + p63.b; + s += p64.a + p64.b; s += p65.a + p65.b; s += p66.a + p66.b; s += p67.a + p67.b; + s += p68.a + p68.b; s += p69.a + p69.b; s += p70.a + p70.b; s += p71.a + p71.b; + s += p72.a + p72.b; s += p73.a + p73.b; s += p74.a + p74.b; s += p75.a + p75.b; + s += p76.a + p76.b; s += p77.a + p77.b; s += p78.a + p78.b; s += p79.a + p79.b; + s += p80.a + p80.b; s += p81.a + p81.b; s += p82.a + p82.b; s += p83.a + p83.b; + s += p84.a + p84.b; s += p85.a + p85.b; s += p86.a + p86.b; s += p87.a + p87.b; + s += p88.a + p88.b; s += p89.a + p89.b; s += p90.a + p90.b; s += p91.a + p91.b; + s += p92.a + p92.b; s += p93.a + p93.b; s += p94.a + p94.b; s += p95.a + p95.b; + s += p96.a + p96.b; s += p97.a + p97.b; s += p98.a + p98.b; s += p99.a + p99.b; + s += p100.a + p100.b; s += p101.a + p101.b; s += p102.a + p102.b; s += p103.a + p103.b; + s += p104.a + p104.b; s += p105.a + p105.b; s += p106.a + p106.b; s += p107.a + p107.b; + s += p108.a + p108.b; s += p109.a + p109.b; s += p110.a + p110.b; s += p111.a + p111.b; + s += p112.a + p112.b; s += p113.a + p113.b; s += p114.a + p114.b; s += p115.a + p115.b; + s += p116.a + p116.b; s += p117.a + p117.b; s += p118.a + p118.b; s += p119.a + p119.b; + s += p120.a + p120.b; s += p121.a + p121.b; s += p122.a + p122.b; s += p123.a + p123.b; + s += p124.a + p124.b; s += p125.a + p125.b; s += p126.a + p126.b; s += p127.a + p127.b; + s += p128.a + p128.b; s += p129.a + p129.b; s += p130.a + p130.b; s += p131.a + p131.b; + s += p132.a + p132.b; s += p133.a + p133.b; s += p134.a + p134.b; s += p135.a + p135.b; + s += p136.a + p136.b; s += p137.a + p137.b; s += p138.a + p138.b; s += p139.a + p139.b; + s += p140.a + p140.b; s += p141.a + p141.b; s += p142.a + p142.b; s += p143.a + p143.b; + s += p144.a + p144.b; s += p145.a + p145.b; s += p146.a + p146.b; s += p147.a + p147.b; + s += p148.a + p148.b; s += p149.a + p149.b; s += p150.a + p150.b; s += p151.a + p151.b; + s += p152.a + p152.b; s += p153.a + p153.b; s += p154.a + p154.b; s += p155.a + p155.b; + s += p156.a + p156.b; s += p157.a + p157.b; s += p158.a + p158.b; s += p159.a + p159.b; + s += p160.a + p160.b; s += p161.a + p161.b; s += p162.a + p162.b; s += p163.a + p163.b; + s += p164.a + p164.b; s += p165.a + p165.b; s += p166.a + p166.b; s += p167.a + p167.b; + s += p168.a + p168.b; s += p169.a + p169.b; s += p170.a + p170.b; s += p171.a + p171.b; + s += p172.a + p172.b; s += p173.a + p173.b; s += p174.a + p174.b; s += p175.a + p175.b; + s += p176.a + p176.b; s += p177.a + p177.b; s += p178.a + p178.b; s += p179.a + p179.b; + s += p180.a + p180.b; s += p181.a + p181.b; s += p182.a + p182.b; s += p183.a + p183.b; + s += p184.a + p184.b; s += p185.a + p185.b; s += p186.a + p186.b; s += p187.a + p187.b; + s += p188.a + p188.b; s += p189.a + p189.b; s += p190.a + p190.b; s += p191.a + p191.b; + s += p192.a + p192.b; s += p193.a + p193.b; s += p194.a + p194.b; s += p195.a + p195.b; + s += p196.a + p196.b; s += p197.a + p197.b; s += p198.a + p198.b; s += p199.a + p199.b; + s += p200.a + p200.b; s += p201.a + p201.b; s += p202.a + p202.b; s += p203.a + p203.b; + s += p204.a + p204.b; s += p205.a + p205.b; s += p206.a + p206.b; s += p207.a + p207.b; + s += p208.a + p208.b; s += p209.a + p209.b; s += p210.a + p210.b; s += p211.a + p211.b; + s += p212.a + p212.b; s += p213.a + p213.b; s += p214.a + p214.b; s += p215.a + p215.b; + s += p216.a + p216.b; s += p217.a + p217.b; s += p218.a + p218.b; s += p219.a + p219.b; + s += p220.a + p220.b; s += p221.a + p221.b; s += p222.a + p222.b; s += p223.a + p223.b; + s += p224.a + p224.b; s += p225.a + p225.b; s += p226.a + p226.b; s += p227.a + p227.b; + s += p228.a + p228.b; s += p229.a + p229.b; s += p230.a + p230.b; s += p231.a + p231.b; + s += p232.a + p232.b; s += p233.a + p233.b; s += p234.a + p234.b; s += p235.a + p235.b; + s += p236.a + p236.b; s += p237.a + p237.b; s += p238.a + p238.b; s += p239.a + p239.b; + s += p240.a + p240.b; s += p241.a + p241.b; s += p242.a + p242.b; s += p243.a + p243.b; + s += p244.a + p244.b; s += p245.a + p245.b; s += p246.a + p246.b; s += p247.a + p247.b; + s += p248.a + p248.b; s += p249.a + p249.b; s += p250.a + p250.b; s += p251.a + p251.b; + s += p252.a + p252.b; s += p253.a + p253.b; s += p254.a + p254.b; s += p255.a + p255.b; + s += p256.a + p256.b; s += p257.a + p257.b; s += p258.a + p258.b; s += p259.a + p259.b; + s += p260.a + p260.b; + return s; +} + +static long sum_longs( + long v1, long v2, long v3, long v4, long v5, long v6, long v7, long v8, + long v9, long v10, long v11, long v12, long v13, long v14, long v15, long v16, + long v17, long v18, long v19, long v20, long v21, long v22, long v23, long v24, + long v25, long v26, long v27, long v28, long v29, long v30, long v31, long v32, + long v33, long v34, long v35, long v36, long v37, long v38, long v39, long v40, + long v41, long v42, long v43, long v44, long v45, long v46, long v47, long v48, + long v49, long v50, long v51, long v52, long v53, long v54, long v55, long v56, + long v57, long v58, long v59, long v60, long v61, long v62, long v63, long v64, + long v65, long v66, long v67, long v68, long v69, long v70, long v71, long v72, + long v73, long v74, long v75, long v76, long v77, long v78, long v79, long v80, + long v81, long v82, long v83, long v84, long v85, long v86, long v87, long v88, + long v89, long v90, long v91, long v92, long v93, long v94, long v95, long v96, + long v97, long v98, long v99, long v100, long v101, long v102, long v103, long v104, + long v105, long v106, long v107, long v108, long v109, long v110, long v111, long v112, + long v113, long v114, long v115, long v116, long v117, long v118, long v119, long v120, + long v121, long v122, long v123, long v124, long v125, long v126, long v127, long v128, + long v129, long v130, long v131, long v132, long v133, long v134, long v135, long v136, + long v137, long v138, long v139, long v140, long v141, long v142, long v143, long v144, + long v145, long v146, long v147, long v148, long v149, long v150, long v151, long v152, + long v153, long v154, long v155, long v156, long v157, long v158, long v159, long v160, + long v161, long v162, long v163, long v164, long v165, long v166, long v167, long v168, + long v169, long v170, long v171, long v172, long v173, long v174, long v175, long v176, + long v177, long v178, long v179, long v180, long v181, long v182, long v183, long v184, + long v185, long v186, long v187, long v188, long v189, long v190, long v191, long v192, + long v193, long v194, long v195, long v196, long v197, long v198, long v199, long v200, + long v201, long v202, long v203, long v204, long v205, long v206, long v207, long v208, + long v209, long v210, long v211, long v212, long v213, long v214, long v215, long v216, + long v217, long v218, long v219, long v220, long v221, long v222, long v223, long v224, + long v225, long v226, long v227, long v228, long v229, long v230, long v231, long v232, + long v233, long v234, long v235, long v236, long v237, long v238, long v239, long v240, + long v241, long v242, long v243, long v244, long v245, long v246, long v247, long v248, + long v249, long v250, long v251, long v252, long v253, long v254, long v255, long v256, + long v257, long v258, long v259, long v260) +{ + long s = 0; + s += v1; s += v2; s += v3; s += v4; s += v5; s += v6; s += v7; s += v8; + s += v9; s += v10; s += v11; s += v12; s += v13; s += v14; s += v15; s += v16; + s += v17; s += v18; s += v19; s += v20; s += v21; s += v22; s += v23; s += v24; + s += v25; s += v26; s += v27; s += v28; s += v29; s += v30; s += v31; s += v32; + s += v33; s += v34; s += v35; s += v36; s += v37; s += v38; s += v39; s += v40; + s += v41; s += v42; s += v43; s += v44; s += v45; s += v46; s += v47; s += v48; + s += v49; s += v50; s += v51; s += v52; s += v53; s += v54; s += v55; s += v56; + s += v57; s += v58; s += v59; s += v60; s += v61; s += v62; s += v63; s += v64; + s += v65; s += v66; s += v67; s += v68; s += v69; s += v70; s += v71; s += v72; + s += v73; s += v74; s += v75; s += v76; s += v77; s += v78; s += v79; s += v80; + s += v81; s += v82; s += v83; s += v84; s += v85; s += v86; s += v87; s += v88; + s += v89; s += v90; s += v91; s += v92; s += v93; s += v94; s += v95; s += v96; + s += v97; s += v98; s += v99; s += v100; s += v101; s += v102; s += v103; s += v104; + s += v105; s += v106; s += v107; s += v108; s += v109; s += v110; s += v111; s += v112; + s += v113; s += v114; s += v115; s += v116; s += v117; s += v118; s += v119; s += v120; + s += v121; s += v122; s += v123; s += v124; s += v125; s += v126; s += v127; s += v128; + s += v129; s += v130; s += v131; s += v132; s += v133; s += v134; s += v135; s += v136; + s += v137; s += v138; s += v139; s += v140; s += v141; s += v142; s += v143; s += v144; + s += v145; s += v146; s += v147; s += v148; s += v149; s += v150; s += v151; s += v152; + s += v153; s += v154; s += v155; s += v156; s += v157; s += v158; s += v159; s += v160; + s += v161; s += v162; s += v163; s += v164; s += v165; s += v166; s += v167; s += v168; + s += v169; s += v170; s += v171; s += v172; s += v173; s += v174; s += v175; s += v176; + s += v177; s += v178; s += v179; s += v180; s += v181; s += v182; s += v183; s += v184; + s += v185; s += v186; s += v187; s += v188; s += v189; s += v190; s += v191; s += v192; + s += v193; s += v194; s += v195; s += v196; s += v197; s += v198; s += v199; s += v200; + s += v201; s += v202; s += v203; s += v204; s += v205; s += v206; s += v207; s += v208; + s += v209; s += v210; s += v211; s += v212; s += v213; s += v214; s += v215; s += v216; + s += v217; s += v218; s += v219; s += v220; s += v221; s += v222; s += v223; s += v224; + s += v225; s += v226; s += v227; s += v228; s += v229; s += v230; s += v231; s += v232; + s += v233; s += v234; s += v235; s += v236; s += v237; s += v238; s += v239; s += v240; + s += v241; s += v242; s += v243; s += v244; s += v245; s += v246; s += v247; s += v248; + s += v249; s += v250; s += v251; s += v252; s += v253; s += v254; s += v255; s += v256; + s += v257; s += v258; s += v259; s += v260; + return s; +} + +int main(void) { + long (*fp)( + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long, long) = sum_longs; + long (*sfp)( + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, struct pair, + struct pair, struct pair, struct pair, struct pair, struct pair) = sum_pairs; + long i; + for (i = 0; i < 261; i++) { + g[i].a = i; + g[i].b = 2 * i; + } + if (sum_pairs( + g[0], g[1], g[2], g[3], g[4], g[5], g[6], g[7], g[8], g[9], + g[10], g[11], g[12], g[13], g[14], g[15], g[16], g[17], g[18], g[19], + g[20], g[21], g[22], g[23], g[24], g[25], g[26], g[27], g[28], g[29], + g[30], g[31], g[32], g[33], g[34], g[35], g[36], g[37], g[38], g[39], + g[40], g[41], g[42], g[43], g[44], g[45], g[46], g[47], g[48], g[49], + g[50], g[51], g[52], g[53], g[54], g[55], g[56], g[57], g[58], g[59], + g[60], g[61], g[62], g[63], g[64], g[65], g[66], g[67], g[68], g[69], + g[70], g[71], g[72], g[73], g[74], g[75], g[76], g[77], g[78], g[79], + g[80], g[81], g[82], g[83], g[84], g[85], g[86], g[87], g[88], g[89], + g[90], g[91], g[92], g[93], g[94], g[95], g[96], g[97], g[98], g[99], + g[100], g[101], g[102], g[103], g[104], g[105], g[106], g[107], g[108], g[109], + g[110], g[111], g[112], g[113], g[114], g[115], g[116], g[117], g[118], g[119], + g[120], g[121], g[122], g[123], g[124], g[125], g[126], g[127], g[128], g[129], + g[130], g[131], g[132], g[133], g[134], g[135], g[136], g[137], g[138], g[139], + g[140], g[141], g[142], g[143], g[144], g[145], g[146], g[147], g[148], g[149], + g[150], g[151], g[152], g[153], g[154], g[155], g[156], g[157], g[158], g[159], + g[160], g[161], g[162], g[163], g[164], g[165], g[166], g[167], g[168], g[169], + g[170], g[171], g[172], g[173], g[174], g[175], g[176], g[177], g[178], g[179], + g[180], g[181], g[182], g[183], g[184], g[185], g[186], g[187], g[188], g[189], + g[190], g[191], g[192], g[193], g[194], g[195], g[196], g[197], g[198], g[199], + g[200], g[201], g[202], g[203], g[204], g[205], g[206], g[207], g[208], g[209], + g[210], g[211], g[212], g[213], g[214], g[215], g[216], g[217], g[218], g[219], + g[220], g[221], g[222], g[223], g[224], g[225], g[226], g[227], g[228], g[229], + g[230], g[231], g[232], g[233], g[234], g[235], g[236], g[237], g[238], g[239], + g[240], g[241], g[242], g[243], g[244], g[245], g[246], g[247], g[248], g[249], + g[250], g[251], g[252], g[253], g[254], g[255], g[256], g[257], g[258], g[259], + g[260]) + != 101790) { + return 1; + } + if (fp( + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, + 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260) + != 33930) { + return 2; + } + if (sfp( + g[0], g[1], g[2], g[3], g[4], g[5], g[6], g[7], g[8], g[9], + g[10], g[11], g[12], g[13], g[14], g[15], g[16], g[17], g[18], g[19], + g[20], g[21], g[22], g[23], g[24], g[25], g[26], g[27], g[28], g[29], + g[30], g[31], g[32], g[33], g[34], g[35], g[36], g[37], g[38], g[39], + g[40], g[41], g[42], g[43], g[44], g[45], g[46], g[47], g[48], g[49], + g[50], g[51], g[52], g[53], g[54], g[55], g[56], g[57], g[58], g[59], + g[60], g[61], g[62], g[63], g[64], g[65], g[66], g[67], g[68], g[69], + g[70], g[71], g[72], g[73], g[74], g[75], g[76], g[77], g[78], g[79], + g[80], g[81], g[82], g[83], g[84], g[85], g[86], g[87], g[88], g[89], + g[90], g[91], g[92], g[93], g[94], g[95], g[96], g[97], g[98], g[99], + g[100], g[101], g[102], g[103], g[104], g[105], g[106], g[107], g[108], g[109], + g[110], g[111], g[112], g[113], g[114], g[115], g[116], g[117], g[118], g[119], + g[120], g[121], g[122], g[123], g[124], g[125], g[126], g[127], g[128], g[129], + g[130], g[131], g[132], g[133], g[134], g[135], g[136], g[137], g[138], g[139], + g[140], g[141], g[142], g[143], g[144], g[145], g[146], g[147], g[148], g[149], + g[150], g[151], g[152], g[153], g[154], g[155], g[156], g[157], g[158], g[159], + g[160], g[161], g[162], g[163], g[164], g[165], g[166], g[167], g[168], g[169], + g[170], g[171], g[172], g[173], g[174], g[175], g[176], g[177], g[178], g[179], + g[180], g[181], g[182], g[183], g[184], g[185], g[186], g[187], g[188], g[189], + g[190], g[191], g[192], g[193], g[194], g[195], g[196], g[197], g[198], g[199], + g[200], g[201], g[202], g[203], g[204], g[205], g[206], g[207], g[208], g[209], + g[210], g[211], g[212], g[213], g[214], g[215], g[216], g[217], g[218], g[219], + g[220], g[221], g[222], g[223], g[224], g[225], g[226], g[227], g[228], g[229], + g[230], g[231], g[232], g[233], g[234], g[235], g[236], g[237], g[238], g[239], + g[240], g[241], g[242], g[243], g[244], g[245], g[246], g[247], g[248], g[249], + g[250], g[251], g[252], g[253], g[254], g[255], g[256], g[257], g[258], g[259], + g[260]) + != 101790) { + return 3; + } + return 0; +} diff --git a/tests/fixtures/c/fp_load_folded_disp.c b/tests/fixtures/c/fp_load_folded_disp.c new file mode 100644 index 000000000..89665af9d --- /dev/null +++ b/tests/fixtures/c/fp_load_folded_disp.c @@ -0,0 +1,40 @@ +/* A constant pointer offset folded into a floating load's displacement + must reach the emitted access: the load reads *(base + c), not *base. + The struct places float and double members at nonzero offsets; the + read-modify-write shares one folded address between a load and a + store. */ +struct pack { + long tag; + float f; /* offset 8 */ + double d; /* offset 16 */ + float g[3]; /* offsets 24, 28, 32 */ +}; + +static float read_f(struct pack *p) { return p->f; } +static double read_d(struct pack *p) { return p->d; } +static float read_g2(struct pack *p) { return p->g[2]; } +static void bump_d(struct pack *p) { p->d = p->d + 0.5; } + +int main(void) { + struct pack p; + p.tag = -1; + p.f = 1.25f; + p.d = 2.5; + p.g[0] = 0.0f; + p.g[1] = 0.0f; + p.g[2] = 4.75f; + if (read_f(&p) != 1.25f) { + return 1; + } + if (read_d(&p) != 2.5) { + return 2; + } + if (read_g2(&p) != 4.75f) { + return 3; + } + bump_d(&p); + if (p.d != 3.0) { + return 4; + } + return 0; +} diff --git a/tests/fixtures/c/indirect_call_target_scratch_exhausted.c b/tests/fixtures/c/indirect_call_target_scratch_exhausted.c new file mode 100644 index 000000000..bc668f843 --- /dev/null +++ b/tests/fixtures/c/indirect_call_target_scratch_exhausted.c @@ -0,0 +1,52 @@ +/* An indirect call whose argument sources occupy every caller-saved + target-capture candidate register must not overwrite a live source + with the function pointer: 17 scalar arguments exercise the + 16-byte-stride push path, 16 by-value structs the host-ABI marshal + path. */ +struct pr { + long a; + long b; +}; + +static struct pr g[16]; + +static long sum17(long v1, long v2, long v3, long v4, long v5, long v6, + long v7, long v8, long v9, long v10, long v11, long v12, + long v13, long v14, long v15, long v16, long v17) { + return v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10 + v11 + v12 + + v13 + v14 + v15 + v16 + v17; +} + +static long sum16p(struct pr p0, struct pr p1, struct pr p2, struct pr p3, + struct pr p4, struct pr p5, struct pr p6, struct pr p7, + struct pr p8, struct pr p9, struct pr p10, struct pr p11, + struct pr p12, struct pr p13, struct pr p14, + struct pr p15) { + return p0.a + p0.b + p1.a + p1.b + p2.a + p2.b + p3.a + p3.b + p4.a + + p4.b + p5.a + p5.b + p6.a + p6.b + p7.a + p7.b + p8.a + p8.b + + p9.a + p9.b + p10.a + p10.b + p11.a + p11.b + p12.a + p12.b + + p13.a + p13.b + p14.a + p14.b + p15.a + p15.b; +} + +int main(void) { + long (*fp)(long, long, long, long, long, long, long, long, long, long, + long, long, long, long, long, long, long) = sum17; + long (*sfp)(struct pr, struct pr, struct pr, struct pr, struct pr, + struct pr, struct pr, struct pr, struct pr, struct pr, + struct pr, struct pr, struct pr, struct pr, struct pr, + struct pr) = sum16p; + long i; + for (i = 0; i < 16; i++) { + g[i].a = i; + g[i].b = 2 * i; + } + if (fp(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17) != + 153) { + return 1; + } + if (sfp(g[0], g[1], g[2], g[3], g[4], g[5], g[6], g[7], g[8], g[9], + g[10], g[11], g[12], g[13], g[14], g[15]) != 360) { + return 2; + } + return 0; +} From 29270c88c705a2f421104cba91e44cf759c4da5a Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 01:30:30 -0700 Subject: [PATCH 60/67] tests: snapshots for the aarch64 FP-displacement and SP-adjust codegen FP loads now fold the displacement in place (disp=N replaces a separate add) and call sites use the 24-bit SP-adjust split, changing the emitted shapes the affected fixtures pin. Co-Authored-By: Claude Fable 5 --- .../asm/addr_of_intrinsic_math.aarch64.asm | 16 +- .../addr_of_intrinsic_math_float.aarch64.asm | 16 +- .../asm/addr_of_libc_strcmp.aarch64.asm | 8 +- .../asm/addr_of_libm_import.aarch64.asm | 10 +- .../asm/anonymous_aggregates.aarch64.asm | 3 +- .../asm/anonymous_aggregates.x64.asm | 4 +- .../asm/array_2d_struct_init.aarch64.asm | 21 +- .../asm/array_2d_struct_init.x64.asm | 23 +- ...irect_target_scratch_collision.aarch64.asm | 2 +- .../call_sp_adjust_imm12_overflow.aarch64.asm | 9673 +++++++++++++++++ .../asm/call_sp_adjust_imm12_overflow.x64.asm | 8393 ++++++++++++++ .../asm/cast_fn_ptr_call.aarch64.asm | 6 +- ..._fn_typedef_ptr_in_initializer.aarch64.asm | 2 +- tests/snapshots/asm/dlopen_atoi.aarch64.asm | 2 +- tests/snapshots/asm/dlopen_strlen.aarch64.asm | 2 +- .../float_arith_in_static_init.aarch64.asm | 9 +- .../asm/float_arith_in_static_init.x64.asm | 11 +- .../asm/float_increment_decrement.aarch64.asm | 24 +- .../asm/float_increment_decrement.x64.asm | 25 +- .../asm/float_is_four_bytes.aarch64.asm | 18 +- .../snapshots/asm/float_is_four_bytes.x64.asm | 19 +- .../asm/fma_numeric_kernels.aarch64.asm | 12 +- .../snapshots/asm/fma_numeric_kernels.x64.asm | 12 +- .../asm/fn_ptr_decay_inside_block.aarch64.asm | 8 +- .../asm/fn_ptr_explicit_deref.aarch64.asm | 8 +- .../asm/fn_ptr_float_arg.aarch64.asm | 8 +- .../asm/fn_ptr_float_arg_narrow.aarch64.asm | 18 +- .../asm/fn_ptr_float_return.aarch64.asm | 6 +- .../asm/fn_ptr_multi_deref.aarch64.asm | 4 +- .../asm/fn_ptr_struct_return.aarch64.asm | 12 +- .../fn_ptr_ternary_call_return.aarch64.asm | 4 +- ...n_ptr_typedef_multi_declarator.aarch64.asm | 4 +- .../asm/fn_returning_fn_ptr.aarch64.asm | 6 +- .../asm/fnptr_param_indirection.aarch64.asm | 6 +- .../fnptr_typedef_return_proto.aarch64.asm | 2 +- .../asm/forge_code_pointer.aarch64.asm | 2 +- .../forward_fn_ptr_in_static_init.aarch64.asm | 2 +- .../asm/fp_load_folded_disp.aarch64.asm | 114 + .../snapshots/asm/fp_load_folded_disp.x64.asm | 134 + .../funcptr_global_addressof_init.aarch64.asm | 4 +- .../asm/function_pointer_typedefs.aarch64.asm | 14 +- .../asm/function_pointers.aarch64.asm | 4 +- .../asm/function_type_typedef.aarch64.asm | 4 +- ...ction_type_typedef_declaration.aarch64.asm | 6 +- .../asm/function_typed_parameter.aarch64.asm | 6 +- .../asm/hfa_param_interleave.aarch64.asm | 12 +- .../asm/hfa_param_interleave.x64.asm | 12 +- .../asm/hfa_struct_return.aarch64.asm | 63 +- tests/snapshots/asm/hfa_struct_return.x64.asm | 64 +- ...t_call_six_args_spilled_target.aarch64.asm | 2 +- ..._call_target_scratch_exhausted.aarch64.asm | 476 + ...rect_call_target_scratch_exhausted.x64.asm | 447 + ...ect_call_through_global_fn_ptr.aarch64.asm | 2 +- .../asm/init_float_to_int.aarch64.asm | 3 +- tests/snapshots/asm/init_float_to_int.x64.asm | 4 +- .../asm/init_scalar_conversion.aarch64.asm | 45 +- .../asm/init_scalar_conversion.x64.asm | 47 +- .../asm/libc_pread64_pwrite64.aarch64.asm | 4 +- .../asm/mem2reg_value_across_call.aarch64.asm | 2 +- .../mixed_sse_int_aggregate_args.aarch64.asm | 12 +- .../asm/mixed_sse_int_aggregate_args.x64.asm | 12 +- .../asm/mixed_struct_gpr_abi.aarch64.asm | 12 +- .../asm/mixed_struct_gpr_abi.x64.asm | 7 +- tests/snapshots/asm/msvc_callconv.aarch64.asm | 4 +- .../negative_float_in_array_init.aarch64.asm | 12 +- .../asm/negative_float_in_array_init.x64.asm | 14 +- .../out_pointer_return_float_args.aarch64.asm | 54 +- .../asm/out_pointer_return_float_args.x64.asm | 55 +- .../snapshots/asm/pthread_create.aarch64.asm | 4 +- tests/snapshots/asm/sqlite_min.aarch64.asm | 8 +- .../asm/static_init_cast_funcptr.aarch64.asm | 8 +- .../static_init_paren_relocation.aarch64.asm | 4 +- .../static_init_struct_fp_call.aarch64.asm | 4 +- .../asm/static_neg_infinity_init.aarch64.asm | 3 +- .../asm/static_neg_infinity_init.x64.asm | 5 +- .../struct_arg_indirect_subscript.aarch64.asm | 3 +- .../asm/struct_arg_indirect_subscript.x64.asm | 5 +- ...struct_fn_ptr_field_deref_call.aarch64.asm | 8 +- .../asm/struct_initializers.aarch64.asm | 10 +- .../asm/sys_addr_in_static_init.aarch64.asm | 8 +- .../asm/thread_local_per_thread.aarch64.asm | 4 +- ...two_d_float_array_partial_init.aarch64.asm | 6 +- .../two_d_float_array_partial_init.x64.asm | 7 +- ..._d_stride_no_leak_across_exprs.aarch64.asm | 3 +- .../two_d_stride_no_leak_across_exprs.x64.asm | 4 +- .../typedef_fn_ptr_struct_field.aarch64.asm | 8 +- ...ary_plus_init_and_param_shadow.aarch64.asm | 9 +- .../unary_plus_init_and_param_shadow.x64.asm | 9 +- .../union_member_unbraced_init.aarch64.asm | 3 +- .../asm/union_member_unbraced_init.x64.asm | 4 +- .../variadic_agg_return_classes.aarch64.asm | 6 +- .../asm/variadic_agg_return_classes.x64.asm | 7 +- .../asm/variadic_hfa_struct_arg.aarch64.asm | 6 +- .../asm/variadic_hfa_struct_arg.x64.asm | 7 +- ...oid_function_produces_no_value.aarch64.asm | 6 +- .../asm/vtable_back_to_back.aarch64.asm | 4 +- .../asm/vtable_back_to_back_4arg.aarch64.asm | 4 +- tests/snapshots/ssa/anonymous_aggregates.ssa | 4 +- tests/snapshots/ssa/array_2d_struct_init.ssa | 26 +- .../ssa/call_sp_adjust_imm12_overflow.ssa | 4835 ++++++++ .../ssa/float_arith_in_static_init.ssa | 10 +- .../ssa/float_increment_decrement.ssa | 30 +- tests/snapshots/ssa/float_is_four_bytes.ssa | 24 +- tests/snapshots/ssa/fma_numeric_kernels.ssa | 16 +- tests/snapshots/ssa/fp_load_folded_disp.ssa | 186 + tests/snapshots/ssa/hfa_param_interleave.ssa | 16 +- tests/snapshots/ssa/hfa_struct_return.ssa | 84 +- ...indirect_call_target_scratch_exhausted.ssa | 322 + tests/snapshots/ssa/init_float_to_int.ssa | 4 +- .../snapshots/ssa/init_scalar_conversion.ssa | 60 +- .../ssa/mixed_sse_int_aggregate_args.ssa | 16 +- tests/snapshots/ssa/mixed_struct_gpr_abi.ssa | 8 +- .../ssa/negative_float_in_array_init.ssa | 10 +- .../ssa/out_pointer_return_float_args.ssa | 72 +- .../ssa/static_neg_infinity_init.ssa | 4 +- .../ssa/struct_arg_indirect_subscript.ssa | 4 +- .../ssa/two_d_float_array_partial_init.ssa | 6 +- .../ssa/two_d_stride_no_leak_across_exprs.ssa | 4 +- .../ssa/unary_plus_init_and_param_shadow.ssa | 6 +- .../ssa/union_member_unbraced_init.ssa | 4 +- .../ssa/variadic_agg_return_classes.ssa | 8 +- .../snapshots/ssa/variadic_hfa_struct_arg.ssa | 8 +- 122 files changed, 25169 insertions(+), 817 deletions(-) create mode 100644 tests/snapshots/asm/call_sp_adjust_imm12_overflow.aarch64.asm create mode 100644 tests/snapshots/asm/call_sp_adjust_imm12_overflow.x64.asm create mode 100644 tests/snapshots/asm/fp_load_folded_disp.aarch64.asm create mode 100644 tests/snapshots/asm/fp_load_folded_disp.x64.asm create mode 100644 tests/snapshots/asm/indirect_call_target_scratch_exhausted.aarch64.asm create mode 100644 tests/snapshots/asm/indirect_call_target_scratch_exhausted.x64.asm create mode 100644 tests/snapshots/ssa/call_sp_adjust_imm12_overflow.ssa create mode 100644 tests/snapshots/ssa/fp_load_folded_disp.ssa create mode 100644 tests/snapshots/ssa/indirect_call_target_scratch_exhausted.ssa diff --git a/tests/snapshots/asm/addr_of_intrinsic_math.aarch64.asm b/tests/snapshots/asm/addr_of_intrinsic_math.aarch64.asm index bd95c9314..9c7e1ab0f 100644 --- a/tests/snapshots/asm/addr_of_intrinsic_math.aarch64.asm +++ b/tests/snapshots/asm/addr_of_intrinsic_math.aarch64.asm @@ -32,9 +32,9 @@ Disassembly of section .text: mov x24, #0x400c000000000000 // =4615063718147915776 fmov d16, x24 fneg d0, d16 - mov x9, x0 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -53,8 +53,8 @@ Disassembly of section .text: ldp x29, x30, [sp], #0x10 ret mov x0, #0x4030000000000000 // =4625196817309499392 - mov x9, x20 str x0, [sp, #-0x10]! + mov x9, x20 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -77,8 +77,8 @@ Disassembly of section .text: movk x0, #0x9999, lsl #16 movk x0, #0x9999, lsl #32 movk x0, #0x4005, lsl #48 - mov x9, x21 str x0, [sp, #-0x10]! + mov x9, x21 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -101,8 +101,8 @@ Disassembly of section .text: movk x0, #0xcccc, lsl #16 movk x0, #0xcccc, lsl #32 movk x0, #0x4000, lsl #48 - mov x9, x22 str x0, [sp, #-0x10]! + mov x9, x22 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -125,8 +125,8 @@ Disassembly of section .text: movk x0, #0x3333, lsl #16 movk x0, #0x3333, lsl #32 movk x0, #0x4007, lsl #48 - mov x9, x23 str x0, [sp, #-0x10]! + mov x9, x23 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -161,9 +161,9 @@ Disassembly of section .text: mov x20, #0x4022000000000000 // =4621256167635550208 fmov d16, x20 fneg d0, d16 - mov x9, x0 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -185,8 +185,8 @@ Disassembly of section .text: ldr x0, [x0, #0x8] mov x1, #0x400000000000 // =70368744177664 movk x1, #0x4054, lsl #48 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -211,8 +211,8 @@ Disassembly of section .text: movk x1, #0x9999, lsl #16 movk x1, #0x9999, lsl #32 movk x1, #0x4017, lsl #48 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/addr_of_intrinsic_math_float.aarch64.asm b/tests/snapshots/asm/addr_of_intrinsic_math_float.aarch64.asm index 4944046c5..aad4e05a0 100644 --- a/tests/snapshots/asm/addr_of_intrinsic_math_float.aarch64.asm +++ b/tests/snapshots/asm/addr_of_intrinsic_math_float.aarch64.asm @@ -30,9 +30,9 @@ Disassembly of section .text: mov x1, #0x4030000000000000 // =4625196817309499392 fmov d16, x1 fcvt s0, d16 - mov x9, x0 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -58,9 +58,9 @@ Disassembly of section .text: movk x0, #0x4005, lsl #48 fmov d16, x0 fcvt s0, d16 - mov x9, x20 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x20 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -86,9 +86,9 @@ Disassembly of section .text: movk x0, #0x4000, lsl #48 fmov d16, x0 fcvt s0, d16 - mov x9, x21 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x21 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -114,9 +114,9 @@ Disassembly of section .text: movk x0, #0x4007, lsl #48 fmov d16, x0 fcvt s0, d16 - mov x9, x22 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x22 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -142,9 +142,9 @@ Disassembly of section .text: fmov d16, x20 fneg d0, d16 fcvt s0, d0 - mov x9, x0 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -192,9 +192,9 @@ Disassembly of section .text: fcvt s9, d16 sub x0, x29, #0x40 ldr x0, [x0] - mov x9, x0 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -216,9 +216,9 @@ Disassembly of section .text: ret sub x0, x29, #0x40 ldr x0, [x0, #0x8] - mov x9, x0 fmov x16, d8 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -240,9 +240,9 @@ Disassembly of section .text: ret sub x0, x29, #0x40 ldr x0, [x0, #0x10] - mov x9, x0 fmov x16, d9 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/addr_of_libc_strcmp.aarch64.asm b/tests/snapshots/asm/addr_of_libc_strcmp.aarch64.asm index 69f0fdf2b..cb1b3934c 100644 --- a/tests/snapshots/asm/addr_of_libc_strcmp.aarch64.asm +++ b/tests/snapshots/asm/addr_of_libc_strcmp.aarch64.asm @@ -22,9 +22,9 @@ Disassembly of section .text: add x0, x0, adrp x1, add x1, x1, - mov x9, x20 str x1, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -43,9 +43,9 @@ Disassembly of section .text: add x0, x0, adrp x1, add x1, x1, - mov x9, x20 str x1, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -64,9 +64,9 @@ Disassembly of section .text: add x0, x0, adrp x1, add x1, x1, - mov x9, x20 str x1, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -92,9 +92,9 @@ Disassembly of section .text: add x0, x0, adrp x1, add x1, x1, - mov x9, x20 str x1, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/addr_of_libm_import.aarch64.asm b/tests/snapshots/asm/addr_of_libm_import.aarch64.asm index 7fbebd3dd..dff444c5b 100644 --- a/tests/snapshots/asm/addr_of_libm_import.aarch64.asm +++ b/tests/snapshots/asm/addr_of_libm_import.aarch64.asm @@ -24,8 +24,8 @@ Disassembly of section .text: adrp x21, add x21, x21, mov x22, #0x0 // =0 - mov x9, x0 str x22, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -42,8 +42,8 @@ Disassembly of section .text: ldp x29, x30, [sp], #0x10 ret mov x0, #0x0 // =0 - mov x9, x20 str x0, [sp, #-0x10]! + mov x9, x20 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -62,9 +62,9 @@ Disassembly of section .text: ret mov x0, #0x4000000000000000 // =4611686018427387904 mov x1, #0x4024000000000000 // =4621819117588971520 - mov x9, x21 str x1, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x21 ldr d0, [sp] ldr d1, [sp, #0x10] blr x9 @@ -94,8 +94,8 @@ Disassembly of section .text: sub x0, x29, #0x28 mov x20, #0x0 // =0 ldr x0, [x0] - mov x9, x0 str x20, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -114,8 +114,8 @@ Disassembly of section .text: sub x0, x29, #0x28 ldr x0, [x0, #0x8] mov x1, #0x0 // =0 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/anonymous_aggregates.aarch64.asm b/tests/snapshots/asm/anonymous_aggregates.aarch64.asm index 5b80184a4..28e97cff9 100644 --- a/tests/snapshots/asm/anonymous_aggregates.aarch64.asm +++ b/tests/snapshots/asm/anonymous_aggregates.aarch64.asm @@ -138,13 +138,12 @@ Disassembly of section .text: ldp x29, x30, [sp], #0x10 ret sub x0, x29, #0x20 - add x0, x0, #0x8 mov x1, #0x851f // =34079 movk x1, #0x51eb, lsl #16 movk x1, #0x1eb8, lsl #32 movk x1, #0x4009, lsl #48 fmov d16, x1 - str d16, [x0] + str d16, [x0, #0x8] sub x0, x29, #0x20 ldrsw x0, [x0] cmp x0, #0x1 diff --git a/tests/snapshots/asm/anonymous_aggregates.x64.asm b/tests/snapshots/asm/anonymous_aggregates.x64.asm index 8debd04c3..83b4498a3 100644 --- a/tests/snapshots/asm/anonymous_aggregates.x64.asm +++ b/tests/snapshots/asm/anonymous_aggregates.x64.asm @@ -122,10 +122,9 @@ Disassembly of section .text: popq %rbp retq leaq -0x20(%rbp), %rax - addq $0x8, %rax movabsq $0x40091eb851eb851f, %rcx # imm = 0x40091EB851EB851F movq %rcx, %xmm14 - movsd %xmm14, (%rax,%riz) + movsd %xmm14, 0x8(%rax,%riz) leaq -0x20(%rbp), %rax movslq (%rax), %rax cmpq $0x1, %rax @@ -317,4 +316,3 @@ Disassembly of section .text: popq %rbp retq addb %al, (%rax) - addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/array_2d_struct_init.aarch64.asm b/tests/snapshots/asm/array_2d_struct_init.aarch64.asm index 81f417eeb..015cb4dde 100644 --- a/tests/snapshots/asm/array_2d_struct_init.aarch64.asm +++ b/tests/snapshots/asm/array_2d_struct_init.aarch64.asm @@ -21,8 +21,7 @@ Disassembly of section .text: fcmp d0, d1 cset x1, ne cbnz x1, - add x1, x0, #0x18 - ldr d0, [x1] + ldr d0, [x0, #0x18] mov x1, #0x4 // =4 scvtf d1, x1 fcmp d0, d1 @@ -31,8 +30,7 @@ Disassembly of section .text: cset x3, ne mov x2, #0x1 // =1 cbnz x3, - add x1, x0, #0x20 - ldr d0, [x1] + ldr d0, [x0, #0x20] mov x1, #0x5 // =5 scvtf d1, x1 fcmp d0, d1 @@ -40,8 +38,7 @@ Disassembly of section .text: cmp x1, #0x0 cset x2, ne cbnz x2, - add x0, x0, #0x38 - ldr d0, [x0] + ldr d0, [x0, #0x38] mov x0, #0x8 // =8 scvtf d1, x0 fcmp d0, d1 @@ -61,8 +58,7 @@ Disassembly of section .text: cbnz x0, adrp x0, add x0, x0, - add x0, x0, #0x78 - ldr d0, [x0] + ldr d0, [x0, #0x78] mov x0, #0x8 // =8 scvtf d1, x0 fcmp d0, d1 @@ -72,8 +68,7 @@ Disassembly of section .text: cbnz x2, adrp x0, add x0, x0, - add x0, x0, #0x50 - ldr d0, [x0] + ldr d0, [x0, #0x50] mov x0, #0x6 // =6 scvtf d1, x0 fcmp d0, d1 @@ -95,8 +90,7 @@ Disassembly of section .text: adrp x0, add x0, x0, mov x1, #0x10 // =16 - add x0, x0, #0x38 - ldr d0, [x0] + ldr d0, [x0, #0x38] scvtf d1, x1 fcmp d0, d1 cset x0, ne @@ -105,8 +99,7 @@ Disassembly of section .text: cbnz x2, adrp x0, add x0, x0, - add x0, x0, #0x10 - ldr d0, [x0] + ldr d0, [x0, #0x10] mov x0, #0xb // =11 scvtf d1, x0 fcmp d0, d1 diff --git a/tests/snapshots/asm/array_2d_struct_init.x64.asm b/tests/snapshots/asm/array_2d_struct_init.x64.asm index f7617676d..8f6592cee 100644 --- a/tests/snapshots/asm/array_2d_struct_init.x64.asm +++ b/tests/snapshots/asm/array_2d_struct_init.x64.asm @@ -26,8 +26,7 @@ Disassembly of section .text: orq %r10, %rcx testq %rcx, %rcx jne - leaq 0x18(%rax), %rcx - movsd (%rcx,%riz), %xmm0 + movsd 0x18(%rax,%riz), %xmm0 movl $0x4, %ecx cvtsi2sd %rcx, %xmm1 ucomisd %xmm1, %xmm0 @@ -42,8 +41,7 @@ Disassembly of section .text: movl $0x1, %edx testq %rsi, %rsi jne - leaq 0x20(%rax), %rcx - movsd (%rcx,%riz), %xmm0 + movsd 0x20(%rax,%riz), %xmm0 movl $0x5, %ecx cvtsi2sd %rcx, %xmm1 ucomisd %xmm1, %xmm0 @@ -57,8 +55,7 @@ Disassembly of section .text: movzbq %dl, %rdx testq %rdx, %rdx jne - addq $0x38, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x38(%rax,%riz), %xmm0 movl $0x8, %eax cvtsi2sd %rax, %xmm1 ucomisd %xmm1, %xmm0 @@ -86,8 +83,7 @@ Disassembly of section .text: testq %rax, %rax jne leaq , %rax - addq $0x78, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x78(%rax,%riz), %xmm0 movl $0x8, %eax cvtsi2sd %rax, %xmm1 ucomisd %xmm1, %xmm0 @@ -102,8 +98,7 @@ Disassembly of section .text: testq %rdx, %rdx jne leaq , %rax - addq $0x50, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x50(%rax,%riz), %xmm0 movl $0x6, %eax cvtsi2sd %rax, %xmm1 ucomisd %xmm1, %xmm0 @@ -133,8 +128,7 @@ Disassembly of section .text: jne leaq , %rax movl $0x10, %ecx - addq $0x38, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x38(%rax,%riz), %xmm0 cvtsi2sd %rcx, %xmm1 ucomisd %xmm1, %xmm0 setne %al @@ -148,8 +142,7 @@ Disassembly of section .text: testq %rdx, %rdx jne leaq , %rax - addq $0x10, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x10(%rax,%riz), %xmm0 movl $0xb, %eax cvtsi2sd %rax, %xmm1 ucomisd %xmm1, %xmm0 @@ -175,4 +168,4 @@ Disassembly of section .text: jmp jmp jmp - addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/call_indirect_target_scratch_collision.aarch64.asm b/tests/snapshots/asm/call_indirect_target_scratch_collision.aarch64.asm index fb26a5adc..f80c2f024 100644 --- a/tests/snapshots/asm/call_indirect_target_scratch_collision.aarch64.asm +++ b/tests/snapshots/asm/call_indirect_target_scratch_collision.aarch64.asm @@ -25,12 +25,12 @@ Disassembly of section .text: ldr x5, [x0] mov x17, #0xffff // =65535 and x3, x3, x17 - mov x9, x5 str x4, [sp, #-0x10]! str x3, [sp, #-0x10]! str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x5 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] diff --git a/tests/snapshots/asm/call_sp_adjust_imm12_overflow.aarch64.asm b/tests/snapshots/asm/call_sp_adjust_imm12_overflow.aarch64.asm new file mode 100644 index 000000000..d01f17e8b --- /dev/null +++ b/tests/snapshots/asm/call_sp_adjust_imm12_overflow.aarch64.asm @@ -0,0 +1,9673 @@ + +call_sp_adjust_imm12_overflow.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x1, lsl #12 // =0x1000 + sub sp, sp, #0x60 + sub x16, x29, #0x10 + str x0, [x16] + str x1, [x16, #0x8] + sub x16, x29, #0x20 + str x2, [x16] + str x3, [x16, #0x8] + sub x16, x29, #0x30 + str x4, [x16] + str x5, [x16, #0x8] + sub x16, x29, #0x40 + str x6, [x16] + str x7, [x16, #0x8] + sub x16, x29, #0x50 + ldr x17, [x29, #0x1060] + str x17, [x16] + ldr x17, [x29, #0x1068] + str x17, [x16, #0x8] + sub x16, x29, #0x60 + ldr x17, [x29, #0x1070] + str x17, [x16] + ldr x17, [x29, #0x1078] + str x17, [x16, #0x8] + sub x16, x29, #0x70 + ldr x17, [x29, #0x1080] + str x17, [x16] + ldr x17, [x29, #0x1088] + str x17, [x16, #0x8] + sub x16, x29, #0x80 + ldr x17, [x29, #0x1090] + str x17, [x16] + ldr x17, [x29, #0x1098] + str x17, [x16, #0x8] + sub x16, x29, #0x90 + ldr x17, [x29, #0x10a0] + str x17, [x16] + ldr x17, [x29, #0x10a8] + str x17, [x16, #0x8] + sub x16, x29, #0xa0 + ldr x17, [x29, #0x10b0] + str x17, [x16] + ldr x17, [x29, #0x10b8] + str x17, [x16, #0x8] + sub x16, x29, #0xb0 + ldr x17, [x29, #0x10c0] + str x17, [x16] + ldr x17, [x29, #0x10c8] + str x17, [x16, #0x8] + sub x16, x29, #0xc0 + ldr x17, [x29, #0x10d0] + str x17, [x16] + ldr x17, [x29, #0x10d8] + str x17, [x16, #0x8] + sub x16, x29, #0xd0 + ldr x17, [x29, #0x10e0] + str x17, [x16] + ldr x17, [x29, #0x10e8] + str x17, [x16, #0x8] + sub x16, x29, #0xe0 + ldr x17, [x29, #0x10f0] + str x17, [x16] + ldr x17, [x29, #0x10f8] + str x17, [x16, #0x8] + sub x16, x29, #0xf0 + ldr x17, [x29, #0x1100] + str x17, [x16] + ldr x17, [x29, #0x1108] + str x17, [x16, #0x8] + sub x16, x29, #0x100 + ldr x17, [x29, #0x1110] + str x17, [x16] + ldr x17, [x29, #0x1118] + str x17, [x16, #0x8] + sub x16, x29, #0x110 + ldr x17, [x29, #0x1120] + str x17, [x16] + ldr x17, [x29, #0x1128] + str x17, [x16, #0x8] + sub x16, x29, #0x120 + ldr x17, [x29, #0x1130] + str x17, [x16] + ldr x17, [x29, #0x1138] + str x17, [x16, #0x8] + sub x16, x29, #0x130 + ldr x17, [x29, #0x1140] + str x17, [x16] + ldr x17, [x29, #0x1148] + str x17, [x16, #0x8] + sub x16, x29, #0x140 + ldr x17, [x29, #0x1150] + str x17, [x16] + ldr x17, [x29, #0x1158] + str x17, [x16, #0x8] + sub x16, x29, #0x150 + ldr x17, [x29, #0x1160] + str x17, [x16] + ldr x17, [x29, #0x1168] + str x17, [x16, #0x8] + sub x16, x29, #0x160 + ldr x17, [x29, #0x1170] + str x17, [x16] + ldr x17, [x29, #0x1178] + str x17, [x16, #0x8] + sub x16, x29, #0x170 + ldr x17, [x29, #0x1180] + str x17, [x16] + ldr x17, [x29, #0x1188] + str x17, [x16, #0x8] + sub x16, x29, #0x180 + ldr x17, [x29, #0x1190] + str x17, [x16] + ldr x17, [x29, #0x1198] + str x17, [x16, #0x8] + sub x16, x29, #0x190 + ldr x17, [x29, #0x11a0] + str x17, [x16] + ldr x17, [x29, #0x11a8] + str x17, [x16, #0x8] + sub x16, x29, #0x1a0 + ldr x17, [x29, #0x11b0] + str x17, [x16] + ldr x17, [x29, #0x11b8] + str x17, [x16, #0x8] + sub x16, x29, #0x1b0 + ldr x17, [x29, #0x11c0] + str x17, [x16] + ldr x17, [x29, #0x11c8] + str x17, [x16, #0x8] + sub x16, x29, #0x1c0 + ldr x17, [x29, #0x11d0] + str x17, [x16] + ldr x17, [x29, #0x11d8] + str x17, [x16, #0x8] + sub x16, x29, #0x1d0 + ldr x17, [x29, #0x11e0] + str x17, [x16] + ldr x17, [x29, #0x11e8] + str x17, [x16, #0x8] + sub x16, x29, #0x1e0 + ldr x17, [x29, #0x11f0] + str x17, [x16] + ldr x17, [x29, #0x11f8] + str x17, [x16, #0x8] + sub x16, x29, #0x1f0 + ldr x17, [x29, #0x1200] + str x17, [x16] + ldr x17, [x29, #0x1208] + str x17, [x16, #0x8] + sub x16, x29, #0x200 + ldr x17, [x29, #0x1210] + str x17, [x16] + ldr x17, [x29, #0x1218] + str x17, [x16, #0x8] + sub x16, x29, #0x210 + ldr x17, [x29, #0x1220] + str x17, [x16] + ldr x17, [x29, #0x1228] + str x17, [x16, #0x8] + sub x16, x29, #0x220 + ldr x17, [x29, #0x1230] + str x17, [x16] + ldr x17, [x29, #0x1238] + str x17, [x16, #0x8] + sub x16, x29, #0x230 + ldr x17, [x29, #0x1240] + str x17, [x16] + ldr x17, [x29, #0x1248] + str x17, [x16, #0x8] + sub x16, x29, #0x240 + ldr x17, [x29, #0x1250] + str x17, [x16] + ldr x17, [x29, #0x1258] + str x17, [x16, #0x8] + sub x16, x29, #0x250 + ldr x17, [x29, #0x1260] + str x17, [x16] + ldr x17, [x29, #0x1268] + str x17, [x16, #0x8] + sub x16, x29, #0x260 + ldr x17, [x29, #0x1270] + str x17, [x16] + ldr x17, [x29, #0x1278] + str x17, [x16, #0x8] + sub x16, x29, #0x270 + ldr x17, [x29, #0x1280] + str x17, [x16] + ldr x17, [x29, #0x1288] + str x17, [x16, #0x8] + sub x16, x29, #0x280 + ldr x17, [x29, #0x1290] + str x17, [x16] + ldr x17, [x29, #0x1298] + str x17, [x16, #0x8] + sub x16, x29, #0x290 + ldr x17, [x29, #0x12a0] + str x17, [x16] + ldr x17, [x29, #0x12a8] + str x17, [x16, #0x8] + sub x16, x29, #0x2a0 + ldr x17, [x29, #0x12b0] + str x17, [x16] + ldr x17, [x29, #0x12b8] + str x17, [x16, #0x8] + sub x16, x29, #0x2b0 + ldr x17, [x29, #0x12c0] + str x17, [x16] + ldr x17, [x29, #0x12c8] + str x17, [x16, #0x8] + sub x16, x29, #0x2c0 + ldr x17, [x29, #0x12d0] + str x17, [x16] + ldr x17, [x29, #0x12d8] + str x17, [x16, #0x8] + sub x16, x29, #0x2d0 + ldr x17, [x29, #0x12e0] + str x17, [x16] + ldr x17, [x29, #0x12e8] + str x17, [x16, #0x8] + sub x16, x29, #0x2e0 + ldr x17, [x29, #0x12f0] + str x17, [x16] + ldr x17, [x29, #0x12f8] + str x17, [x16, #0x8] + sub x16, x29, #0x2f0 + ldr x17, [x29, #0x1300] + str x17, [x16] + ldr x17, [x29, #0x1308] + str x17, [x16, #0x8] + sub x16, x29, #0x300 + ldr x17, [x29, #0x1310] + str x17, [x16] + ldr x17, [x29, #0x1318] + str x17, [x16, #0x8] + sub x16, x29, #0x310 + ldr x17, [x29, #0x1320] + str x17, [x16] + ldr x17, [x29, #0x1328] + str x17, [x16, #0x8] + sub x16, x29, #0x320 + ldr x17, [x29, #0x1330] + str x17, [x16] + ldr x17, [x29, #0x1338] + str x17, [x16, #0x8] + sub x16, x29, #0x330 + ldr x17, [x29, #0x1340] + str x17, [x16] + ldr x17, [x29, #0x1348] + str x17, [x16, #0x8] + sub x16, x29, #0x340 + ldr x17, [x29, #0x1350] + str x17, [x16] + ldr x17, [x29, #0x1358] + str x17, [x16, #0x8] + sub x16, x29, #0x350 + ldr x17, [x29, #0x1360] + str x17, [x16] + ldr x17, [x29, #0x1368] + str x17, [x16, #0x8] + sub x16, x29, #0x360 + ldr x17, [x29, #0x1370] + str x17, [x16] + ldr x17, [x29, #0x1378] + str x17, [x16, #0x8] + sub x16, x29, #0x370 + ldr x17, [x29, #0x1380] + str x17, [x16] + ldr x17, [x29, #0x1388] + str x17, [x16, #0x8] + sub x16, x29, #0x380 + ldr x17, [x29, #0x1390] + str x17, [x16] + ldr x17, [x29, #0x1398] + str x17, [x16, #0x8] + sub x16, x29, #0x390 + ldr x17, [x29, #0x13a0] + str x17, [x16] + ldr x17, [x29, #0x13a8] + str x17, [x16, #0x8] + sub x16, x29, #0x3a0 + ldr x17, [x29, #0x13b0] + str x17, [x16] + ldr x17, [x29, #0x13b8] + str x17, [x16, #0x8] + sub x16, x29, #0x3b0 + ldr x17, [x29, #0x13c0] + str x17, [x16] + ldr x17, [x29, #0x13c8] + str x17, [x16, #0x8] + sub x16, x29, #0x3c0 + ldr x17, [x29, #0x13d0] + str x17, [x16] + ldr x17, [x29, #0x13d8] + str x17, [x16, #0x8] + sub x16, x29, #0x3d0 + ldr x17, [x29, #0x13e0] + str x17, [x16] + ldr x17, [x29, #0x13e8] + str x17, [x16, #0x8] + sub x16, x29, #0x3e0 + ldr x17, [x29, #0x13f0] + str x17, [x16] + ldr x17, [x29, #0x13f8] + str x17, [x16, #0x8] + sub x16, x29, #0x3f0 + ldr x17, [x29, #0x1400] + str x17, [x16] + ldr x17, [x29, #0x1408] + str x17, [x16, #0x8] + sub x16, x29, #0x400 + ldr x17, [x29, #0x1410] + str x17, [x16] + ldr x17, [x29, #0x1418] + str x17, [x16, #0x8] + sub x16, x29, #0x410 + ldr x17, [x29, #0x1420] + str x17, [x16] + ldr x17, [x29, #0x1428] + str x17, [x16, #0x8] + sub x16, x29, #0x420 + ldr x17, [x29, #0x1430] + str x17, [x16] + ldr x17, [x29, #0x1438] + str x17, [x16, #0x8] + sub x16, x29, #0x430 + ldr x17, [x29, #0x1440] + str x17, [x16] + ldr x17, [x29, #0x1448] + str x17, [x16, #0x8] + sub x16, x29, #0x440 + ldr x17, [x29, #0x1450] + str x17, [x16] + ldr x17, [x29, #0x1458] + str x17, [x16, #0x8] + sub x16, x29, #0x450 + ldr x17, [x29, #0x1460] + str x17, [x16] + ldr x17, [x29, #0x1468] + str x17, [x16, #0x8] + sub x16, x29, #0x460 + ldr x17, [x29, #0x1470] + str x17, [x16] + ldr x17, [x29, #0x1478] + str x17, [x16, #0x8] + sub x16, x29, #0x470 + ldr x17, [x29, #0x1480] + str x17, [x16] + ldr x17, [x29, #0x1488] + str x17, [x16, #0x8] + sub x16, x29, #0x480 + ldr x17, [x29, #0x1490] + str x17, [x16] + ldr x17, [x29, #0x1498] + str x17, [x16, #0x8] + sub x16, x29, #0x490 + ldr x17, [x29, #0x14a0] + str x17, [x16] + ldr x17, [x29, #0x14a8] + str x17, [x16, #0x8] + sub x16, x29, #0x4a0 + ldr x17, [x29, #0x14b0] + str x17, [x16] + ldr x17, [x29, #0x14b8] + str x17, [x16, #0x8] + sub x16, x29, #0x4b0 + ldr x17, [x29, #0x14c0] + str x17, [x16] + ldr x17, [x29, #0x14c8] + str x17, [x16, #0x8] + sub x16, x29, #0x4c0 + ldr x17, [x29, #0x14d0] + str x17, [x16] + ldr x17, [x29, #0x14d8] + str x17, [x16, #0x8] + sub x16, x29, #0x4d0 + ldr x17, [x29, #0x14e0] + str x17, [x16] + ldr x17, [x29, #0x14e8] + str x17, [x16, #0x8] + sub x16, x29, #0x4e0 + ldr x17, [x29, #0x14f0] + str x17, [x16] + ldr x17, [x29, #0x14f8] + str x17, [x16, #0x8] + sub x16, x29, #0x4f0 + ldr x17, [x29, #0x1500] + str x17, [x16] + ldr x17, [x29, #0x1508] + str x17, [x16, #0x8] + sub x16, x29, #0x500 + ldr x17, [x29, #0x1510] + str x17, [x16] + ldr x17, [x29, #0x1518] + str x17, [x16, #0x8] + sub x16, x29, #0x510 + ldr x17, [x29, #0x1520] + str x17, [x16] + ldr x17, [x29, #0x1528] + str x17, [x16, #0x8] + sub x16, x29, #0x520 + ldr x17, [x29, #0x1530] + str x17, [x16] + ldr x17, [x29, #0x1538] + str x17, [x16, #0x8] + sub x16, x29, #0x530 + ldr x17, [x29, #0x1540] + str x17, [x16] + ldr x17, [x29, #0x1548] + str x17, [x16, #0x8] + sub x16, x29, #0x540 + ldr x17, [x29, #0x1550] + str x17, [x16] + ldr x17, [x29, #0x1558] + str x17, [x16, #0x8] + sub x16, x29, #0x550 + ldr x17, [x29, #0x1560] + str x17, [x16] + ldr x17, [x29, #0x1568] + str x17, [x16, #0x8] + sub x16, x29, #0x560 + ldr x17, [x29, #0x1570] + str x17, [x16] + ldr x17, [x29, #0x1578] + str x17, [x16, #0x8] + sub x16, x29, #0x570 + ldr x17, [x29, #0x1580] + str x17, [x16] + ldr x17, [x29, #0x1588] + str x17, [x16, #0x8] + sub x16, x29, #0x580 + ldr x17, [x29, #0x1590] + str x17, [x16] + ldr x17, [x29, #0x1598] + str x17, [x16, #0x8] + sub x16, x29, #0x590 + ldr x17, [x29, #0x15a0] + str x17, [x16] + ldr x17, [x29, #0x15a8] + str x17, [x16, #0x8] + sub x16, x29, #0x5a0 + ldr x17, [x29, #0x15b0] + str x17, [x16] + ldr x17, [x29, #0x15b8] + str x17, [x16, #0x8] + sub x16, x29, #0x5b0 + ldr x17, [x29, #0x15c0] + str x17, [x16] + ldr x17, [x29, #0x15c8] + str x17, [x16, #0x8] + sub x16, x29, #0x5c0 + ldr x17, [x29, #0x15d0] + str x17, [x16] + ldr x17, [x29, #0x15d8] + str x17, [x16, #0x8] + sub x16, x29, #0x5d0 + ldr x17, [x29, #0x15e0] + str x17, [x16] + ldr x17, [x29, #0x15e8] + str x17, [x16, #0x8] + sub x16, x29, #0x5e0 + ldr x17, [x29, #0x15f0] + str x17, [x16] + ldr x17, [x29, #0x15f8] + str x17, [x16, #0x8] + sub x16, x29, #0x5f0 + ldr x17, [x29, #0x1600] + str x17, [x16] + ldr x17, [x29, #0x1608] + str x17, [x16, #0x8] + sub x16, x29, #0x600 + ldr x17, [x29, #0x1610] + str x17, [x16] + ldr x17, [x29, #0x1618] + str x17, [x16, #0x8] + sub x16, x29, #0x610 + ldr x17, [x29, #0x1620] + str x17, [x16] + ldr x17, [x29, #0x1628] + str x17, [x16, #0x8] + sub x16, x29, #0x620 + ldr x17, [x29, #0x1630] + str x17, [x16] + ldr x17, [x29, #0x1638] + str x17, [x16, #0x8] + sub x16, x29, #0x630 + ldr x17, [x29, #0x1640] + str x17, [x16] + ldr x17, [x29, #0x1648] + str x17, [x16, #0x8] + sub x16, x29, #0x640 + ldr x17, [x29, #0x1650] + str x17, [x16] + ldr x17, [x29, #0x1658] + str x17, [x16, #0x8] + sub x16, x29, #0x650 + ldr x17, [x29, #0x1660] + str x17, [x16] + ldr x17, [x29, #0x1668] + str x17, [x16, #0x8] + sub x16, x29, #0x660 + ldr x17, [x29, #0x1670] + str x17, [x16] + ldr x17, [x29, #0x1678] + str x17, [x16, #0x8] + sub x16, x29, #0x670 + ldr x17, [x29, #0x1680] + str x17, [x16] + ldr x17, [x29, #0x1688] + str x17, [x16, #0x8] + sub x16, x29, #0x680 + ldr x17, [x29, #0x1690] + str x17, [x16] + ldr x17, [x29, #0x1698] + str x17, [x16, #0x8] + sub x16, x29, #0x690 + ldr x17, [x29, #0x16a0] + str x17, [x16] + ldr x17, [x29, #0x16a8] + str x17, [x16, #0x8] + sub x16, x29, #0x6a0 + ldr x17, [x29, #0x16b0] + str x17, [x16] + ldr x17, [x29, #0x16b8] + str x17, [x16, #0x8] + sub x16, x29, #0x6b0 + ldr x17, [x29, #0x16c0] + str x17, [x16] + ldr x17, [x29, #0x16c8] + str x17, [x16, #0x8] + sub x16, x29, #0x6c0 + ldr x17, [x29, #0x16d0] + str x17, [x16] + ldr x17, [x29, #0x16d8] + str x17, [x16, #0x8] + sub x16, x29, #0x6d0 + ldr x17, [x29, #0x16e0] + str x17, [x16] + ldr x17, [x29, #0x16e8] + str x17, [x16, #0x8] + sub x16, x29, #0x6e0 + ldr x17, [x29, #0x16f0] + str x17, [x16] + ldr x17, [x29, #0x16f8] + str x17, [x16, #0x8] + sub x16, x29, #0x6f0 + ldr x17, [x29, #0x1700] + str x17, [x16] + ldr x17, [x29, #0x1708] + str x17, [x16, #0x8] + sub x16, x29, #0x700 + ldr x17, [x29, #0x1710] + str x17, [x16] + ldr x17, [x29, #0x1718] + str x17, [x16, #0x8] + sub x16, x29, #0x710 + ldr x17, [x29, #0x1720] + str x17, [x16] + ldr x17, [x29, #0x1728] + str x17, [x16, #0x8] + sub x16, x29, #0x720 + ldr x17, [x29, #0x1730] + str x17, [x16] + ldr x17, [x29, #0x1738] + str x17, [x16, #0x8] + sub x16, x29, #0x730 + ldr x17, [x29, #0x1740] + str x17, [x16] + ldr x17, [x29, #0x1748] + str x17, [x16, #0x8] + sub x16, x29, #0x740 + ldr x17, [x29, #0x1750] + str x17, [x16] + ldr x17, [x29, #0x1758] + str x17, [x16, #0x8] + sub x16, x29, #0x750 + ldr x17, [x29, #0x1760] + str x17, [x16] + ldr x17, [x29, #0x1768] + str x17, [x16, #0x8] + sub x16, x29, #0x760 + ldr x17, [x29, #0x1770] + str x17, [x16] + ldr x17, [x29, #0x1778] + str x17, [x16, #0x8] + sub x16, x29, #0x770 + ldr x17, [x29, #0x1780] + str x17, [x16] + ldr x17, [x29, #0x1788] + str x17, [x16, #0x8] + sub x16, x29, #0x780 + ldr x17, [x29, #0x1790] + str x17, [x16] + ldr x17, [x29, #0x1798] + str x17, [x16, #0x8] + sub x16, x29, #0x790 + ldr x17, [x29, #0x17a0] + str x17, [x16] + ldr x17, [x29, #0x17a8] + str x17, [x16, #0x8] + sub x16, x29, #0x7a0 + ldr x17, [x29, #0x17b0] + str x17, [x16] + ldr x17, [x29, #0x17b8] + str x17, [x16, #0x8] + sub x16, x29, #0x7b0 + ldr x17, [x29, #0x17c0] + str x17, [x16] + ldr x17, [x29, #0x17c8] + str x17, [x16, #0x8] + sub x16, x29, #0x7c0 + ldr x17, [x29, #0x17d0] + str x17, [x16] + ldr x17, [x29, #0x17d8] + str x17, [x16, #0x8] + sub x16, x29, #0x7d0 + ldr x17, [x29, #0x17e0] + str x17, [x16] + ldr x17, [x29, #0x17e8] + str x17, [x16, #0x8] + sub x16, x29, #0x7e0 + ldr x17, [x29, #0x17f0] + str x17, [x16] + ldr x17, [x29, #0x17f8] + str x17, [x16, #0x8] + sub x16, x29, #0x7f0 + ldr x17, [x29, #0x1800] + str x17, [x16] + ldr x17, [x29, #0x1808] + str x17, [x16, #0x8] + sub x16, x29, #0x800 + ldr x17, [x29, #0x1810] + str x17, [x16] + ldr x17, [x29, #0x1818] + str x17, [x16, #0x8] + sub x16, x29, #0x810 + ldr x17, [x29, #0x1820] + str x17, [x16] + ldr x17, [x29, #0x1828] + str x17, [x16, #0x8] + sub x16, x29, #0x820 + ldr x17, [x29, #0x1830] + str x17, [x16] + ldr x17, [x29, #0x1838] + str x17, [x16, #0x8] + sub x16, x29, #0x830 + ldr x17, [x29, #0x1840] + str x17, [x16] + ldr x17, [x29, #0x1848] + str x17, [x16, #0x8] + sub x16, x29, #0x840 + ldr x17, [x29, #0x1850] + str x17, [x16] + ldr x17, [x29, #0x1858] + str x17, [x16, #0x8] + sub x16, x29, #0x850 + ldr x17, [x29, #0x1860] + str x17, [x16] + ldr x17, [x29, #0x1868] + str x17, [x16, #0x8] + sub x16, x29, #0x860 + ldr x17, [x29, #0x1870] + str x17, [x16] + ldr x17, [x29, #0x1878] + str x17, [x16, #0x8] + sub x16, x29, #0x870 + ldr x17, [x29, #0x1880] + str x17, [x16] + ldr x17, [x29, #0x1888] + str x17, [x16, #0x8] + sub x16, x29, #0x880 + ldr x17, [x29, #0x1890] + str x17, [x16] + ldr x17, [x29, #0x1898] + str x17, [x16, #0x8] + sub x16, x29, #0x890 + ldr x17, [x29, #0x18a0] + str x17, [x16] + ldr x17, [x29, #0x18a8] + str x17, [x16, #0x8] + sub x16, x29, #0x8a0 + ldr x17, [x29, #0x18b0] + str x17, [x16] + ldr x17, [x29, #0x18b8] + str x17, [x16, #0x8] + sub x16, x29, #0x8b0 + ldr x17, [x29, #0x18c0] + str x17, [x16] + ldr x17, [x29, #0x18c8] + str x17, [x16, #0x8] + sub x16, x29, #0x8c0 + ldr x17, [x29, #0x18d0] + str x17, [x16] + ldr x17, [x29, #0x18d8] + str x17, [x16, #0x8] + sub x16, x29, #0x8d0 + ldr x17, [x29, #0x18e0] + str x17, [x16] + ldr x17, [x29, #0x18e8] + str x17, [x16, #0x8] + sub x16, x29, #0x8e0 + ldr x17, [x29, #0x18f0] + str x17, [x16] + ldr x17, [x29, #0x18f8] + str x17, [x16, #0x8] + sub x16, x29, #0x8f0 + ldr x17, [x29, #0x1900] + str x17, [x16] + ldr x17, [x29, #0x1908] + str x17, [x16, #0x8] + sub x16, x29, #0x900 + ldr x17, [x29, #0x1910] + str x17, [x16] + ldr x17, [x29, #0x1918] + str x17, [x16, #0x8] + sub x16, x29, #0x910 + ldr x17, [x29, #0x1920] + str x17, [x16] + ldr x17, [x29, #0x1928] + str x17, [x16, #0x8] + sub x16, x29, #0x920 + ldr x17, [x29, #0x1930] + str x17, [x16] + ldr x17, [x29, #0x1938] + str x17, [x16, #0x8] + sub x16, x29, #0x930 + ldr x17, [x29, #0x1940] + str x17, [x16] + ldr x17, [x29, #0x1948] + str x17, [x16, #0x8] + sub x16, x29, #0x940 + ldr x17, [x29, #0x1950] + str x17, [x16] + ldr x17, [x29, #0x1958] + str x17, [x16, #0x8] + sub x16, x29, #0x950 + ldr x17, [x29, #0x1960] + str x17, [x16] + ldr x17, [x29, #0x1968] + str x17, [x16, #0x8] + sub x16, x29, #0x960 + ldr x17, [x29, #0x1970] + str x17, [x16] + ldr x17, [x29, #0x1978] + str x17, [x16, #0x8] + sub x16, x29, #0x970 + ldr x17, [x29, #0x1980] + str x17, [x16] + ldr x17, [x29, #0x1988] + str x17, [x16, #0x8] + sub x16, x29, #0x980 + ldr x17, [x29, #0x1990] + str x17, [x16] + ldr x17, [x29, #0x1998] + str x17, [x16, #0x8] + sub x16, x29, #0x990 + ldr x17, [x29, #0x19a0] + str x17, [x16] + ldr x17, [x29, #0x19a8] + str x17, [x16, #0x8] + sub x16, x29, #0x9a0 + ldr x17, [x29, #0x19b0] + str x17, [x16] + ldr x17, [x29, #0x19b8] + str x17, [x16, #0x8] + sub x16, x29, #0x9b0 + ldr x17, [x29, #0x19c0] + str x17, [x16] + ldr x17, [x29, #0x19c8] + str x17, [x16, #0x8] + sub x16, x29, #0x9c0 + ldr x17, [x29, #0x19d0] + str x17, [x16] + ldr x17, [x29, #0x19d8] + str x17, [x16, #0x8] + sub x16, x29, #0x9d0 + ldr x17, [x29, #0x19e0] + str x17, [x16] + ldr x17, [x29, #0x19e8] + str x17, [x16, #0x8] + sub x16, x29, #0x9e0 + ldr x17, [x29, #0x19f0] + str x17, [x16] + ldr x17, [x29, #0x19f8] + str x17, [x16, #0x8] + sub x16, x29, #0x9f0 + ldr x17, [x29, #0x1a00] + str x17, [x16] + ldr x17, [x29, #0x1a08] + str x17, [x16, #0x8] + sub x16, x29, #0xa00 + ldr x17, [x29, #0x1a10] + str x17, [x16] + ldr x17, [x29, #0x1a18] + str x17, [x16, #0x8] + sub x16, x29, #0xa10 + ldr x17, [x29, #0x1a20] + str x17, [x16] + ldr x17, [x29, #0x1a28] + str x17, [x16, #0x8] + sub x16, x29, #0xa20 + ldr x17, [x29, #0x1a30] + str x17, [x16] + ldr x17, [x29, #0x1a38] + str x17, [x16, #0x8] + sub x16, x29, #0xa30 + ldr x17, [x29, #0x1a40] + str x17, [x16] + ldr x17, [x29, #0x1a48] + str x17, [x16, #0x8] + sub x16, x29, #0xa40 + ldr x17, [x29, #0x1a50] + str x17, [x16] + ldr x17, [x29, #0x1a58] + str x17, [x16, #0x8] + sub x16, x29, #0xa50 + ldr x17, [x29, #0x1a60] + str x17, [x16] + ldr x17, [x29, #0x1a68] + str x17, [x16, #0x8] + sub x16, x29, #0xa60 + ldr x17, [x29, #0x1a70] + str x17, [x16] + ldr x17, [x29, #0x1a78] + str x17, [x16, #0x8] + sub x16, x29, #0xa70 + ldr x17, [x29, #0x1a80] + str x17, [x16] + ldr x17, [x29, #0x1a88] + str x17, [x16, #0x8] + sub x16, x29, #0xa80 + ldr x17, [x29, #0x1a90] + str x17, [x16] + ldr x17, [x29, #0x1a98] + str x17, [x16, #0x8] + sub x16, x29, #0xa90 + ldr x17, [x29, #0x1aa0] + str x17, [x16] + ldr x17, [x29, #0x1aa8] + str x17, [x16, #0x8] + sub x16, x29, #0xaa0 + ldr x17, [x29, #0x1ab0] + str x17, [x16] + ldr x17, [x29, #0x1ab8] + str x17, [x16, #0x8] + sub x16, x29, #0xab0 + ldr x17, [x29, #0x1ac0] + str x17, [x16] + ldr x17, [x29, #0x1ac8] + str x17, [x16, #0x8] + sub x16, x29, #0xac0 + ldr x17, [x29, #0x1ad0] + str x17, [x16] + ldr x17, [x29, #0x1ad8] + str x17, [x16, #0x8] + sub x16, x29, #0xad0 + ldr x17, [x29, #0x1ae0] + str x17, [x16] + ldr x17, [x29, #0x1ae8] + str x17, [x16, #0x8] + sub x16, x29, #0xae0 + ldr x17, [x29, #0x1af0] + str x17, [x16] + ldr x17, [x29, #0x1af8] + str x17, [x16, #0x8] + sub x16, x29, #0xaf0 + ldr x17, [x29, #0x1b00] + str x17, [x16] + ldr x17, [x29, #0x1b08] + str x17, [x16, #0x8] + sub x16, x29, #0xb00 + ldr x17, [x29, #0x1b10] + str x17, [x16] + ldr x17, [x29, #0x1b18] + str x17, [x16, #0x8] + sub x16, x29, #0xb10 + ldr x17, [x29, #0x1b20] + str x17, [x16] + ldr x17, [x29, #0x1b28] + str x17, [x16, #0x8] + sub x16, x29, #0xb20 + ldr x17, [x29, #0x1b30] + str x17, [x16] + ldr x17, [x29, #0x1b38] + str x17, [x16, #0x8] + sub x16, x29, #0xb30 + ldr x17, [x29, #0x1b40] + str x17, [x16] + ldr x17, [x29, #0x1b48] + str x17, [x16, #0x8] + sub x16, x29, #0xb40 + ldr x17, [x29, #0x1b50] + str x17, [x16] + ldr x17, [x29, #0x1b58] + str x17, [x16, #0x8] + sub x16, x29, #0xb50 + ldr x17, [x29, #0x1b60] + str x17, [x16] + ldr x17, [x29, #0x1b68] + str x17, [x16, #0x8] + sub x16, x29, #0xb60 + ldr x17, [x29, #0x1b70] + str x17, [x16] + ldr x17, [x29, #0x1b78] + str x17, [x16, #0x8] + sub x16, x29, #0xb70 + ldr x17, [x29, #0x1b80] + str x17, [x16] + ldr x17, [x29, #0x1b88] + str x17, [x16, #0x8] + sub x16, x29, #0xb80 + ldr x17, [x29, #0x1b90] + str x17, [x16] + ldr x17, [x29, #0x1b98] + str x17, [x16, #0x8] + sub x16, x29, #0xb90 + ldr x17, [x29, #0x1ba0] + str x17, [x16] + ldr x17, [x29, #0x1ba8] + str x17, [x16, #0x8] + sub x16, x29, #0xba0 + ldr x17, [x29, #0x1bb0] + str x17, [x16] + ldr x17, [x29, #0x1bb8] + str x17, [x16, #0x8] + sub x16, x29, #0xbb0 + ldr x17, [x29, #0x1bc0] + str x17, [x16] + ldr x17, [x29, #0x1bc8] + str x17, [x16, #0x8] + sub x16, x29, #0xbc0 + ldr x17, [x29, #0x1bd0] + str x17, [x16] + ldr x17, [x29, #0x1bd8] + str x17, [x16, #0x8] + sub x16, x29, #0xbd0 + ldr x17, [x29, #0x1be0] + str x17, [x16] + ldr x17, [x29, #0x1be8] + str x17, [x16, #0x8] + sub x16, x29, #0xbe0 + ldr x17, [x29, #0x1bf0] + str x17, [x16] + ldr x17, [x29, #0x1bf8] + str x17, [x16, #0x8] + sub x16, x29, #0xbf0 + ldr x17, [x29, #0x1c00] + str x17, [x16] + ldr x17, [x29, #0x1c08] + str x17, [x16, #0x8] + sub x16, x29, #0xc00 + ldr x17, [x29, #0x1c10] + str x17, [x16] + ldr x17, [x29, #0x1c18] + str x17, [x16, #0x8] + sub x16, x29, #0xc10 + ldr x17, [x29, #0x1c20] + str x17, [x16] + ldr x17, [x29, #0x1c28] + str x17, [x16, #0x8] + sub x16, x29, #0xc20 + ldr x17, [x29, #0x1c30] + str x17, [x16] + ldr x17, [x29, #0x1c38] + str x17, [x16, #0x8] + sub x16, x29, #0xc30 + ldr x17, [x29, #0x1c40] + str x17, [x16] + ldr x17, [x29, #0x1c48] + str x17, [x16, #0x8] + sub x16, x29, #0xc40 + ldr x17, [x29, #0x1c50] + str x17, [x16] + ldr x17, [x29, #0x1c58] + str x17, [x16, #0x8] + sub x16, x29, #0xc50 + ldr x17, [x29, #0x1c60] + str x17, [x16] + ldr x17, [x29, #0x1c68] + str x17, [x16, #0x8] + sub x16, x29, #0xc60 + ldr x17, [x29, #0x1c70] + str x17, [x16] + ldr x17, [x29, #0x1c78] + str x17, [x16, #0x8] + sub x16, x29, #0xc70 + ldr x17, [x29, #0x1c80] + str x17, [x16] + ldr x17, [x29, #0x1c88] + str x17, [x16, #0x8] + sub x16, x29, #0xc80 + ldr x17, [x29, #0x1c90] + str x17, [x16] + ldr x17, [x29, #0x1c98] + str x17, [x16, #0x8] + sub x16, x29, #0xc90 + ldr x17, [x29, #0x1ca0] + str x17, [x16] + ldr x17, [x29, #0x1ca8] + str x17, [x16, #0x8] + sub x16, x29, #0xca0 + ldr x17, [x29, #0x1cb0] + str x17, [x16] + ldr x17, [x29, #0x1cb8] + str x17, [x16, #0x8] + sub x16, x29, #0xcb0 + ldr x17, [x29, #0x1cc0] + str x17, [x16] + ldr x17, [x29, #0x1cc8] + str x17, [x16, #0x8] + sub x16, x29, #0xcc0 + ldr x17, [x29, #0x1cd0] + str x17, [x16] + ldr x17, [x29, #0x1cd8] + str x17, [x16, #0x8] + sub x16, x29, #0xcd0 + ldr x17, [x29, #0x1ce0] + str x17, [x16] + ldr x17, [x29, #0x1ce8] + str x17, [x16, #0x8] + sub x16, x29, #0xce0 + ldr x17, [x29, #0x1cf0] + str x17, [x16] + ldr x17, [x29, #0x1cf8] + str x17, [x16, #0x8] + sub x16, x29, #0xcf0 + ldr x17, [x29, #0x1d00] + str x17, [x16] + ldr x17, [x29, #0x1d08] + str x17, [x16, #0x8] + sub x16, x29, #0xd00 + ldr x17, [x29, #0x1d10] + str x17, [x16] + ldr x17, [x29, #0x1d18] + str x17, [x16, #0x8] + sub x16, x29, #0xd10 + ldr x17, [x29, #0x1d20] + str x17, [x16] + ldr x17, [x29, #0x1d28] + str x17, [x16, #0x8] + sub x16, x29, #0xd20 + ldr x17, [x29, #0x1d30] + str x17, [x16] + ldr x17, [x29, #0x1d38] + str x17, [x16, #0x8] + sub x16, x29, #0xd30 + ldr x17, [x29, #0x1d40] + str x17, [x16] + ldr x17, [x29, #0x1d48] + str x17, [x16, #0x8] + sub x16, x29, #0xd40 + ldr x17, [x29, #0x1d50] + str x17, [x16] + ldr x17, [x29, #0x1d58] + str x17, [x16, #0x8] + sub x16, x29, #0xd50 + ldr x17, [x29, #0x1d60] + str x17, [x16] + ldr x17, [x29, #0x1d68] + str x17, [x16, #0x8] + sub x16, x29, #0xd60 + ldr x17, [x29, #0x1d70] + str x17, [x16] + ldr x17, [x29, #0x1d78] + str x17, [x16, #0x8] + sub x16, x29, #0xd70 + ldr x17, [x29, #0x1d80] + str x17, [x16] + ldr x17, [x29, #0x1d88] + str x17, [x16, #0x8] + sub x16, x29, #0xd80 + ldr x17, [x29, #0x1d90] + str x17, [x16] + ldr x17, [x29, #0x1d98] + str x17, [x16, #0x8] + sub x16, x29, #0xd90 + ldr x17, [x29, #0x1da0] + str x17, [x16] + ldr x17, [x29, #0x1da8] + str x17, [x16, #0x8] + sub x16, x29, #0xda0 + ldr x17, [x29, #0x1db0] + str x17, [x16] + ldr x17, [x29, #0x1db8] + str x17, [x16, #0x8] + sub x16, x29, #0xdb0 + ldr x17, [x29, #0x1dc0] + str x17, [x16] + ldr x17, [x29, #0x1dc8] + str x17, [x16, #0x8] + sub x16, x29, #0xdc0 + ldr x17, [x29, #0x1dd0] + str x17, [x16] + ldr x17, [x29, #0x1dd8] + str x17, [x16, #0x8] + sub x16, x29, #0xdd0 + ldr x17, [x29, #0x1de0] + str x17, [x16] + ldr x17, [x29, #0x1de8] + str x17, [x16, #0x8] + sub x16, x29, #0xde0 + ldr x17, [x29, #0x1df0] + str x17, [x16] + ldr x17, [x29, #0x1df8] + str x17, [x16, #0x8] + sub x16, x29, #0xdf0 + ldr x17, [x29, #0x1e00] + str x17, [x16] + ldr x17, [x29, #0x1e08] + str x17, [x16, #0x8] + sub x16, x29, #0xe00 + ldr x17, [x29, #0x1e10] + str x17, [x16] + ldr x17, [x29, #0x1e18] + str x17, [x16, #0x8] + sub x16, x29, #0xe10 + ldr x17, [x29, #0x1e20] + str x17, [x16] + ldr x17, [x29, #0x1e28] + str x17, [x16, #0x8] + sub x16, x29, #0xe20 + ldr x17, [x29, #0x1e30] + str x17, [x16] + ldr x17, [x29, #0x1e38] + str x17, [x16, #0x8] + sub x16, x29, #0xe30 + ldr x17, [x29, #0x1e40] + str x17, [x16] + ldr x17, [x29, #0x1e48] + str x17, [x16, #0x8] + sub x16, x29, #0xe40 + ldr x17, [x29, #0x1e50] + str x17, [x16] + ldr x17, [x29, #0x1e58] + str x17, [x16, #0x8] + sub x16, x29, #0xe50 + ldr x17, [x29, #0x1e60] + str x17, [x16] + ldr x17, [x29, #0x1e68] + str x17, [x16, #0x8] + sub x16, x29, #0xe60 + ldr x17, [x29, #0x1e70] + str x17, [x16] + ldr x17, [x29, #0x1e78] + str x17, [x16, #0x8] + sub x16, x29, #0xe70 + ldr x17, [x29, #0x1e80] + str x17, [x16] + ldr x17, [x29, #0x1e88] + str x17, [x16, #0x8] + sub x16, x29, #0xe80 + ldr x17, [x29, #0x1e90] + str x17, [x16] + ldr x17, [x29, #0x1e98] + str x17, [x16, #0x8] + sub x16, x29, #0xe90 + ldr x17, [x29, #0x1ea0] + str x17, [x16] + ldr x17, [x29, #0x1ea8] + str x17, [x16, #0x8] + sub x16, x29, #0xea0 + ldr x17, [x29, #0x1eb0] + str x17, [x16] + ldr x17, [x29, #0x1eb8] + str x17, [x16, #0x8] + sub x16, x29, #0xeb0 + ldr x17, [x29, #0x1ec0] + str x17, [x16] + ldr x17, [x29, #0x1ec8] + str x17, [x16, #0x8] + sub x16, x29, #0xec0 + ldr x17, [x29, #0x1ed0] + str x17, [x16] + ldr x17, [x29, #0x1ed8] + str x17, [x16, #0x8] + sub x16, x29, #0xed0 + ldr x17, [x29, #0x1ee0] + str x17, [x16] + ldr x17, [x29, #0x1ee8] + str x17, [x16, #0x8] + sub x16, x29, #0xee0 + ldr x17, [x29, #0x1ef0] + str x17, [x16] + ldr x17, [x29, #0x1ef8] + str x17, [x16, #0x8] + sub x16, x29, #0xef0 + ldr x17, [x29, #0x1f00] + str x17, [x16] + ldr x17, [x29, #0x1f08] + str x17, [x16, #0x8] + sub x16, x29, #0xf00 + ldr x17, [x29, #0x1f10] + str x17, [x16] + ldr x17, [x29, #0x1f18] + str x17, [x16, #0x8] + sub x16, x29, #0xf10 + ldr x17, [x29, #0x1f20] + str x17, [x16] + ldr x17, [x29, #0x1f28] + str x17, [x16, #0x8] + sub x16, x29, #0xf20 + ldr x17, [x29, #0x1f30] + str x17, [x16] + ldr x17, [x29, #0x1f38] + str x17, [x16, #0x8] + sub x16, x29, #0xf30 + ldr x17, [x29, #0x1f40] + str x17, [x16] + ldr x17, [x29, #0x1f48] + str x17, [x16, #0x8] + sub x16, x29, #0xf40 + ldr x17, [x29, #0x1f50] + str x17, [x16] + ldr x17, [x29, #0x1f58] + str x17, [x16, #0x8] + sub x16, x29, #0xf50 + ldr x17, [x29, #0x1f60] + str x17, [x16] + ldr x17, [x29, #0x1f68] + str x17, [x16, #0x8] + sub x16, x29, #0xf60 + ldr x17, [x29, #0x1f70] + str x17, [x16] + ldr x17, [x29, #0x1f78] + str x17, [x16, #0x8] + sub x16, x29, #0xf70 + ldr x17, [x29, #0x1f80] + str x17, [x16] + ldr x17, [x29, #0x1f88] + str x17, [x16, #0x8] + sub x16, x29, #0xf80 + ldr x17, [x29, #0x1f90] + str x17, [x16] + ldr x17, [x29, #0x1f98] + str x17, [x16, #0x8] + sub x16, x29, #0xf90 + ldr x17, [x29, #0x1fa0] + str x17, [x16] + ldr x17, [x29, #0x1fa8] + str x17, [x16, #0x8] + sub x16, x29, #0xfa0 + ldr x17, [x29, #0x1fb0] + str x17, [x16] + ldr x17, [x29, #0x1fb8] + str x17, [x16, #0x8] + sub x16, x29, #0xfb0 + ldr x17, [x29, #0x1fc0] + str x17, [x16] + ldr x17, [x29, #0x1fc8] + str x17, [x16, #0x8] + sub x16, x29, #0xfc0 + ldr x17, [x29, #0x1fd0] + str x17, [x16] + ldr x17, [x29, #0x1fd8] + str x17, [x16, #0x8] + sub x16, x29, #0xfd0 + ldr x17, [x29, #0x1fe0] + str x17, [x16] + ldr x17, [x29, #0x1fe8] + str x17, [x16, #0x8] + sub x16, x29, #0xfe0 + ldr x17, [x29, #0x1ff0] + str x17, [x16] + ldr x17, [x29, #0x1ff8] + str x17, [x16, #0x8] + sub x16, x29, #0xff0 + ldr x17, [x29, #0x2000] + str x17, [x16] + ldr x17, [x29, #0x2008] + str x17, [x16, #0x8] + sub x16, x29, #0x1, lsl #12 // =0x1000 + ldr x17, [x29, #0x2010] + str x17, [x16] + ldr x17, [x29, #0x2018] + str x17, [x16, #0x8] + sub x16, x29, #0x1, lsl #12 // =0x1000 + sub x16, x16, #0x10 + ldr x17, [x29, #0x2020] + str x17, [x16] + ldr x17, [x29, #0x2028] + str x17, [x16, #0x8] + sub x16, x29, #0x1, lsl #12 // =0x1000 + sub x16, x16, #0x20 + ldr x17, [x29, #0x2030] + str x17, [x16] + ldr x17, [x29, #0x2038] + str x17, [x16, #0x8] + sub x16, x29, #0x1, lsl #12 // =0x1000 + sub x16, x16, #0x30 + ldr x17, [x29, #0x2040] + str x17, [x16] + ldr x17, [x29, #0x2048] + str x17, [x16, #0x8] + sub x16, x29, #0x1, lsl #12 // =0x1000 + sub x16, x16, #0x40 + ldr x17, [x29, #0x2050] + str x17, [x16] + ldr x17, [x29, #0x2058] + str x17, [x16, #0x8] + sub x16, x29, #0x1, lsl #12 // =0x1000 + sub x16, x16, #0x50 + ldr x17, [x29, #0x2060] + str x17, [x16] + ldr x17, [x29, #0x2068] + str x17, [x16, #0x8] + mov x0, #0x0 // =0 + sub x1, x29, #0x10 + ldr x1, [x1] + sub x2, x29, #0x10 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x20 + ldr x1, [x1] + sub x2, x29, #0x20 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x30 + ldr x1, [x1] + sub x2, x29, #0x30 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x40 + ldr x1, [x1] + sub x2, x29, #0x40 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x50 + ldr x1, [x1] + sub x2, x29, #0x50 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x60 + ldr x1, [x1] + sub x2, x29, #0x60 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x70 + ldr x1, [x1] + sub x2, x29, #0x70 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x80 + ldr x1, [x1] + sub x2, x29, #0x80 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x90 + ldr x1, [x1] + sub x2, x29, #0x90 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xa0 + ldr x1, [x1] + sub x2, x29, #0xa0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xb0 + ldr x1, [x1] + sub x2, x29, #0xb0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xc0 + ldr x1, [x1] + sub x2, x29, #0xc0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xd0 + ldr x1, [x1] + sub x2, x29, #0xd0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xe0 + ldr x1, [x1] + sub x2, x29, #0xe0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xf0 + ldr x1, [x1] + sub x2, x29, #0xf0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x100 + ldr x1, [x1] + sub x2, x29, #0x100 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x110 + ldr x1, [x1] + sub x2, x29, #0x110 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x120 + ldr x1, [x1] + sub x2, x29, #0x120 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x130 + ldr x1, [x1] + sub x2, x29, #0x130 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x140 + ldr x1, [x1] + sub x2, x29, #0x140 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x150 + ldr x1, [x1] + sub x2, x29, #0x150 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x160 + ldr x1, [x1] + sub x2, x29, #0x160 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x170 + ldr x1, [x1] + sub x2, x29, #0x170 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x180 + ldr x1, [x1] + sub x2, x29, #0x180 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x190 + ldr x1, [x1] + sub x2, x29, #0x190 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x1a0 + ldr x1, [x1] + sub x2, x29, #0x1a0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x1b0 + ldr x1, [x1] + sub x2, x29, #0x1b0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x1c0 + ldr x1, [x1] + sub x2, x29, #0x1c0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x1d0 + ldr x1, [x1] + sub x2, x29, #0x1d0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x1e0 + ldr x1, [x1] + sub x2, x29, #0x1e0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x1f0 + ldr x1, [x1] + sub x2, x29, #0x1f0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x200 + ldr x1, [x1] + sub x2, x29, #0x200 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x210 + ldr x1, [x1] + sub x2, x29, #0x210 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x220 + ldr x1, [x1] + sub x2, x29, #0x220 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x230 + ldr x1, [x1] + sub x2, x29, #0x230 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x240 + ldr x1, [x1] + sub x2, x29, #0x240 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x250 + ldr x1, [x1] + sub x2, x29, #0x250 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x260 + ldr x1, [x1] + sub x2, x29, #0x260 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x270 + ldr x1, [x1] + sub x2, x29, #0x270 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x280 + ldr x1, [x1] + sub x2, x29, #0x280 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x290 + ldr x1, [x1] + sub x2, x29, #0x290 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x2a0 + ldr x1, [x1] + sub x2, x29, #0x2a0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x2b0 + ldr x1, [x1] + sub x2, x29, #0x2b0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x2c0 + ldr x1, [x1] + sub x2, x29, #0x2c0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x2d0 + ldr x1, [x1] + sub x2, x29, #0x2d0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x2e0 + ldr x1, [x1] + sub x2, x29, #0x2e0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x2f0 + ldr x1, [x1] + sub x2, x29, #0x2f0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x300 + ldr x1, [x1] + sub x2, x29, #0x300 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x310 + ldr x1, [x1] + sub x2, x29, #0x310 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x320 + ldr x1, [x1] + sub x2, x29, #0x320 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x330 + ldr x1, [x1] + sub x2, x29, #0x330 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x340 + ldr x1, [x1] + sub x2, x29, #0x340 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x350 + ldr x1, [x1] + sub x2, x29, #0x350 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x360 + ldr x1, [x1] + sub x2, x29, #0x360 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x370 + ldr x1, [x1] + sub x2, x29, #0x370 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x380 + ldr x1, [x1] + sub x2, x29, #0x380 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x390 + ldr x1, [x1] + sub x2, x29, #0x390 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x3a0 + ldr x1, [x1] + sub x2, x29, #0x3a0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x3b0 + ldr x1, [x1] + sub x2, x29, #0x3b0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x3c0 + ldr x1, [x1] + sub x2, x29, #0x3c0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x3d0 + ldr x1, [x1] + sub x2, x29, #0x3d0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x3e0 + ldr x1, [x1] + sub x2, x29, #0x3e0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x3f0 + ldr x1, [x1] + sub x2, x29, #0x3f0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x400 + ldr x1, [x1] + sub x2, x29, #0x400 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x410 + ldr x1, [x1] + sub x2, x29, #0x410 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x420 + ldr x1, [x1] + sub x2, x29, #0x420 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x430 + ldr x1, [x1] + sub x2, x29, #0x430 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x440 + ldr x1, [x1] + sub x2, x29, #0x440 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x450 + ldr x1, [x1] + sub x2, x29, #0x450 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x460 + ldr x1, [x1] + sub x2, x29, #0x460 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x470 + ldr x1, [x1] + sub x2, x29, #0x470 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x480 + ldr x1, [x1] + sub x2, x29, #0x480 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x490 + ldr x1, [x1] + sub x2, x29, #0x490 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x4a0 + ldr x1, [x1] + sub x2, x29, #0x4a0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x4b0 + ldr x1, [x1] + sub x2, x29, #0x4b0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x4c0 + ldr x1, [x1] + sub x2, x29, #0x4c0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x4d0 + ldr x1, [x1] + sub x2, x29, #0x4d0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x4e0 + ldr x1, [x1] + sub x2, x29, #0x4e0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x4f0 + ldr x1, [x1] + sub x2, x29, #0x4f0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x500 + ldr x1, [x1] + sub x2, x29, #0x500 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x510 + ldr x1, [x1] + sub x2, x29, #0x510 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x520 + ldr x1, [x1] + sub x2, x29, #0x520 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x530 + ldr x1, [x1] + sub x2, x29, #0x530 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x540 + ldr x1, [x1] + sub x2, x29, #0x540 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x550 + ldr x1, [x1] + sub x2, x29, #0x550 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x560 + ldr x1, [x1] + sub x2, x29, #0x560 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x570 + ldr x1, [x1] + sub x2, x29, #0x570 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x580 + ldr x1, [x1] + sub x2, x29, #0x580 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x590 + ldr x1, [x1] + sub x2, x29, #0x590 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x5a0 + ldr x1, [x1] + sub x2, x29, #0x5a0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x5b0 + ldr x1, [x1] + sub x2, x29, #0x5b0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x5c0 + ldr x1, [x1] + sub x2, x29, #0x5c0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x5d0 + ldr x1, [x1] + sub x2, x29, #0x5d0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x5e0 + ldr x1, [x1] + sub x2, x29, #0x5e0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x5f0 + ldr x1, [x1] + sub x2, x29, #0x5f0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x600 + ldr x1, [x1] + sub x2, x29, #0x600 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x610 + ldr x1, [x1] + sub x2, x29, #0x610 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x620 + ldr x1, [x1] + sub x2, x29, #0x620 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x630 + ldr x1, [x1] + sub x2, x29, #0x630 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x640 + ldr x1, [x1] + sub x2, x29, #0x640 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x650 + ldr x1, [x1] + sub x2, x29, #0x650 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x660 + ldr x1, [x1] + sub x2, x29, #0x660 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x670 + ldr x1, [x1] + sub x2, x29, #0x670 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x680 + ldr x1, [x1] + sub x2, x29, #0x680 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x690 + ldr x1, [x1] + sub x2, x29, #0x690 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x6a0 + ldr x1, [x1] + sub x2, x29, #0x6a0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x6b0 + ldr x1, [x1] + sub x2, x29, #0x6b0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x6c0 + ldr x1, [x1] + sub x2, x29, #0x6c0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x6d0 + ldr x1, [x1] + sub x2, x29, #0x6d0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x6e0 + ldr x1, [x1] + sub x2, x29, #0x6e0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x6f0 + ldr x1, [x1] + sub x2, x29, #0x6f0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x700 + ldr x1, [x1] + sub x2, x29, #0x700 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x710 + ldr x1, [x1] + sub x2, x29, #0x710 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x720 + ldr x1, [x1] + sub x2, x29, #0x720 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x730 + ldr x1, [x1] + sub x2, x29, #0x730 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x740 + ldr x1, [x1] + sub x2, x29, #0x740 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x750 + ldr x1, [x1] + sub x2, x29, #0x750 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x760 + ldr x1, [x1] + sub x2, x29, #0x760 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x770 + ldr x1, [x1] + sub x2, x29, #0x770 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x780 + ldr x1, [x1] + sub x2, x29, #0x780 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x790 + ldr x1, [x1] + sub x2, x29, #0x790 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x7a0 + ldr x1, [x1] + sub x2, x29, #0x7a0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x7b0 + ldr x1, [x1] + sub x2, x29, #0x7b0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x7c0 + ldr x1, [x1] + sub x2, x29, #0x7c0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x7d0 + ldr x1, [x1] + sub x2, x29, #0x7d0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x7e0 + ldr x1, [x1] + sub x2, x29, #0x7e0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x7f0 + ldr x1, [x1] + sub x2, x29, #0x7f0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x800 + ldr x1, [x1] + sub x2, x29, #0x800 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x810 + ldr x1, [x1] + sub x2, x29, #0x810 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x820 + ldr x1, [x1] + sub x2, x29, #0x820 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x830 + ldr x1, [x1] + sub x2, x29, #0x830 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x840 + ldr x1, [x1] + sub x2, x29, #0x840 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x850 + ldr x1, [x1] + sub x2, x29, #0x850 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x860 + ldr x1, [x1] + sub x2, x29, #0x860 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x870 + ldr x1, [x1] + sub x2, x29, #0x870 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x880 + ldr x1, [x1] + sub x2, x29, #0x880 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x890 + ldr x1, [x1] + sub x2, x29, #0x890 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x8a0 + ldr x1, [x1] + sub x2, x29, #0x8a0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x8b0 + ldr x1, [x1] + sub x2, x29, #0x8b0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x8c0 + ldr x1, [x1] + sub x2, x29, #0x8c0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x8d0 + ldr x1, [x1] + sub x2, x29, #0x8d0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x8e0 + ldr x1, [x1] + sub x2, x29, #0x8e0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x8f0 + ldr x1, [x1] + sub x2, x29, #0x8f0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x900 + ldr x1, [x1] + sub x2, x29, #0x900 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x910 + ldr x1, [x1] + sub x2, x29, #0x910 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x920 + ldr x1, [x1] + sub x2, x29, #0x920 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x930 + ldr x1, [x1] + sub x2, x29, #0x930 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x940 + ldr x1, [x1] + sub x2, x29, #0x940 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x950 + ldr x1, [x1] + sub x2, x29, #0x950 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x960 + ldr x1, [x1] + sub x2, x29, #0x960 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x970 + ldr x1, [x1] + sub x2, x29, #0x970 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x980 + ldr x1, [x1] + sub x2, x29, #0x980 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x990 + ldr x1, [x1] + sub x2, x29, #0x990 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x9a0 + ldr x1, [x1] + sub x2, x29, #0x9a0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x9b0 + ldr x1, [x1] + sub x2, x29, #0x9b0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x9c0 + ldr x1, [x1] + sub x2, x29, #0x9c0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x9d0 + ldr x1, [x1] + sub x2, x29, #0x9d0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x9e0 + ldr x1, [x1] + sub x2, x29, #0x9e0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x9f0 + ldr x1, [x1] + sub x2, x29, #0x9f0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xa00 + ldr x1, [x1] + sub x2, x29, #0xa00 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xa10 + ldr x1, [x1] + sub x2, x29, #0xa10 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xa20 + ldr x1, [x1] + sub x2, x29, #0xa20 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xa30 + ldr x1, [x1] + sub x2, x29, #0xa30 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xa40 + ldr x1, [x1] + sub x2, x29, #0xa40 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xa50 + ldr x1, [x1] + sub x2, x29, #0xa50 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xa60 + ldr x1, [x1] + sub x2, x29, #0xa60 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xa70 + ldr x1, [x1] + sub x2, x29, #0xa70 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xa80 + ldr x1, [x1] + sub x2, x29, #0xa80 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xa90 + ldr x1, [x1] + sub x2, x29, #0xa90 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xaa0 + ldr x1, [x1] + sub x2, x29, #0xaa0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xab0 + ldr x1, [x1] + sub x2, x29, #0xab0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xac0 + ldr x1, [x1] + sub x2, x29, #0xac0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xad0 + ldr x1, [x1] + sub x2, x29, #0xad0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xae0 + ldr x1, [x1] + sub x2, x29, #0xae0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xaf0 + ldr x1, [x1] + sub x2, x29, #0xaf0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xb00 + ldr x1, [x1] + sub x2, x29, #0xb00 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xb10 + ldr x1, [x1] + sub x2, x29, #0xb10 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xb20 + ldr x1, [x1] + sub x2, x29, #0xb20 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xb30 + ldr x1, [x1] + sub x2, x29, #0xb30 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xb40 + ldr x1, [x1] + sub x2, x29, #0xb40 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xb50 + ldr x1, [x1] + sub x2, x29, #0xb50 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xb60 + ldr x1, [x1] + sub x2, x29, #0xb60 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xb70 + ldr x1, [x1] + sub x2, x29, #0xb70 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xb80 + ldr x1, [x1] + sub x2, x29, #0xb80 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xb90 + ldr x1, [x1] + sub x2, x29, #0xb90 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xba0 + ldr x1, [x1] + sub x2, x29, #0xba0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xbb0 + ldr x1, [x1] + sub x2, x29, #0xbb0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xbc0 + ldr x1, [x1] + sub x2, x29, #0xbc0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xbd0 + ldr x1, [x1] + sub x2, x29, #0xbd0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xbe0 + ldr x1, [x1] + sub x2, x29, #0xbe0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xbf0 + ldr x1, [x1] + sub x2, x29, #0xbf0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xc00 + ldr x1, [x1] + sub x2, x29, #0xc00 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xc10 + ldr x1, [x1] + sub x2, x29, #0xc10 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xc20 + ldr x1, [x1] + sub x2, x29, #0xc20 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xc30 + ldr x1, [x1] + sub x2, x29, #0xc30 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xc40 + ldr x1, [x1] + sub x2, x29, #0xc40 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xc50 + ldr x1, [x1] + sub x2, x29, #0xc50 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xc60 + ldr x1, [x1] + sub x2, x29, #0xc60 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xc70 + ldr x1, [x1] + sub x2, x29, #0xc70 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xc80 + ldr x1, [x1] + sub x2, x29, #0xc80 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xc90 + ldr x1, [x1] + sub x2, x29, #0xc90 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xca0 + ldr x1, [x1] + sub x2, x29, #0xca0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xcb0 + ldr x1, [x1] + sub x2, x29, #0xcb0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xcc0 + ldr x1, [x1] + sub x2, x29, #0xcc0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xcd0 + ldr x1, [x1] + sub x2, x29, #0xcd0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xce0 + ldr x1, [x1] + sub x2, x29, #0xce0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xcf0 + ldr x1, [x1] + sub x2, x29, #0xcf0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xd00 + ldr x1, [x1] + sub x2, x29, #0xd00 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xd10 + ldr x1, [x1] + sub x2, x29, #0xd10 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xd20 + ldr x1, [x1] + sub x2, x29, #0xd20 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xd30 + ldr x1, [x1] + sub x2, x29, #0xd30 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xd40 + ldr x1, [x1] + sub x2, x29, #0xd40 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xd50 + ldr x1, [x1] + sub x2, x29, #0xd50 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xd60 + ldr x1, [x1] + sub x2, x29, #0xd60 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xd70 + ldr x1, [x1] + sub x2, x29, #0xd70 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xd80 + ldr x1, [x1] + sub x2, x29, #0xd80 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xd90 + ldr x1, [x1] + sub x2, x29, #0xd90 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xda0 + ldr x1, [x1] + sub x2, x29, #0xda0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xdb0 + ldr x1, [x1] + sub x2, x29, #0xdb0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xdc0 + ldr x1, [x1] + sub x2, x29, #0xdc0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xdd0 + ldr x1, [x1] + sub x2, x29, #0xdd0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xde0 + ldr x1, [x1] + sub x2, x29, #0xde0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xdf0 + ldr x1, [x1] + sub x2, x29, #0xdf0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xe00 + ldr x1, [x1] + sub x2, x29, #0xe00 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xe10 + ldr x1, [x1] + sub x2, x29, #0xe10 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xe20 + ldr x1, [x1] + sub x2, x29, #0xe20 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xe30 + ldr x1, [x1] + sub x2, x29, #0xe30 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xe40 + ldr x1, [x1] + sub x2, x29, #0xe40 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xe50 + ldr x1, [x1] + sub x2, x29, #0xe50 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xe60 + ldr x1, [x1] + sub x2, x29, #0xe60 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xe70 + ldr x1, [x1] + sub x2, x29, #0xe70 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xe80 + ldr x1, [x1] + sub x2, x29, #0xe80 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xe90 + ldr x1, [x1] + sub x2, x29, #0xe90 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xea0 + ldr x1, [x1] + sub x2, x29, #0xea0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xeb0 + ldr x1, [x1] + sub x2, x29, #0xeb0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xec0 + ldr x1, [x1] + sub x2, x29, #0xec0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xed0 + ldr x1, [x1] + sub x2, x29, #0xed0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xee0 + ldr x1, [x1] + sub x2, x29, #0xee0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xef0 + ldr x1, [x1] + sub x2, x29, #0xef0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xf00 + ldr x1, [x1] + sub x2, x29, #0xf00 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xf10 + ldr x1, [x1] + sub x2, x29, #0xf10 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xf20 + ldr x1, [x1] + sub x2, x29, #0xf20 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xf30 + ldr x1, [x1] + sub x2, x29, #0xf30 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xf40 + ldr x1, [x1] + sub x2, x29, #0xf40 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xf50 + ldr x1, [x1] + sub x2, x29, #0xf50 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xf60 + ldr x1, [x1] + sub x2, x29, #0xf60 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xf70 + ldr x1, [x1] + sub x2, x29, #0xf70 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xf80 + ldr x1, [x1] + sub x2, x29, #0xf80 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xf90 + ldr x1, [x1] + sub x2, x29, #0xf90 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xfa0 + ldr x1, [x1] + sub x2, x29, #0xfa0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xfb0 + ldr x1, [x1] + sub x2, x29, #0xfb0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xfc0 + ldr x1, [x1] + sub x2, x29, #0xfc0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xfd0 + ldr x1, [x1] + sub x2, x29, #0xfd0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xfe0 + ldr x1, [x1] + sub x2, x29, #0xfe0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0xff0 + ldr x1, [x1] + sub x2, x29, #0xff0 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x1, lsl #12 // =0x1000 + ldr x1, [x1] + sub x2, x29, #0x1, lsl #12 // =0x1000 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x1, lsl #12 // =0x1000 + sub x1, x1, #0x10 + ldr x1, [x1] + sub x2, x29, #0x1, lsl #12 // =0x1000 + sub x2, x2, #0x10 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x1, lsl #12 // =0x1000 + sub x1, x1, #0x20 + ldr x1, [x1] + sub x2, x29, #0x1, lsl #12 // =0x1000 + sub x2, x2, #0x20 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x1, lsl #12 // =0x1000 + sub x1, x1, #0x30 + ldr x1, [x1] + sub x2, x29, #0x1, lsl #12 // =0x1000 + sub x2, x2, #0x30 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x1, lsl #12 // =0x1000 + sub x1, x1, #0x40 + ldr x1, [x1] + sub x2, x29, #0x1, lsl #12 // =0x1000 + sub x2, x2, #0x40 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + sub x1, x29, #0x1, lsl #12 // =0x1000 + sub x1, x1, #0x50 + ldr x1, [x1] + sub x2, x29, #0x1, lsl #12 // =0x1000 + sub x2, x2, #0x50 + ldr x2, [x2, #0x8] + add x1, x1, x2 + add x0, x0, x1 + add sp, sp, #0x1, lsl #12 // =0x1000 + add sp, sp, #0x60 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0x1, lsl #12 // =0x1000 + add sp, sp, #0x50 + ret + +: + sub sp, sp, #0xfc0 + ldr x16, [sp, #0xfc0] + str x16, [sp] + ldr x16, [sp, #0xfc8] + str x16, [sp, #0x10] + ldr x16, [sp, #0xfd0] + str x16, [sp, #0x20] + ldr x16, [sp, #0xfd8] + str x16, [sp, #0x30] + ldr x16, [sp, #0xfe0] + str x16, [sp, #0x40] + ldr x16, [sp, #0xfe8] + str x16, [sp, #0x50] + ldr x16, [sp, #0xff0] + str x16, [sp, #0x60] + ldr x16, [sp, #0xff8] + str x16, [sp, #0x70] + ldr x16, [sp, #0x1000] + str x16, [sp, #0x80] + ldr x16, [sp, #0x1008] + str x16, [sp, #0x90] + ldr x16, [sp, #0x1010] + str x16, [sp, #0xa0] + ldr x16, [sp, #0x1018] + str x16, [sp, #0xb0] + ldr x16, [sp, #0x1020] + str x16, [sp, #0xc0] + ldr x16, [sp, #0x1028] + str x16, [sp, #0xd0] + ldr x16, [sp, #0x1030] + str x16, [sp, #0xe0] + ldr x16, [sp, #0x1038] + str x16, [sp, #0xf0] + ldr x16, [sp, #0x1040] + str x16, [sp, #0x100] + ldr x16, [sp, #0x1048] + str x16, [sp, #0x110] + ldr x16, [sp, #0x1050] + str x16, [sp, #0x120] + ldr x16, [sp, #0x1058] + str x16, [sp, #0x130] + ldr x16, [sp, #0x1060] + str x16, [sp, #0x140] + ldr x16, [sp, #0x1068] + str x16, [sp, #0x150] + ldr x16, [sp, #0x1070] + str x16, [sp, #0x160] + ldr x16, [sp, #0x1078] + str x16, [sp, #0x170] + ldr x16, [sp, #0x1080] + str x16, [sp, #0x180] + ldr x16, [sp, #0x1088] + str x16, [sp, #0x190] + ldr x16, [sp, #0x1090] + str x16, [sp, #0x1a0] + ldr x16, [sp, #0x1098] + str x16, [sp, #0x1b0] + ldr x16, [sp, #0x10a0] + str x16, [sp, #0x1c0] + ldr x16, [sp, #0x10a8] + str x16, [sp, #0x1d0] + ldr x16, [sp, #0x10b0] + str x16, [sp, #0x1e0] + ldr x16, [sp, #0x10b8] + str x16, [sp, #0x1f0] + ldr x16, [sp, #0x10c0] + str x16, [sp, #0x200] + ldr x16, [sp, #0x10c8] + str x16, [sp, #0x210] + ldr x16, [sp, #0x10d0] + str x16, [sp, #0x220] + ldr x16, [sp, #0x10d8] + str x16, [sp, #0x230] + ldr x16, [sp, #0x10e0] + str x16, [sp, #0x240] + ldr x16, [sp, #0x10e8] + str x16, [sp, #0x250] + ldr x16, [sp, #0x10f0] + str x16, [sp, #0x260] + ldr x16, [sp, #0x10f8] + str x16, [sp, #0x270] + ldr x16, [sp, #0x1100] + str x16, [sp, #0x280] + ldr x16, [sp, #0x1108] + str x16, [sp, #0x290] + ldr x16, [sp, #0x1110] + str x16, [sp, #0x2a0] + ldr x16, [sp, #0x1118] + str x16, [sp, #0x2b0] + ldr x16, [sp, #0x1120] + str x16, [sp, #0x2c0] + ldr x16, [sp, #0x1128] + str x16, [sp, #0x2d0] + ldr x16, [sp, #0x1130] + str x16, [sp, #0x2e0] + ldr x16, [sp, #0x1138] + str x16, [sp, #0x2f0] + ldr x16, [sp, #0x1140] + str x16, [sp, #0x300] + ldr x16, [sp, #0x1148] + str x16, [sp, #0x310] + ldr x16, [sp, #0x1150] + str x16, [sp, #0x320] + ldr x16, [sp, #0x1158] + str x16, [sp, #0x330] + ldr x16, [sp, #0x1160] + str x16, [sp, #0x340] + ldr x16, [sp, #0x1168] + str x16, [sp, #0x350] + ldr x16, [sp, #0x1170] + str x16, [sp, #0x360] + ldr x16, [sp, #0x1178] + str x16, [sp, #0x370] + ldr x16, [sp, #0x1180] + str x16, [sp, #0x380] + ldr x16, [sp, #0x1188] + str x16, [sp, #0x390] + ldr x16, [sp, #0x1190] + str x16, [sp, #0x3a0] + ldr x16, [sp, #0x1198] + str x16, [sp, #0x3b0] + ldr x16, [sp, #0x11a0] + str x16, [sp, #0x3c0] + ldr x16, [sp, #0x11a8] + str x16, [sp, #0x3d0] + ldr x16, [sp, #0x11b0] + str x16, [sp, #0x3e0] + ldr x16, [sp, #0x11b8] + str x16, [sp, #0x3f0] + ldr x16, [sp, #0x11c0] + str x16, [sp, #0x400] + ldr x16, [sp, #0x11c8] + str x16, [sp, #0x410] + ldr x16, [sp, #0x11d0] + str x16, [sp, #0x420] + ldr x16, [sp, #0x11d8] + str x16, [sp, #0x430] + ldr x16, [sp, #0x11e0] + str x16, [sp, #0x440] + ldr x16, [sp, #0x11e8] + str x16, [sp, #0x450] + ldr x16, [sp, #0x11f0] + str x16, [sp, #0x460] + ldr x16, [sp, #0x11f8] + str x16, [sp, #0x470] + ldr x16, [sp, #0x1200] + str x16, [sp, #0x480] + ldr x16, [sp, #0x1208] + str x16, [sp, #0x490] + ldr x16, [sp, #0x1210] + str x16, [sp, #0x4a0] + ldr x16, [sp, #0x1218] + str x16, [sp, #0x4b0] + ldr x16, [sp, #0x1220] + str x16, [sp, #0x4c0] + ldr x16, [sp, #0x1228] + str x16, [sp, #0x4d0] + ldr x16, [sp, #0x1230] + str x16, [sp, #0x4e0] + ldr x16, [sp, #0x1238] + str x16, [sp, #0x4f0] + ldr x16, [sp, #0x1240] + str x16, [sp, #0x500] + ldr x16, [sp, #0x1248] + str x16, [sp, #0x510] + ldr x16, [sp, #0x1250] + str x16, [sp, #0x520] + ldr x16, [sp, #0x1258] + str x16, [sp, #0x530] + ldr x16, [sp, #0x1260] + str x16, [sp, #0x540] + ldr x16, [sp, #0x1268] + str x16, [sp, #0x550] + ldr x16, [sp, #0x1270] + str x16, [sp, #0x560] + ldr x16, [sp, #0x1278] + str x16, [sp, #0x570] + ldr x16, [sp, #0x1280] + str x16, [sp, #0x580] + ldr x16, [sp, #0x1288] + str x16, [sp, #0x590] + ldr x16, [sp, #0x1290] + str x16, [sp, #0x5a0] + ldr x16, [sp, #0x1298] + str x16, [sp, #0x5b0] + ldr x16, [sp, #0x12a0] + str x16, [sp, #0x5c0] + ldr x16, [sp, #0x12a8] + str x16, [sp, #0x5d0] + ldr x16, [sp, #0x12b0] + str x16, [sp, #0x5e0] + ldr x16, [sp, #0x12b8] + str x16, [sp, #0x5f0] + ldr x16, [sp, #0x12c0] + str x16, [sp, #0x600] + ldr x16, [sp, #0x12c8] + str x16, [sp, #0x610] + ldr x16, [sp, #0x12d0] + str x16, [sp, #0x620] + ldr x16, [sp, #0x12d8] + str x16, [sp, #0x630] + ldr x16, [sp, #0x12e0] + str x16, [sp, #0x640] + ldr x16, [sp, #0x12e8] + str x16, [sp, #0x650] + ldr x16, [sp, #0x12f0] + str x16, [sp, #0x660] + ldr x16, [sp, #0x12f8] + str x16, [sp, #0x670] + ldr x16, [sp, #0x1300] + str x16, [sp, #0x680] + ldr x16, [sp, #0x1308] + str x16, [sp, #0x690] + ldr x16, [sp, #0x1310] + str x16, [sp, #0x6a0] + ldr x16, [sp, #0x1318] + str x16, [sp, #0x6b0] + ldr x16, [sp, #0x1320] + str x16, [sp, #0x6c0] + ldr x16, [sp, #0x1328] + str x16, [sp, #0x6d0] + ldr x16, [sp, #0x1330] + str x16, [sp, #0x6e0] + ldr x16, [sp, #0x1338] + str x16, [sp, #0x6f0] + ldr x16, [sp, #0x1340] + str x16, [sp, #0x700] + ldr x16, [sp, #0x1348] + str x16, [sp, #0x710] + ldr x16, [sp, #0x1350] + str x16, [sp, #0x720] + ldr x16, [sp, #0x1358] + str x16, [sp, #0x730] + ldr x16, [sp, #0x1360] + str x16, [sp, #0x740] + ldr x16, [sp, #0x1368] + str x16, [sp, #0x750] + ldr x16, [sp, #0x1370] + str x16, [sp, #0x760] + ldr x16, [sp, #0x1378] + str x16, [sp, #0x770] + ldr x16, [sp, #0x1380] + str x16, [sp, #0x780] + ldr x16, [sp, #0x1388] + str x16, [sp, #0x790] + ldr x16, [sp, #0x1390] + str x16, [sp, #0x7a0] + ldr x16, [sp, #0x1398] + str x16, [sp, #0x7b0] + ldr x16, [sp, #0x13a0] + str x16, [sp, #0x7c0] + ldr x16, [sp, #0x13a8] + str x16, [sp, #0x7d0] + ldr x16, [sp, #0x13b0] + str x16, [sp, #0x7e0] + ldr x16, [sp, #0x13b8] + str x16, [sp, #0x7f0] + ldr x16, [sp, #0x13c0] + str x16, [sp, #0x800] + ldr x16, [sp, #0x13c8] + str x16, [sp, #0x810] + ldr x16, [sp, #0x13d0] + str x16, [sp, #0x820] + ldr x16, [sp, #0x13d8] + str x16, [sp, #0x830] + ldr x16, [sp, #0x13e0] + str x16, [sp, #0x840] + ldr x16, [sp, #0x13e8] + str x16, [sp, #0x850] + ldr x16, [sp, #0x13f0] + str x16, [sp, #0x860] + ldr x16, [sp, #0x13f8] + str x16, [sp, #0x870] + ldr x16, [sp, #0x1400] + str x16, [sp, #0x880] + ldr x16, [sp, #0x1408] + str x16, [sp, #0x890] + ldr x16, [sp, #0x1410] + str x16, [sp, #0x8a0] + ldr x16, [sp, #0x1418] + str x16, [sp, #0x8b0] + ldr x16, [sp, #0x1420] + str x16, [sp, #0x8c0] + ldr x16, [sp, #0x1428] + str x16, [sp, #0x8d0] + ldr x16, [sp, #0x1430] + str x16, [sp, #0x8e0] + ldr x16, [sp, #0x1438] + str x16, [sp, #0x8f0] + ldr x16, [sp, #0x1440] + str x16, [sp, #0x900] + ldr x16, [sp, #0x1448] + str x16, [sp, #0x910] + ldr x16, [sp, #0x1450] + str x16, [sp, #0x920] + ldr x16, [sp, #0x1458] + str x16, [sp, #0x930] + ldr x16, [sp, #0x1460] + str x16, [sp, #0x940] + ldr x16, [sp, #0x1468] + str x16, [sp, #0x950] + ldr x16, [sp, #0x1470] + str x16, [sp, #0x960] + ldr x16, [sp, #0x1478] + str x16, [sp, #0x970] + ldr x16, [sp, #0x1480] + str x16, [sp, #0x980] + ldr x16, [sp, #0x1488] + str x16, [sp, #0x990] + ldr x16, [sp, #0x1490] + str x16, [sp, #0x9a0] + ldr x16, [sp, #0x1498] + str x16, [sp, #0x9b0] + ldr x16, [sp, #0x14a0] + str x16, [sp, #0x9c0] + ldr x16, [sp, #0x14a8] + str x16, [sp, #0x9d0] + ldr x16, [sp, #0x14b0] + str x16, [sp, #0x9e0] + ldr x16, [sp, #0x14b8] + str x16, [sp, #0x9f0] + ldr x16, [sp, #0x14c0] + str x16, [sp, #0xa00] + ldr x16, [sp, #0x14c8] + str x16, [sp, #0xa10] + ldr x16, [sp, #0x14d0] + str x16, [sp, #0xa20] + ldr x16, [sp, #0x14d8] + str x16, [sp, #0xa30] + ldr x16, [sp, #0x14e0] + str x16, [sp, #0xa40] + ldr x16, [sp, #0x14e8] + str x16, [sp, #0xa50] + ldr x16, [sp, #0x14f0] + str x16, [sp, #0xa60] + ldr x16, [sp, #0x14f8] + str x16, [sp, #0xa70] + ldr x16, [sp, #0x1500] + str x16, [sp, #0xa80] + ldr x16, [sp, #0x1508] + str x16, [sp, #0xa90] + ldr x16, [sp, #0x1510] + str x16, [sp, #0xaa0] + ldr x16, [sp, #0x1518] + str x16, [sp, #0xab0] + ldr x16, [sp, #0x1520] + str x16, [sp, #0xac0] + ldr x16, [sp, #0x1528] + str x16, [sp, #0xad0] + ldr x16, [sp, #0x1530] + str x16, [sp, #0xae0] + ldr x16, [sp, #0x1538] + str x16, [sp, #0xaf0] + ldr x16, [sp, #0x1540] + str x16, [sp, #0xb00] + ldr x16, [sp, #0x1548] + str x16, [sp, #0xb10] + ldr x16, [sp, #0x1550] + str x16, [sp, #0xb20] + ldr x16, [sp, #0x1558] + str x16, [sp, #0xb30] + ldr x16, [sp, #0x1560] + str x16, [sp, #0xb40] + ldr x16, [sp, #0x1568] + str x16, [sp, #0xb50] + ldr x16, [sp, #0x1570] + str x16, [sp, #0xb60] + ldr x16, [sp, #0x1578] + str x16, [sp, #0xb70] + ldr x16, [sp, #0x1580] + str x16, [sp, #0xb80] + ldr x16, [sp, #0x1588] + str x16, [sp, #0xb90] + ldr x16, [sp, #0x1590] + str x16, [sp, #0xba0] + ldr x16, [sp, #0x1598] + str x16, [sp, #0xbb0] + ldr x16, [sp, #0x15a0] + str x16, [sp, #0xbc0] + ldr x16, [sp, #0x15a8] + str x16, [sp, #0xbd0] + ldr x16, [sp, #0x15b0] + str x16, [sp, #0xbe0] + ldr x16, [sp, #0x15b8] + str x16, [sp, #0xbf0] + ldr x16, [sp, #0x15c0] + str x16, [sp, #0xc00] + ldr x16, [sp, #0x15c8] + str x16, [sp, #0xc10] + ldr x16, [sp, #0x15d0] + str x16, [sp, #0xc20] + ldr x16, [sp, #0x15d8] + str x16, [sp, #0xc30] + ldr x16, [sp, #0x15e0] + str x16, [sp, #0xc40] + ldr x16, [sp, #0x15e8] + str x16, [sp, #0xc50] + ldr x16, [sp, #0x15f0] + str x16, [sp, #0xc60] + ldr x16, [sp, #0x15f8] + str x16, [sp, #0xc70] + ldr x16, [sp, #0x1600] + str x16, [sp, #0xc80] + ldr x16, [sp, #0x1608] + str x16, [sp, #0xc90] + ldr x16, [sp, #0x1610] + str x16, [sp, #0xca0] + ldr x16, [sp, #0x1618] + str x16, [sp, #0xcb0] + ldr x16, [sp, #0x1620] + str x16, [sp, #0xcc0] + ldr x16, [sp, #0x1628] + str x16, [sp, #0xcd0] + ldr x16, [sp, #0x1630] + str x16, [sp, #0xce0] + ldr x16, [sp, #0x1638] + str x16, [sp, #0xcf0] + ldr x16, [sp, #0x1640] + str x16, [sp, #0xd00] + ldr x16, [sp, #0x1648] + str x16, [sp, #0xd10] + ldr x16, [sp, #0x1650] + str x16, [sp, #0xd20] + ldr x16, [sp, #0x1658] + str x16, [sp, #0xd30] + ldr x16, [sp, #0x1660] + str x16, [sp, #0xd40] + ldr x16, [sp, #0x1668] + str x16, [sp, #0xd50] + ldr x16, [sp, #0x1670] + str x16, [sp, #0xd60] + ldr x16, [sp, #0x1678] + str x16, [sp, #0xd70] + ldr x16, [sp, #0x1680] + str x16, [sp, #0xd80] + ldr x16, [sp, #0x1688] + str x16, [sp, #0xd90] + ldr x16, [sp, #0x1690] + str x16, [sp, #0xda0] + ldr x16, [sp, #0x1698] + str x16, [sp, #0xdb0] + ldr x16, [sp, #0x16a0] + str x16, [sp, #0xdc0] + ldr x16, [sp, #0x16a8] + str x16, [sp, #0xdd0] + ldr x16, [sp, #0x16b0] + str x16, [sp, #0xde0] + ldr x16, [sp, #0x16b8] + str x16, [sp, #0xdf0] + ldr x16, [sp, #0x16c0] + str x16, [sp, #0xe00] + ldr x16, [sp, #0x16c8] + str x16, [sp, #0xe10] + ldr x16, [sp, #0x16d0] + str x16, [sp, #0xe20] + ldr x16, [sp, #0x16d8] + str x16, [sp, #0xe30] + ldr x16, [sp, #0x16e0] + str x16, [sp, #0xe40] + ldr x16, [sp, #0x16e8] + str x16, [sp, #0xe50] + ldr x16, [sp, #0x16f0] + str x16, [sp, #0xe60] + ldr x16, [sp, #0x16f8] + str x16, [sp, #0xe70] + ldr x16, [sp, #0x1700] + str x16, [sp, #0xe80] + ldr x16, [sp, #0x1708] + str x16, [sp, #0xe90] + ldr x16, [sp, #0x1710] + str x16, [sp, #0xea0] + ldr x16, [sp, #0x1718] + str x16, [sp, #0xeb0] + ldr x16, [sp, #0x1720] + str x16, [sp, #0xec0] + ldr x16, [sp, #0x1728] + str x16, [sp, #0xed0] + ldr x16, [sp, #0x1730] + str x16, [sp, #0xee0] + ldr x16, [sp, #0x1738] + str x16, [sp, #0xef0] + ldr x16, [sp, #0x1740] + str x16, [sp, #0xf00] + ldr x16, [sp, #0x1748] + str x16, [sp, #0xf10] + ldr x16, [sp, #0x1750] + str x16, [sp, #0xf20] + ldr x16, [sp, #0x1758] + str x16, [sp, #0xf30] + ldr x16, [sp, #0x1760] + str x16, [sp, #0xf40] + ldr x16, [sp, #0x1768] + str x16, [sp, #0xf50] + ldr x16, [sp, #0x1770] + str x16, [sp, #0xf60] + ldr x16, [sp, #0x1778] + str x16, [sp, #0xf70] + ldr x16, [sp, #0x1780] + str x16, [sp, #0xf80] + ldr x16, [sp, #0x1788] + str x16, [sp, #0xf90] + ldr x16, [sp, #0x1790] + str x16, [sp, #0xfa0] + ldr x16, [sp, #0x1798] + str x16, [sp, #0xfb0] + sub sp, sp, #0x80 + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x10 + mov x8, #0x0 // =0 + add x0, x8, x0 + add x0, x0, x1 + add x0, x0, x2 + add x0, x0, x3 + add x0, x0, x4 + add x0, x0, x5 + add x0, x0, x6 + add x0, x0, x7 + ldur x1, [x29, #0x90] + add x0, x0, x1 + ldur x1, [x29, #0xa0] + add x0, x0, x1 + ldur x1, [x29, #0xb0] + add x0, x0, x1 + ldur x1, [x29, #0xc0] + add x0, x0, x1 + ldur x1, [x29, #0xd0] + add x0, x0, x1 + ldur x1, [x29, #0xe0] + add x0, x0, x1 + ldur x1, [x29, #0xf0] + add x0, x0, x1 + add x16, x29, #0x100 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x110 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x120 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x130 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x140 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x150 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x160 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x170 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x180 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x190 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x1a0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x1b0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x1c0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x1d0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x1e0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x1f0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x200 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x210 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x220 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x230 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x240 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x250 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x260 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x270 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x280 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x290 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x2a0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x2b0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x2c0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x2d0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x2e0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x2f0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x300 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x310 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x320 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x330 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x340 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x350 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x360 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x370 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x380 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x390 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x3a0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x3b0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x3c0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x3d0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x3e0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x3f0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x400 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x410 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x420 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x430 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x440 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x450 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x460 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x470 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x480 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x490 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x4a0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x4b0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x4c0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x4d0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x4e0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x4f0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x500 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x510 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x520 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x530 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x540 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x550 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x560 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x570 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x580 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x590 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x5a0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x5b0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x5c0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x5d0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x5e0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x5f0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x600 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x610 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x620 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x630 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x640 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x650 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x660 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x670 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x680 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x690 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x6a0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x6b0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x6c0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x6d0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x6e0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x6f0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x700 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x710 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x720 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x730 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x740 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x750 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x760 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x770 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x780 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x790 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x7a0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x7b0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x7c0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x7d0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x7e0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x7f0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x800 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x810 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x820 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x830 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x840 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x850 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x860 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x870 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x880 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x890 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x8a0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x8b0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x8c0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x8d0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x8e0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x8f0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x900 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x910 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x920 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x930 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x940 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x950 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x960 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x970 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x980 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x990 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x9a0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x9b0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x9c0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x9d0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x9e0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x9f0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xa00 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xa10 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xa20 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xa30 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xa40 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xa50 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xa60 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xa70 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xa80 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xa90 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xaa0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xab0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xac0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xad0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xae0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xaf0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xb00 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xb10 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xb20 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xb30 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xb40 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xb50 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xb60 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xb70 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xb80 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xb90 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xba0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xbb0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xbc0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xbd0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xbe0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xbf0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xc00 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xc10 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xc20 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xc30 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xc40 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xc50 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xc60 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xc70 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xc80 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xc90 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xca0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xcb0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xcc0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xcd0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xce0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xcf0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xd00 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xd10 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xd20 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xd30 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xd40 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xd50 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xd60 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xd70 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xd80 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xd90 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xda0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xdb0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xdc0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xdd0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xde0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xdf0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xe00 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xe10 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xe20 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xe30 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xe40 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xe50 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xe60 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xe70 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xe80 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xe90 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xea0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xeb0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xec0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xed0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xee0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xef0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xf00 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xf10 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xf20 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xf30 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xf40 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xf50 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xf60 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xf70 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xf80 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xf90 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xfa0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xfb0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xfc0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xfd0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xfe0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0xff0 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x1, lsl #12 // =0x1000 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x1, lsl #12 // =0x1000 + add x16, x16, #0x10 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x1, lsl #12 // =0x1000 + add x16, x16, #0x20 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x1, lsl #12 // =0x1000 + add x16, x16, #0x30 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x1, lsl #12 // =0x1000 + add x16, x16, #0x40 + ldr x1, [x16] + add x0, x0, x1 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0x1, lsl #12 // =0x1000 + add sp, sp, #0x40 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x1, lsl #12 // =0x1000 + sub sp, sp, #0x10 + str x20, [sp] + str x21, [sp, #0x8] + str x22, [sp, #0x10] + str x23, [sp, #0x18] + str x24, [sp, #0x20] + str x25, [sp, #0x28] + str x26, [sp, #0x30] + str x27, [sp, #0x38] + str x28, [sp, #0x40] + str x19, [sp, #0x50] + adrp x20, + add x20, x20, #0x370 + adrp x21, + add x21, x21, + mov x1, #0x0 // =0 + cmp x1, #0x105 + b.ge + b + add x1, x1, #0x1 + b + adrp x0, + add x0, x0, + lsl x2, x1, #4 + add x2, x0, x2 + str x1, [x2] + lsl x2, x1, #4 + add x0, x0, x2 + lsl x2, x1, #1 + str x2, [x0, #0x8] + b + adrp x0, + add x0, x0, + add x1, x0, #0x10 + add x2, x0, #0x20 + add x3, x0, #0x30 + add x4, x0, #0x40 + add x5, x0, #0x50 + add x6, x0, #0x60 + add x7, x0, #0x70 + add x8, x0, #0x80 + add x9, x0, #0x90 + add x10, x0, #0xa0 + add x11, x0, #0xb0 + add x12, x0, #0xc0 + add x13, x0, #0xd0 + add x14, x0, #0xe0 + add x15, x0, #0xf0 + add x22, x0, #0x100 + add x23, x0, #0x110 + add x24, x0, #0x120 + add x25, x0, #0x130 + add x26, x0, #0x140 + add x27, x0, #0x150 + add x28, x0, #0x160 + add x16, x0, #0x170 + str x16, [sp, #0x7c8] + add x16, x0, #0x180 + str x16, [sp, #0x7c0] + add x16, x0, #0x190 + str x16, [sp, #0x7b8] + add x16, x0, #0x1a0 + str x16, [sp, #0x7b0] + add x16, x0, #0x1b0 + str x16, [sp, #0x7a8] + add x16, x0, #0x1c0 + str x16, [sp, #0x7a0] + add x16, x0, #0x1d0 + str x16, [sp, #0x798] + add x16, x0, #0x1e0 + str x16, [sp, #0x790] + add x16, x0, #0x1f0 + str x16, [sp, #0x788] + add x16, x0, #0x200 + str x16, [sp, #0x780] + add x16, x0, #0x210 + str x16, [sp, #0x778] + add x16, x0, #0x220 + str x16, [sp, #0x770] + add x16, x0, #0x230 + str x16, [sp, #0x768] + add x16, x0, #0x240 + str x16, [sp, #0x760] + add x16, x0, #0x250 + str x16, [sp, #0x758] + add x16, x0, #0x260 + str x16, [sp, #0x750] + add x16, x0, #0x270 + str x16, [sp, #0x748] + add x16, x0, #0x280 + str x16, [sp, #0x740] + add x16, x0, #0x290 + str x16, [sp, #0x738] + add x16, x0, #0x2a0 + str x16, [sp, #0x730] + add x16, x0, #0x2b0 + str x16, [sp, #0x728] + add x16, x0, #0x2c0 + str x16, [sp, #0x720] + add x16, x0, #0x2d0 + str x16, [sp, #0x718] + add x16, x0, #0x2e0 + str x16, [sp, #0x710] + add x16, x0, #0x2f0 + str x16, [sp, #0x708] + add x16, x0, #0x300 + str x16, [sp, #0x700] + add x16, x0, #0x310 + str x16, [sp, #0x6f8] + add x16, x0, #0x320 + str x16, [sp, #0x6f0] + add x16, x0, #0x330 + str x16, [sp, #0x6e8] + add x16, x0, #0x340 + str x16, [sp, #0x6e0] + add x16, x0, #0x350 + str x16, [sp, #0x6d8] + add x16, x0, #0x360 + str x16, [sp, #0x6d0] + add x16, x0, #0x370 + str x16, [sp, #0x6c8] + add x16, x0, #0x380 + str x16, [sp, #0x6c0] + add x16, x0, #0x390 + str x16, [sp, #0x6b8] + add x16, x0, #0x3a0 + str x16, [sp, #0x6b0] + add x16, x0, #0x3b0 + str x16, [sp, #0x6a8] + add x16, x0, #0x3c0 + str x16, [sp, #0x6a0] + add x16, x0, #0x3d0 + str x16, [sp, #0x698] + add x16, x0, #0x3e0 + str x16, [sp, #0x690] + add x16, x0, #0x3f0 + str x16, [sp, #0x688] + add x16, x0, #0x400 + str x16, [sp, #0x680] + add x16, x0, #0x410 + str x16, [sp, #0x678] + add x16, x0, #0x420 + str x16, [sp, #0x670] + add x16, x0, #0x430 + str x16, [sp, #0x668] + add x16, x0, #0x440 + str x16, [sp, #0x660] + add x16, x0, #0x450 + str x16, [sp, #0x658] + add x16, x0, #0x460 + str x16, [sp, #0x650] + add x16, x0, #0x470 + str x16, [sp, #0x648] + add x16, x0, #0x480 + str x16, [sp, #0x640] + add x16, x0, #0x490 + str x16, [sp, #0x638] + add x16, x0, #0x4a0 + str x16, [sp, #0x630] + add x16, x0, #0x4b0 + str x16, [sp, #0x628] + add x16, x0, #0x4c0 + str x16, [sp, #0x620] + add x16, x0, #0x4d0 + str x16, [sp, #0x618] + add x16, x0, #0x4e0 + str x16, [sp, #0x610] + add x16, x0, #0x4f0 + str x16, [sp, #0x608] + add x16, x0, #0x500 + str x16, [sp, #0x600] + add x16, x0, #0x510 + str x16, [sp, #0x5f8] + add x16, x0, #0x520 + str x16, [sp, #0x5f0] + add x16, x0, #0x530 + str x16, [sp, #0x5e8] + add x16, x0, #0x540 + str x16, [sp, #0x5e0] + add x16, x0, #0x550 + str x16, [sp, #0x5d8] + add x16, x0, #0x560 + str x16, [sp, #0x5d0] + add x16, x0, #0x570 + str x16, [sp, #0x5c8] + add x16, x0, #0x580 + str x16, [sp, #0x5c0] + add x16, x0, #0x590 + str x16, [sp, #0x5b8] + add x16, x0, #0x5a0 + str x16, [sp, #0x5b0] + add x16, x0, #0x5b0 + str x16, [sp, #0x5a8] + add x16, x0, #0x5c0 + str x16, [sp, #0x5a0] + add x16, x0, #0x5d0 + str x16, [sp, #0x598] + add x16, x0, #0x5e0 + str x16, [sp, #0x590] + add x16, x0, #0x5f0 + str x16, [sp, #0x588] + add x16, x0, #0x600 + str x16, [sp, #0x580] + add x16, x0, #0x610 + str x16, [sp, #0x578] + add x16, x0, #0x620 + str x16, [sp, #0x570] + add x16, x0, #0x630 + str x16, [sp, #0x568] + add x16, x0, #0x640 + str x16, [sp, #0x560] + add x16, x0, #0x650 + str x16, [sp, #0x558] + add x16, x0, #0x660 + str x16, [sp, #0x550] + add x16, x0, #0x670 + str x16, [sp, #0x548] + add x16, x0, #0x680 + str x16, [sp, #0x540] + add x16, x0, #0x690 + str x16, [sp, #0x538] + add x16, x0, #0x6a0 + str x16, [sp, #0x530] + add x16, x0, #0x6b0 + str x16, [sp, #0x528] + add x16, x0, #0x6c0 + str x16, [sp, #0x520] + add x16, x0, #0x6d0 + str x16, [sp, #0x518] + add x16, x0, #0x6e0 + str x16, [sp, #0x510] + add x16, x0, #0x6f0 + str x16, [sp, #0x508] + add x16, x0, #0x700 + str x16, [sp, #0x500] + add x16, x0, #0x710 + str x16, [sp, #0x4f8] + add x16, x0, #0x720 + str x16, [sp, #0x4f0] + add x16, x0, #0x730 + str x16, [sp, #0x4e8] + add x16, x0, #0x740 + str x16, [sp, #0x4e0] + add x16, x0, #0x750 + str x16, [sp, #0x4d8] + add x16, x0, #0x760 + str x16, [sp, #0x4d0] + add x16, x0, #0x770 + str x16, [sp, #0x4c8] + add x16, x0, #0x780 + str x16, [sp, #0x4c0] + add x16, x0, #0x790 + str x16, [sp, #0x4b8] + add x16, x0, #0x7a0 + str x16, [sp, #0x4b0] + add x16, x0, #0x7b0 + str x16, [sp, #0x4a8] + add x16, x0, #0x7c0 + str x16, [sp, #0x4a0] + add x16, x0, #0x7d0 + str x16, [sp, #0x498] + add x16, x0, #0x7e0 + str x16, [sp, #0x490] + add x16, x0, #0x7f0 + str x16, [sp, #0x488] + add x16, x0, #0x800 + str x16, [sp, #0x480] + add x16, x0, #0x810 + str x16, [sp, #0x478] + add x16, x0, #0x820 + str x16, [sp, #0x470] + add x16, x0, #0x830 + str x16, [sp, #0x468] + add x16, x0, #0x840 + str x16, [sp, #0x460] + add x16, x0, #0x850 + str x16, [sp, #0x458] + add x16, x0, #0x860 + str x16, [sp, #0x450] + add x16, x0, #0x870 + str x16, [sp, #0x448] + add x16, x0, #0x880 + str x16, [sp, #0x440] + add x16, x0, #0x890 + str x16, [sp, #0x438] + add x16, x0, #0x8a0 + str x16, [sp, #0x430] + add x16, x0, #0x8b0 + str x16, [sp, #0x428] + add x16, x0, #0x8c0 + str x16, [sp, #0x420] + add x16, x0, #0x8d0 + str x16, [sp, #0x418] + add x16, x0, #0x8e0 + str x16, [sp, #0x410] + add x16, x0, #0x8f0 + str x16, [sp, #0x408] + add x16, x0, #0x900 + str x16, [sp, #0x400] + add x16, x0, #0x910 + str x16, [sp, #0x3f8] + add x16, x0, #0x920 + str x16, [sp, #0x3f0] + add x16, x0, #0x930 + str x16, [sp, #0x3e8] + add x16, x0, #0x940 + str x16, [sp, #0x3e0] + add x16, x0, #0x950 + str x16, [sp, #0x3d8] + add x16, x0, #0x960 + str x16, [sp, #0x3d0] + add x16, x0, #0x970 + str x16, [sp, #0x3c8] + add x16, x0, #0x980 + str x16, [sp, #0x3c0] + add x16, x0, #0x990 + str x16, [sp, #0x3b8] + add x16, x0, #0x9a0 + str x16, [sp, #0x3b0] + add x16, x0, #0x9b0 + str x16, [sp, #0x3a8] + add x16, x0, #0x9c0 + str x16, [sp, #0x3a0] + add x16, x0, #0x9d0 + str x16, [sp, #0x398] + add x16, x0, #0x9e0 + str x16, [sp, #0x390] + add x16, x0, #0x9f0 + str x16, [sp, #0x388] + add x16, x0, #0xa00 + str x16, [sp, #0x380] + add x16, x0, #0xa10 + str x16, [sp, #0x378] + add x16, x0, #0xa20 + str x16, [sp, #0x370] + add x16, x0, #0xa30 + str x16, [sp, #0x368] + add x16, x0, #0xa40 + str x16, [sp, #0x360] + add x16, x0, #0xa50 + str x16, [sp, #0x358] + add x16, x0, #0xa60 + str x16, [sp, #0x350] + add x16, x0, #0xa70 + str x16, [sp, #0x348] + add x16, x0, #0xa80 + str x16, [sp, #0x340] + add x16, x0, #0xa90 + str x16, [sp, #0x338] + add x16, x0, #0xaa0 + str x16, [sp, #0x330] + add x16, x0, #0xab0 + str x16, [sp, #0x328] + add x16, x0, #0xac0 + str x16, [sp, #0x320] + add x16, x0, #0xad0 + str x16, [sp, #0x318] + add x16, x0, #0xae0 + str x16, [sp, #0x310] + add x16, x0, #0xaf0 + str x16, [sp, #0x308] + add x16, x0, #0xb00 + str x16, [sp, #0x300] + add x16, x0, #0xb10 + str x16, [sp, #0x2f8] + add x16, x0, #0xb20 + str x16, [sp, #0x2f0] + add x16, x0, #0xb30 + str x16, [sp, #0x2e8] + add x16, x0, #0xb40 + str x16, [sp, #0x2e0] + add x16, x0, #0xb50 + str x16, [sp, #0x2d8] + add x16, x0, #0xb60 + str x16, [sp, #0x2d0] + add x16, x0, #0xb70 + str x16, [sp, #0x2c8] + add x16, x0, #0xb80 + str x16, [sp, #0x2c0] + add x16, x0, #0xb90 + str x16, [sp, #0x2b8] + add x16, x0, #0xba0 + str x16, [sp, #0x2b0] + add x16, x0, #0xbb0 + str x16, [sp, #0x2a8] + add x16, x0, #0xbc0 + str x16, [sp, #0x2a0] + add x16, x0, #0xbd0 + str x16, [sp, #0x298] + add x16, x0, #0xbe0 + str x16, [sp, #0x290] + add x16, x0, #0xbf0 + str x16, [sp, #0x288] + add x16, x0, #0xc00 + str x16, [sp, #0x280] + add x16, x0, #0xc10 + str x16, [sp, #0x278] + add x16, x0, #0xc20 + str x16, [sp, #0x270] + add x16, x0, #0xc30 + str x16, [sp, #0x268] + add x16, x0, #0xc40 + str x16, [sp, #0x260] + add x16, x0, #0xc50 + str x16, [sp, #0x258] + add x16, x0, #0xc60 + str x16, [sp, #0x250] + add x16, x0, #0xc70 + str x16, [sp, #0x248] + add x16, x0, #0xc80 + str x16, [sp, #0x240] + add x16, x0, #0xc90 + str x16, [sp, #0x238] + add x16, x0, #0xca0 + str x16, [sp, #0x230] + add x16, x0, #0xcb0 + str x16, [sp, #0x228] + add x16, x0, #0xcc0 + str x16, [sp, #0x220] + add x16, x0, #0xcd0 + str x16, [sp, #0x218] + add x16, x0, #0xce0 + str x16, [sp, #0x210] + add x16, x0, #0xcf0 + str x16, [sp, #0x208] + add x16, x0, #0xd00 + str x16, [sp, #0x200] + add x16, x0, #0xd10 + str x16, [sp, #0x1f8] + add x16, x0, #0xd20 + str x16, [sp, #0x1f0] + add x16, x0, #0xd30 + str x16, [sp, #0x1e8] + add x16, x0, #0xd40 + str x16, [sp, #0x1e0] + add x16, x0, #0xd50 + str x16, [sp, #0x1d8] + add x16, x0, #0xd60 + str x16, [sp, #0x1d0] + add x16, x0, #0xd70 + str x16, [sp, #0x1c8] + add x16, x0, #0xd80 + str x16, [sp, #0x1c0] + add x16, x0, #0xd90 + str x16, [sp, #0x1b8] + add x16, x0, #0xda0 + str x16, [sp, #0x1b0] + add x16, x0, #0xdb0 + str x16, [sp, #0x1a8] + add x16, x0, #0xdc0 + str x16, [sp, #0x1a0] + add x16, x0, #0xdd0 + str x16, [sp, #0x198] + add x16, x0, #0xde0 + str x16, [sp, #0x190] + add x16, x0, #0xdf0 + str x16, [sp, #0x188] + add x16, x0, #0xe00 + str x16, [sp, #0x180] + add x16, x0, #0xe10 + str x16, [sp, #0x178] + add x16, x0, #0xe20 + str x16, [sp, #0x170] + add x16, x0, #0xe30 + str x16, [sp, #0x168] + add x16, x0, #0xe40 + str x16, [sp, #0x160] + add x16, x0, #0xe50 + str x16, [sp, #0x158] + add x16, x0, #0xe60 + str x16, [sp, #0x150] + add x16, x0, #0xe70 + str x16, [sp, #0x148] + add x16, x0, #0xe80 + str x16, [sp, #0x140] + add x16, x0, #0xe90 + str x16, [sp, #0x138] + add x16, x0, #0xea0 + str x16, [sp, #0x130] + add x16, x0, #0xeb0 + str x16, [sp, #0x128] + add x16, x0, #0xec0 + str x16, [sp, #0x120] + add x16, x0, #0xed0 + str x16, [sp, #0x118] + add x16, x0, #0xee0 + str x16, [sp, #0x110] + add x16, x0, #0xef0 + str x16, [sp, #0x108] + add x16, x0, #0xf00 + str x16, [sp, #0x100] + add x16, x0, #0xf10 + str x16, [sp, #0xf8] + add x16, x0, #0xf20 + str x16, [sp, #0xf0] + add x16, x0, #0xf30 + str x16, [sp, #0xe8] + add x16, x0, #0xf40 + str x16, [sp, #0xe0] + add x16, x0, #0xf50 + str x16, [sp, #0xd8] + add x16, x0, #0xf60 + str x16, [sp, #0xd0] + add x16, x0, #0xf70 + str x16, [sp, #0xc8] + add x16, x0, #0xf80 + str x16, [sp, #0xc0] + add x16, x0, #0xf90 + str x16, [sp, #0xb8] + add x16, x0, #0xfa0 + str x16, [sp, #0xb0] + add x16, x0, #0xfb0 + str x16, [sp, #0xa8] + add x16, x0, #0xfc0 + str x16, [sp, #0xa0] + add x16, x0, #0xfd0 + str x16, [sp, #0x98] + add x16, x0, #0xfe0 + str x16, [sp, #0x90] + add x16, x0, #0xff0 + str x16, [sp, #0x88] + mov x17, #0x1000 // =4096 + add x16, x0, x17 + str x16, [sp, #0x80] + mov x17, #0x1010 // =4112 + add x16, x0, x17 + str x16, [sp, #0x78] + mov x17, #0x1020 // =4128 + add x16, x0, x17 + str x16, [sp, #0x70] + mov x17, #0x1030 // =4144 + add x16, x0, x17 + str x16, [sp, #0x68] + mov x17, #0x1040 // =4160 + add x16, x0, x17 + str x16, [sp, #0x60] + sub sp, sp, #0x1, lsl #12 // =0x1000 + sub sp, sp, #0x10 + mov x16, x4 + ldr x17, [x16] + str x17, [sp] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8] + mov x16, x5 + ldr x17, [x16] + str x17, [sp, #0x10] + ldr x17, [x16, #0x8] + str x17, [sp, #0x18] + mov x16, x6 + ldr x17, [x16] + str x17, [sp, #0x20] + ldr x17, [x16, #0x8] + str x17, [sp, #0x28] + mov x16, x7 + ldr x17, [x16] + str x17, [sp, #0x30] + ldr x17, [x16, #0x8] + str x17, [sp, #0x38] + mov x16, x8 + ldr x17, [x16] + str x17, [sp, #0x40] + ldr x17, [x16, #0x8] + str x17, [sp, #0x48] + mov x16, x9 + ldr x17, [x16] + str x17, [sp, #0x50] + ldr x17, [x16, #0x8] + str x17, [sp, #0x58] + mov x16, x10 + ldr x17, [x16] + str x17, [sp, #0x60] + ldr x17, [x16, #0x8] + str x17, [sp, #0x68] + mov x16, x11 + ldr x17, [x16] + str x17, [sp, #0x70] + ldr x17, [x16, #0x8] + str x17, [sp, #0x78] + mov x16, x12 + ldr x17, [x16] + str x17, [sp, #0x80] + ldr x17, [x16, #0x8] + str x17, [sp, #0x88] + mov x16, x13 + ldr x17, [x16] + str x17, [sp, #0x90] + ldr x17, [x16, #0x8] + str x17, [sp, #0x98] + mov x16, x14 + ldr x17, [x16] + str x17, [sp, #0xa0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa8] + mov x16, x15 + ldr x17, [x16] + str x17, [sp, #0xb0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb8] + mov x16, x22 + ldr x17, [x16] + str x17, [sp, #0xc0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc8] + mov x16, x23 + ldr x17, [x16] + str x17, [sp, #0xd0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd8] + mov x16, x24 + ldr x17, [x16] + str x17, [sp, #0xe0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe8] + mov x16, x25 + ldr x17, [x16] + str x17, [sp, #0xf0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf8] + mov x16, x26 + ldr x17, [x16] + str x17, [sp, #0x100] + ldr x17, [x16, #0x8] + str x17, [sp, #0x108] + mov x16, x27 + ldr x17, [x16] + str x17, [sp, #0x110] + ldr x17, [x16, #0x8] + str x17, [sp, #0x118] + mov x16, x28 + ldr x17, [x16] + str x17, [sp, #0x120] + ldr x17, [x16, #0x8] + str x17, [sp, #0x128] + ldr x16, [sp, #0x17d8] + ldr x17, [x16] + str x17, [sp, #0x130] + ldr x17, [x16, #0x8] + str x17, [sp, #0x138] + ldr x16, [sp, #0x17d0] + ldr x17, [x16] + str x17, [sp, #0x140] + ldr x17, [x16, #0x8] + str x17, [sp, #0x148] + ldr x16, [sp, #0x17c8] + ldr x17, [x16] + str x17, [sp, #0x150] + ldr x17, [x16, #0x8] + str x17, [sp, #0x158] + ldr x16, [sp, #0x17c0] + ldr x17, [x16] + str x17, [sp, #0x160] + ldr x17, [x16, #0x8] + str x17, [sp, #0x168] + ldr x16, [sp, #0x17b8] + ldr x17, [x16] + str x17, [sp, #0x170] + ldr x17, [x16, #0x8] + str x17, [sp, #0x178] + ldr x16, [sp, #0x17b0] + ldr x17, [x16] + str x17, [sp, #0x180] + ldr x17, [x16, #0x8] + str x17, [sp, #0x188] + ldr x16, [sp, #0x17a8] + ldr x17, [x16] + str x17, [sp, #0x190] + ldr x17, [x16, #0x8] + str x17, [sp, #0x198] + ldr x16, [sp, #0x17a0] + ldr x17, [x16] + str x17, [sp, #0x1a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1a8] + ldr x16, [sp, #0x1798] + ldr x17, [x16] + str x17, [sp, #0x1b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1b8] + ldr x16, [sp, #0x1790] + ldr x17, [x16] + str x17, [sp, #0x1c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1c8] + ldr x16, [sp, #0x1788] + ldr x17, [x16] + str x17, [sp, #0x1d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1d8] + ldr x16, [sp, #0x1780] + ldr x17, [x16] + str x17, [sp, #0x1e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1e8] + ldr x16, [sp, #0x1778] + ldr x17, [x16] + str x17, [sp, #0x1f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1f8] + ldr x16, [sp, #0x1770] + ldr x17, [x16] + str x17, [sp, #0x200] + ldr x17, [x16, #0x8] + str x17, [sp, #0x208] + ldr x16, [sp, #0x1768] + ldr x17, [x16] + str x17, [sp, #0x210] + ldr x17, [x16, #0x8] + str x17, [sp, #0x218] + ldr x16, [sp, #0x1760] + ldr x17, [x16] + str x17, [sp, #0x220] + ldr x17, [x16, #0x8] + str x17, [sp, #0x228] + ldr x16, [sp, #0x1758] + ldr x17, [x16] + str x17, [sp, #0x230] + ldr x17, [x16, #0x8] + str x17, [sp, #0x238] + ldr x16, [sp, #0x1750] + ldr x17, [x16] + str x17, [sp, #0x240] + ldr x17, [x16, #0x8] + str x17, [sp, #0x248] + ldr x16, [sp, #0x1748] + ldr x17, [x16] + str x17, [sp, #0x250] + ldr x17, [x16, #0x8] + str x17, [sp, #0x258] + ldr x16, [sp, #0x1740] + ldr x17, [x16] + str x17, [sp, #0x260] + ldr x17, [x16, #0x8] + str x17, [sp, #0x268] + ldr x16, [sp, #0x1738] + ldr x17, [x16] + str x17, [sp, #0x270] + ldr x17, [x16, #0x8] + str x17, [sp, #0x278] + ldr x16, [sp, #0x1730] + ldr x17, [x16] + str x17, [sp, #0x280] + ldr x17, [x16, #0x8] + str x17, [sp, #0x288] + ldr x16, [sp, #0x1728] + ldr x17, [x16] + str x17, [sp, #0x290] + ldr x17, [x16, #0x8] + str x17, [sp, #0x298] + ldr x16, [sp, #0x1720] + ldr x17, [x16] + str x17, [sp, #0x2a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x2a8] + ldr x16, [sp, #0x1718] + ldr x17, [x16] + str x17, [sp, #0x2b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x2b8] + ldr x16, [sp, #0x1710] + ldr x17, [x16] + str x17, [sp, #0x2c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x2c8] + ldr x16, [sp, #0x1708] + ldr x17, [x16] + str x17, [sp, #0x2d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x2d8] + ldr x16, [sp, #0x1700] + ldr x17, [x16] + str x17, [sp, #0x2e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x2e8] + ldr x16, [sp, #0x16f8] + ldr x17, [x16] + str x17, [sp, #0x2f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x2f8] + ldr x16, [sp, #0x16f0] + ldr x17, [x16] + str x17, [sp, #0x300] + ldr x17, [x16, #0x8] + str x17, [sp, #0x308] + ldr x16, [sp, #0x16e8] + ldr x17, [x16] + str x17, [sp, #0x310] + ldr x17, [x16, #0x8] + str x17, [sp, #0x318] + ldr x16, [sp, #0x16e0] + ldr x17, [x16] + str x17, [sp, #0x320] + ldr x17, [x16, #0x8] + str x17, [sp, #0x328] + ldr x16, [sp, #0x16d8] + ldr x17, [x16] + str x17, [sp, #0x330] + ldr x17, [x16, #0x8] + str x17, [sp, #0x338] + ldr x16, [sp, #0x16d0] + ldr x17, [x16] + str x17, [sp, #0x340] + ldr x17, [x16, #0x8] + str x17, [sp, #0x348] + ldr x16, [sp, #0x16c8] + ldr x17, [x16] + str x17, [sp, #0x350] + ldr x17, [x16, #0x8] + str x17, [sp, #0x358] + ldr x16, [sp, #0x16c0] + ldr x17, [x16] + str x17, [sp, #0x360] + ldr x17, [x16, #0x8] + str x17, [sp, #0x368] + ldr x16, [sp, #0x16b8] + ldr x17, [x16] + str x17, [sp, #0x370] + ldr x17, [x16, #0x8] + str x17, [sp, #0x378] + ldr x16, [sp, #0x16b0] + ldr x17, [x16] + str x17, [sp, #0x380] + ldr x17, [x16, #0x8] + str x17, [sp, #0x388] + ldr x16, [sp, #0x16a8] + ldr x17, [x16] + str x17, [sp, #0x390] + ldr x17, [x16, #0x8] + str x17, [sp, #0x398] + ldr x16, [sp, #0x16a0] + ldr x17, [x16] + str x17, [sp, #0x3a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x3a8] + ldr x16, [sp, #0x1698] + ldr x17, [x16] + str x17, [sp, #0x3b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x3b8] + ldr x16, [sp, #0x1690] + ldr x17, [x16] + str x17, [sp, #0x3c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x3c8] + ldr x16, [sp, #0x1688] + ldr x17, [x16] + str x17, [sp, #0x3d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x3d8] + ldr x16, [sp, #0x1680] + ldr x17, [x16] + str x17, [sp, #0x3e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x3e8] + ldr x16, [sp, #0x1678] + ldr x17, [x16] + str x17, [sp, #0x3f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x3f8] + ldr x16, [sp, #0x1670] + ldr x17, [x16] + str x17, [sp, #0x400] + ldr x17, [x16, #0x8] + str x17, [sp, #0x408] + ldr x16, [sp, #0x1668] + ldr x17, [x16] + str x17, [sp, #0x410] + ldr x17, [x16, #0x8] + str x17, [sp, #0x418] + ldr x16, [sp, #0x1660] + ldr x17, [x16] + str x17, [sp, #0x420] + ldr x17, [x16, #0x8] + str x17, [sp, #0x428] + ldr x16, [sp, #0x1658] + ldr x17, [x16] + str x17, [sp, #0x430] + ldr x17, [x16, #0x8] + str x17, [sp, #0x438] + ldr x16, [sp, #0x1650] + ldr x17, [x16] + str x17, [sp, #0x440] + ldr x17, [x16, #0x8] + str x17, [sp, #0x448] + ldr x16, [sp, #0x1648] + ldr x17, [x16] + str x17, [sp, #0x450] + ldr x17, [x16, #0x8] + str x17, [sp, #0x458] + ldr x16, [sp, #0x1640] + ldr x17, [x16] + str x17, [sp, #0x460] + ldr x17, [x16, #0x8] + str x17, [sp, #0x468] + ldr x16, [sp, #0x1638] + ldr x17, [x16] + str x17, [sp, #0x470] + ldr x17, [x16, #0x8] + str x17, [sp, #0x478] + ldr x16, [sp, #0x1630] + ldr x17, [x16] + str x17, [sp, #0x480] + ldr x17, [x16, #0x8] + str x17, [sp, #0x488] + ldr x16, [sp, #0x1628] + ldr x17, [x16] + str x17, [sp, #0x490] + ldr x17, [x16, #0x8] + str x17, [sp, #0x498] + ldr x16, [sp, #0x1620] + ldr x17, [x16] + str x17, [sp, #0x4a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x4a8] + ldr x16, [sp, #0x1618] + ldr x17, [x16] + str x17, [sp, #0x4b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x4b8] + ldr x16, [sp, #0x1610] + ldr x17, [x16] + str x17, [sp, #0x4c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x4c8] + ldr x16, [sp, #0x1608] + ldr x17, [x16] + str x17, [sp, #0x4d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x4d8] + ldr x16, [sp, #0x1600] + ldr x17, [x16] + str x17, [sp, #0x4e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x4e8] + ldr x16, [sp, #0x15f8] + ldr x17, [x16] + str x17, [sp, #0x4f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x4f8] + ldr x16, [sp, #0x15f0] + ldr x17, [x16] + str x17, [sp, #0x500] + ldr x17, [x16, #0x8] + str x17, [sp, #0x508] + ldr x16, [sp, #0x15e8] + ldr x17, [x16] + str x17, [sp, #0x510] + ldr x17, [x16, #0x8] + str x17, [sp, #0x518] + ldr x16, [sp, #0x15e0] + ldr x17, [x16] + str x17, [sp, #0x520] + ldr x17, [x16, #0x8] + str x17, [sp, #0x528] + ldr x16, [sp, #0x15d8] + ldr x17, [x16] + str x17, [sp, #0x530] + ldr x17, [x16, #0x8] + str x17, [sp, #0x538] + ldr x16, [sp, #0x15d0] + ldr x17, [x16] + str x17, [sp, #0x540] + ldr x17, [x16, #0x8] + str x17, [sp, #0x548] + ldr x16, [sp, #0x15c8] + ldr x17, [x16] + str x17, [sp, #0x550] + ldr x17, [x16, #0x8] + str x17, [sp, #0x558] + ldr x16, [sp, #0x15c0] + ldr x17, [x16] + str x17, [sp, #0x560] + ldr x17, [x16, #0x8] + str x17, [sp, #0x568] + ldr x16, [sp, #0x15b8] + ldr x17, [x16] + str x17, [sp, #0x570] + ldr x17, [x16, #0x8] + str x17, [sp, #0x578] + ldr x16, [sp, #0x15b0] + ldr x17, [x16] + str x17, [sp, #0x580] + ldr x17, [x16, #0x8] + str x17, [sp, #0x588] + ldr x16, [sp, #0x15a8] + ldr x17, [x16] + str x17, [sp, #0x590] + ldr x17, [x16, #0x8] + str x17, [sp, #0x598] + ldr x16, [sp, #0x15a0] + ldr x17, [x16] + str x17, [sp, #0x5a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x5a8] + ldr x16, [sp, #0x1598] + ldr x17, [x16] + str x17, [sp, #0x5b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x5b8] + ldr x16, [sp, #0x1590] + ldr x17, [x16] + str x17, [sp, #0x5c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x5c8] + ldr x16, [sp, #0x1588] + ldr x17, [x16] + str x17, [sp, #0x5d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x5d8] + ldr x16, [sp, #0x1580] + ldr x17, [x16] + str x17, [sp, #0x5e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x5e8] + ldr x16, [sp, #0x1578] + ldr x17, [x16] + str x17, [sp, #0x5f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x5f8] + ldr x16, [sp, #0x1570] + ldr x17, [x16] + str x17, [sp, #0x600] + ldr x17, [x16, #0x8] + str x17, [sp, #0x608] + ldr x16, [sp, #0x1568] + ldr x17, [x16] + str x17, [sp, #0x610] + ldr x17, [x16, #0x8] + str x17, [sp, #0x618] + ldr x16, [sp, #0x1560] + ldr x17, [x16] + str x17, [sp, #0x620] + ldr x17, [x16, #0x8] + str x17, [sp, #0x628] + ldr x16, [sp, #0x1558] + ldr x17, [x16] + str x17, [sp, #0x630] + ldr x17, [x16, #0x8] + str x17, [sp, #0x638] + ldr x16, [sp, #0x1550] + ldr x17, [x16] + str x17, [sp, #0x640] + ldr x17, [x16, #0x8] + str x17, [sp, #0x648] + ldr x16, [sp, #0x1548] + ldr x17, [x16] + str x17, [sp, #0x650] + ldr x17, [x16, #0x8] + str x17, [sp, #0x658] + ldr x16, [sp, #0x1540] + ldr x17, [x16] + str x17, [sp, #0x660] + ldr x17, [x16, #0x8] + str x17, [sp, #0x668] + ldr x16, [sp, #0x1538] + ldr x17, [x16] + str x17, [sp, #0x670] + ldr x17, [x16, #0x8] + str x17, [sp, #0x678] + ldr x16, [sp, #0x1530] + ldr x17, [x16] + str x17, [sp, #0x680] + ldr x17, [x16, #0x8] + str x17, [sp, #0x688] + ldr x16, [sp, #0x1528] + ldr x17, [x16] + str x17, [sp, #0x690] + ldr x17, [x16, #0x8] + str x17, [sp, #0x698] + ldr x16, [sp, #0x1520] + ldr x17, [x16] + str x17, [sp, #0x6a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x6a8] + ldr x16, [sp, #0x1518] + ldr x17, [x16] + str x17, [sp, #0x6b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x6b8] + ldr x16, [sp, #0x1510] + ldr x17, [x16] + str x17, [sp, #0x6c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x6c8] + ldr x16, [sp, #0x1508] + ldr x17, [x16] + str x17, [sp, #0x6d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x6d8] + ldr x16, [sp, #0x1500] + ldr x17, [x16] + str x17, [sp, #0x6e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x6e8] + ldr x16, [sp, #0x14f8] + ldr x17, [x16] + str x17, [sp, #0x6f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x6f8] + ldr x16, [sp, #0x14f0] + ldr x17, [x16] + str x17, [sp, #0x700] + ldr x17, [x16, #0x8] + str x17, [sp, #0x708] + ldr x16, [sp, #0x14e8] + ldr x17, [x16] + str x17, [sp, #0x710] + ldr x17, [x16, #0x8] + str x17, [sp, #0x718] + ldr x16, [sp, #0x14e0] + ldr x17, [x16] + str x17, [sp, #0x720] + ldr x17, [x16, #0x8] + str x17, [sp, #0x728] + ldr x16, [sp, #0x14d8] + ldr x17, [x16] + str x17, [sp, #0x730] + ldr x17, [x16, #0x8] + str x17, [sp, #0x738] + ldr x16, [sp, #0x14d0] + ldr x17, [x16] + str x17, [sp, #0x740] + ldr x17, [x16, #0x8] + str x17, [sp, #0x748] + ldr x16, [sp, #0x14c8] + ldr x17, [x16] + str x17, [sp, #0x750] + ldr x17, [x16, #0x8] + str x17, [sp, #0x758] + ldr x16, [sp, #0x14c0] + ldr x17, [x16] + str x17, [sp, #0x760] + ldr x17, [x16, #0x8] + str x17, [sp, #0x768] + ldr x16, [sp, #0x14b8] + ldr x17, [x16] + str x17, [sp, #0x770] + ldr x17, [x16, #0x8] + str x17, [sp, #0x778] + ldr x16, [sp, #0x14b0] + ldr x17, [x16] + str x17, [sp, #0x780] + ldr x17, [x16, #0x8] + str x17, [sp, #0x788] + ldr x16, [sp, #0x14a8] + ldr x17, [x16] + str x17, [sp, #0x790] + ldr x17, [x16, #0x8] + str x17, [sp, #0x798] + ldr x16, [sp, #0x14a0] + ldr x17, [x16] + str x17, [sp, #0x7a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x7a8] + ldr x16, [sp, #0x1498] + ldr x17, [x16] + str x17, [sp, #0x7b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x7b8] + ldr x16, [sp, #0x1490] + ldr x17, [x16] + str x17, [sp, #0x7c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x7c8] + ldr x16, [sp, #0x1488] + ldr x17, [x16] + str x17, [sp, #0x7d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x7d8] + ldr x16, [sp, #0x1480] + ldr x17, [x16] + str x17, [sp, #0x7e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x7e8] + ldr x16, [sp, #0x1478] + ldr x17, [x16] + str x17, [sp, #0x7f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x7f8] + ldr x16, [sp, #0x1470] + ldr x17, [x16] + str x17, [sp, #0x800] + ldr x17, [x16, #0x8] + str x17, [sp, #0x808] + ldr x16, [sp, #0x1468] + ldr x17, [x16] + str x17, [sp, #0x810] + ldr x17, [x16, #0x8] + str x17, [sp, #0x818] + ldr x16, [sp, #0x1460] + ldr x17, [x16] + str x17, [sp, #0x820] + ldr x17, [x16, #0x8] + str x17, [sp, #0x828] + ldr x16, [sp, #0x1458] + ldr x17, [x16] + str x17, [sp, #0x830] + ldr x17, [x16, #0x8] + str x17, [sp, #0x838] + ldr x16, [sp, #0x1450] + ldr x17, [x16] + str x17, [sp, #0x840] + ldr x17, [x16, #0x8] + str x17, [sp, #0x848] + ldr x16, [sp, #0x1448] + ldr x17, [x16] + str x17, [sp, #0x850] + ldr x17, [x16, #0x8] + str x17, [sp, #0x858] + ldr x16, [sp, #0x1440] + ldr x17, [x16] + str x17, [sp, #0x860] + ldr x17, [x16, #0x8] + str x17, [sp, #0x868] + ldr x16, [sp, #0x1438] + ldr x17, [x16] + str x17, [sp, #0x870] + ldr x17, [x16, #0x8] + str x17, [sp, #0x878] + ldr x16, [sp, #0x1430] + ldr x17, [x16] + str x17, [sp, #0x880] + ldr x17, [x16, #0x8] + str x17, [sp, #0x888] + ldr x16, [sp, #0x1428] + ldr x17, [x16] + str x17, [sp, #0x890] + ldr x17, [x16, #0x8] + str x17, [sp, #0x898] + ldr x16, [sp, #0x1420] + ldr x17, [x16] + str x17, [sp, #0x8a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8a8] + ldr x16, [sp, #0x1418] + ldr x17, [x16] + str x17, [sp, #0x8b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8b8] + ldr x16, [sp, #0x1410] + ldr x17, [x16] + str x17, [sp, #0x8c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8c8] + ldr x16, [sp, #0x1408] + ldr x17, [x16] + str x17, [sp, #0x8d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8d8] + ldr x16, [sp, #0x1400] + ldr x17, [x16] + str x17, [sp, #0x8e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8e8] + ldr x16, [sp, #0x13f8] + ldr x17, [x16] + str x17, [sp, #0x8f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8f8] + ldr x16, [sp, #0x13f0] + ldr x17, [x16] + str x17, [sp, #0x900] + ldr x17, [x16, #0x8] + str x17, [sp, #0x908] + ldr x16, [sp, #0x13e8] + ldr x17, [x16] + str x17, [sp, #0x910] + ldr x17, [x16, #0x8] + str x17, [sp, #0x918] + ldr x16, [sp, #0x13e0] + ldr x17, [x16] + str x17, [sp, #0x920] + ldr x17, [x16, #0x8] + str x17, [sp, #0x928] + ldr x16, [sp, #0x13d8] + ldr x17, [x16] + str x17, [sp, #0x930] + ldr x17, [x16, #0x8] + str x17, [sp, #0x938] + ldr x16, [sp, #0x13d0] + ldr x17, [x16] + str x17, [sp, #0x940] + ldr x17, [x16, #0x8] + str x17, [sp, #0x948] + ldr x16, [sp, #0x13c8] + ldr x17, [x16] + str x17, [sp, #0x950] + ldr x17, [x16, #0x8] + str x17, [sp, #0x958] + ldr x16, [sp, #0x13c0] + ldr x17, [x16] + str x17, [sp, #0x960] + ldr x17, [x16, #0x8] + str x17, [sp, #0x968] + ldr x16, [sp, #0x13b8] + ldr x17, [x16] + str x17, [sp, #0x970] + ldr x17, [x16, #0x8] + str x17, [sp, #0x978] + ldr x16, [sp, #0x13b0] + ldr x17, [x16] + str x17, [sp, #0x980] + ldr x17, [x16, #0x8] + str x17, [sp, #0x988] + ldr x16, [sp, #0x13a8] + ldr x17, [x16] + str x17, [sp, #0x990] + ldr x17, [x16, #0x8] + str x17, [sp, #0x998] + ldr x16, [sp, #0x13a0] + ldr x17, [x16] + str x17, [sp, #0x9a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x9a8] + ldr x16, [sp, #0x1398] + ldr x17, [x16] + str x17, [sp, #0x9b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x9b8] + ldr x16, [sp, #0x1390] + ldr x17, [x16] + str x17, [sp, #0x9c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x9c8] + ldr x16, [sp, #0x1388] + ldr x17, [x16] + str x17, [sp, #0x9d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x9d8] + ldr x16, [sp, #0x1380] + ldr x17, [x16] + str x17, [sp, #0x9e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x9e8] + ldr x16, [sp, #0x1378] + ldr x17, [x16] + str x17, [sp, #0x9f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x9f8] + ldr x16, [sp, #0x1370] + ldr x17, [x16] + str x17, [sp, #0xa00] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa08] + ldr x16, [sp, #0x1368] + ldr x17, [x16] + str x17, [sp, #0xa10] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa18] + ldr x16, [sp, #0x1360] + ldr x17, [x16] + str x17, [sp, #0xa20] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa28] + ldr x16, [sp, #0x1358] + ldr x17, [x16] + str x17, [sp, #0xa30] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa38] + ldr x16, [sp, #0x1350] + ldr x17, [x16] + str x17, [sp, #0xa40] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa48] + ldr x16, [sp, #0x1348] + ldr x17, [x16] + str x17, [sp, #0xa50] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa58] + ldr x16, [sp, #0x1340] + ldr x17, [x16] + str x17, [sp, #0xa60] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa68] + ldr x16, [sp, #0x1338] + ldr x17, [x16] + str x17, [sp, #0xa70] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa78] + ldr x16, [sp, #0x1330] + ldr x17, [x16] + str x17, [sp, #0xa80] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa88] + ldr x16, [sp, #0x1328] + ldr x17, [x16] + str x17, [sp, #0xa90] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa98] + ldr x16, [sp, #0x1320] + ldr x17, [x16] + str x17, [sp, #0xaa0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xaa8] + ldr x16, [sp, #0x1318] + ldr x17, [x16] + str x17, [sp, #0xab0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xab8] + ldr x16, [sp, #0x1310] + ldr x17, [x16] + str x17, [sp, #0xac0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xac8] + ldr x16, [sp, #0x1308] + ldr x17, [x16] + str x17, [sp, #0xad0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xad8] + ldr x16, [sp, #0x1300] + ldr x17, [x16] + str x17, [sp, #0xae0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xae8] + ldr x16, [sp, #0x12f8] + ldr x17, [x16] + str x17, [sp, #0xaf0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xaf8] + ldr x16, [sp, #0x12f0] + ldr x17, [x16] + str x17, [sp, #0xb00] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb08] + ldr x16, [sp, #0x12e8] + ldr x17, [x16] + str x17, [sp, #0xb10] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb18] + ldr x16, [sp, #0x12e0] + ldr x17, [x16] + str x17, [sp, #0xb20] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb28] + ldr x16, [sp, #0x12d8] + ldr x17, [x16] + str x17, [sp, #0xb30] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb38] + ldr x16, [sp, #0x12d0] + ldr x17, [x16] + str x17, [sp, #0xb40] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb48] + ldr x16, [sp, #0x12c8] + ldr x17, [x16] + str x17, [sp, #0xb50] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb58] + ldr x16, [sp, #0x12c0] + ldr x17, [x16] + str x17, [sp, #0xb60] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb68] + ldr x16, [sp, #0x12b8] + ldr x17, [x16] + str x17, [sp, #0xb70] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb78] + ldr x16, [sp, #0x12b0] + ldr x17, [x16] + str x17, [sp, #0xb80] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb88] + ldr x16, [sp, #0x12a8] + ldr x17, [x16] + str x17, [sp, #0xb90] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb98] + ldr x16, [sp, #0x12a0] + ldr x17, [x16] + str x17, [sp, #0xba0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xba8] + ldr x16, [sp, #0x1298] + ldr x17, [x16] + str x17, [sp, #0xbb0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xbb8] + ldr x16, [sp, #0x1290] + ldr x17, [x16] + str x17, [sp, #0xbc0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xbc8] + ldr x16, [sp, #0x1288] + ldr x17, [x16] + str x17, [sp, #0xbd0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xbd8] + ldr x16, [sp, #0x1280] + ldr x17, [x16] + str x17, [sp, #0xbe0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xbe8] + ldr x16, [sp, #0x1278] + ldr x17, [x16] + str x17, [sp, #0xbf0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xbf8] + ldr x16, [sp, #0x1270] + ldr x17, [x16] + str x17, [sp, #0xc00] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc08] + ldr x16, [sp, #0x1268] + ldr x17, [x16] + str x17, [sp, #0xc10] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc18] + ldr x16, [sp, #0x1260] + ldr x17, [x16] + str x17, [sp, #0xc20] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc28] + ldr x16, [sp, #0x1258] + ldr x17, [x16] + str x17, [sp, #0xc30] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc38] + ldr x16, [sp, #0x1250] + ldr x17, [x16] + str x17, [sp, #0xc40] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc48] + ldr x16, [sp, #0x1248] + ldr x17, [x16] + str x17, [sp, #0xc50] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc58] + ldr x16, [sp, #0x1240] + ldr x17, [x16] + str x17, [sp, #0xc60] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc68] + ldr x16, [sp, #0x1238] + ldr x17, [x16] + str x17, [sp, #0xc70] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc78] + ldr x16, [sp, #0x1230] + ldr x17, [x16] + str x17, [sp, #0xc80] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc88] + ldr x16, [sp, #0x1228] + ldr x17, [x16] + str x17, [sp, #0xc90] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc98] + ldr x16, [sp, #0x1220] + ldr x17, [x16] + str x17, [sp, #0xca0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xca8] + ldr x16, [sp, #0x1218] + ldr x17, [x16] + str x17, [sp, #0xcb0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xcb8] + ldr x16, [sp, #0x1210] + ldr x17, [x16] + str x17, [sp, #0xcc0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xcc8] + ldr x16, [sp, #0x1208] + ldr x17, [x16] + str x17, [sp, #0xcd0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xcd8] + ldr x16, [sp, #0x1200] + ldr x17, [x16] + str x17, [sp, #0xce0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xce8] + ldr x16, [sp, #0x11f8] + ldr x17, [x16] + str x17, [sp, #0xcf0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xcf8] + ldr x16, [sp, #0x11f0] + ldr x17, [x16] + str x17, [sp, #0xd00] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd08] + ldr x16, [sp, #0x11e8] + ldr x17, [x16] + str x17, [sp, #0xd10] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd18] + ldr x16, [sp, #0x11e0] + ldr x17, [x16] + str x17, [sp, #0xd20] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd28] + ldr x16, [sp, #0x11d8] + ldr x17, [x16] + str x17, [sp, #0xd30] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd38] + ldr x16, [sp, #0x11d0] + ldr x17, [x16] + str x17, [sp, #0xd40] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd48] + ldr x16, [sp, #0x11c8] + ldr x17, [x16] + str x17, [sp, #0xd50] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd58] + ldr x16, [sp, #0x11c0] + ldr x17, [x16] + str x17, [sp, #0xd60] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd68] + ldr x16, [sp, #0x11b8] + ldr x17, [x16] + str x17, [sp, #0xd70] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd78] + ldr x16, [sp, #0x11b0] + ldr x17, [x16] + str x17, [sp, #0xd80] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd88] + ldr x16, [sp, #0x11a8] + ldr x17, [x16] + str x17, [sp, #0xd90] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd98] + ldr x16, [sp, #0x11a0] + ldr x17, [x16] + str x17, [sp, #0xda0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xda8] + ldr x16, [sp, #0x1198] + ldr x17, [x16] + str x17, [sp, #0xdb0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xdb8] + ldr x16, [sp, #0x1190] + ldr x17, [x16] + str x17, [sp, #0xdc0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xdc8] + ldr x16, [sp, #0x1188] + ldr x17, [x16] + str x17, [sp, #0xdd0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xdd8] + ldr x16, [sp, #0x1180] + ldr x17, [x16] + str x17, [sp, #0xde0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xde8] + ldr x16, [sp, #0x1178] + ldr x17, [x16] + str x17, [sp, #0xdf0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xdf8] + ldr x16, [sp, #0x1170] + ldr x17, [x16] + str x17, [sp, #0xe00] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe08] + ldr x16, [sp, #0x1168] + ldr x17, [x16] + str x17, [sp, #0xe10] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe18] + ldr x16, [sp, #0x1160] + ldr x17, [x16] + str x17, [sp, #0xe20] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe28] + ldr x16, [sp, #0x1158] + ldr x17, [x16] + str x17, [sp, #0xe30] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe38] + ldr x16, [sp, #0x1150] + ldr x17, [x16] + str x17, [sp, #0xe40] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe48] + ldr x16, [sp, #0x1148] + ldr x17, [x16] + str x17, [sp, #0xe50] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe58] + ldr x16, [sp, #0x1140] + ldr x17, [x16] + str x17, [sp, #0xe60] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe68] + ldr x16, [sp, #0x1138] + ldr x17, [x16] + str x17, [sp, #0xe70] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe78] + ldr x16, [sp, #0x1130] + ldr x17, [x16] + str x17, [sp, #0xe80] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe88] + ldr x16, [sp, #0x1128] + ldr x17, [x16] + str x17, [sp, #0xe90] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe98] + ldr x16, [sp, #0x1120] + ldr x17, [x16] + str x17, [sp, #0xea0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xea8] + ldr x16, [sp, #0x1118] + ldr x17, [x16] + str x17, [sp, #0xeb0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xeb8] + ldr x16, [sp, #0x1110] + ldr x17, [x16] + str x17, [sp, #0xec0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xec8] + ldr x16, [sp, #0x1108] + ldr x17, [x16] + str x17, [sp, #0xed0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xed8] + ldr x16, [sp, #0x1100] + ldr x17, [x16] + str x17, [sp, #0xee0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xee8] + ldr x16, [sp, #0x10f8] + ldr x17, [x16] + str x17, [sp, #0xef0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xef8] + ldr x16, [sp, #0x10f0] + ldr x17, [x16] + str x17, [sp, #0xf00] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf08] + ldr x16, [sp, #0x10e8] + ldr x17, [x16] + str x17, [sp, #0xf10] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf18] + ldr x16, [sp, #0x10e0] + ldr x17, [x16] + str x17, [sp, #0xf20] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf28] + ldr x16, [sp, #0x10d8] + ldr x17, [x16] + str x17, [sp, #0xf30] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf38] + ldr x16, [sp, #0x10d0] + ldr x17, [x16] + str x17, [sp, #0xf40] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf48] + ldr x16, [sp, #0x10c8] + ldr x17, [x16] + str x17, [sp, #0xf50] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf58] + ldr x16, [sp, #0x10c0] + ldr x17, [x16] + str x17, [sp, #0xf60] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf68] + ldr x16, [sp, #0x10b8] + ldr x17, [x16] + str x17, [sp, #0xf70] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf78] + ldr x16, [sp, #0x10b0] + ldr x17, [x16] + str x17, [sp, #0xf80] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf88] + ldr x16, [sp, #0x10a8] + ldr x17, [x16] + str x17, [sp, #0xf90] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf98] + ldr x16, [sp, #0x10a0] + ldr x17, [x16] + str x17, [sp, #0xfa0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xfa8] + ldr x16, [sp, #0x1098] + ldr x17, [x16] + str x17, [sp, #0xfb0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xfb8] + ldr x16, [sp, #0x1090] + ldr x17, [x16] + str x17, [sp, #0xfc0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xfc8] + ldr x16, [sp, #0x1088] + ldr x17, [x16] + str x17, [sp, #0xfd0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xfd8] + ldr x16, [sp, #0x1080] + ldr x17, [x16] + str x17, [sp, #0xfe0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xfe8] + ldr x16, [sp, #0x1078] + ldr x17, [x16] + str x17, [sp, #0xff0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xff8] + ldr x16, [sp, #0x1070] + ldr x17, [x16] + str x17, [sp, #0x1000] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1008] + mov x4, x2 + mov x6, x3 + mov x2, x1 + ldr x1, [x0, #0x8] + ldr x0, [x0] + ldr x3, [x2, #0x8] + ldr x2, [x2] + ldr x5, [x4, #0x8] + ldr x4, [x4] + ldr x7, [x6, #0x8] + ldr x6, [x6] + bl + add sp, sp, #0x1, lsl #12 // =0x1000 + add sp, sp, #0x10 + mov x17, #0x8d9e // =36254 + movk x17, #0x1, lsl #16 + cmp x0, x17 + b.eq + mov x0, #0x1 // =1 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + ldr x23, [sp, #0x18] + ldr x24, [sp, #0x20] + ldr x25, [sp, #0x28] + ldr x26, [sp, #0x30] + ldr x27, [sp, #0x38] + ldr x28, [sp, #0x40] + ldr x19, [sp, #0x50] + add sp, sp, #0x1, lsl #12 // =0x1000 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x1 // =1 + mov x1, #0x2 // =2 + mov x2, #0x3 // =3 + mov x3, #0x4 // =4 + mov x4, #0x5 // =5 + mov x5, #0x6 // =6 + mov x6, #0x7 // =7 + mov x7, #0x8 // =8 + mov x8, #0x9 // =9 + mov x9, #0xa // =10 + mov x10, #0xb // =11 + mov x11, #0xc // =12 + mov x12, #0xd // =13 + mov x13, #0xe // =14 + mov x14, #0xf // =15 + mov x15, #0x10 // =16 + mov x22, #0x11 // =17 + mov x23, #0x12 // =18 + mov x24, #0x13 // =19 + mov x25, #0x14 // =20 + mov x26, #0x15 // =21 + mov x27, #0x16 // =22 + mov x28, #0x17 // =23 + mov x16, #0x18 // =24 + str x16, [sp, #0x7c8] + mov x16, #0x19 // =25 + str x16, [sp, #0x7c0] + mov x16, #0x1a // =26 + str x16, [sp, #0x7b8] + mov x16, #0x1b // =27 + str x16, [sp, #0x7b0] + mov x16, #0x1c // =28 + str x16, [sp, #0x7a8] + mov x16, #0x1d // =29 + str x16, [sp, #0x7a0] + mov x16, #0x1e // =30 + str x16, [sp, #0x798] + mov x16, #0x1f // =31 + str x16, [sp, #0x790] + mov x16, #0x20 // =32 + str x16, [sp, #0x788] + mov x16, #0x21 // =33 + str x16, [sp, #0x780] + mov x16, #0x22 // =34 + str x16, [sp, #0x778] + mov x16, #0x23 // =35 + str x16, [sp, #0x770] + mov x16, #0x24 // =36 + str x16, [sp, #0x768] + mov x16, #0x25 // =37 + str x16, [sp, #0x760] + mov x16, #0x26 // =38 + str x16, [sp, #0x758] + mov x16, #0x27 // =39 + str x16, [sp, #0x750] + mov x16, #0x28 // =40 + str x16, [sp, #0x748] + mov x16, #0x29 // =41 + str x16, [sp, #0x740] + mov x16, #0x2a // =42 + str x16, [sp, #0x738] + mov x16, #0x2b // =43 + str x16, [sp, #0x730] + mov x16, #0x2c // =44 + str x16, [sp, #0x728] + mov x16, #0x2d // =45 + str x16, [sp, #0x720] + mov x16, #0x2e // =46 + str x16, [sp, #0x718] + mov x16, #0x2f // =47 + str x16, [sp, #0x710] + mov x16, #0x30 // =48 + str x16, [sp, #0x708] + mov x16, #0x31 // =49 + str x16, [sp, #0x700] + mov x16, #0x32 // =50 + str x16, [sp, #0x6f8] + mov x16, #0x33 // =51 + str x16, [sp, #0x6f0] + mov x16, #0x34 // =52 + str x16, [sp, #0x6e8] + mov x16, #0x35 // =53 + str x16, [sp, #0x6e0] + mov x16, #0x36 // =54 + str x16, [sp, #0x6d8] + mov x16, #0x37 // =55 + str x16, [sp, #0x6d0] + mov x16, #0x38 // =56 + str x16, [sp, #0x6c8] + mov x16, #0x39 // =57 + str x16, [sp, #0x6c0] + mov x16, #0x3a // =58 + str x16, [sp, #0x6b8] + mov x16, #0x3b // =59 + str x16, [sp, #0x6b0] + mov x16, #0x3c // =60 + str x16, [sp, #0x6a8] + mov x16, #0x3d // =61 + str x16, [sp, #0x6a0] + mov x16, #0x3e // =62 + str x16, [sp, #0x698] + mov x16, #0x3f // =63 + str x16, [sp, #0x690] + mov x16, #0x40 // =64 + str x16, [sp, #0x688] + mov x16, #0x41 // =65 + str x16, [sp, #0x680] + mov x16, #0x42 // =66 + str x16, [sp, #0x678] + mov x16, #0x43 // =67 + str x16, [sp, #0x670] + mov x16, #0x44 // =68 + str x16, [sp, #0x668] + mov x16, #0x45 // =69 + str x16, [sp, #0x660] + mov x16, #0x46 // =70 + str x16, [sp, #0x658] + mov x16, #0x47 // =71 + str x16, [sp, #0x650] + mov x16, #0x48 // =72 + str x16, [sp, #0x648] + mov x16, #0x49 // =73 + str x16, [sp, #0x640] + mov x16, #0x4a // =74 + str x16, [sp, #0x638] + mov x16, #0x4b // =75 + str x16, [sp, #0x630] + mov x16, #0x4c // =76 + str x16, [sp, #0x628] + mov x16, #0x4d // =77 + str x16, [sp, #0x620] + mov x16, #0x4e // =78 + str x16, [sp, #0x618] + mov x16, #0x4f // =79 + str x16, [sp, #0x610] + mov x16, #0x50 // =80 + str x16, [sp, #0x608] + mov x16, #0x51 // =81 + str x16, [sp, #0x600] + mov x16, #0x52 // =82 + str x16, [sp, #0x5f8] + mov x16, #0x53 // =83 + str x16, [sp, #0x5f0] + mov x16, #0x54 // =84 + str x16, [sp, #0x5e8] + mov x16, #0x55 // =85 + str x16, [sp, #0x5e0] + mov x16, #0x56 // =86 + str x16, [sp, #0x5d8] + mov x16, #0x57 // =87 + str x16, [sp, #0x5d0] + mov x16, #0x58 // =88 + str x16, [sp, #0x5c8] + mov x16, #0x59 // =89 + str x16, [sp, #0x5c0] + mov x16, #0x5a // =90 + str x16, [sp, #0x5b8] + mov x16, #0x5b // =91 + str x16, [sp, #0x5b0] + mov x16, #0x5c // =92 + str x16, [sp, #0x5a8] + mov x16, #0x5d // =93 + str x16, [sp, #0x5a0] + mov x16, #0x5e // =94 + str x16, [sp, #0x598] + mov x16, #0x5f // =95 + str x16, [sp, #0x590] + mov x16, #0x60 // =96 + str x16, [sp, #0x588] + mov x16, #0x61 // =97 + str x16, [sp, #0x580] + mov x16, #0x62 // =98 + str x16, [sp, #0x578] + mov x16, #0x63 // =99 + str x16, [sp, #0x570] + mov x16, #0x64 // =100 + str x16, [sp, #0x568] + mov x16, #0x65 // =101 + str x16, [sp, #0x560] + mov x16, #0x66 // =102 + str x16, [sp, #0x558] + mov x16, #0x67 // =103 + str x16, [sp, #0x550] + mov x16, #0x68 // =104 + str x16, [sp, #0x548] + mov x16, #0x69 // =105 + str x16, [sp, #0x540] + mov x16, #0x6a // =106 + str x16, [sp, #0x538] + mov x16, #0x6b // =107 + str x16, [sp, #0x530] + mov x16, #0x6c // =108 + str x16, [sp, #0x528] + mov x16, #0x6d // =109 + str x16, [sp, #0x520] + mov x16, #0x6e // =110 + str x16, [sp, #0x518] + mov x16, #0x6f // =111 + str x16, [sp, #0x510] + mov x16, #0x70 // =112 + str x16, [sp, #0x508] + mov x16, #0x71 // =113 + str x16, [sp, #0x500] + mov x16, #0x72 // =114 + str x16, [sp, #0x4f8] + mov x16, #0x73 // =115 + str x16, [sp, #0x4f0] + mov x16, #0x74 // =116 + str x16, [sp, #0x4e8] + mov x16, #0x75 // =117 + str x16, [sp, #0x4e0] + mov x16, #0x76 // =118 + str x16, [sp, #0x4d8] + mov x16, #0x77 // =119 + str x16, [sp, #0x4d0] + mov x16, #0x78 // =120 + str x16, [sp, #0x4c8] + mov x16, #0x79 // =121 + str x16, [sp, #0x4c0] + mov x16, #0x7a // =122 + str x16, [sp, #0x4b8] + mov x16, #0x7b // =123 + str x16, [sp, #0x4b0] + mov x16, #0x7c // =124 + str x16, [sp, #0x4a8] + mov x16, #0x7d // =125 + str x16, [sp, #0x4a0] + mov x16, #0x7e // =126 + str x16, [sp, #0x498] + mov x16, #0x7f // =127 + str x16, [sp, #0x490] + mov x16, #0x80 // =128 + str x16, [sp, #0x488] + mov x16, #0x81 // =129 + str x16, [sp, #0x480] + mov x16, #0x82 // =130 + str x16, [sp, #0x478] + mov x16, #0x83 // =131 + str x16, [sp, #0x470] + mov x16, #0x84 // =132 + str x16, [sp, #0x468] + mov x16, #0x85 // =133 + str x16, [sp, #0x460] + mov x16, #0x86 // =134 + str x16, [sp, #0x458] + mov x16, #0x87 // =135 + str x16, [sp, #0x450] + mov x16, #0x88 // =136 + str x16, [sp, #0x448] + mov x16, #0x89 // =137 + str x16, [sp, #0x440] + mov x16, #0x8a // =138 + str x16, [sp, #0x438] + mov x16, #0x8b // =139 + str x16, [sp, #0x430] + mov x16, #0x8c // =140 + str x16, [sp, #0x428] + mov x16, #0x8d // =141 + str x16, [sp, #0x420] + mov x16, #0x8e // =142 + str x16, [sp, #0x418] + mov x16, #0x8f // =143 + str x16, [sp, #0x410] + mov x16, #0x90 // =144 + str x16, [sp, #0x408] + mov x16, #0x91 // =145 + str x16, [sp, #0x400] + mov x16, #0x92 // =146 + str x16, [sp, #0x3f8] + mov x16, #0x93 // =147 + str x16, [sp, #0x3f0] + mov x16, #0x94 // =148 + str x16, [sp, #0x3e8] + mov x16, #0x95 // =149 + str x16, [sp, #0x3e0] + mov x16, #0x96 // =150 + str x16, [sp, #0x3d8] + mov x16, #0x97 // =151 + str x16, [sp, #0x3d0] + mov x16, #0x98 // =152 + str x16, [sp, #0x3c8] + mov x16, #0x99 // =153 + str x16, [sp, #0x3c0] + mov x16, #0x9a // =154 + str x16, [sp, #0x3b8] + mov x16, #0x9b // =155 + str x16, [sp, #0x3b0] + mov x16, #0x9c // =156 + str x16, [sp, #0x3a8] + mov x16, #0x9d // =157 + str x16, [sp, #0x3a0] + mov x16, #0x9e // =158 + str x16, [sp, #0x398] + mov x16, #0x9f // =159 + str x16, [sp, #0x390] + mov x16, #0xa0 // =160 + str x16, [sp, #0x388] + mov x16, #0xa1 // =161 + str x16, [sp, #0x380] + mov x16, #0xa2 // =162 + str x16, [sp, #0x378] + mov x16, #0xa3 // =163 + str x16, [sp, #0x370] + mov x16, #0xa4 // =164 + str x16, [sp, #0x368] + mov x16, #0xa5 // =165 + str x16, [sp, #0x360] + mov x16, #0xa6 // =166 + str x16, [sp, #0x358] + mov x16, #0xa7 // =167 + str x16, [sp, #0x350] + mov x16, #0xa8 // =168 + str x16, [sp, #0x348] + mov x16, #0xa9 // =169 + str x16, [sp, #0x340] + mov x16, #0xaa // =170 + str x16, [sp, #0x338] + mov x16, #0xab // =171 + str x16, [sp, #0x330] + mov x16, #0xac // =172 + str x16, [sp, #0x328] + mov x16, #0xad // =173 + str x16, [sp, #0x320] + mov x16, #0xae // =174 + str x16, [sp, #0x318] + mov x16, #0xaf // =175 + str x16, [sp, #0x310] + mov x16, #0xb0 // =176 + str x16, [sp, #0x308] + mov x16, #0xb1 // =177 + str x16, [sp, #0x300] + mov x16, #0xb2 // =178 + str x16, [sp, #0x2f8] + mov x16, #0xb3 // =179 + str x16, [sp, #0x2f0] + mov x16, #0xb4 // =180 + str x16, [sp, #0x2e8] + mov x16, #0xb5 // =181 + str x16, [sp, #0x2e0] + mov x16, #0xb6 // =182 + str x16, [sp, #0x2d8] + mov x16, #0xb7 // =183 + str x16, [sp, #0x2d0] + mov x16, #0xb8 // =184 + str x16, [sp, #0x2c8] + mov x16, #0xb9 // =185 + str x16, [sp, #0x2c0] + mov x16, #0xba // =186 + str x16, [sp, #0x2b8] + mov x16, #0xbb // =187 + str x16, [sp, #0x2b0] + mov x16, #0xbc // =188 + str x16, [sp, #0x2a8] + mov x16, #0xbd // =189 + str x16, [sp, #0x2a0] + mov x16, #0xbe // =190 + str x16, [sp, #0x298] + mov x16, #0xbf // =191 + str x16, [sp, #0x290] + mov x16, #0xc0 // =192 + str x16, [sp, #0x288] + mov x16, #0xc1 // =193 + str x16, [sp, #0x280] + mov x16, #0xc2 // =194 + str x16, [sp, #0x278] + mov x16, #0xc3 // =195 + str x16, [sp, #0x270] + mov x16, #0xc4 // =196 + str x16, [sp, #0x268] + mov x16, #0xc5 // =197 + str x16, [sp, #0x260] + mov x16, #0xc6 // =198 + str x16, [sp, #0x258] + mov x16, #0xc7 // =199 + str x16, [sp, #0x250] + mov x16, #0xc8 // =200 + str x16, [sp, #0x248] + mov x16, #0xc9 // =201 + str x16, [sp, #0x240] + mov x16, #0xca // =202 + str x16, [sp, #0x238] + mov x16, #0xcb // =203 + str x16, [sp, #0x230] + mov x16, #0xcc // =204 + str x16, [sp, #0x228] + mov x16, #0xcd // =205 + str x16, [sp, #0x220] + mov x16, #0xce // =206 + str x16, [sp, #0x218] + mov x16, #0xcf // =207 + str x16, [sp, #0x210] + mov x16, #0xd0 // =208 + str x16, [sp, #0x208] + mov x16, #0xd1 // =209 + str x16, [sp, #0x200] + mov x16, #0xd2 // =210 + str x16, [sp, #0x1f8] + mov x16, #0xd3 // =211 + str x16, [sp, #0x1f0] + mov x16, #0xd4 // =212 + str x16, [sp, #0x1e8] + mov x16, #0xd5 // =213 + str x16, [sp, #0x1e0] + mov x16, #0xd6 // =214 + str x16, [sp, #0x1d8] + mov x16, #0xd7 // =215 + str x16, [sp, #0x1d0] + mov x16, #0xd8 // =216 + str x16, [sp, #0x1c8] + mov x16, #0xd9 // =217 + str x16, [sp, #0x1c0] + mov x16, #0xda // =218 + str x16, [sp, #0x1b8] + mov x16, #0xdb // =219 + str x16, [sp, #0x1b0] + mov x16, #0xdc // =220 + str x16, [sp, #0x1a8] + mov x16, #0xdd // =221 + str x16, [sp, #0x1a0] + mov x16, #0xde // =222 + str x16, [sp, #0x198] + mov x16, #0xdf // =223 + str x16, [sp, #0x190] + mov x16, #0xe0 // =224 + str x16, [sp, #0x188] + mov x16, #0xe1 // =225 + str x16, [sp, #0x180] + mov x16, #0xe2 // =226 + str x16, [sp, #0x178] + mov x16, #0xe3 // =227 + str x16, [sp, #0x170] + mov x16, #0xe4 // =228 + str x16, [sp, #0x168] + mov x16, #0xe5 // =229 + str x16, [sp, #0x160] + mov x16, #0xe6 // =230 + str x16, [sp, #0x158] + mov x16, #0xe7 // =231 + str x16, [sp, #0x150] + mov x16, #0xe8 // =232 + str x16, [sp, #0x148] + mov x16, #0xe9 // =233 + str x16, [sp, #0x140] + mov x16, #0xea // =234 + str x16, [sp, #0x138] + mov x16, #0xeb // =235 + str x16, [sp, #0x130] + mov x16, #0xec // =236 + str x16, [sp, #0x128] + mov x16, #0xed // =237 + str x16, [sp, #0x120] + mov x16, #0xee // =238 + str x16, [sp, #0x118] + mov x16, #0xef // =239 + str x16, [sp, #0x110] + mov x16, #0xf0 // =240 + str x16, [sp, #0x108] + mov x16, #0xf1 // =241 + str x16, [sp, #0x100] + mov x16, #0xf2 // =242 + str x16, [sp, #0xf8] + mov x16, #0xf3 // =243 + str x16, [sp, #0xf0] + mov x16, #0xf4 // =244 + str x16, [sp, #0xe8] + mov x16, #0xf5 // =245 + str x16, [sp, #0xe0] + mov x16, #0xf6 // =246 + str x16, [sp, #0xd8] + mov x16, #0xf7 // =247 + str x16, [sp, #0xd0] + mov x16, #0xf8 // =248 + str x16, [sp, #0xc8] + mov x16, #0xf9 // =249 + str x16, [sp, #0xc0] + mov x16, #0xfa // =250 + str x16, [sp, #0xb8] + mov x16, #0xfb // =251 + str x16, [sp, #0xb0] + mov x16, #0xfc // =252 + str x16, [sp, #0xa8] + mov x16, #0xfd // =253 + str x16, [sp, #0xa0] + mov x16, #0xfe // =254 + str x16, [sp, #0x98] + mov x16, #0xff // =255 + str x16, [sp, #0x90] + mov x16, #0x100 // =256 + str x16, [sp, #0x88] + mov x16, #0x101 // =257 + str x16, [sp, #0x80] + mov x16, #0x102 // =258 + str x16, [sp, #0x78] + mov x16, #0x103 // =259 + str x16, [sp, #0x70] + mov x16, #0x104 // =260 + str x16, [sp, #0x68] + ldr x16, [sp, #0x68] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x80] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x98] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xb0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xc8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xe0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xf8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x110] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x128] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x140] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x158] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x170] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x188] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1a0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1b8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1d0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1e8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x200] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x218] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x230] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x248] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x260] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x278] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x290] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x2a8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x2c0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x2d8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x2f0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x308] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x320] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x338] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x350] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x368] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x380] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x398] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x3b0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x3c8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x3e0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x3f8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x410] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x428] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x440] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x458] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x470] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x488] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x4a0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x4b8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x4d0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x4e8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x500] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x518] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x530] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x548] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x560] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x578] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x590] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x5a8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x5c0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x5d8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x5f0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x608] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x620] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x638] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x650] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x668] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x680] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x698] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x6b0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x6c8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x6e0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x6f8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x710] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x728] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x740] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x758] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x770] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x788] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x7a0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x7b8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x7d0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x7e8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x800] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x818] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x830] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x848] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x860] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x878] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x890] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x8a8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x8c0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x8d8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x8f0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x908] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x920] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x938] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x950] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x968] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x980] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x998] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x9b0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x9c8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x9e0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x9f8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xa10] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xa28] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xa40] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xa58] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xa70] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xa88] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xaa0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xab8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xad0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xae8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xb00] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xb18] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xb30] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xb48] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xb60] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xb78] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xb90] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xba8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xbc0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xbd8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xbf0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xc08] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xc20] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xc38] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xc50] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xc68] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xc80] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xc98] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xcb0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xcc8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xce0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xcf8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xd10] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xd28] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xd40] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xd58] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xd70] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xd88] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xda0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xdb8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xdd0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xde8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xe00] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xe18] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xe30] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xe48] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xe60] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xe78] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xe90] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xea8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xec0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xed8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xef0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xf08] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xf20] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xf38] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xf50] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xf68] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xf80] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xf98] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xfb0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xfc8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xfe0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0xff8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1010] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1028] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1040] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1058] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1070] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1088] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x10a0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x10b8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x10d0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x10e8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1100] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1118] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1130] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1148] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1160] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1178] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1190] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x11a8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x11c0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x11d8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x11f0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1208] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1220] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1238] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1250] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1268] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1280] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1298] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x12b0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x12c8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x12e0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x12f8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1310] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1328] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1340] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1358] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1370] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1388] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x13a0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x13b8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x13d0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x13e8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1400] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1418] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1430] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1448] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1460] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1478] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1490] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x14a8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x14c0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x14d8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x14f0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1508] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1520] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1538] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1550] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1568] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1580] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1598] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x15b0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x15c8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x15e0] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x15f8] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1610] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1628] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1640] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1658] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1670] + str x16, [sp, #-0x10]! + ldr x16, [sp, #0x1688] + str x16, [sp, #-0x10]! + str x28, [sp, #-0x10]! + str x27, [sp, #-0x10]! + str x26, [sp, #-0x10]! + str x25, [sp, #-0x10]! + str x24, [sp, #-0x10]! + str x23, [sp, #-0x10]! + str x22, [sp, #-0x10]! + str x15, [sp, #-0x10]! + str x14, [sp, #-0x10]! + str x13, [sp, #-0x10]! + str x12, [sp, #-0x10]! + str x11, [sp, #-0x10]! + str x10, [sp, #-0x10]! + str x9, [sp, #-0x10]! + str x8, [sp, #-0x10]! + str x7, [sp, #-0x10]! + str x6, [sp, #-0x10]! + str x5, [sp, #-0x10]! + str x4, [sp, #-0x10]! + str x3, [sp, #-0x10]! + str x2, [sp, #-0x10]! + str x1, [sp, #-0x10]! + str x0, [sp, #-0x10]! + mov x9, x20 + sub sp, sp, #0x7e0 + ldr x0, [sp, #0x7e0] + ldr x1, [sp, #0x7f0] + ldr x2, [sp, #0x800] + ldr x3, [sp, #0x810] + ldr x4, [sp, #0x820] + ldr x5, [sp, #0x830] + ldr x6, [sp, #0x840] + ldr x7, [sp, #0x850] + ldr x16, [sp, #0x860] + str x16, [sp] + ldr x16, [sp, #0x870] + str x16, [sp, #0x8] + ldr x16, [sp, #0x880] + str x16, [sp, #0x10] + ldr x16, [sp, #0x890] + str x16, [sp, #0x18] + ldr x16, [sp, #0x8a0] + str x16, [sp, #0x20] + ldr x16, [sp, #0x8b0] + str x16, [sp, #0x28] + ldr x16, [sp, #0x8c0] + str x16, [sp, #0x30] + ldr x16, [sp, #0x8d0] + str x16, [sp, #0x38] + ldr x16, [sp, #0x8e0] + str x16, [sp, #0x40] + ldr x16, [sp, #0x8f0] + str x16, [sp, #0x48] + ldr x16, [sp, #0x900] + str x16, [sp, #0x50] + ldr x16, [sp, #0x910] + str x16, [sp, #0x58] + ldr x16, [sp, #0x920] + str x16, [sp, #0x60] + ldr x16, [sp, #0x930] + str x16, [sp, #0x68] + ldr x16, [sp, #0x940] + str x16, [sp, #0x70] + ldr x16, [sp, #0x950] + str x16, [sp, #0x78] + ldr x16, [sp, #0x960] + str x16, [sp, #0x80] + ldr x16, [sp, #0x970] + str x16, [sp, #0x88] + ldr x16, [sp, #0x980] + str x16, [sp, #0x90] + ldr x16, [sp, #0x990] + str x16, [sp, #0x98] + ldr x16, [sp, #0x9a0] + str x16, [sp, #0xa0] + ldr x16, [sp, #0x9b0] + str x16, [sp, #0xa8] + ldr x16, [sp, #0x9c0] + str x16, [sp, #0xb0] + ldr x16, [sp, #0x9d0] + str x16, [sp, #0xb8] + ldr x16, [sp, #0x9e0] + str x16, [sp, #0xc0] + ldr x16, [sp, #0x9f0] + str x16, [sp, #0xc8] + ldr x16, [sp, #0xa00] + str x16, [sp, #0xd0] + ldr x16, [sp, #0xa10] + str x16, [sp, #0xd8] + ldr x16, [sp, #0xa20] + str x16, [sp, #0xe0] + ldr x16, [sp, #0xa30] + str x16, [sp, #0xe8] + ldr x16, [sp, #0xa40] + str x16, [sp, #0xf0] + ldr x16, [sp, #0xa50] + str x16, [sp, #0xf8] + ldr x16, [sp, #0xa60] + str x16, [sp, #0x100] + ldr x16, [sp, #0xa70] + str x16, [sp, #0x108] + ldr x16, [sp, #0xa80] + str x16, [sp, #0x110] + ldr x16, [sp, #0xa90] + str x16, [sp, #0x118] + ldr x16, [sp, #0xaa0] + str x16, [sp, #0x120] + ldr x16, [sp, #0xab0] + str x16, [sp, #0x128] + ldr x16, [sp, #0xac0] + str x16, [sp, #0x130] + ldr x16, [sp, #0xad0] + str x16, [sp, #0x138] + ldr x16, [sp, #0xae0] + str x16, [sp, #0x140] + ldr x16, [sp, #0xaf0] + str x16, [sp, #0x148] + ldr x16, [sp, #0xb00] + str x16, [sp, #0x150] + ldr x16, [sp, #0xb10] + str x16, [sp, #0x158] + ldr x16, [sp, #0xb20] + str x16, [sp, #0x160] + ldr x16, [sp, #0xb30] + str x16, [sp, #0x168] + ldr x16, [sp, #0xb40] + str x16, [sp, #0x170] + ldr x16, [sp, #0xb50] + str x16, [sp, #0x178] + ldr x16, [sp, #0xb60] + str x16, [sp, #0x180] + ldr x16, [sp, #0xb70] + str x16, [sp, #0x188] + ldr x16, [sp, #0xb80] + str x16, [sp, #0x190] + ldr x16, [sp, #0xb90] + str x16, [sp, #0x198] + ldr x16, [sp, #0xba0] + str x16, [sp, #0x1a0] + ldr x16, [sp, #0xbb0] + str x16, [sp, #0x1a8] + ldr x16, [sp, #0xbc0] + str x16, [sp, #0x1b0] + ldr x16, [sp, #0xbd0] + str x16, [sp, #0x1b8] + ldr x16, [sp, #0xbe0] + str x16, [sp, #0x1c0] + ldr x16, [sp, #0xbf0] + str x16, [sp, #0x1c8] + ldr x16, [sp, #0xc00] + str x16, [sp, #0x1d0] + ldr x16, [sp, #0xc10] + str x16, [sp, #0x1d8] + ldr x16, [sp, #0xc20] + str x16, [sp, #0x1e0] + ldr x16, [sp, #0xc30] + str x16, [sp, #0x1e8] + ldr x16, [sp, #0xc40] + str x16, [sp, #0x1f0] + ldr x16, [sp, #0xc50] + str x16, [sp, #0x1f8] + ldr x16, [sp, #0xc60] + str x16, [sp, #0x200] + ldr x16, [sp, #0xc70] + str x16, [sp, #0x208] + ldr x16, [sp, #0xc80] + str x16, [sp, #0x210] + ldr x16, [sp, #0xc90] + str x16, [sp, #0x218] + ldr x16, [sp, #0xca0] + str x16, [sp, #0x220] + ldr x16, [sp, #0xcb0] + str x16, [sp, #0x228] + ldr x16, [sp, #0xcc0] + str x16, [sp, #0x230] + ldr x16, [sp, #0xcd0] + str x16, [sp, #0x238] + ldr x16, [sp, #0xce0] + str x16, [sp, #0x240] + ldr x16, [sp, #0xcf0] + str x16, [sp, #0x248] + ldr x16, [sp, #0xd00] + str x16, [sp, #0x250] + ldr x16, [sp, #0xd10] + str x16, [sp, #0x258] + ldr x16, [sp, #0xd20] + str x16, [sp, #0x260] + ldr x16, [sp, #0xd30] + str x16, [sp, #0x268] + ldr x16, [sp, #0xd40] + str x16, [sp, #0x270] + ldr x16, [sp, #0xd50] + str x16, [sp, #0x278] + ldr x16, [sp, #0xd60] + str x16, [sp, #0x280] + ldr x16, [sp, #0xd70] + str x16, [sp, #0x288] + ldr x16, [sp, #0xd80] + str x16, [sp, #0x290] + ldr x16, [sp, #0xd90] + str x16, [sp, #0x298] + ldr x16, [sp, #0xda0] + str x16, [sp, #0x2a0] + ldr x16, [sp, #0xdb0] + str x16, [sp, #0x2a8] + ldr x16, [sp, #0xdc0] + str x16, [sp, #0x2b0] + ldr x16, [sp, #0xdd0] + str x16, [sp, #0x2b8] + ldr x16, [sp, #0xde0] + str x16, [sp, #0x2c0] + ldr x16, [sp, #0xdf0] + str x16, [sp, #0x2c8] + ldr x16, [sp, #0xe00] + str x16, [sp, #0x2d0] + ldr x16, [sp, #0xe10] + str x16, [sp, #0x2d8] + ldr x16, [sp, #0xe20] + str x16, [sp, #0x2e0] + ldr x16, [sp, #0xe30] + str x16, [sp, #0x2e8] + ldr x16, [sp, #0xe40] + str x16, [sp, #0x2f0] + ldr x16, [sp, #0xe50] + str x16, [sp, #0x2f8] + ldr x16, [sp, #0xe60] + str x16, [sp, #0x300] + ldr x16, [sp, #0xe70] + str x16, [sp, #0x308] + ldr x16, [sp, #0xe80] + str x16, [sp, #0x310] + ldr x16, [sp, #0xe90] + str x16, [sp, #0x318] + ldr x16, [sp, #0xea0] + str x16, [sp, #0x320] + ldr x16, [sp, #0xeb0] + str x16, [sp, #0x328] + ldr x16, [sp, #0xec0] + str x16, [sp, #0x330] + ldr x16, [sp, #0xed0] + str x16, [sp, #0x338] + ldr x16, [sp, #0xee0] + str x16, [sp, #0x340] + ldr x16, [sp, #0xef0] + str x16, [sp, #0x348] + ldr x16, [sp, #0xf00] + str x16, [sp, #0x350] + ldr x16, [sp, #0xf10] + str x16, [sp, #0x358] + ldr x16, [sp, #0xf20] + str x16, [sp, #0x360] + ldr x16, [sp, #0xf30] + str x16, [sp, #0x368] + ldr x16, [sp, #0xf40] + str x16, [sp, #0x370] + ldr x16, [sp, #0xf50] + str x16, [sp, #0x378] + ldr x16, [sp, #0xf60] + str x16, [sp, #0x380] + ldr x16, [sp, #0xf70] + str x16, [sp, #0x388] + ldr x16, [sp, #0xf80] + str x16, [sp, #0x390] + ldr x16, [sp, #0xf90] + str x16, [sp, #0x398] + ldr x16, [sp, #0xfa0] + str x16, [sp, #0x3a0] + ldr x16, [sp, #0xfb0] + str x16, [sp, #0x3a8] + ldr x16, [sp, #0xfc0] + str x16, [sp, #0x3b0] + ldr x16, [sp, #0xfd0] + str x16, [sp, #0x3b8] + ldr x16, [sp, #0xfe0] + str x16, [sp, #0x3c0] + ldr x16, [sp, #0xff0] + str x16, [sp, #0x3c8] + ldr x16, [sp, #0x1000] + str x16, [sp, #0x3d0] + ldr x16, [sp, #0x1010] + str x16, [sp, #0x3d8] + ldr x16, [sp, #0x1020] + str x16, [sp, #0x3e0] + ldr x16, [sp, #0x1030] + str x16, [sp, #0x3e8] + ldr x16, [sp, #0x1040] + str x16, [sp, #0x3f0] + ldr x16, [sp, #0x1050] + str x16, [sp, #0x3f8] + ldr x16, [sp, #0x1060] + str x16, [sp, #0x400] + ldr x16, [sp, #0x1070] + str x16, [sp, #0x408] + ldr x16, [sp, #0x1080] + str x16, [sp, #0x410] + ldr x16, [sp, #0x1090] + str x16, [sp, #0x418] + ldr x16, [sp, #0x10a0] + str x16, [sp, #0x420] + ldr x16, [sp, #0x10b0] + str x16, [sp, #0x428] + ldr x16, [sp, #0x10c0] + str x16, [sp, #0x430] + ldr x16, [sp, #0x10d0] + str x16, [sp, #0x438] + ldr x16, [sp, #0x10e0] + str x16, [sp, #0x440] + ldr x16, [sp, #0x10f0] + str x16, [sp, #0x448] + ldr x16, [sp, #0x1100] + str x16, [sp, #0x450] + ldr x16, [sp, #0x1110] + str x16, [sp, #0x458] + ldr x16, [sp, #0x1120] + str x16, [sp, #0x460] + ldr x16, [sp, #0x1130] + str x16, [sp, #0x468] + ldr x16, [sp, #0x1140] + str x16, [sp, #0x470] + ldr x16, [sp, #0x1150] + str x16, [sp, #0x478] + ldr x16, [sp, #0x1160] + str x16, [sp, #0x480] + ldr x16, [sp, #0x1170] + str x16, [sp, #0x488] + ldr x16, [sp, #0x1180] + str x16, [sp, #0x490] + ldr x16, [sp, #0x1190] + str x16, [sp, #0x498] + ldr x16, [sp, #0x11a0] + str x16, [sp, #0x4a0] + ldr x16, [sp, #0x11b0] + str x16, [sp, #0x4a8] + ldr x16, [sp, #0x11c0] + str x16, [sp, #0x4b0] + ldr x16, [sp, #0x11d0] + str x16, [sp, #0x4b8] + ldr x16, [sp, #0x11e0] + str x16, [sp, #0x4c0] + ldr x16, [sp, #0x11f0] + str x16, [sp, #0x4c8] + ldr x16, [sp, #0x1200] + str x16, [sp, #0x4d0] + ldr x16, [sp, #0x1210] + str x16, [sp, #0x4d8] + ldr x16, [sp, #0x1220] + str x16, [sp, #0x4e0] + ldr x16, [sp, #0x1230] + str x16, [sp, #0x4e8] + ldr x16, [sp, #0x1240] + str x16, [sp, #0x4f0] + ldr x16, [sp, #0x1250] + str x16, [sp, #0x4f8] + ldr x16, [sp, #0x1260] + str x16, [sp, #0x500] + ldr x16, [sp, #0x1270] + str x16, [sp, #0x508] + ldr x16, [sp, #0x1280] + str x16, [sp, #0x510] + ldr x16, [sp, #0x1290] + str x16, [sp, #0x518] + ldr x16, [sp, #0x12a0] + str x16, [sp, #0x520] + ldr x16, [sp, #0x12b0] + str x16, [sp, #0x528] + ldr x16, [sp, #0x12c0] + str x16, [sp, #0x530] + ldr x16, [sp, #0x12d0] + str x16, [sp, #0x538] + ldr x16, [sp, #0x12e0] + str x16, [sp, #0x540] + ldr x16, [sp, #0x12f0] + str x16, [sp, #0x548] + ldr x16, [sp, #0x1300] + str x16, [sp, #0x550] + ldr x16, [sp, #0x1310] + str x16, [sp, #0x558] + ldr x16, [sp, #0x1320] + str x16, [sp, #0x560] + ldr x16, [sp, #0x1330] + str x16, [sp, #0x568] + ldr x16, [sp, #0x1340] + str x16, [sp, #0x570] + ldr x16, [sp, #0x1350] + str x16, [sp, #0x578] + ldr x16, [sp, #0x1360] + str x16, [sp, #0x580] + ldr x16, [sp, #0x1370] + str x16, [sp, #0x588] + ldr x16, [sp, #0x1380] + str x16, [sp, #0x590] + ldr x16, [sp, #0x1390] + str x16, [sp, #0x598] + ldr x16, [sp, #0x13a0] + str x16, [sp, #0x5a0] + ldr x16, [sp, #0x13b0] + str x16, [sp, #0x5a8] + ldr x16, [sp, #0x13c0] + str x16, [sp, #0x5b0] + ldr x16, [sp, #0x13d0] + str x16, [sp, #0x5b8] + ldr x16, [sp, #0x13e0] + str x16, [sp, #0x5c0] + ldr x16, [sp, #0x13f0] + str x16, [sp, #0x5c8] + ldr x16, [sp, #0x1400] + str x16, [sp, #0x5d0] + ldr x16, [sp, #0x1410] + str x16, [sp, #0x5d8] + ldr x16, [sp, #0x1420] + str x16, [sp, #0x5e0] + ldr x16, [sp, #0x1430] + str x16, [sp, #0x5e8] + ldr x16, [sp, #0x1440] + str x16, [sp, #0x5f0] + ldr x16, [sp, #0x1450] + str x16, [sp, #0x5f8] + ldr x16, [sp, #0x1460] + str x16, [sp, #0x600] + ldr x16, [sp, #0x1470] + str x16, [sp, #0x608] + ldr x16, [sp, #0x1480] + str x16, [sp, #0x610] + ldr x16, [sp, #0x1490] + str x16, [sp, #0x618] + ldr x16, [sp, #0x14a0] + str x16, [sp, #0x620] + ldr x16, [sp, #0x14b0] + str x16, [sp, #0x628] + ldr x16, [sp, #0x14c0] + str x16, [sp, #0x630] + ldr x16, [sp, #0x14d0] + str x16, [sp, #0x638] + ldr x16, [sp, #0x14e0] + str x16, [sp, #0x640] + ldr x16, [sp, #0x14f0] + str x16, [sp, #0x648] + ldr x16, [sp, #0x1500] + str x16, [sp, #0x650] + ldr x16, [sp, #0x1510] + str x16, [sp, #0x658] + ldr x16, [sp, #0x1520] + str x16, [sp, #0x660] + ldr x16, [sp, #0x1530] + str x16, [sp, #0x668] + ldr x16, [sp, #0x1540] + str x16, [sp, #0x670] + ldr x16, [sp, #0x1550] + str x16, [sp, #0x678] + ldr x16, [sp, #0x1560] + str x16, [sp, #0x680] + ldr x16, [sp, #0x1570] + str x16, [sp, #0x688] + ldr x16, [sp, #0x1580] + str x16, [sp, #0x690] + ldr x16, [sp, #0x1590] + str x16, [sp, #0x698] + ldr x16, [sp, #0x15a0] + str x16, [sp, #0x6a0] + ldr x16, [sp, #0x15b0] + str x16, [sp, #0x6a8] + ldr x16, [sp, #0x15c0] + str x16, [sp, #0x6b0] + ldr x16, [sp, #0x15d0] + str x16, [sp, #0x6b8] + ldr x16, [sp, #0x15e0] + str x16, [sp, #0x6c0] + ldr x16, [sp, #0x15f0] + str x16, [sp, #0x6c8] + ldr x16, [sp, #0x1600] + str x16, [sp, #0x6d0] + ldr x16, [sp, #0x1610] + str x16, [sp, #0x6d8] + ldr x16, [sp, #0x1620] + str x16, [sp, #0x6e0] + ldr x16, [sp, #0x1630] + str x16, [sp, #0x6e8] + ldr x16, [sp, #0x1640] + str x16, [sp, #0x6f0] + ldr x16, [sp, #0x1650] + str x16, [sp, #0x6f8] + ldr x16, [sp, #0x1660] + str x16, [sp, #0x700] + ldr x16, [sp, #0x1670] + str x16, [sp, #0x708] + ldr x16, [sp, #0x1680] + str x16, [sp, #0x710] + ldr x16, [sp, #0x1690] + str x16, [sp, #0x718] + ldr x16, [sp, #0x16a0] + str x16, [sp, #0x720] + ldr x16, [sp, #0x16b0] + str x16, [sp, #0x728] + ldr x16, [sp, #0x16c0] + str x16, [sp, #0x730] + ldr x16, [sp, #0x16d0] + str x16, [sp, #0x738] + ldr x16, [sp, #0x16e0] + str x16, [sp, #0x740] + ldr x16, [sp, #0x16f0] + str x16, [sp, #0x748] + ldr x16, [sp, #0x1700] + str x16, [sp, #0x750] + ldr x16, [sp, #0x1710] + str x16, [sp, #0x758] + ldr x16, [sp, #0x1720] + str x16, [sp, #0x760] + ldr x16, [sp, #0x1730] + str x16, [sp, #0x768] + ldr x16, [sp, #0x1740] + str x16, [sp, #0x770] + ldr x16, [sp, #0x1750] + str x16, [sp, #0x778] + ldr x16, [sp, #0x1760] + str x16, [sp, #0x780] + ldr x16, [sp, #0x1770] + str x16, [sp, #0x788] + ldr x16, [sp, #0x1780] + str x16, [sp, #0x790] + ldr x16, [sp, #0x1790] + str x16, [sp, #0x798] + ldr x16, [sp, #0x17a0] + str x16, [sp, #0x7a0] + ldr x16, [sp, #0x17b0] + str x16, [sp, #0x7a8] + ldr x16, [sp, #0x17c0] + str x16, [sp, #0x7b0] + ldr x16, [sp, #0x17d0] + str x16, [sp, #0x7b8] + ldr x16, [sp, #0x17e0] + str x16, [sp, #0x7c0] + ldr x16, [sp, #0x17f0] + str x16, [sp, #0x7c8] + ldr x16, [sp, #0x1800] + str x16, [sp, #0x7d0] + ldr x16, [sp, #0x1810] + str x16, [sp, #0x7d8] + blr x9 + add sp, sp, #0x7e0 + add sp, sp, #0x1, lsl #12 // =0x1000 + add sp, sp, #0x40 + mov x17, #0x848a // =33930 + cmp x0, x17 + b.eq + mov x0, #0x2 // =2 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + ldr x23, [sp, #0x18] + ldr x24, [sp, #0x20] + ldr x25, [sp, #0x28] + ldr x26, [sp, #0x30] + ldr x27, [sp, #0x38] + ldr x28, [sp, #0x40] + ldr x19, [sp, #0x50] + add sp, sp, #0x1, lsl #12 // =0x1000 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + adrp x0, + add x0, x0, + add x1, x0, #0x10 + add x2, x0, #0x20 + add x3, x0, #0x30 + add x4, x0, #0x40 + add x5, x0, #0x50 + add x6, x0, #0x60 + add x7, x0, #0x70 + add x8, x0, #0x80 + add x9, x0, #0x90 + add x10, x0, #0xa0 + add x11, x0, #0xb0 + add x12, x0, #0xc0 + add x13, x0, #0xd0 + add x14, x0, #0xe0 + add x15, x0, #0xf0 + add x20, x0, #0x100 + add x22, x0, #0x110 + add x23, x0, #0x120 + add x24, x0, #0x130 + add x25, x0, #0x140 + add x26, x0, #0x150 + add x27, x0, #0x160 + add x28, x0, #0x170 + add x16, x0, #0x180 + str x16, [sp, #0x7c8] + add x16, x0, #0x190 + str x16, [sp, #0x7c0] + add x16, x0, #0x1a0 + str x16, [sp, #0x7b8] + add x16, x0, #0x1b0 + str x16, [sp, #0x7b0] + add x16, x0, #0x1c0 + str x16, [sp, #0x7a8] + add x16, x0, #0x1d0 + str x16, [sp, #0x7a0] + add x16, x0, #0x1e0 + str x16, [sp, #0x798] + add x16, x0, #0x1f0 + str x16, [sp, #0x790] + add x16, x0, #0x200 + str x16, [sp, #0x788] + add x16, x0, #0x210 + str x16, [sp, #0x780] + add x16, x0, #0x220 + str x16, [sp, #0x778] + add x16, x0, #0x230 + str x16, [sp, #0x770] + add x16, x0, #0x240 + str x16, [sp, #0x768] + add x16, x0, #0x250 + str x16, [sp, #0x760] + add x16, x0, #0x260 + str x16, [sp, #0x758] + add x16, x0, #0x270 + str x16, [sp, #0x750] + add x16, x0, #0x280 + str x16, [sp, #0x748] + add x16, x0, #0x290 + str x16, [sp, #0x740] + add x16, x0, #0x2a0 + str x16, [sp, #0x738] + add x16, x0, #0x2b0 + str x16, [sp, #0x730] + add x16, x0, #0x2c0 + str x16, [sp, #0x728] + add x16, x0, #0x2d0 + str x16, [sp, #0x720] + add x16, x0, #0x2e0 + str x16, [sp, #0x718] + add x16, x0, #0x2f0 + str x16, [sp, #0x710] + add x16, x0, #0x300 + str x16, [sp, #0x708] + add x16, x0, #0x310 + str x16, [sp, #0x700] + add x16, x0, #0x320 + str x16, [sp, #0x6f8] + add x16, x0, #0x330 + str x16, [sp, #0x6f0] + add x16, x0, #0x340 + str x16, [sp, #0x6e8] + add x16, x0, #0x350 + str x16, [sp, #0x6e0] + add x16, x0, #0x360 + str x16, [sp, #0x6d8] + add x16, x0, #0x370 + str x16, [sp, #0x6d0] + add x16, x0, #0x380 + str x16, [sp, #0x6c8] + add x16, x0, #0x390 + str x16, [sp, #0x6c0] + add x16, x0, #0x3a0 + str x16, [sp, #0x6b8] + add x16, x0, #0x3b0 + str x16, [sp, #0x6b0] + add x16, x0, #0x3c0 + str x16, [sp, #0x6a8] + add x16, x0, #0x3d0 + str x16, [sp, #0x6a0] + add x16, x0, #0x3e0 + str x16, [sp, #0x698] + add x16, x0, #0x3f0 + str x16, [sp, #0x690] + add x16, x0, #0x400 + str x16, [sp, #0x688] + add x16, x0, #0x410 + str x16, [sp, #0x680] + add x16, x0, #0x420 + str x16, [sp, #0x678] + add x16, x0, #0x430 + str x16, [sp, #0x670] + add x16, x0, #0x440 + str x16, [sp, #0x668] + add x16, x0, #0x450 + str x16, [sp, #0x660] + add x16, x0, #0x460 + str x16, [sp, #0x658] + add x16, x0, #0x470 + str x16, [sp, #0x650] + add x16, x0, #0x480 + str x16, [sp, #0x648] + add x16, x0, #0x490 + str x16, [sp, #0x640] + add x16, x0, #0x4a0 + str x16, [sp, #0x638] + add x16, x0, #0x4b0 + str x16, [sp, #0x630] + add x16, x0, #0x4c0 + str x16, [sp, #0x628] + add x16, x0, #0x4d0 + str x16, [sp, #0x620] + add x16, x0, #0x4e0 + str x16, [sp, #0x618] + add x16, x0, #0x4f0 + str x16, [sp, #0x610] + add x16, x0, #0x500 + str x16, [sp, #0x608] + add x16, x0, #0x510 + str x16, [sp, #0x600] + add x16, x0, #0x520 + str x16, [sp, #0x5f8] + add x16, x0, #0x530 + str x16, [sp, #0x5f0] + add x16, x0, #0x540 + str x16, [sp, #0x5e8] + add x16, x0, #0x550 + str x16, [sp, #0x5e0] + add x16, x0, #0x560 + str x16, [sp, #0x5d8] + add x16, x0, #0x570 + str x16, [sp, #0x5d0] + add x16, x0, #0x580 + str x16, [sp, #0x5c8] + add x16, x0, #0x590 + str x16, [sp, #0x5c0] + add x16, x0, #0x5a0 + str x16, [sp, #0x5b8] + add x16, x0, #0x5b0 + str x16, [sp, #0x5b0] + add x16, x0, #0x5c0 + str x16, [sp, #0x5a8] + add x16, x0, #0x5d0 + str x16, [sp, #0x5a0] + add x16, x0, #0x5e0 + str x16, [sp, #0x598] + add x16, x0, #0x5f0 + str x16, [sp, #0x590] + add x16, x0, #0x600 + str x16, [sp, #0x588] + add x16, x0, #0x610 + str x16, [sp, #0x580] + add x16, x0, #0x620 + str x16, [sp, #0x578] + add x16, x0, #0x630 + str x16, [sp, #0x570] + add x16, x0, #0x640 + str x16, [sp, #0x568] + add x16, x0, #0x650 + str x16, [sp, #0x560] + add x16, x0, #0x660 + str x16, [sp, #0x558] + add x16, x0, #0x670 + str x16, [sp, #0x550] + add x16, x0, #0x680 + str x16, [sp, #0x548] + add x16, x0, #0x690 + str x16, [sp, #0x540] + add x16, x0, #0x6a0 + str x16, [sp, #0x538] + add x16, x0, #0x6b0 + str x16, [sp, #0x530] + add x16, x0, #0x6c0 + str x16, [sp, #0x528] + add x16, x0, #0x6d0 + str x16, [sp, #0x520] + add x16, x0, #0x6e0 + str x16, [sp, #0x518] + add x16, x0, #0x6f0 + str x16, [sp, #0x510] + add x16, x0, #0x700 + str x16, [sp, #0x508] + add x16, x0, #0x710 + str x16, [sp, #0x500] + add x16, x0, #0x720 + str x16, [sp, #0x4f8] + add x16, x0, #0x730 + str x16, [sp, #0x4f0] + add x16, x0, #0x740 + str x16, [sp, #0x4e8] + add x16, x0, #0x750 + str x16, [sp, #0x4e0] + add x16, x0, #0x760 + str x16, [sp, #0x4d8] + add x16, x0, #0x770 + str x16, [sp, #0x4d0] + add x16, x0, #0x780 + str x16, [sp, #0x4c8] + add x16, x0, #0x790 + str x16, [sp, #0x4c0] + add x16, x0, #0x7a0 + str x16, [sp, #0x4b8] + add x16, x0, #0x7b0 + str x16, [sp, #0x4b0] + add x16, x0, #0x7c0 + str x16, [sp, #0x4a8] + add x16, x0, #0x7d0 + str x16, [sp, #0x4a0] + add x16, x0, #0x7e0 + str x16, [sp, #0x498] + add x16, x0, #0x7f0 + str x16, [sp, #0x490] + add x16, x0, #0x800 + str x16, [sp, #0x488] + add x16, x0, #0x810 + str x16, [sp, #0x480] + add x16, x0, #0x820 + str x16, [sp, #0x478] + add x16, x0, #0x830 + str x16, [sp, #0x470] + add x16, x0, #0x840 + str x16, [sp, #0x468] + add x16, x0, #0x850 + str x16, [sp, #0x460] + add x16, x0, #0x860 + str x16, [sp, #0x458] + add x16, x0, #0x870 + str x16, [sp, #0x450] + add x16, x0, #0x880 + str x16, [sp, #0x448] + add x16, x0, #0x890 + str x16, [sp, #0x440] + add x16, x0, #0x8a0 + str x16, [sp, #0x438] + add x16, x0, #0x8b0 + str x16, [sp, #0x430] + add x16, x0, #0x8c0 + str x16, [sp, #0x428] + add x16, x0, #0x8d0 + str x16, [sp, #0x420] + add x16, x0, #0x8e0 + str x16, [sp, #0x418] + add x16, x0, #0x8f0 + str x16, [sp, #0x410] + add x16, x0, #0x900 + str x16, [sp, #0x408] + add x16, x0, #0x910 + str x16, [sp, #0x400] + add x16, x0, #0x920 + str x16, [sp, #0x3f8] + add x16, x0, #0x930 + str x16, [sp, #0x3f0] + add x16, x0, #0x940 + str x16, [sp, #0x3e8] + add x16, x0, #0x950 + str x16, [sp, #0x3e0] + add x16, x0, #0x960 + str x16, [sp, #0x3d8] + add x16, x0, #0x970 + str x16, [sp, #0x3d0] + add x16, x0, #0x980 + str x16, [sp, #0x3c8] + add x16, x0, #0x990 + str x16, [sp, #0x3c0] + add x16, x0, #0x9a0 + str x16, [sp, #0x3b8] + add x16, x0, #0x9b0 + str x16, [sp, #0x3b0] + add x16, x0, #0x9c0 + str x16, [sp, #0x3a8] + add x16, x0, #0x9d0 + str x16, [sp, #0x3a0] + add x16, x0, #0x9e0 + str x16, [sp, #0x398] + add x16, x0, #0x9f0 + str x16, [sp, #0x390] + add x16, x0, #0xa00 + str x16, [sp, #0x388] + add x16, x0, #0xa10 + str x16, [sp, #0x380] + add x16, x0, #0xa20 + str x16, [sp, #0x378] + add x16, x0, #0xa30 + str x16, [sp, #0x370] + add x16, x0, #0xa40 + str x16, [sp, #0x368] + add x16, x0, #0xa50 + str x16, [sp, #0x360] + add x16, x0, #0xa60 + str x16, [sp, #0x358] + add x16, x0, #0xa70 + str x16, [sp, #0x350] + add x16, x0, #0xa80 + str x16, [sp, #0x348] + add x16, x0, #0xa90 + str x16, [sp, #0x340] + add x16, x0, #0xaa0 + str x16, [sp, #0x338] + add x16, x0, #0xab0 + str x16, [sp, #0x330] + add x16, x0, #0xac0 + str x16, [sp, #0x328] + add x16, x0, #0xad0 + str x16, [sp, #0x320] + add x16, x0, #0xae0 + str x16, [sp, #0x318] + add x16, x0, #0xaf0 + str x16, [sp, #0x310] + add x16, x0, #0xb00 + str x16, [sp, #0x308] + add x16, x0, #0xb10 + str x16, [sp, #0x300] + add x16, x0, #0xb20 + str x16, [sp, #0x2f8] + add x16, x0, #0xb30 + str x16, [sp, #0x2f0] + add x16, x0, #0xb40 + str x16, [sp, #0x2e8] + add x16, x0, #0xb50 + str x16, [sp, #0x2e0] + add x16, x0, #0xb60 + str x16, [sp, #0x2d8] + add x16, x0, #0xb70 + str x16, [sp, #0x2d0] + add x16, x0, #0xb80 + str x16, [sp, #0x2c8] + add x16, x0, #0xb90 + str x16, [sp, #0x2c0] + add x16, x0, #0xba0 + str x16, [sp, #0x2b8] + add x16, x0, #0xbb0 + str x16, [sp, #0x2b0] + add x16, x0, #0xbc0 + str x16, [sp, #0x2a8] + add x16, x0, #0xbd0 + str x16, [sp, #0x2a0] + add x16, x0, #0xbe0 + str x16, [sp, #0x298] + add x16, x0, #0xbf0 + str x16, [sp, #0x290] + add x16, x0, #0xc00 + str x16, [sp, #0x288] + add x16, x0, #0xc10 + str x16, [sp, #0x280] + add x16, x0, #0xc20 + str x16, [sp, #0x278] + add x16, x0, #0xc30 + str x16, [sp, #0x270] + add x16, x0, #0xc40 + str x16, [sp, #0x268] + add x16, x0, #0xc50 + str x16, [sp, #0x260] + add x16, x0, #0xc60 + str x16, [sp, #0x258] + add x16, x0, #0xc70 + str x16, [sp, #0x250] + add x16, x0, #0xc80 + str x16, [sp, #0x248] + add x16, x0, #0xc90 + str x16, [sp, #0x240] + add x16, x0, #0xca0 + str x16, [sp, #0x238] + add x16, x0, #0xcb0 + str x16, [sp, #0x230] + add x16, x0, #0xcc0 + str x16, [sp, #0x228] + add x16, x0, #0xcd0 + str x16, [sp, #0x220] + add x16, x0, #0xce0 + str x16, [sp, #0x218] + add x16, x0, #0xcf0 + str x16, [sp, #0x210] + add x16, x0, #0xd00 + str x16, [sp, #0x208] + add x16, x0, #0xd10 + str x16, [sp, #0x200] + add x16, x0, #0xd20 + str x16, [sp, #0x1f8] + add x16, x0, #0xd30 + str x16, [sp, #0x1f0] + add x16, x0, #0xd40 + str x16, [sp, #0x1e8] + add x16, x0, #0xd50 + str x16, [sp, #0x1e0] + add x16, x0, #0xd60 + str x16, [sp, #0x1d8] + add x16, x0, #0xd70 + str x16, [sp, #0x1d0] + add x16, x0, #0xd80 + str x16, [sp, #0x1c8] + add x16, x0, #0xd90 + str x16, [sp, #0x1c0] + add x16, x0, #0xda0 + str x16, [sp, #0x1b8] + add x16, x0, #0xdb0 + str x16, [sp, #0x1b0] + add x16, x0, #0xdc0 + str x16, [sp, #0x1a8] + add x16, x0, #0xdd0 + str x16, [sp, #0x1a0] + add x16, x0, #0xde0 + str x16, [sp, #0x198] + add x16, x0, #0xdf0 + str x16, [sp, #0x190] + add x16, x0, #0xe00 + str x16, [sp, #0x188] + add x16, x0, #0xe10 + str x16, [sp, #0x180] + add x16, x0, #0xe20 + str x16, [sp, #0x178] + add x16, x0, #0xe30 + str x16, [sp, #0x170] + add x16, x0, #0xe40 + str x16, [sp, #0x168] + add x16, x0, #0xe50 + str x16, [sp, #0x160] + add x16, x0, #0xe60 + str x16, [sp, #0x158] + add x16, x0, #0xe70 + str x16, [sp, #0x150] + add x16, x0, #0xe80 + str x16, [sp, #0x148] + add x16, x0, #0xe90 + str x16, [sp, #0x140] + add x16, x0, #0xea0 + str x16, [sp, #0x138] + add x16, x0, #0xeb0 + str x16, [sp, #0x130] + add x16, x0, #0xec0 + str x16, [sp, #0x128] + add x16, x0, #0xed0 + str x16, [sp, #0x120] + add x16, x0, #0xee0 + str x16, [sp, #0x118] + add x16, x0, #0xef0 + str x16, [sp, #0x110] + add x16, x0, #0xf00 + str x16, [sp, #0x108] + add x16, x0, #0xf10 + str x16, [sp, #0x100] + add x16, x0, #0xf20 + str x16, [sp, #0xf8] + add x16, x0, #0xf30 + str x16, [sp, #0xf0] + add x16, x0, #0xf40 + str x16, [sp, #0xe8] + add x16, x0, #0xf50 + str x16, [sp, #0xe0] + add x16, x0, #0xf60 + str x16, [sp, #0xd8] + add x16, x0, #0xf70 + str x16, [sp, #0xd0] + add x16, x0, #0xf80 + str x16, [sp, #0xc8] + add x16, x0, #0xf90 + str x16, [sp, #0xc0] + add x16, x0, #0xfa0 + str x16, [sp, #0xb8] + add x16, x0, #0xfb0 + str x16, [sp, #0xb0] + add x16, x0, #0xfc0 + str x16, [sp, #0xa8] + add x16, x0, #0xfd0 + str x16, [sp, #0xa0] + add x16, x0, #0xfe0 + str x16, [sp, #0x98] + add x16, x0, #0xff0 + str x16, [sp, #0x90] + mov x17, #0x1000 // =4096 + add x16, x0, x17 + str x16, [sp, #0x88] + mov x17, #0x1010 // =4112 + add x16, x0, x17 + str x16, [sp, #0x80] + mov x17, #0x1020 // =4128 + add x16, x0, x17 + str x16, [sp, #0x78] + mov x17, #0x1030 // =4144 + add x16, x0, x17 + str x16, [sp, #0x70] + mov x17, #0x1040 // =4160 + add x16, x0, x17 + str x16, [sp, #0x68] + mov x16, x21 + sub sp, sp, #0x1, lsl #12 // =0x1000 + sub sp, sp, #0x20 + str x16, [sp, #0x1010] + mov x16, x4 + ldr x17, [x16] + str x17, [sp] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8] + mov x16, x5 + ldr x17, [x16] + str x17, [sp, #0x10] + ldr x17, [x16, #0x8] + str x17, [sp, #0x18] + mov x16, x6 + ldr x17, [x16] + str x17, [sp, #0x20] + ldr x17, [x16, #0x8] + str x17, [sp, #0x28] + mov x16, x7 + ldr x17, [x16] + str x17, [sp, #0x30] + ldr x17, [x16, #0x8] + str x17, [sp, #0x38] + mov x16, x8 + ldr x17, [x16] + str x17, [sp, #0x40] + ldr x17, [x16, #0x8] + str x17, [sp, #0x48] + mov x16, x9 + ldr x17, [x16] + str x17, [sp, #0x50] + ldr x17, [x16, #0x8] + str x17, [sp, #0x58] + mov x16, x10 + ldr x17, [x16] + str x17, [sp, #0x60] + ldr x17, [x16, #0x8] + str x17, [sp, #0x68] + mov x16, x11 + ldr x17, [x16] + str x17, [sp, #0x70] + ldr x17, [x16, #0x8] + str x17, [sp, #0x78] + mov x16, x12 + ldr x17, [x16] + str x17, [sp, #0x80] + ldr x17, [x16, #0x8] + str x17, [sp, #0x88] + mov x16, x13 + ldr x17, [x16] + str x17, [sp, #0x90] + ldr x17, [x16, #0x8] + str x17, [sp, #0x98] + mov x16, x14 + ldr x17, [x16] + str x17, [sp, #0xa0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa8] + mov x16, x15 + ldr x17, [x16] + str x17, [sp, #0xb0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb8] + mov x16, x20 + ldr x17, [x16] + str x17, [sp, #0xc0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc8] + mov x16, x22 + ldr x17, [x16] + str x17, [sp, #0xd0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd8] + mov x16, x23 + ldr x17, [x16] + str x17, [sp, #0xe0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe8] + mov x16, x24 + ldr x17, [x16] + str x17, [sp, #0xf0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf8] + mov x16, x25 + ldr x17, [x16] + str x17, [sp, #0x100] + ldr x17, [x16, #0x8] + str x17, [sp, #0x108] + mov x16, x26 + ldr x17, [x16] + str x17, [sp, #0x110] + ldr x17, [x16, #0x8] + str x17, [sp, #0x118] + mov x16, x27 + ldr x17, [x16] + str x17, [sp, #0x120] + ldr x17, [x16, #0x8] + str x17, [sp, #0x128] + mov x16, x28 + ldr x17, [x16] + str x17, [sp, #0x130] + ldr x17, [x16, #0x8] + str x17, [sp, #0x138] + ldr x16, [sp, #0x17e8] + ldr x17, [x16] + str x17, [sp, #0x140] + ldr x17, [x16, #0x8] + str x17, [sp, #0x148] + ldr x16, [sp, #0x17e0] + ldr x17, [x16] + str x17, [sp, #0x150] + ldr x17, [x16, #0x8] + str x17, [sp, #0x158] + ldr x16, [sp, #0x17d8] + ldr x17, [x16] + str x17, [sp, #0x160] + ldr x17, [x16, #0x8] + str x17, [sp, #0x168] + ldr x16, [sp, #0x17d0] + ldr x17, [x16] + str x17, [sp, #0x170] + ldr x17, [x16, #0x8] + str x17, [sp, #0x178] + ldr x16, [sp, #0x17c8] + ldr x17, [x16] + str x17, [sp, #0x180] + ldr x17, [x16, #0x8] + str x17, [sp, #0x188] + ldr x16, [sp, #0x17c0] + ldr x17, [x16] + str x17, [sp, #0x190] + ldr x17, [x16, #0x8] + str x17, [sp, #0x198] + ldr x16, [sp, #0x17b8] + ldr x17, [x16] + str x17, [sp, #0x1a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1a8] + ldr x16, [sp, #0x17b0] + ldr x17, [x16] + str x17, [sp, #0x1b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1b8] + ldr x16, [sp, #0x17a8] + ldr x17, [x16] + str x17, [sp, #0x1c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1c8] + ldr x16, [sp, #0x17a0] + ldr x17, [x16] + str x17, [sp, #0x1d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1d8] + ldr x16, [sp, #0x1798] + ldr x17, [x16] + str x17, [sp, #0x1e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1e8] + ldr x16, [sp, #0x1790] + ldr x17, [x16] + str x17, [sp, #0x1f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1f8] + ldr x16, [sp, #0x1788] + ldr x17, [x16] + str x17, [sp, #0x200] + ldr x17, [x16, #0x8] + str x17, [sp, #0x208] + ldr x16, [sp, #0x1780] + ldr x17, [x16] + str x17, [sp, #0x210] + ldr x17, [x16, #0x8] + str x17, [sp, #0x218] + ldr x16, [sp, #0x1778] + ldr x17, [x16] + str x17, [sp, #0x220] + ldr x17, [x16, #0x8] + str x17, [sp, #0x228] + ldr x16, [sp, #0x1770] + ldr x17, [x16] + str x17, [sp, #0x230] + ldr x17, [x16, #0x8] + str x17, [sp, #0x238] + ldr x16, [sp, #0x1768] + ldr x17, [x16] + str x17, [sp, #0x240] + ldr x17, [x16, #0x8] + str x17, [sp, #0x248] + ldr x16, [sp, #0x1760] + ldr x17, [x16] + str x17, [sp, #0x250] + ldr x17, [x16, #0x8] + str x17, [sp, #0x258] + ldr x16, [sp, #0x1758] + ldr x17, [x16] + str x17, [sp, #0x260] + ldr x17, [x16, #0x8] + str x17, [sp, #0x268] + ldr x16, [sp, #0x1750] + ldr x17, [x16] + str x17, [sp, #0x270] + ldr x17, [x16, #0x8] + str x17, [sp, #0x278] + ldr x16, [sp, #0x1748] + ldr x17, [x16] + str x17, [sp, #0x280] + ldr x17, [x16, #0x8] + str x17, [sp, #0x288] + ldr x16, [sp, #0x1740] + ldr x17, [x16] + str x17, [sp, #0x290] + ldr x17, [x16, #0x8] + str x17, [sp, #0x298] + ldr x16, [sp, #0x1738] + ldr x17, [x16] + str x17, [sp, #0x2a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x2a8] + ldr x16, [sp, #0x1730] + ldr x17, [x16] + str x17, [sp, #0x2b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x2b8] + ldr x16, [sp, #0x1728] + ldr x17, [x16] + str x17, [sp, #0x2c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x2c8] + ldr x16, [sp, #0x1720] + ldr x17, [x16] + str x17, [sp, #0x2d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x2d8] + ldr x16, [sp, #0x1718] + ldr x17, [x16] + str x17, [sp, #0x2e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x2e8] + ldr x16, [sp, #0x1710] + ldr x17, [x16] + str x17, [sp, #0x2f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x2f8] + ldr x16, [sp, #0x1708] + ldr x17, [x16] + str x17, [sp, #0x300] + ldr x17, [x16, #0x8] + str x17, [sp, #0x308] + ldr x16, [sp, #0x1700] + ldr x17, [x16] + str x17, [sp, #0x310] + ldr x17, [x16, #0x8] + str x17, [sp, #0x318] + ldr x16, [sp, #0x16f8] + ldr x17, [x16] + str x17, [sp, #0x320] + ldr x17, [x16, #0x8] + str x17, [sp, #0x328] + ldr x16, [sp, #0x16f0] + ldr x17, [x16] + str x17, [sp, #0x330] + ldr x17, [x16, #0x8] + str x17, [sp, #0x338] + ldr x16, [sp, #0x16e8] + ldr x17, [x16] + str x17, [sp, #0x340] + ldr x17, [x16, #0x8] + str x17, [sp, #0x348] + ldr x16, [sp, #0x16e0] + ldr x17, [x16] + str x17, [sp, #0x350] + ldr x17, [x16, #0x8] + str x17, [sp, #0x358] + ldr x16, [sp, #0x16d8] + ldr x17, [x16] + str x17, [sp, #0x360] + ldr x17, [x16, #0x8] + str x17, [sp, #0x368] + ldr x16, [sp, #0x16d0] + ldr x17, [x16] + str x17, [sp, #0x370] + ldr x17, [x16, #0x8] + str x17, [sp, #0x378] + ldr x16, [sp, #0x16c8] + ldr x17, [x16] + str x17, [sp, #0x380] + ldr x17, [x16, #0x8] + str x17, [sp, #0x388] + ldr x16, [sp, #0x16c0] + ldr x17, [x16] + str x17, [sp, #0x390] + ldr x17, [x16, #0x8] + str x17, [sp, #0x398] + ldr x16, [sp, #0x16b8] + ldr x17, [x16] + str x17, [sp, #0x3a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x3a8] + ldr x16, [sp, #0x16b0] + ldr x17, [x16] + str x17, [sp, #0x3b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x3b8] + ldr x16, [sp, #0x16a8] + ldr x17, [x16] + str x17, [sp, #0x3c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x3c8] + ldr x16, [sp, #0x16a0] + ldr x17, [x16] + str x17, [sp, #0x3d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x3d8] + ldr x16, [sp, #0x1698] + ldr x17, [x16] + str x17, [sp, #0x3e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x3e8] + ldr x16, [sp, #0x1690] + ldr x17, [x16] + str x17, [sp, #0x3f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x3f8] + ldr x16, [sp, #0x1688] + ldr x17, [x16] + str x17, [sp, #0x400] + ldr x17, [x16, #0x8] + str x17, [sp, #0x408] + ldr x16, [sp, #0x1680] + ldr x17, [x16] + str x17, [sp, #0x410] + ldr x17, [x16, #0x8] + str x17, [sp, #0x418] + ldr x16, [sp, #0x1678] + ldr x17, [x16] + str x17, [sp, #0x420] + ldr x17, [x16, #0x8] + str x17, [sp, #0x428] + ldr x16, [sp, #0x1670] + ldr x17, [x16] + str x17, [sp, #0x430] + ldr x17, [x16, #0x8] + str x17, [sp, #0x438] + ldr x16, [sp, #0x1668] + ldr x17, [x16] + str x17, [sp, #0x440] + ldr x17, [x16, #0x8] + str x17, [sp, #0x448] + ldr x16, [sp, #0x1660] + ldr x17, [x16] + str x17, [sp, #0x450] + ldr x17, [x16, #0x8] + str x17, [sp, #0x458] + ldr x16, [sp, #0x1658] + ldr x17, [x16] + str x17, [sp, #0x460] + ldr x17, [x16, #0x8] + str x17, [sp, #0x468] + ldr x16, [sp, #0x1650] + ldr x17, [x16] + str x17, [sp, #0x470] + ldr x17, [x16, #0x8] + str x17, [sp, #0x478] + ldr x16, [sp, #0x1648] + ldr x17, [x16] + str x17, [sp, #0x480] + ldr x17, [x16, #0x8] + str x17, [sp, #0x488] + ldr x16, [sp, #0x1640] + ldr x17, [x16] + str x17, [sp, #0x490] + ldr x17, [x16, #0x8] + str x17, [sp, #0x498] + ldr x16, [sp, #0x1638] + ldr x17, [x16] + str x17, [sp, #0x4a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x4a8] + ldr x16, [sp, #0x1630] + ldr x17, [x16] + str x17, [sp, #0x4b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x4b8] + ldr x16, [sp, #0x1628] + ldr x17, [x16] + str x17, [sp, #0x4c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x4c8] + ldr x16, [sp, #0x1620] + ldr x17, [x16] + str x17, [sp, #0x4d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x4d8] + ldr x16, [sp, #0x1618] + ldr x17, [x16] + str x17, [sp, #0x4e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x4e8] + ldr x16, [sp, #0x1610] + ldr x17, [x16] + str x17, [sp, #0x4f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x4f8] + ldr x16, [sp, #0x1608] + ldr x17, [x16] + str x17, [sp, #0x500] + ldr x17, [x16, #0x8] + str x17, [sp, #0x508] + ldr x16, [sp, #0x1600] + ldr x17, [x16] + str x17, [sp, #0x510] + ldr x17, [x16, #0x8] + str x17, [sp, #0x518] + ldr x16, [sp, #0x15f8] + ldr x17, [x16] + str x17, [sp, #0x520] + ldr x17, [x16, #0x8] + str x17, [sp, #0x528] + ldr x16, [sp, #0x15f0] + ldr x17, [x16] + str x17, [sp, #0x530] + ldr x17, [x16, #0x8] + str x17, [sp, #0x538] + ldr x16, [sp, #0x15e8] + ldr x17, [x16] + str x17, [sp, #0x540] + ldr x17, [x16, #0x8] + str x17, [sp, #0x548] + ldr x16, [sp, #0x15e0] + ldr x17, [x16] + str x17, [sp, #0x550] + ldr x17, [x16, #0x8] + str x17, [sp, #0x558] + ldr x16, [sp, #0x15d8] + ldr x17, [x16] + str x17, [sp, #0x560] + ldr x17, [x16, #0x8] + str x17, [sp, #0x568] + ldr x16, [sp, #0x15d0] + ldr x17, [x16] + str x17, [sp, #0x570] + ldr x17, [x16, #0x8] + str x17, [sp, #0x578] + ldr x16, [sp, #0x15c8] + ldr x17, [x16] + str x17, [sp, #0x580] + ldr x17, [x16, #0x8] + str x17, [sp, #0x588] + ldr x16, [sp, #0x15c0] + ldr x17, [x16] + str x17, [sp, #0x590] + ldr x17, [x16, #0x8] + str x17, [sp, #0x598] + ldr x16, [sp, #0x15b8] + ldr x17, [x16] + str x17, [sp, #0x5a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x5a8] + ldr x16, [sp, #0x15b0] + ldr x17, [x16] + str x17, [sp, #0x5b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x5b8] + ldr x16, [sp, #0x15a8] + ldr x17, [x16] + str x17, [sp, #0x5c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x5c8] + ldr x16, [sp, #0x15a0] + ldr x17, [x16] + str x17, [sp, #0x5d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x5d8] + ldr x16, [sp, #0x1598] + ldr x17, [x16] + str x17, [sp, #0x5e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x5e8] + ldr x16, [sp, #0x1590] + ldr x17, [x16] + str x17, [sp, #0x5f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x5f8] + ldr x16, [sp, #0x1588] + ldr x17, [x16] + str x17, [sp, #0x600] + ldr x17, [x16, #0x8] + str x17, [sp, #0x608] + ldr x16, [sp, #0x1580] + ldr x17, [x16] + str x17, [sp, #0x610] + ldr x17, [x16, #0x8] + str x17, [sp, #0x618] + ldr x16, [sp, #0x1578] + ldr x17, [x16] + str x17, [sp, #0x620] + ldr x17, [x16, #0x8] + str x17, [sp, #0x628] + ldr x16, [sp, #0x1570] + ldr x17, [x16] + str x17, [sp, #0x630] + ldr x17, [x16, #0x8] + str x17, [sp, #0x638] + ldr x16, [sp, #0x1568] + ldr x17, [x16] + str x17, [sp, #0x640] + ldr x17, [x16, #0x8] + str x17, [sp, #0x648] + ldr x16, [sp, #0x1560] + ldr x17, [x16] + str x17, [sp, #0x650] + ldr x17, [x16, #0x8] + str x17, [sp, #0x658] + ldr x16, [sp, #0x1558] + ldr x17, [x16] + str x17, [sp, #0x660] + ldr x17, [x16, #0x8] + str x17, [sp, #0x668] + ldr x16, [sp, #0x1550] + ldr x17, [x16] + str x17, [sp, #0x670] + ldr x17, [x16, #0x8] + str x17, [sp, #0x678] + ldr x16, [sp, #0x1548] + ldr x17, [x16] + str x17, [sp, #0x680] + ldr x17, [x16, #0x8] + str x17, [sp, #0x688] + ldr x16, [sp, #0x1540] + ldr x17, [x16] + str x17, [sp, #0x690] + ldr x17, [x16, #0x8] + str x17, [sp, #0x698] + ldr x16, [sp, #0x1538] + ldr x17, [x16] + str x17, [sp, #0x6a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x6a8] + ldr x16, [sp, #0x1530] + ldr x17, [x16] + str x17, [sp, #0x6b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x6b8] + ldr x16, [sp, #0x1528] + ldr x17, [x16] + str x17, [sp, #0x6c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x6c8] + ldr x16, [sp, #0x1520] + ldr x17, [x16] + str x17, [sp, #0x6d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x6d8] + ldr x16, [sp, #0x1518] + ldr x17, [x16] + str x17, [sp, #0x6e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x6e8] + ldr x16, [sp, #0x1510] + ldr x17, [x16] + str x17, [sp, #0x6f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x6f8] + ldr x16, [sp, #0x1508] + ldr x17, [x16] + str x17, [sp, #0x700] + ldr x17, [x16, #0x8] + str x17, [sp, #0x708] + ldr x16, [sp, #0x1500] + ldr x17, [x16] + str x17, [sp, #0x710] + ldr x17, [x16, #0x8] + str x17, [sp, #0x718] + ldr x16, [sp, #0x14f8] + ldr x17, [x16] + str x17, [sp, #0x720] + ldr x17, [x16, #0x8] + str x17, [sp, #0x728] + ldr x16, [sp, #0x14f0] + ldr x17, [x16] + str x17, [sp, #0x730] + ldr x17, [x16, #0x8] + str x17, [sp, #0x738] + ldr x16, [sp, #0x14e8] + ldr x17, [x16] + str x17, [sp, #0x740] + ldr x17, [x16, #0x8] + str x17, [sp, #0x748] + ldr x16, [sp, #0x14e0] + ldr x17, [x16] + str x17, [sp, #0x750] + ldr x17, [x16, #0x8] + str x17, [sp, #0x758] + ldr x16, [sp, #0x14d8] + ldr x17, [x16] + str x17, [sp, #0x760] + ldr x17, [x16, #0x8] + str x17, [sp, #0x768] + ldr x16, [sp, #0x14d0] + ldr x17, [x16] + str x17, [sp, #0x770] + ldr x17, [x16, #0x8] + str x17, [sp, #0x778] + ldr x16, [sp, #0x14c8] + ldr x17, [x16] + str x17, [sp, #0x780] + ldr x17, [x16, #0x8] + str x17, [sp, #0x788] + ldr x16, [sp, #0x14c0] + ldr x17, [x16] + str x17, [sp, #0x790] + ldr x17, [x16, #0x8] + str x17, [sp, #0x798] + ldr x16, [sp, #0x14b8] + ldr x17, [x16] + str x17, [sp, #0x7a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x7a8] + ldr x16, [sp, #0x14b0] + ldr x17, [x16] + str x17, [sp, #0x7b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x7b8] + ldr x16, [sp, #0x14a8] + ldr x17, [x16] + str x17, [sp, #0x7c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x7c8] + ldr x16, [sp, #0x14a0] + ldr x17, [x16] + str x17, [sp, #0x7d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x7d8] + ldr x16, [sp, #0x1498] + ldr x17, [x16] + str x17, [sp, #0x7e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x7e8] + ldr x16, [sp, #0x1490] + ldr x17, [x16] + str x17, [sp, #0x7f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x7f8] + ldr x16, [sp, #0x1488] + ldr x17, [x16] + str x17, [sp, #0x800] + ldr x17, [x16, #0x8] + str x17, [sp, #0x808] + ldr x16, [sp, #0x1480] + ldr x17, [x16] + str x17, [sp, #0x810] + ldr x17, [x16, #0x8] + str x17, [sp, #0x818] + ldr x16, [sp, #0x1478] + ldr x17, [x16] + str x17, [sp, #0x820] + ldr x17, [x16, #0x8] + str x17, [sp, #0x828] + ldr x16, [sp, #0x1470] + ldr x17, [x16] + str x17, [sp, #0x830] + ldr x17, [x16, #0x8] + str x17, [sp, #0x838] + ldr x16, [sp, #0x1468] + ldr x17, [x16] + str x17, [sp, #0x840] + ldr x17, [x16, #0x8] + str x17, [sp, #0x848] + ldr x16, [sp, #0x1460] + ldr x17, [x16] + str x17, [sp, #0x850] + ldr x17, [x16, #0x8] + str x17, [sp, #0x858] + ldr x16, [sp, #0x1458] + ldr x17, [x16] + str x17, [sp, #0x860] + ldr x17, [x16, #0x8] + str x17, [sp, #0x868] + ldr x16, [sp, #0x1450] + ldr x17, [x16] + str x17, [sp, #0x870] + ldr x17, [x16, #0x8] + str x17, [sp, #0x878] + ldr x16, [sp, #0x1448] + ldr x17, [x16] + str x17, [sp, #0x880] + ldr x17, [x16, #0x8] + str x17, [sp, #0x888] + ldr x16, [sp, #0x1440] + ldr x17, [x16] + str x17, [sp, #0x890] + ldr x17, [x16, #0x8] + str x17, [sp, #0x898] + ldr x16, [sp, #0x1438] + ldr x17, [x16] + str x17, [sp, #0x8a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8a8] + ldr x16, [sp, #0x1430] + ldr x17, [x16] + str x17, [sp, #0x8b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8b8] + ldr x16, [sp, #0x1428] + ldr x17, [x16] + str x17, [sp, #0x8c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8c8] + ldr x16, [sp, #0x1420] + ldr x17, [x16] + str x17, [sp, #0x8d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8d8] + ldr x16, [sp, #0x1418] + ldr x17, [x16] + str x17, [sp, #0x8e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8e8] + ldr x16, [sp, #0x1410] + ldr x17, [x16] + str x17, [sp, #0x8f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8f8] + ldr x16, [sp, #0x1408] + ldr x17, [x16] + str x17, [sp, #0x900] + ldr x17, [x16, #0x8] + str x17, [sp, #0x908] + ldr x16, [sp, #0x1400] + ldr x17, [x16] + str x17, [sp, #0x910] + ldr x17, [x16, #0x8] + str x17, [sp, #0x918] + ldr x16, [sp, #0x13f8] + ldr x17, [x16] + str x17, [sp, #0x920] + ldr x17, [x16, #0x8] + str x17, [sp, #0x928] + ldr x16, [sp, #0x13f0] + ldr x17, [x16] + str x17, [sp, #0x930] + ldr x17, [x16, #0x8] + str x17, [sp, #0x938] + ldr x16, [sp, #0x13e8] + ldr x17, [x16] + str x17, [sp, #0x940] + ldr x17, [x16, #0x8] + str x17, [sp, #0x948] + ldr x16, [sp, #0x13e0] + ldr x17, [x16] + str x17, [sp, #0x950] + ldr x17, [x16, #0x8] + str x17, [sp, #0x958] + ldr x16, [sp, #0x13d8] + ldr x17, [x16] + str x17, [sp, #0x960] + ldr x17, [x16, #0x8] + str x17, [sp, #0x968] + ldr x16, [sp, #0x13d0] + ldr x17, [x16] + str x17, [sp, #0x970] + ldr x17, [x16, #0x8] + str x17, [sp, #0x978] + ldr x16, [sp, #0x13c8] + ldr x17, [x16] + str x17, [sp, #0x980] + ldr x17, [x16, #0x8] + str x17, [sp, #0x988] + ldr x16, [sp, #0x13c0] + ldr x17, [x16] + str x17, [sp, #0x990] + ldr x17, [x16, #0x8] + str x17, [sp, #0x998] + ldr x16, [sp, #0x13b8] + ldr x17, [x16] + str x17, [sp, #0x9a0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x9a8] + ldr x16, [sp, #0x13b0] + ldr x17, [x16] + str x17, [sp, #0x9b0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x9b8] + ldr x16, [sp, #0x13a8] + ldr x17, [x16] + str x17, [sp, #0x9c0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x9c8] + ldr x16, [sp, #0x13a0] + ldr x17, [x16] + str x17, [sp, #0x9d0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x9d8] + ldr x16, [sp, #0x1398] + ldr x17, [x16] + str x17, [sp, #0x9e0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x9e8] + ldr x16, [sp, #0x1390] + ldr x17, [x16] + str x17, [sp, #0x9f0] + ldr x17, [x16, #0x8] + str x17, [sp, #0x9f8] + ldr x16, [sp, #0x1388] + ldr x17, [x16] + str x17, [sp, #0xa00] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa08] + ldr x16, [sp, #0x1380] + ldr x17, [x16] + str x17, [sp, #0xa10] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa18] + ldr x16, [sp, #0x1378] + ldr x17, [x16] + str x17, [sp, #0xa20] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa28] + ldr x16, [sp, #0x1370] + ldr x17, [x16] + str x17, [sp, #0xa30] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa38] + ldr x16, [sp, #0x1368] + ldr x17, [x16] + str x17, [sp, #0xa40] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa48] + ldr x16, [sp, #0x1360] + ldr x17, [x16] + str x17, [sp, #0xa50] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa58] + ldr x16, [sp, #0x1358] + ldr x17, [x16] + str x17, [sp, #0xa60] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa68] + ldr x16, [sp, #0x1350] + ldr x17, [x16] + str x17, [sp, #0xa70] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa78] + ldr x16, [sp, #0x1348] + ldr x17, [x16] + str x17, [sp, #0xa80] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa88] + ldr x16, [sp, #0x1340] + ldr x17, [x16] + str x17, [sp, #0xa90] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa98] + ldr x16, [sp, #0x1338] + ldr x17, [x16] + str x17, [sp, #0xaa0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xaa8] + ldr x16, [sp, #0x1330] + ldr x17, [x16] + str x17, [sp, #0xab0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xab8] + ldr x16, [sp, #0x1328] + ldr x17, [x16] + str x17, [sp, #0xac0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xac8] + ldr x16, [sp, #0x1320] + ldr x17, [x16] + str x17, [sp, #0xad0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xad8] + ldr x16, [sp, #0x1318] + ldr x17, [x16] + str x17, [sp, #0xae0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xae8] + ldr x16, [sp, #0x1310] + ldr x17, [x16] + str x17, [sp, #0xaf0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xaf8] + ldr x16, [sp, #0x1308] + ldr x17, [x16] + str x17, [sp, #0xb00] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb08] + ldr x16, [sp, #0x1300] + ldr x17, [x16] + str x17, [sp, #0xb10] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb18] + ldr x16, [sp, #0x12f8] + ldr x17, [x16] + str x17, [sp, #0xb20] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb28] + ldr x16, [sp, #0x12f0] + ldr x17, [x16] + str x17, [sp, #0xb30] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb38] + ldr x16, [sp, #0x12e8] + ldr x17, [x16] + str x17, [sp, #0xb40] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb48] + ldr x16, [sp, #0x12e0] + ldr x17, [x16] + str x17, [sp, #0xb50] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb58] + ldr x16, [sp, #0x12d8] + ldr x17, [x16] + str x17, [sp, #0xb60] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb68] + ldr x16, [sp, #0x12d0] + ldr x17, [x16] + str x17, [sp, #0xb70] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb78] + ldr x16, [sp, #0x12c8] + ldr x17, [x16] + str x17, [sp, #0xb80] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb88] + ldr x16, [sp, #0x12c0] + ldr x17, [x16] + str x17, [sp, #0xb90] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb98] + ldr x16, [sp, #0x12b8] + ldr x17, [x16] + str x17, [sp, #0xba0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xba8] + ldr x16, [sp, #0x12b0] + ldr x17, [x16] + str x17, [sp, #0xbb0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xbb8] + ldr x16, [sp, #0x12a8] + ldr x17, [x16] + str x17, [sp, #0xbc0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xbc8] + ldr x16, [sp, #0x12a0] + ldr x17, [x16] + str x17, [sp, #0xbd0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xbd8] + ldr x16, [sp, #0x1298] + ldr x17, [x16] + str x17, [sp, #0xbe0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xbe8] + ldr x16, [sp, #0x1290] + ldr x17, [x16] + str x17, [sp, #0xbf0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xbf8] + ldr x16, [sp, #0x1288] + ldr x17, [x16] + str x17, [sp, #0xc00] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc08] + ldr x16, [sp, #0x1280] + ldr x17, [x16] + str x17, [sp, #0xc10] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc18] + ldr x16, [sp, #0x1278] + ldr x17, [x16] + str x17, [sp, #0xc20] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc28] + ldr x16, [sp, #0x1270] + ldr x17, [x16] + str x17, [sp, #0xc30] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc38] + ldr x16, [sp, #0x1268] + ldr x17, [x16] + str x17, [sp, #0xc40] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc48] + ldr x16, [sp, #0x1260] + ldr x17, [x16] + str x17, [sp, #0xc50] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc58] + ldr x16, [sp, #0x1258] + ldr x17, [x16] + str x17, [sp, #0xc60] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc68] + ldr x16, [sp, #0x1250] + ldr x17, [x16] + str x17, [sp, #0xc70] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc78] + ldr x16, [sp, #0x1248] + ldr x17, [x16] + str x17, [sp, #0xc80] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc88] + ldr x16, [sp, #0x1240] + ldr x17, [x16] + str x17, [sp, #0xc90] + ldr x17, [x16, #0x8] + str x17, [sp, #0xc98] + ldr x16, [sp, #0x1238] + ldr x17, [x16] + str x17, [sp, #0xca0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xca8] + ldr x16, [sp, #0x1230] + ldr x17, [x16] + str x17, [sp, #0xcb0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xcb8] + ldr x16, [sp, #0x1228] + ldr x17, [x16] + str x17, [sp, #0xcc0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xcc8] + ldr x16, [sp, #0x1220] + ldr x17, [x16] + str x17, [sp, #0xcd0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xcd8] + ldr x16, [sp, #0x1218] + ldr x17, [x16] + str x17, [sp, #0xce0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xce8] + ldr x16, [sp, #0x1210] + ldr x17, [x16] + str x17, [sp, #0xcf0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xcf8] + ldr x16, [sp, #0x1208] + ldr x17, [x16] + str x17, [sp, #0xd00] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd08] + ldr x16, [sp, #0x1200] + ldr x17, [x16] + str x17, [sp, #0xd10] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd18] + ldr x16, [sp, #0x11f8] + ldr x17, [x16] + str x17, [sp, #0xd20] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd28] + ldr x16, [sp, #0x11f0] + ldr x17, [x16] + str x17, [sp, #0xd30] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd38] + ldr x16, [sp, #0x11e8] + ldr x17, [x16] + str x17, [sp, #0xd40] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd48] + ldr x16, [sp, #0x11e0] + ldr x17, [x16] + str x17, [sp, #0xd50] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd58] + ldr x16, [sp, #0x11d8] + ldr x17, [x16] + str x17, [sp, #0xd60] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd68] + ldr x16, [sp, #0x11d0] + ldr x17, [x16] + str x17, [sp, #0xd70] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd78] + ldr x16, [sp, #0x11c8] + ldr x17, [x16] + str x17, [sp, #0xd80] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd88] + ldr x16, [sp, #0x11c0] + ldr x17, [x16] + str x17, [sp, #0xd90] + ldr x17, [x16, #0x8] + str x17, [sp, #0xd98] + ldr x16, [sp, #0x11b8] + ldr x17, [x16] + str x17, [sp, #0xda0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xda8] + ldr x16, [sp, #0x11b0] + ldr x17, [x16] + str x17, [sp, #0xdb0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xdb8] + ldr x16, [sp, #0x11a8] + ldr x17, [x16] + str x17, [sp, #0xdc0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xdc8] + ldr x16, [sp, #0x11a0] + ldr x17, [x16] + str x17, [sp, #0xdd0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xdd8] + ldr x16, [sp, #0x1198] + ldr x17, [x16] + str x17, [sp, #0xde0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xde8] + ldr x16, [sp, #0x1190] + ldr x17, [x16] + str x17, [sp, #0xdf0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xdf8] + ldr x16, [sp, #0x1188] + ldr x17, [x16] + str x17, [sp, #0xe00] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe08] + ldr x16, [sp, #0x1180] + ldr x17, [x16] + str x17, [sp, #0xe10] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe18] + ldr x16, [sp, #0x1178] + ldr x17, [x16] + str x17, [sp, #0xe20] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe28] + ldr x16, [sp, #0x1170] + ldr x17, [x16] + str x17, [sp, #0xe30] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe38] + ldr x16, [sp, #0x1168] + ldr x17, [x16] + str x17, [sp, #0xe40] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe48] + ldr x16, [sp, #0x1160] + ldr x17, [x16] + str x17, [sp, #0xe50] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe58] + ldr x16, [sp, #0x1158] + ldr x17, [x16] + str x17, [sp, #0xe60] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe68] + ldr x16, [sp, #0x1150] + ldr x17, [x16] + str x17, [sp, #0xe70] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe78] + ldr x16, [sp, #0x1148] + ldr x17, [x16] + str x17, [sp, #0xe80] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe88] + ldr x16, [sp, #0x1140] + ldr x17, [x16] + str x17, [sp, #0xe90] + ldr x17, [x16, #0x8] + str x17, [sp, #0xe98] + ldr x16, [sp, #0x1138] + ldr x17, [x16] + str x17, [sp, #0xea0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xea8] + ldr x16, [sp, #0x1130] + ldr x17, [x16] + str x17, [sp, #0xeb0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xeb8] + ldr x16, [sp, #0x1128] + ldr x17, [x16] + str x17, [sp, #0xec0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xec8] + ldr x16, [sp, #0x1120] + ldr x17, [x16] + str x17, [sp, #0xed0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xed8] + ldr x16, [sp, #0x1118] + ldr x17, [x16] + str x17, [sp, #0xee0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xee8] + ldr x16, [sp, #0x1110] + ldr x17, [x16] + str x17, [sp, #0xef0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xef8] + ldr x16, [sp, #0x1108] + ldr x17, [x16] + str x17, [sp, #0xf00] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf08] + ldr x16, [sp, #0x1100] + ldr x17, [x16] + str x17, [sp, #0xf10] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf18] + ldr x16, [sp, #0x10f8] + ldr x17, [x16] + str x17, [sp, #0xf20] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf28] + ldr x16, [sp, #0x10f0] + ldr x17, [x16] + str x17, [sp, #0xf30] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf38] + ldr x16, [sp, #0x10e8] + ldr x17, [x16] + str x17, [sp, #0xf40] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf48] + ldr x16, [sp, #0x10e0] + ldr x17, [x16] + str x17, [sp, #0xf50] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf58] + ldr x16, [sp, #0x10d8] + ldr x17, [x16] + str x17, [sp, #0xf60] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf68] + ldr x16, [sp, #0x10d0] + ldr x17, [x16] + str x17, [sp, #0xf70] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf78] + ldr x16, [sp, #0x10c8] + ldr x17, [x16] + str x17, [sp, #0xf80] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf88] + ldr x16, [sp, #0x10c0] + ldr x17, [x16] + str x17, [sp, #0xf90] + ldr x17, [x16, #0x8] + str x17, [sp, #0xf98] + ldr x16, [sp, #0x10b8] + ldr x17, [x16] + str x17, [sp, #0xfa0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xfa8] + ldr x16, [sp, #0x10b0] + ldr x17, [x16] + str x17, [sp, #0xfb0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xfb8] + ldr x16, [sp, #0x10a8] + ldr x17, [x16] + str x17, [sp, #0xfc0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xfc8] + ldr x16, [sp, #0x10a0] + ldr x17, [x16] + str x17, [sp, #0xfd0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xfd8] + ldr x16, [sp, #0x1098] + ldr x17, [x16] + str x17, [sp, #0xfe0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xfe8] + ldr x16, [sp, #0x1090] + ldr x17, [x16] + str x17, [sp, #0xff0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xff8] + ldr x16, [sp, #0x1088] + ldr x17, [x16] + str x17, [sp, #0x1000] + ldr x17, [x16, #0x8] + str x17, [sp, #0x1008] + mov x4, x2 + mov x6, x3 + mov x2, x1 + ldr x1, [x0, #0x8] + ldr x0, [x0] + ldr x3, [x2, #0x8] + ldr x2, [x2] + ldr x5, [x4, #0x8] + ldr x4, [x4] + ldr x7, [x6, #0x8] + ldr x6, [x6] + ldr x9, [sp, #0x1010] + blr x9 + add sp, sp, #0x1, lsl #12 // =0x1000 + add sp, sp, #0x20 + mov x17, #0x8d9e // =36254 + movk x17, #0x1, lsl #16 + cmp x0, x17 + b.eq + mov x0, #0x3 // =3 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + ldr x23, [sp, #0x18] + ldr x24, [sp, #0x20] + ldr x25, [sp, #0x28] + ldr x26, [sp, #0x30] + ldr x27, [sp, #0x38] + ldr x28, [sp, #0x40] + ldr x19, [sp, #0x50] + add sp, sp, #0x1, lsl #12 // =0x1000 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + ldr x23, [sp, #0x18] + ldr x24, [sp, #0x20] + ldr x25, [sp, #0x28] + ldr x26, [sp, #0x30] + ldr x27, [sp, #0x38] + ldr x28, [sp, #0x40] + ldr x19, [sp, #0x50] + add sp, sp, #0x1, lsl #12 // =0x1000 + add sp, sp, #0x10 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/call_sp_adjust_imm12_overflow.x64.asm b/tests/snapshots/asm/call_sp_adjust_imm12_overflow.x64.asm new file mode 100644 index 000000000..1136e11f4 --- /dev/null +++ b/tests/snapshots/asm/call_sp_adjust_imm12_overflow.x64.asm @@ -0,0 +1,8393 @@ + +call_sp_adjust_imm12_overflow.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + popq %r10 + subq $0x1050, %rsp # imm = 0x1050 + pushq %r10 + pushq %rbp + movq %rsp, %rbp + subq $0x1060, %rsp # imm = 0x1060 + movq %rdi, -0x10(%rbp) + movq %rsi, -0x8(%rbp) + movq %rdx, -0x20(%rbp) + movq %rcx, -0x18(%rbp) + movq %r8, -0x30(%rbp) + movq %r9, -0x28(%rbp) + movq 0x1060(%rbp), %r10 + movq %r10, -0x40(%rbp) + movq 0x1068(%rbp), %r10 + movq %r10, -0x38(%rbp) + movq 0x1070(%rbp), %r10 + movq %r10, -0x50(%rbp) + movq 0x1078(%rbp), %r10 + movq %r10, -0x48(%rbp) + movq 0x1080(%rbp), %r10 + movq %r10, -0x60(%rbp) + movq 0x1088(%rbp), %r10 + movq %r10, -0x58(%rbp) + movq 0x1090(%rbp), %r10 + movq %r10, -0x70(%rbp) + movq 0x1098(%rbp), %r10 + movq %r10, -0x68(%rbp) + movq 0x10a0(%rbp), %r10 + movq %r10, -0x80(%rbp) + movq 0x10a8(%rbp), %r10 + movq %r10, -0x78(%rbp) + movq 0x10b0(%rbp), %r10 + movq %r10, -0x90(%rbp) + movq 0x10b8(%rbp), %r10 + movq %r10, -0x88(%rbp) + movq 0x10c0(%rbp), %r10 + movq %r10, -0xa0(%rbp) + movq 0x10c8(%rbp), %r10 + movq %r10, -0x98(%rbp) + movq 0x10d0(%rbp), %r10 + movq %r10, -0xb0(%rbp) + movq 0x10d8(%rbp), %r10 + movq %r10, -0xa8(%rbp) + movq 0x10e0(%rbp), %r10 + movq %r10, -0xc0(%rbp) + movq 0x10e8(%rbp), %r10 + movq %r10, -0xb8(%rbp) + movq 0x10f0(%rbp), %r10 + movq %r10, -0xd0(%rbp) + movq 0x10f8(%rbp), %r10 + movq %r10, -0xc8(%rbp) + movq 0x1100(%rbp), %r10 + movq %r10, -0xe0(%rbp) + movq 0x1108(%rbp), %r10 + movq %r10, -0xd8(%rbp) + movq 0x1110(%rbp), %r10 + movq %r10, -0xf0(%rbp) + movq 0x1118(%rbp), %r10 + movq %r10, -0xe8(%rbp) + movq 0x1120(%rbp), %r10 + movq %r10, -0x100(%rbp) + movq 0x1128(%rbp), %r10 + movq %r10, -0xf8(%rbp) + movq 0x1130(%rbp), %r10 + movq %r10, -0x110(%rbp) + movq 0x1138(%rbp), %r10 + movq %r10, -0x108(%rbp) + movq 0x1140(%rbp), %r10 + movq %r10, -0x120(%rbp) + movq 0x1148(%rbp), %r10 + movq %r10, -0x118(%rbp) + movq 0x1150(%rbp), %r10 + movq %r10, -0x130(%rbp) + movq 0x1158(%rbp), %r10 + movq %r10, -0x128(%rbp) + movq 0x1160(%rbp), %r10 + movq %r10, -0x140(%rbp) + movq 0x1168(%rbp), %r10 + movq %r10, -0x138(%rbp) + movq 0x1170(%rbp), %r10 + movq %r10, -0x150(%rbp) + movq 0x1178(%rbp), %r10 + movq %r10, -0x148(%rbp) + movq 0x1180(%rbp), %r10 + movq %r10, -0x160(%rbp) + movq 0x1188(%rbp), %r10 + movq %r10, -0x158(%rbp) + movq 0x1190(%rbp), %r10 + movq %r10, -0x170(%rbp) + movq 0x1198(%rbp), %r10 + movq %r10, -0x168(%rbp) + movq 0x11a0(%rbp), %r10 + movq %r10, -0x180(%rbp) + movq 0x11a8(%rbp), %r10 + movq %r10, -0x178(%rbp) + movq 0x11b0(%rbp), %r10 + movq %r10, -0x190(%rbp) + movq 0x11b8(%rbp), %r10 + movq %r10, -0x188(%rbp) + movq 0x11c0(%rbp), %r10 + movq %r10, -0x1a0(%rbp) + movq 0x11c8(%rbp), %r10 + movq %r10, -0x198(%rbp) + movq 0x11d0(%rbp), %r10 + movq %r10, -0x1b0(%rbp) + movq 0x11d8(%rbp), %r10 + movq %r10, -0x1a8(%rbp) + movq 0x11e0(%rbp), %r10 + movq %r10, -0x1c0(%rbp) + movq 0x11e8(%rbp), %r10 + movq %r10, -0x1b8(%rbp) + movq 0x11f0(%rbp), %r10 + movq %r10, -0x1d0(%rbp) + movq 0x11f8(%rbp), %r10 + movq %r10, -0x1c8(%rbp) + movq 0x1200(%rbp), %r10 + movq %r10, -0x1e0(%rbp) + movq 0x1208(%rbp), %r10 + movq %r10, -0x1d8(%rbp) + movq 0x1210(%rbp), %r10 + movq %r10, -0x1f0(%rbp) + movq 0x1218(%rbp), %r10 + movq %r10, -0x1e8(%rbp) + movq 0x1220(%rbp), %r10 + movq %r10, -0x200(%rbp) + movq 0x1228(%rbp), %r10 + movq %r10, -0x1f8(%rbp) + movq 0x1230(%rbp), %r10 + movq %r10, -0x210(%rbp) + movq 0x1238(%rbp), %r10 + movq %r10, -0x208(%rbp) + movq 0x1240(%rbp), %r10 + movq %r10, -0x220(%rbp) + movq 0x1248(%rbp), %r10 + movq %r10, -0x218(%rbp) + movq 0x1250(%rbp), %r10 + movq %r10, -0x230(%rbp) + movq 0x1258(%rbp), %r10 + movq %r10, -0x228(%rbp) + movq 0x1260(%rbp), %r10 + movq %r10, -0x240(%rbp) + movq 0x1268(%rbp), %r10 + movq %r10, -0x238(%rbp) + movq 0x1270(%rbp), %r10 + movq %r10, -0x250(%rbp) + movq 0x1278(%rbp), %r10 + movq %r10, -0x248(%rbp) + movq 0x1280(%rbp), %r10 + movq %r10, -0x260(%rbp) + movq 0x1288(%rbp), %r10 + movq %r10, -0x258(%rbp) + movq 0x1290(%rbp), %r10 + movq %r10, -0x270(%rbp) + movq 0x1298(%rbp), %r10 + movq %r10, -0x268(%rbp) + movq 0x12a0(%rbp), %r10 + movq %r10, -0x280(%rbp) + movq 0x12a8(%rbp), %r10 + movq %r10, -0x278(%rbp) + movq 0x12b0(%rbp), %r10 + movq %r10, -0x290(%rbp) + movq 0x12b8(%rbp), %r10 + movq %r10, -0x288(%rbp) + movq 0x12c0(%rbp), %r10 + movq %r10, -0x2a0(%rbp) + movq 0x12c8(%rbp), %r10 + movq %r10, -0x298(%rbp) + movq 0x12d0(%rbp), %r10 + movq %r10, -0x2b0(%rbp) + movq 0x12d8(%rbp), %r10 + movq %r10, -0x2a8(%rbp) + movq 0x12e0(%rbp), %r10 + movq %r10, -0x2c0(%rbp) + movq 0x12e8(%rbp), %r10 + movq %r10, -0x2b8(%rbp) + movq 0x12f0(%rbp), %r10 + movq %r10, -0x2d0(%rbp) + movq 0x12f8(%rbp), %r10 + movq %r10, -0x2c8(%rbp) + movq 0x1300(%rbp), %r10 + movq %r10, -0x2e0(%rbp) + movq 0x1308(%rbp), %r10 + movq %r10, -0x2d8(%rbp) + movq 0x1310(%rbp), %r10 + movq %r10, -0x2f0(%rbp) + movq 0x1318(%rbp), %r10 + movq %r10, -0x2e8(%rbp) + movq 0x1320(%rbp), %r10 + movq %r10, -0x300(%rbp) + movq 0x1328(%rbp), %r10 + movq %r10, -0x2f8(%rbp) + movq 0x1330(%rbp), %r10 + movq %r10, -0x310(%rbp) + movq 0x1338(%rbp), %r10 + movq %r10, -0x308(%rbp) + movq 0x1340(%rbp), %r10 + movq %r10, -0x320(%rbp) + movq 0x1348(%rbp), %r10 + movq %r10, -0x318(%rbp) + movq 0x1350(%rbp), %r10 + movq %r10, -0x330(%rbp) + movq 0x1358(%rbp), %r10 + movq %r10, -0x328(%rbp) + movq 0x1360(%rbp), %r10 + movq %r10, -0x340(%rbp) + movq 0x1368(%rbp), %r10 + movq %r10, -0x338(%rbp) + movq 0x1370(%rbp), %r10 + movq %r10, -0x350(%rbp) + movq 0x1378(%rbp), %r10 + movq %r10, -0x348(%rbp) + movq 0x1380(%rbp), %r10 + movq %r10, -0x360(%rbp) + movq 0x1388(%rbp), %r10 + movq %r10, -0x358(%rbp) + movq 0x1390(%rbp), %r10 + movq %r10, -0x370(%rbp) + movq 0x1398(%rbp), %r10 + movq %r10, -0x368(%rbp) + movq 0x13a0(%rbp), %r10 + movq %r10, -0x380(%rbp) + movq 0x13a8(%rbp), %r10 + movq %r10, -0x378(%rbp) + movq 0x13b0(%rbp), %r10 + movq %r10, -0x390(%rbp) + movq 0x13b8(%rbp), %r10 + movq %r10, -0x388(%rbp) + movq 0x13c0(%rbp), %r10 + movq %r10, -0x3a0(%rbp) + movq 0x13c8(%rbp), %r10 + movq %r10, -0x398(%rbp) + movq 0x13d0(%rbp), %r10 + movq %r10, -0x3b0(%rbp) + movq 0x13d8(%rbp), %r10 + movq %r10, -0x3a8(%rbp) + movq 0x13e0(%rbp), %r10 + movq %r10, -0x3c0(%rbp) + movq 0x13e8(%rbp), %r10 + movq %r10, -0x3b8(%rbp) + movq 0x13f0(%rbp), %r10 + movq %r10, -0x3d0(%rbp) + movq 0x13f8(%rbp), %r10 + movq %r10, -0x3c8(%rbp) + movq 0x1400(%rbp), %r10 + movq %r10, -0x3e0(%rbp) + movq 0x1408(%rbp), %r10 + movq %r10, -0x3d8(%rbp) + movq 0x1410(%rbp), %r10 + movq %r10, -0x3f0(%rbp) + movq 0x1418(%rbp), %r10 + movq %r10, -0x3e8(%rbp) + movq 0x1420(%rbp), %r10 + movq %r10, -0x400(%rbp) + movq 0x1428(%rbp), %r10 + movq %r10, -0x3f8(%rbp) + movq 0x1430(%rbp), %r10 + movq %r10, -0x410(%rbp) + movq 0x1438(%rbp), %r10 + movq %r10, -0x408(%rbp) + movq 0x1440(%rbp), %r10 + movq %r10, -0x420(%rbp) + movq 0x1448(%rbp), %r10 + movq %r10, -0x418(%rbp) + movq 0x1450(%rbp), %r10 + movq %r10, -0x430(%rbp) + movq 0x1458(%rbp), %r10 + movq %r10, -0x428(%rbp) + movq 0x1460(%rbp), %r10 + movq %r10, -0x440(%rbp) + movq 0x1468(%rbp), %r10 + movq %r10, -0x438(%rbp) + movq 0x1470(%rbp), %r10 + movq %r10, -0x450(%rbp) + movq 0x1478(%rbp), %r10 + movq %r10, -0x448(%rbp) + movq 0x1480(%rbp), %r10 + movq %r10, -0x460(%rbp) + movq 0x1488(%rbp), %r10 + movq %r10, -0x458(%rbp) + movq 0x1490(%rbp), %r10 + movq %r10, -0x470(%rbp) + movq 0x1498(%rbp), %r10 + movq %r10, -0x468(%rbp) + movq 0x14a0(%rbp), %r10 + movq %r10, -0x480(%rbp) + movq 0x14a8(%rbp), %r10 + movq %r10, -0x478(%rbp) + movq 0x14b0(%rbp), %r10 + movq %r10, -0x490(%rbp) + movq 0x14b8(%rbp), %r10 + movq %r10, -0x488(%rbp) + movq 0x14c0(%rbp), %r10 + movq %r10, -0x4a0(%rbp) + movq 0x14c8(%rbp), %r10 + movq %r10, -0x498(%rbp) + movq 0x14d0(%rbp), %r10 + movq %r10, -0x4b0(%rbp) + movq 0x14d8(%rbp), %r10 + movq %r10, -0x4a8(%rbp) + movq 0x14e0(%rbp), %r10 + movq %r10, -0x4c0(%rbp) + movq 0x14e8(%rbp), %r10 + movq %r10, -0x4b8(%rbp) + movq 0x14f0(%rbp), %r10 + movq %r10, -0x4d0(%rbp) + movq 0x14f8(%rbp), %r10 + movq %r10, -0x4c8(%rbp) + movq 0x1500(%rbp), %r10 + movq %r10, -0x4e0(%rbp) + movq 0x1508(%rbp), %r10 + movq %r10, -0x4d8(%rbp) + movq 0x1510(%rbp), %r10 + movq %r10, -0x4f0(%rbp) + movq 0x1518(%rbp), %r10 + movq %r10, -0x4e8(%rbp) + movq 0x1520(%rbp), %r10 + movq %r10, -0x500(%rbp) + movq 0x1528(%rbp), %r10 + movq %r10, -0x4f8(%rbp) + movq 0x1530(%rbp), %r10 + movq %r10, -0x510(%rbp) + movq 0x1538(%rbp), %r10 + movq %r10, -0x508(%rbp) + movq 0x1540(%rbp), %r10 + movq %r10, -0x520(%rbp) + movq 0x1548(%rbp), %r10 + movq %r10, -0x518(%rbp) + movq 0x1550(%rbp), %r10 + movq %r10, -0x530(%rbp) + movq 0x1558(%rbp), %r10 + movq %r10, -0x528(%rbp) + movq 0x1560(%rbp), %r10 + movq %r10, -0x540(%rbp) + movq 0x1568(%rbp), %r10 + movq %r10, -0x538(%rbp) + movq 0x1570(%rbp), %r10 + movq %r10, -0x550(%rbp) + movq 0x1578(%rbp), %r10 + movq %r10, -0x548(%rbp) + movq 0x1580(%rbp), %r10 + movq %r10, -0x560(%rbp) + movq 0x1588(%rbp), %r10 + movq %r10, -0x558(%rbp) + movq 0x1590(%rbp), %r10 + movq %r10, -0x570(%rbp) + movq 0x1598(%rbp), %r10 + movq %r10, -0x568(%rbp) + movq 0x15a0(%rbp), %r10 + movq %r10, -0x580(%rbp) + movq 0x15a8(%rbp), %r10 + movq %r10, -0x578(%rbp) + movq 0x15b0(%rbp), %r10 + movq %r10, -0x590(%rbp) + movq 0x15b8(%rbp), %r10 + movq %r10, -0x588(%rbp) + movq 0x15c0(%rbp), %r10 + movq %r10, -0x5a0(%rbp) + movq 0x15c8(%rbp), %r10 + movq %r10, -0x598(%rbp) + movq 0x15d0(%rbp), %r10 + movq %r10, -0x5b0(%rbp) + movq 0x15d8(%rbp), %r10 + movq %r10, -0x5a8(%rbp) + movq 0x15e0(%rbp), %r10 + movq %r10, -0x5c0(%rbp) + movq 0x15e8(%rbp), %r10 + movq %r10, -0x5b8(%rbp) + movq 0x15f0(%rbp), %r10 + movq %r10, -0x5d0(%rbp) + movq 0x15f8(%rbp), %r10 + movq %r10, -0x5c8(%rbp) + movq 0x1600(%rbp), %r10 + movq %r10, -0x5e0(%rbp) + movq 0x1608(%rbp), %r10 + movq %r10, -0x5d8(%rbp) + movq 0x1610(%rbp), %r10 + movq %r10, -0x5f0(%rbp) + movq 0x1618(%rbp), %r10 + movq %r10, -0x5e8(%rbp) + movq 0x1620(%rbp), %r10 + movq %r10, -0x600(%rbp) + movq 0x1628(%rbp), %r10 + movq %r10, -0x5f8(%rbp) + movq 0x1630(%rbp), %r10 + movq %r10, -0x610(%rbp) + movq 0x1638(%rbp), %r10 + movq %r10, -0x608(%rbp) + movq 0x1640(%rbp), %r10 + movq %r10, -0x620(%rbp) + movq 0x1648(%rbp), %r10 + movq %r10, -0x618(%rbp) + movq 0x1650(%rbp), %r10 + movq %r10, -0x630(%rbp) + movq 0x1658(%rbp), %r10 + movq %r10, -0x628(%rbp) + movq 0x1660(%rbp), %r10 + movq %r10, -0x640(%rbp) + movq 0x1668(%rbp), %r10 + movq %r10, -0x638(%rbp) + movq 0x1670(%rbp), %r10 + movq %r10, -0x650(%rbp) + movq 0x1678(%rbp), %r10 + movq %r10, -0x648(%rbp) + movq 0x1680(%rbp), %r10 + movq %r10, -0x660(%rbp) + movq 0x1688(%rbp), %r10 + movq %r10, -0x658(%rbp) + movq 0x1690(%rbp), %r10 + movq %r10, -0x670(%rbp) + movq 0x1698(%rbp), %r10 + movq %r10, -0x668(%rbp) + movq 0x16a0(%rbp), %r10 + movq %r10, -0x680(%rbp) + movq 0x16a8(%rbp), %r10 + movq %r10, -0x678(%rbp) + movq 0x16b0(%rbp), %r10 + movq %r10, -0x690(%rbp) + movq 0x16b8(%rbp), %r10 + movq %r10, -0x688(%rbp) + movq 0x16c0(%rbp), %r10 + movq %r10, -0x6a0(%rbp) + movq 0x16c8(%rbp), %r10 + movq %r10, -0x698(%rbp) + movq 0x16d0(%rbp), %r10 + movq %r10, -0x6b0(%rbp) + movq 0x16d8(%rbp), %r10 + movq %r10, -0x6a8(%rbp) + movq 0x16e0(%rbp), %r10 + movq %r10, -0x6c0(%rbp) + movq 0x16e8(%rbp), %r10 + movq %r10, -0x6b8(%rbp) + movq 0x16f0(%rbp), %r10 + movq %r10, -0x6d0(%rbp) + movq 0x16f8(%rbp), %r10 + movq %r10, -0x6c8(%rbp) + movq 0x1700(%rbp), %r10 + movq %r10, -0x6e0(%rbp) + movq 0x1708(%rbp), %r10 + movq %r10, -0x6d8(%rbp) + movq 0x1710(%rbp), %r10 + movq %r10, -0x6f0(%rbp) + movq 0x1718(%rbp), %r10 + movq %r10, -0x6e8(%rbp) + movq 0x1720(%rbp), %r10 + movq %r10, -0x700(%rbp) + movq 0x1728(%rbp), %r10 + movq %r10, -0x6f8(%rbp) + movq 0x1730(%rbp), %r10 + movq %r10, -0x710(%rbp) + movq 0x1738(%rbp), %r10 + movq %r10, -0x708(%rbp) + movq 0x1740(%rbp), %r10 + movq %r10, -0x720(%rbp) + movq 0x1748(%rbp), %r10 + movq %r10, -0x718(%rbp) + movq 0x1750(%rbp), %r10 + movq %r10, -0x730(%rbp) + movq 0x1758(%rbp), %r10 + movq %r10, -0x728(%rbp) + movq 0x1760(%rbp), %r10 + movq %r10, -0x740(%rbp) + movq 0x1768(%rbp), %r10 + movq %r10, -0x738(%rbp) + movq 0x1770(%rbp), %r10 + movq %r10, -0x750(%rbp) + movq 0x1778(%rbp), %r10 + movq %r10, -0x748(%rbp) + movq 0x1780(%rbp), %r10 + movq %r10, -0x760(%rbp) + movq 0x1788(%rbp), %r10 + movq %r10, -0x758(%rbp) + movq 0x1790(%rbp), %r10 + movq %r10, -0x770(%rbp) + movq 0x1798(%rbp), %r10 + movq %r10, -0x768(%rbp) + movq 0x17a0(%rbp), %r10 + movq %r10, -0x780(%rbp) + movq 0x17a8(%rbp), %r10 + movq %r10, -0x778(%rbp) + movq 0x17b0(%rbp), %r10 + movq %r10, -0x790(%rbp) + movq 0x17b8(%rbp), %r10 + movq %r10, -0x788(%rbp) + movq 0x17c0(%rbp), %r10 + movq %r10, -0x7a0(%rbp) + movq 0x17c8(%rbp), %r10 + movq %r10, -0x798(%rbp) + movq 0x17d0(%rbp), %r10 + movq %r10, -0x7b0(%rbp) + movq 0x17d8(%rbp), %r10 + movq %r10, -0x7a8(%rbp) + movq 0x17e0(%rbp), %r10 + movq %r10, -0x7c0(%rbp) + movq 0x17e8(%rbp), %r10 + movq %r10, -0x7b8(%rbp) + movq 0x17f0(%rbp), %r10 + movq %r10, -0x7d0(%rbp) + movq 0x17f8(%rbp), %r10 + movq %r10, -0x7c8(%rbp) + movq 0x1800(%rbp), %r10 + movq %r10, -0x7e0(%rbp) + movq 0x1808(%rbp), %r10 + movq %r10, -0x7d8(%rbp) + movq 0x1810(%rbp), %r10 + movq %r10, -0x7f0(%rbp) + movq 0x1818(%rbp), %r10 + movq %r10, -0x7e8(%rbp) + movq 0x1820(%rbp), %r10 + movq %r10, -0x800(%rbp) + movq 0x1828(%rbp), %r10 + movq %r10, -0x7f8(%rbp) + movq 0x1830(%rbp), %r10 + movq %r10, -0x810(%rbp) + movq 0x1838(%rbp), %r10 + movq %r10, -0x808(%rbp) + movq 0x1840(%rbp), %r10 + movq %r10, -0x820(%rbp) + movq 0x1848(%rbp), %r10 + movq %r10, -0x818(%rbp) + movq 0x1850(%rbp), %r10 + movq %r10, -0x830(%rbp) + movq 0x1858(%rbp), %r10 + movq %r10, -0x828(%rbp) + movq 0x1860(%rbp), %r10 + movq %r10, -0x840(%rbp) + movq 0x1868(%rbp), %r10 + movq %r10, -0x838(%rbp) + movq 0x1870(%rbp), %r10 + movq %r10, -0x850(%rbp) + movq 0x1878(%rbp), %r10 + movq %r10, -0x848(%rbp) + movq 0x1880(%rbp), %r10 + movq %r10, -0x860(%rbp) + movq 0x1888(%rbp), %r10 + movq %r10, -0x858(%rbp) + movq 0x1890(%rbp), %r10 + movq %r10, -0x870(%rbp) + movq 0x1898(%rbp), %r10 + movq %r10, -0x868(%rbp) + movq 0x18a0(%rbp), %r10 + movq %r10, -0x880(%rbp) + movq 0x18a8(%rbp), %r10 + movq %r10, -0x878(%rbp) + movq 0x18b0(%rbp), %r10 + movq %r10, -0x890(%rbp) + movq 0x18b8(%rbp), %r10 + movq %r10, -0x888(%rbp) + movq 0x18c0(%rbp), %r10 + movq %r10, -0x8a0(%rbp) + movq 0x18c8(%rbp), %r10 + movq %r10, -0x898(%rbp) + movq 0x18d0(%rbp), %r10 + movq %r10, -0x8b0(%rbp) + movq 0x18d8(%rbp), %r10 + movq %r10, -0x8a8(%rbp) + movq 0x18e0(%rbp), %r10 + movq %r10, -0x8c0(%rbp) + movq 0x18e8(%rbp), %r10 + movq %r10, -0x8b8(%rbp) + movq 0x18f0(%rbp), %r10 + movq %r10, -0x8d0(%rbp) + movq 0x18f8(%rbp), %r10 + movq %r10, -0x8c8(%rbp) + movq 0x1900(%rbp), %r10 + movq %r10, -0x8e0(%rbp) + movq 0x1908(%rbp), %r10 + movq %r10, -0x8d8(%rbp) + movq 0x1910(%rbp), %r10 + movq %r10, -0x8f0(%rbp) + movq 0x1918(%rbp), %r10 + movq %r10, -0x8e8(%rbp) + movq 0x1920(%rbp), %r10 + movq %r10, -0x900(%rbp) + movq 0x1928(%rbp), %r10 + movq %r10, -0x8f8(%rbp) + movq 0x1930(%rbp), %r10 + movq %r10, -0x910(%rbp) + movq 0x1938(%rbp), %r10 + movq %r10, -0x908(%rbp) + movq 0x1940(%rbp), %r10 + movq %r10, -0x920(%rbp) + movq 0x1948(%rbp), %r10 + movq %r10, -0x918(%rbp) + movq 0x1950(%rbp), %r10 + movq %r10, -0x930(%rbp) + movq 0x1958(%rbp), %r10 + movq %r10, -0x928(%rbp) + movq 0x1960(%rbp), %r10 + movq %r10, -0x940(%rbp) + movq 0x1968(%rbp), %r10 + movq %r10, -0x938(%rbp) + movq 0x1970(%rbp), %r10 + movq %r10, -0x950(%rbp) + movq 0x1978(%rbp), %r10 + movq %r10, -0x948(%rbp) + movq 0x1980(%rbp), %r10 + movq %r10, -0x960(%rbp) + movq 0x1988(%rbp), %r10 + movq %r10, -0x958(%rbp) + movq 0x1990(%rbp), %r10 + movq %r10, -0x970(%rbp) + movq 0x1998(%rbp), %r10 + movq %r10, -0x968(%rbp) + movq 0x19a0(%rbp), %r10 + movq %r10, -0x980(%rbp) + movq 0x19a8(%rbp), %r10 + movq %r10, -0x978(%rbp) + movq 0x19b0(%rbp), %r10 + movq %r10, -0x990(%rbp) + movq 0x19b8(%rbp), %r10 + movq %r10, -0x988(%rbp) + movq 0x19c0(%rbp), %r10 + movq %r10, -0x9a0(%rbp) + movq 0x19c8(%rbp), %r10 + movq %r10, -0x998(%rbp) + movq 0x19d0(%rbp), %r10 + movq %r10, -0x9b0(%rbp) + movq 0x19d8(%rbp), %r10 + movq %r10, -0x9a8(%rbp) + movq 0x19e0(%rbp), %r10 + movq %r10, -0x9c0(%rbp) + movq 0x19e8(%rbp), %r10 + movq %r10, -0x9b8(%rbp) + movq 0x19f0(%rbp), %r10 + movq %r10, -0x9d0(%rbp) + movq 0x19f8(%rbp), %r10 + movq %r10, -0x9c8(%rbp) + movq 0x1a00(%rbp), %r10 + movq %r10, -0x9e0(%rbp) + movq 0x1a08(%rbp), %r10 + movq %r10, -0x9d8(%rbp) + movq 0x1a10(%rbp), %r10 + movq %r10, -0x9f0(%rbp) + movq 0x1a18(%rbp), %r10 + movq %r10, -0x9e8(%rbp) + movq 0x1a20(%rbp), %r10 + movq %r10, -0xa00(%rbp) + movq 0x1a28(%rbp), %r10 + movq %r10, -0x9f8(%rbp) + movq 0x1a30(%rbp), %r10 + movq %r10, -0xa10(%rbp) + movq 0x1a38(%rbp), %r10 + movq %r10, -0xa08(%rbp) + movq 0x1a40(%rbp), %r10 + movq %r10, -0xa20(%rbp) + movq 0x1a48(%rbp), %r10 + movq %r10, -0xa18(%rbp) + movq 0x1a50(%rbp), %r10 + movq %r10, -0xa30(%rbp) + movq 0x1a58(%rbp), %r10 + movq %r10, -0xa28(%rbp) + movq 0x1a60(%rbp), %r10 + movq %r10, -0xa40(%rbp) + movq 0x1a68(%rbp), %r10 + movq %r10, -0xa38(%rbp) + movq 0x1a70(%rbp), %r10 + movq %r10, -0xa50(%rbp) + movq 0x1a78(%rbp), %r10 + movq %r10, -0xa48(%rbp) + movq 0x1a80(%rbp), %r10 + movq %r10, -0xa60(%rbp) + movq 0x1a88(%rbp), %r10 + movq %r10, -0xa58(%rbp) + movq 0x1a90(%rbp), %r10 + movq %r10, -0xa70(%rbp) + movq 0x1a98(%rbp), %r10 + movq %r10, -0xa68(%rbp) + movq 0x1aa0(%rbp), %r10 + movq %r10, -0xa80(%rbp) + movq 0x1aa8(%rbp), %r10 + movq %r10, -0xa78(%rbp) + movq 0x1ab0(%rbp), %r10 + movq %r10, -0xa90(%rbp) + movq 0x1ab8(%rbp), %r10 + movq %r10, -0xa88(%rbp) + movq 0x1ac0(%rbp), %r10 + movq %r10, -0xaa0(%rbp) + movq 0x1ac8(%rbp), %r10 + movq %r10, -0xa98(%rbp) + movq 0x1ad0(%rbp), %r10 + movq %r10, -0xab0(%rbp) + movq 0x1ad8(%rbp), %r10 + movq %r10, -0xaa8(%rbp) + movq 0x1ae0(%rbp), %r10 + movq %r10, -0xac0(%rbp) + movq 0x1ae8(%rbp), %r10 + movq %r10, -0xab8(%rbp) + movq 0x1af0(%rbp), %r10 + movq %r10, -0xad0(%rbp) + movq 0x1af8(%rbp), %r10 + movq %r10, -0xac8(%rbp) + movq 0x1b00(%rbp), %r10 + movq %r10, -0xae0(%rbp) + movq 0x1b08(%rbp), %r10 + movq %r10, -0xad8(%rbp) + movq 0x1b10(%rbp), %r10 + movq %r10, -0xaf0(%rbp) + movq 0x1b18(%rbp), %r10 + movq %r10, -0xae8(%rbp) + movq 0x1b20(%rbp), %r10 + movq %r10, -0xb00(%rbp) + movq 0x1b28(%rbp), %r10 + movq %r10, -0xaf8(%rbp) + movq 0x1b30(%rbp), %r10 + movq %r10, -0xb10(%rbp) + movq 0x1b38(%rbp), %r10 + movq %r10, -0xb08(%rbp) + movq 0x1b40(%rbp), %r10 + movq %r10, -0xb20(%rbp) + movq 0x1b48(%rbp), %r10 + movq %r10, -0xb18(%rbp) + movq 0x1b50(%rbp), %r10 + movq %r10, -0xb30(%rbp) + movq 0x1b58(%rbp), %r10 + movq %r10, -0xb28(%rbp) + movq 0x1b60(%rbp), %r10 + movq %r10, -0xb40(%rbp) + movq 0x1b68(%rbp), %r10 + movq %r10, -0xb38(%rbp) + movq 0x1b70(%rbp), %r10 + movq %r10, -0xb50(%rbp) + movq 0x1b78(%rbp), %r10 + movq %r10, -0xb48(%rbp) + movq 0x1b80(%rbp), %r10 + movq %r10, -0xb60(%rbp) + movq 0x1b88(%rbp), %r10 + movq %r10, -0xb58(%rbp) + movq 0x1b90(%rbp), %r10 + movq %r10, -0xb70(%rbp) + movq 0x1b98(%rbp), %r10 + movq %r10, -0xb68(%rbp) + movq 0x1ba0(%rbp), %r10 + movq %r10, -0xb80(%rbp) + movq 0x1ba8(%rbp), %r10 + movq %r10, -0xb78(%rbp) + movq 0x1bb0(%rbp), %r10 + movq %r10, -0xb90(%rbp) + movq 0x1bb8(%rbp), %r10 + movq %r10, -0xb88(%rbp) + movq 0x1bc0(%rbp), %r10 + movq %r10, -0xba0(%rbp) + movq 0x1bc8(%rbp), %r10 + movq %r10, -0xb98(%rbp) + movq 0x1bd0(%rbp), %r10 + movq %r10, -0xbb0(%rbp) + movq 0x1bd8(%rbp), %r10 + movq %r10, -0xba8(%rbp) + movq 0x1be0(%rbp), %r10 + movq %r10, -0xbc0(%rbp) + movq 0x1be8(%rbp), %r10 + movq %r10, -0xbb8(%rbp) + movq 0x1bf0(%rbp), %r10 + movq %r10, -0xbd0(%rbp) + movq 0x1bf8(%rbp), %r10 + movq %r10, -0xbc8(%rbp) + movq 0x1c00(%rbp), %r10 + movq %r10, -0xbe0(%rbp) + movq 0x1c08(%rbp), %r10 + movq %r10, -0xbd8(%rbp) + movq 0x1c10(%rbp), %r10 + movq %r10, -0xbf0(%rbp) + movq 0x1c18(%rbp), %r10 + movq %r10, -0xbe8(%rbp) + movq 0x1c20(%rbp), %r10 + movq %r10, -0xc00(%rbp) + movq 0x1c28(%rbp), %r10 + movq %r10, -0xbf8(%rbp) + movq 0x1c30(%rbp), %r10 + movq %r10, -0xc10(%rbp) + movq 0x1c38(%rbp), %r10 + movq %r10, -0xc08(%rbp) + movq 0x1c40(%rbp), %r10 + movq %r10, -0xc20(%rbp) + movq 0x1c48(%rbp), %r10 + movq %r10, -0xc18(%rbp) + movq 0x1c50(%rbp), %r10 + movq %r10, -0xc30(%rbp) + movq 0x1c58(%rbp), %r10 + movq %r10, -0xc28(%rbp) + movq 0x1c60(%rbp), %r10 + movq %r10, -0xc40(%rbp) + movq 0x1c68(%rbp), %r10 + movq %r10, -0xc38(%rbp) + movq 0x1c70(%rbp), %r10 + movq %r10, -0xc50(%rbp) + movq 0x1c78(%rbp), %r10 + movq %r10, -0xc48(%rbp) + movq 0x1c80(%rbp), %r10 + movq %r10, -0xc60(%rbp) + movq 0x1c88(%rbp), %r10 + movq %r10, -0xc58(%rbp) + movq 0x1c90(%rbp), %r10 + movq %r10, -0xc70(%rbp) + movq 0x1c98(%rbp), %r10 + movq %r10, -0xc68(%rbp) + movq 0x1ca0(%rbp), %r10 + movq %r10, -0xc80(%rbp) + movq 0x1ca8(%rbp), %r10 + movq %r10, -0xc78(%rbp) + movq 0x1cb0(%rbp), %r10 + movq %r10, -0xc90(%rbp) + movq 0x1cb8(%rbp), %r10 + movq %r10, -0xc88(%rbp) + movq 0x1cc0(%rbp), %r10 + movq %r10, -0xca0(%rbp) + movq 0x1cc8(%rbp), %r10 + movq %r10, -0xc98(%rbp) + movq 0x1cd0(%rbp), %r10 + movq %r10, -0xcb0(%rbp) + movq 0x1cd8(%rbp), %r10 + movq %r10, -0xca8(%rbp) + movq 0x1ce0(%rbp), %r10 + movq %r10, -0xcc0(%rbp) + movq 0x1ce8(%rbp), %r10 + movq %r10, -0xcb8(%rbp) + movq 0x1cf0(%rbp), %r10 + movq %r10, -0xcd0(%rbp) + movq 0x1cf8(%rbp), %r10 + movq %r10, -0xcc8(%rbp) + movq 0x1d00(%rbp), %r10 + movq %r10, -0xce0(%rbp) + movq 0x1d08(%rbp), %r10 + movq %r10, -0xcd8(%rbp) + movq 0x1d10(%rbp), %r10 + movq %r10, -0xcf0(%rbp) + movq 0x1d18(%rbp), %r10 + movq %r10, -0xce8(%rbp) + movq 0x1d20(%rbp), %r10 + movq %r10, -0xd00(%rbp) + movq 0x1d28(%rbp), %r10 + movq %r10, -0xcf8(%rbp) + movq 0x1d30(%rbp), %r10 + movq %r10, -0xd10(%rbp) + movq 0x1d38(%rbp), %r10 + movq %r10, -0xd08(%rbp) + movq 0x1d40(%rbp), %r10 + movq %r10, -0xd20(%rbp) + movq 0x1d48(%rbp), %r10 + movq %r10, -0xd18(%rbp) + movq 0x1d50(%rbp), %r10 + movq %r10, -0xd30(%rbp) + movq 0x1d58(%rbp), %r10 + movq %r10, -0xd28(%rbp) + movq 0x1d60(%rbp), %r10 + movq %r10, -0xd40(%rbp) + movq 0x1d68(%rbp), %r10 + movq %r10, -0xd38(%rbp) + movq 0x1d70(%rbp), %r10 + movq %r10, -0xd50(%rbp) + movq 0x1d78(%rbp), %r10 + movq %r10, -0xd48(%rbp) + movq 0x1d80(%rbp), %r10 + movq %r10, -0xd60(%rbp) + movq 0x1d88(%rbp), %r10 + movq %r10, -0xd58(%rbp) + movq 0x1d90(%rbp), %r10 + movq %r10, -0xd70(%rbp) + movq 0x1d98(%rbp), %r10 + movq %r10, -0xd68(%rbp) + movq 0x1da0(%rbp), %r10 + movq %r10, -0xd80(%rbp) + movq 0x1da8(%rbp), %r10 + movq %r10, -0xd78(%rbp) + movq 0x1db0(%rbp), %r10 + movq %r10, -0xd90(%rbp) + movq 0x1db8(%rbp), %r10 + movq %r10, -0xd88(%rbp) + movq 0x1dc0(%rbp), %r10 + movq %r10, -0xda0(%rbp) + movq 0x1dc8(%rbp), %r10 + movq %r10, -0xd98(%rbp) + movq 0x1dd0(%rbp), %r10 + movq %r10, -0xdb0(%rbp) + movq 0x1dd8(%rbp), %r10 + movq %r10, -0xda8(%rbp) + movq 0x1de0(%rbp), %r10 + movq %r10, -0xdc0(%rbp) + movq 0x1de8(%rbp), %r10 + movq %r10, -0xdb8(%rbp) + movq 0x1df0(%rbp), %r10 + movq %r10, -0xdd0(%rbp) + movq 0x1df8(%rbp), %r10 + movq %r10, -0xdc8(%rbp) + movq 0x1e00(%rbp), %r10 + movq %r10, -0xde0(%rbp) + movq 0x1e08(%rbp), %r10 + movq %r10, -0xdd8(%rbp) + movq 0x1e10(%rbp), %r10 + movq %r10, -0xdf0(%rbp) + movq 0x1e18(%rbp), %r10 + movq %r10, -0xde8(%rbp) + movq 0x1e20(%rbp), %r10 + movq %r10, -0xe00(%rbp) + movq 0x1e28(%rbp), %r10 + movq %r10, -0xdf8(%rbp) + movq 0x1e30(%rbp), %r10 + movq %r10, -0xe10(%rbp) + movq 0x1e38(%rbp), %r10 + movq %r10, -0xe08(%rbp) + movq 0x1e40(%rbp), %r10 + movq %r10, -0xe20(%rbp) + movq 0x1e48(%rbp), %r10 + movq %r10, -0xe18(%rbp) + movq 0x1e50(%rbp), %r10 + movq %r10, -0xe30(%rbp) + movq 0x1e58(%rbp), %r10 + movq %r10, -0xe28(%rbp) + movq 0x1e60(%rbp), %r10 + movq %r10, -0xe40(%rbp) + movq 0x1e68(%rbp), %r10 + movq %r10, -0xe38(%rbp) + movq 0x1e70(%rbp), %r10 + movq %r10, -0xe50(%rbp) + movq 0x1e78(%rbp), %r10 + movq %r10, -0xe48(%rbp) + movq 0x1e80(%rbp), %r10 + movq %r10, -0xe60(%rbp) + movq 0x1e88(%rbp), %r10 + movq %r10, -0xe58(%rbp) + movq 0x1e90(%rbp), %r10 + movq %r10, -0xe70(%rbp) + movq 0x1e98(%rbp), %r10 + movq %r10, -0xe68(%rbp) + movq 0x1ea0(%rbp), %r10 + movq %r10, -0xe80(%rbp) + movq 0x1ea8(%rbp), %r10 + movq %r10, -0xe78(%rbp) + movq 0x1eb0(%rbp), %r10 + movq %r10, -0xe90(%rbp) + movq 0x1eb8(%rbp), %r10 + movq %r10, -0xe88(%rbp) + movq 0x1ec0(%rbp), %r10 + movq %r10, -0xea0(%rbp) + movq 0x1ec8(%rbp), %r10 + movq %r10, -0xe98(%rbp) + movq 0x1ed0(%rbp), %r10 + movq %r10, -0xeb0(%rbp) + movq 0x1ed8(%rbp), %r10 + movq %r10, -0xea8(%rbp) + movq 0x1ee0(%rbp), %r10 + movq %r10, -0xec0(%rbp) + movq 0x1ee8(%rbp), %r10 + movq %r10, -0xeb8(%rbp) + movq 0x1ef0(%rbp), %r10 + movq %r10, -0xed0(%rbp) + movq 0x1ef8(%rbp), %r10 + movq %r10, -0xec8(%rbp) + movq 0x1f00(%rbp), %r10 + movq %r10, -0xee0(%rbp) + movq 0x1f08(%rbp), %r10 + movq %r10, -0xed8(%rbp) + movq 0x1f10(%rbp), %r10 + movq %r10, -0xef0(%rbp) + movq 0x1f18(%rbp), %r10 + movq %r10, -0xee8(%rbp) + movq 0x1f20(%rbp), %r10 + movq %r10, -0xf00(%rbp) + movq 0x1f28(%rbp), %r10 + movq %r10, -0xef8(%rbp) + movq 0x1f30(%rbp), %r10 + movq %r10, -0xf10(%rbp) + movq 0x1f38(%rbp), %r10 + movq %r10, -0xf08(%rbp) + movq 0x1f40(%rbp), %r10 + movq %r10, -0xf20(%rbp) + movq 0x1f48(%rbp), %r10 + movq %r10, -0xf18(%rbp) + movq 0x1f50(%rbp), %r10 + movq %r10, -0xf30(%rbp) + movq 0x1f58(%rbp), %r10 + movq %r10, -0xf28(%rbp) + movq 0x1f60(%rbp), %r10 + movq %r10, -0xf40(%rbp) + movq 0x1f68(%rbp), %r10 + movq %r10, -0xf38(%rbp) + movq 0x1f70(%rbp), %r10 + movq %r10, -0xf50(%rbp) + movq 0x1f78(%rbp), %r10 + movq %r10, -0xf48(%rbp) + movq 0x1f80(%rbp), %r10 + movq %r10, -0xf60(%rbp) + movq 0x1f88(%rbp), %r10 + movq %r10, -0xf58(%rbp) + movq 0x1f90(%rbp), %r10 + movq %r10, -0xf70(%rbp) + movq 0x1f98(%rbp), %r10 + movq %r10, -0xf68(%rbp) + movq 0x1fa0(%rbp), %r10 + movq %r10, -0xf80(%rbp) + movq 0x1fa8(%rbp), %r10 + movq %r10, -0xf78(%rbp) + movq 0x1fb0(%rbp), %r10 + movq %r10, -0xf90(%rbp) + movq 0x1fb8(%rbp), %r10 + movq %r10, -0xf88(%rbp) + movq 0x1fc0(%rbp), %r10 + movq %r10, -0xfa0(%rbp) + movq 0x1fc8(%rbp), %r10 + movq %r10, -0xf98(%rbp) + movq 0x1fd0(%rbp), %r10 + movq %r10, -0xfb0(%rbp) + movq 0x1fd8(%rbp), %r10 + movq %r10, -0xfa8(%rbp) + movq 0x1fe0(%rbp), %r10 + movq %r10, -0xfc0(%rbp) + movq 0x1fe8(%rbp), %r10 + movq %r10, -0xfb8(%rbp) + movq 0x1ff0(%rbp), %r10 + movq %r10, -0xfd0(%rbp) + movq 0x1ff8(%rbp), %r10 + movq %r10, -0xfc8(%rbp) + movq 0x2000(%rbp), %r10 + movq %r10, -0xfe0(%rbp) + movq 0x2008(%rbp), %r10 + movq %r10, -0xfd8(%rbp) + movq 0x2010(%rbp), %r10 + movq %r10, -0xff0(%rbp) + movq 0x2018(%rbp), %r10 + movq %r10, -0xfe8(%rbp) + movq 0x2020(%rbp), %r10 + movq %r10, -0x1000(%rbp) + movq 0x2028(%rbp), %r10 + movq %r10, -0xff8(%rbp) + movq 0x2030(%rbp), %r10 + movq %r10, -0x1010(%rbp) + movq 0x2038(%rbp), %r10 + movq %r10, -0x1008(%rbp) + movq 0x2040(%rbp), %r10 + movq %r10, -0x1020(%rbp) + movq 0x2048(%rbp), %r10 + movq %r10, -0x1018(%rbp) + movq 0x2050(%rbp), %r10 + movq %r10, -0x1030(%rbp) + movq 0x2058(%rbp), %r10 + movq %r10, -0x1028(%rbp) + movq 0x2060(%rbp), %r10 + movq %r10, -0x1040(%rbp) + movq 0x2068(%rbp), %r10 + movq %r10, -0x1038(%rbp) + movq 0x2070(%rbp), %r10 + movq %r10, -0x1050(%rbp) + movq 0x2078(%rbp), %r10 + movq %r10, -0x1048(%rbp) + xorq %rax, %rax + leaq -0x10(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x10(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x20(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x20(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x30(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x30(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x40(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x40(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x50(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x50(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x60(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x60(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x70(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x70(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x80(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x80(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x90(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x90(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xa0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xa0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xb0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xb0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xc0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xc0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xd0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xd0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xe0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xe0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xf0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xf0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x100(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x100(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x110(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x110(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x120(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x120(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x130(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x130(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x140(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x140(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x150(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x150(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x160(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x160(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x170(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x170(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x180(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x180(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x190(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x190(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x1a0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x1a0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x1b0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x1b0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x1c0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x1c0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x1d0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x1d0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x1e0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x1e0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x1f0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x1f0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x200(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x200(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x210(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x210(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x220(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x220(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x230(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x230(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x240(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x240(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x250(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x250(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x260(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x260(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x270(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x270(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x280(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x280(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x290(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x290(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x2a0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x2a0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x2b0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x2b0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x2c0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x2c0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x2d0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x2d0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x2e0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x2e0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x2f0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x2f0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x300(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x300(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x310(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x310(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x320(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x320(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x330(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x330(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x340(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x340(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x350(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x350(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x360(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x360(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x370(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x370(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x380(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x380(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x390(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x390(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x3a0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x3a0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x3b0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x3b0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x3c0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x3c0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x3d0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x3d0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x3e0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x3e0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x3f0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x3f0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x400(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x400(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x410(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x410(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x420(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x420(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x430(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x430(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x440(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x440(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x450(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x450(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x460(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x460(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x470(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x470(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x480(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x480(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x490(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x490(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x4a0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x4a0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x4b0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x4b0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x4c0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x4c0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x4d0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x4d0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x4e0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x4e0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x4f0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x4f0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x500(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x500(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x510(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x510(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x520(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x520(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x530(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x530(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x540(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x540(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x550(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x550(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x560(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x560(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x570(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x570(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x580(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x580(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x590(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x590(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x5a0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x5a0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x5b0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x5b0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x5c0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x5c0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x5d0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x5d0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x5e0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x5e0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x5f0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x5f0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x600(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x600(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x610(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x610(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x620(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x620(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x630(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x630(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x640(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x640(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x650(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x650(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x660(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x660(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x670(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x670(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x680(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x680(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x690(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x690(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x6a0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x6a0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x6b0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x6b0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x6c0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x6c0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x6d0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x6d0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x6e0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x6e0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x6f0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x6f0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x700(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x700(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x710(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x710(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x720(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x720(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x730(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x730(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x740(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x740(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x750(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x750(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x760(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x760(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x770(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x770(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x780(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x780(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x790(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x790(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x7a0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x7a0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x7b0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x7b0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x7c0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x7c0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x7d0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x7d0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x7e0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x7e0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x7f0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x7f0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x800(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x800(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x810(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x810(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x820(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x820(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x830(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x830(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x840(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x840(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x850(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x850(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x860(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x860(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x870(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x870(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x880(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x880(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x890(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x890(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x8a0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x8a0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x8b0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x8b0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x8c0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x8c0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x8d0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x8d0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x8e0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x8e0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x8f0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x8f0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x900(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x900(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x910(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x910(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x920(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x920(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x930(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x930(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x940(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x940(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x950(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x950(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x960(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x960(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x970(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x970(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x980(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x980(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x990(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x990(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x9a0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x9a0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x9b0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x9b0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x9c0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x9c0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x9d0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x9d0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x9e0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x9e0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x9f0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x9f0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xa00(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xa00(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xa10(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xa10(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xa20(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xa20(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xa30(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xa30(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xa40(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xa40(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xa50(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xa50(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xa60(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xa60(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xa70(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xa70(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xa80(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xa80(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xa90(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xa90(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xaa0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xaa0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xab0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xab0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xac0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xac0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xad0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xad0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xae0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xae0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xaf0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xaf0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xb00(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xb00(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xb10(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xb10(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xb20(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xb20(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xb30(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xb30(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xb40(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xb40(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xb50(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xb50(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xb60(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xb60(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xb70(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xb70(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xb80(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xb80(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xb90(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xb90(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xba0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xba0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xbb0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xbb0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xbc0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xbc0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xbd0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xbd0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xbe0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xbe0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xbf0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xbf0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xc00(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xc00(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xc10(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xc10(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xc20(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xc20(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xc30(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xc30(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xc40(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xc40(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xc50(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xc50(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xc60(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xc60(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xc70(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xc70(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xc80(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xc80(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xc90(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xc90(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xca0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xca0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xcb0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xcb0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xcc0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xcc0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xcd0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xcd0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xce0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xce0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xcf0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xcf0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xd00(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xd00(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xd10(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xd10(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xd20(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xd20(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xd30(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xd30(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xd40(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xd40(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xd50(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xd50(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xd60(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xd60(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xd70(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xd70(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xd80(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xd80(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xd90(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xd90(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xda0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xda0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xdb0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xdb0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xdc0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xdc0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xdd0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xdd0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xde0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xde0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xdf0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xdf0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xe00(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xe00(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xe10(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xe10(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xe20(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xe20(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xe30(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xe30(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xe40(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xe40(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xe50(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xe50(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xe60(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xe60(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xe70(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xe70(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xe80(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xe80(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xe90(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xe90(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xea0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xea0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xeb0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xeb0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xec0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xec0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xed0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xed0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xee0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xee0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xef0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xef0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xf00(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xf00(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xf10(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xf10(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xf20(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xf20(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xf30(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xf30(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xf40(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xf40(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xf50(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xf50(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xf60(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xf60(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xf70(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xf70(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xf80(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xf80(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xf90(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xf90(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xfa0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xfa0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xfb0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xfb0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xfc0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xfc0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xfd0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xfd0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xfe0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xfe0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0xff0(%rbp), %rcx + movq (%rcx), %rcx + leaq -0xff0(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x1000(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x1000(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x1010(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x1010(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x1020(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x1020(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x1030(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x1030(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x1040(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x1040(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + leaq -0x1050(%rbp), %rcx + movq (%rcx), %rcx + leaq -0x1050(%rbp), %rdx + movq 0x8(%rdx), %rdx + addq %rdx, %rcx + addq %rcx, %rax + addq $0x1060, %rsp # imm = 0x1060 + popq %rbp + popq %r11 + addq $0x1050, %rsp # imm = 0x1050 + pushq %r11 + retq + +: + popq %r10 + subq $0x1040, %rsp # imm = 0x1040 + movq 0x1040(%rsp), %rax + movq %rax, 0x60(%rsp) + movq 0x1048(%rsp), %rax + movq %rax, 0x70(%rsp) + movq 0x1050(%rsp), %rax + movq %rax, 0x80(%rsp) + movq 0x1058(%rsp), %rax + movq %rax, 0x90(%rsp) + movq 0x1060(%rsp), %rax + movq %rax, 0xa0(%rsp) + movq 0x1068(%rsp), %rax + movq %rax, 0xb0(%rsp) + movq 0x1070(%rsp), %rax + movq %rax, 0xc0(%rsp) + movq 0x1078(%rsp), %rax + movq %rax, 0xd0(%rsp) + movq 0x1080(%rsp), %rax + movq %rax, 0xe0(%rsp) + movq 0x1088(%rsp), %rax + movq %rax, 0xf0(%rsp) + movq 0x1090(%rsp), %rax + movq %rax, 0x100(%rsp) + movq 0x1098(%rsp), %rax + movq %rax, 0x110(%rsp) + movq 0x10a0(%rsp), %rax + movq %rax, 0x120(%rsp) + movq 0x10a8(%rsp), %rax + movq %rax, 0x130(%rsp) + movq 0x10b0(%rsp), %rax + movq %rax, 0x140(%rsp) + movq 0x10b8(%rsp), %rax + movq %rax, 0x150(%rsp) + movq 0x10c0(%rsp), %rax + movq %rax, 0x160(%rsp) + movq 0x10c8(%rsp), %rax + movq %rax, 0x170(%rsp) + movq 0x10d0(%rsp), %rax + movq %rax, 0x180(%rsp) + movq 0x10d8(%rsp), %rax + movq %rax, 0x190(%rsp) + movq 0x10e0(%rsp), %rax + movq %rax, 0x1a0(%rsp) + movq 0x10e8(%rsp), %rax + movq %rax, 0x1b0(%rsp) + movq 0x10f0(%rsp), %rax + movq %rax, 0x1c0(%rsp) + movq 0x10f8(%rsp), %rax + movq %rax, 0x1d0(%rsp) + movq 0x1100(%rsp), %rax + movq %rax, 0x1e0(%rsp) + movq 0x1108(%rsp), %rax + movq %rax, 0x1f0(%rsp) + movq 0x1110(%rsp), %rax + movq %rax, 0x200(%rsp) + movq 0x1118(%rsp), %rax + movq %rax, 0x210(%rsp) + movq 0x1120(%rsp), %rax + movq %rax, 0x220(%rsp) + movq 0x1128(%rsp), %rax + movq %rax, 0x230(%rsp) + movq 0x1130(%rsp), %rax + movq %rax, 0x240(%rsp) + movq 0x1138(%rsp), %rax + movq %rax, 0x250(%rsp) + movq 0x1140(%rsp), %rax + movq %rax, 0x260(%rsp) + movq 0x1148(%rsp), %rax + movq %rax, 0x270(%rsp) + movq 0x1150(%rsp), %rax + movq %rax, 0x280(%rsp) + movq 0x1158(%rsp), %rax + movq %rax, 0x290(%rsp) + movq 0x1160(%rsp), %rax + movq %rax, 0x2a0(%rsp) + movq 0x1168(%rsp), %rax + movq %rax, 0x2b0(%rsp) + movq 0x1170(%rsp), %rax + movq %rax, 0x2c0(%rsp) + movq 0x1178(%rsp), %rax + movq %rax, 0x2d0(%rsp) + movq 0x1180(%rsp), %rax + movq %rax, 0x2e0(%rsp) + movq 0x1188(%rsp), %rax + movq %rax, 0x2f0(%rsp) + movq 0x1190(%rsp), %rax + movq %rax, 0x300(%rsp) + movq 0x1198(%rsp), %rax + movq %rax, 0x310(%rsp) + movq 0x11a0(%rsp), %rax + movq %rax, 0x320(%rsp) + movq 0x11a8(%rsp), %rax + movq %rax, 0x330(%rsp) + movq 0x11b0(%rsp), %rax + movq %rax, 0x340(%rsp) + movq 0x11b8(%rsp), %rax + movq %rax, 0x350(%rsp) + movq 0x11c0(%rsp), %rax + movq %rax, 0x360(%rsp) + movq 0x11c8(%rsp), %rax + movq %rax, 0x370(%rsp) + movq 0x11d0(%rsp), %rax + movq %rax, 0x380(%rsp) + movq 0x11d8(%rsp), %rax + movq %rax, 0x390(%rsp) + movq 0x11e0(%rsp), %rax + movq %rax, 0x3a0(%rsp) + movq 0x11e8(%rsp), %rax + movq %rax, 0x3b0(%rsp) + movq 0x11f0(%rsp), %rax + movq %rax, 0x3c0(%rsp) + movq 0x11f8(%rsp), %rax + movq %rax, 0x3d0(%rsp) + movq 0x1200(%rsp), %rax + movq %rax, 0x3e0(%rsp) + movq 0x1208(%rsp), %rax + movq %rax, 0x3f0(%rsp) + movq 0x1210(%rsp), %rax + movq %rax, 0x400(%rsp) + movq 0x1218(%rsp), %rax + movq %rax, 0x410(%rsp) + movq 0x1220(%rsp), %rax + movq %rax, 0x420(%rsp) + movq 0x1228(%rsp), %rax + movq %rax, 0x430(%rsp) + movq 0x1230(%rsp), %rax + movq %rax, 0x440(%rsp) + movq 0x1238(%rsp), %rax + movq %rax, 0x450(%rsp) + movq 0x1240(%rsp), %rax + movq %rax, 0x460(%rsp) + movq 0x1248(%rsp), %rax + movq %rax, 0x470(%rsp) + movq 0x1250(%rsp), %rax + movq %rax, 0x480(%rsp) + movq 0x1258(%rsp), %rax + movq %rax, 0x490(%rsp) + movq 0x1260(%rsp), %rax + movq %rax, 0x4a0(%rsp) + movq 0x1268(%rsp), %rax + movq %rax, 0x4b0(%rsp) + movq 0x1270(%rsp), %rax + movq %rax, 0x4c0(%rsp) + movq 0x1278(%rsp), %rax + movq %rax, 0x4d0(%rsp) + movq 0x1280(%rsp), %rax + movq %rax, 0x4e0(%rsp) + movq 0x1288(%rsp), %rax + movq %rax, 0x4f0(%rsp) + movq 0x1290(%rsp), %rax + movq %rax, 0x500(%rsp) + movq 0x1298(%rsp), %rax + movq %rax, 0x510(%rsp) + movq 0x12a0(%rsp), %rax + movq %rax, 0x520(%rsp) + movq 0x12a8(%rsp), %rax + movq %rax, 0x530(%rsp) + movq 0x12b0(%rsp), %rax + movq %rax, 0x540(%rsp) + movq 0x12b8(%rsp), %rax + movq %rax, 0x550(%rsp) + movq 0x12c0(%rsp), %rax + movq %rax, 0x560(%rsp) + movq 0x12c8(%rsp), %rax + movq %rax, 0x570(%rsp) + movq 0x12d0(%rsp), %rax + movq %rax, 0x580(%rsp) + movq 0x12d8(%rsp), %rax + movq %rax, 0x590(%rsp) + movq 0x12e0(%rsp), %rax + movq %rax, 0x5a0(%rsp) + movq 0x12e8(%rsp), %rax + movq %rax, 0x5b0(%rsp) + movq 0x12f0(%rsp), %rax + movq %rax, 0x5c0(%rsp) + movq 0x12f8(%rsp), %rax + movq %rax, 0x5d0(%rsp) + movq 0x1300(%rsp), %rax + movq %rax, 0x5e0(%rsp) + movq 0x1308(%rsp), %rax + movq %rax, 0x5f0(%rsp) + movq 0x1310(%rsp), %rax + movq %rax, 0x600(%rsp) + movq 0x1318(%rsp), %rax + movq %rax, 0x610(%rsp) + movq 0x1320(%rsp), %rax + movq %rax, 0x620(%rsp) + movq 0x1328(%rsp), %rax + movq %rax, 0x630(%rsp) + movq 0x1330(%rsp), %rax + movq %rax, 0x640(%rsp) + movq 0x1338(%rsp), %rax + movq %rax, 0x650(%rsp) + movq 0x1340(%rsp), %rax + movq %rax, 0x660(%rsp) + movq 0x1348(%rsp), %rax + movq %rax, 0x670(%rsp) + movq 0x1350(%rsp), %rax + movq %rax, 0x680(%rsp) + movq 0x1358(%rsp), %rax + movq %rax, 0x690(%rsp) + movq 0x1360(%rsp), %rax + movq %rax, 0x6a0(%rsp) + movq 0x1368(%rsp), %rax + movq %rax, 0x6b0(%rsp) + movq 0x1370(%rsp), %rax + movq %rax, 0x6c0(%rsp) + movq 0x1378(%rsp), %rax + movq %rax, 0x6d0(%rsp) + movq 0x1380(%rsp), %rax + movq %rax, 0x6e0(%rsp) + movq 0x1388(%rsp), %rax + movq %rax, 0x6f0(%rsp) + movq 0x1390(%rsp), %rax + movq %rax, 0x700(%rsp) + movq 0x1398(%rsp), %rax + movq %rax, 0x710(%rsp) + movq 0x13a0(%rsp), %rax + movq %rax, 0x720(%rsp) + movq 0x13a8(%rsp), %rax + movq %rax, 0x730(%rsp) + movq 0x13b0(%rsp), %rax + movq %rax, 0x740(%rsp) + movq 0x13b8(%rsp), %rax + movq %rax, 0x750(%rsp) + movq 0x13c0(%rsp), %rax + movq %rax, 0x760(%rsp) + movq 0x13c8(%rsp), %rax + movq %rax, 0x770(%rsp) + movq 0x13d0(%rsp), %rax + movq %rax, 0x780(%rsp) + movq 0x13d8(%rsp), %rax + movq %rax, 0x790(%rsp) + movq 0x13e0(%rsp), %rax + movq %rax, 0x7a0(%rsp) + movq 0x13e8(%rsp), %rax + movq %rax, 0x7b0(%rsp) + movq 0x13f0(%rsp), %rax + movq %rax, 0x7c0(%rsp) + movq 0x13f8(%rsp), %rax + movq %rax, 0x7d0(%rsp) + movq 0x1400(%rsp), %rax + movq %rax, 0x7e0(%rsp) + movq 0x1408(%rsp), %rax + movq %rax, 0x7f0(%rsp) + movq 0x1410(%rsp), %rax + movq %rax, 0x800(%rsp) + movq 0x1418(%rsp), %rax + movq %rax, 0x810(%rsp) + movq 0x1420(%rsp), %rax + movq %rax, 0x820(%rsp) + movq 0x1428(%rsp), %rax + movq %rax, 0x830(%rsp) + movq 0x1430(%rsp), %rax + movq %rax, 0x840(%rsp) + movq 0x1438(%rsp), %rax + movq %rax, 0x850(%rsp) + movq 0x1440(%rsp), %rax + movq %rax, 0x860(%rsp) + movq 0x1448(%rsp), %rax + movq %rax, 0x870(%rsp) + movq 0x1450(%rsp), %rax + movq %rax, 0x880(%rsp) + movq 0x1458(%rsp), %rax + movq %rax, 0x890(%rsp) + movq 0x1460(%rsp), %rax + movq %rax, 0x8a0(%rsp) + movq 0x1468(%rsp), %rax + movq %rax, 0x8b0(%rsp) + movq 0x1470(%rsp), %rax + movq %rax, 0x8c0(%rsp) + movq 0x1478(%rsp), %rax + movq %rax, 0x8d0(%rsp) + movq 0x1480(%rsp), %rax + movq %rax, 0x8e0(%rsp) + movq 0x1488(%rsp), %rax + movq %rax, 0x8f0(%rsp) + movq 0x1490(%rsp), %rax + movq %rax, 0x900(%rsp) + movq 0x1498(%rsp), %rax + movq %rax, 0x910(%rsp) + movq 0x14a0(%rsp), %rax + movq %rax, 0x920(%rsp) + movq 0x14a8(%rsp), %rax + movq %rax, 0x930(%rsp) + movq 0x14b0(%rsp), %rax + movq %rax, 0x940(%rsp) + movq 0x14b8(%rsp), %rax + movq %rax, 0x950(%rsp) + movq 0x14c0(%rsp), %rax + movq %rax, 0x960(%rsp) + movq 0x14c8(%rsp), %rax + movq %rax, 0x970(%rsp) + movq 0x14d0(%rsp), %rax + movq %rax, 0x980(%rsp) + movq 0x14d8(%rsp), %rax + movq %rax, 0x990(%rsp) + movq 0x14e0(%rsp), %rax + movq %rax, 0x9a0(%rsp) + movq 0x14e8(%rsp), %rax + movq %rax, 0x9b0(%rsp) + movq 0x14f0(%rsp), %rax + movq %rax, 0x9c0(%rsp) + movq 0x14f8(%rsp), %rax + movq %rax, 0x9d0(%rsp) + movq 0x1500(%rsp), %rax + movq %rax, 0x9e0(%rsp) + movq 0x1508(%rsp), %rax + movq %rax, 0x9f0(%rsp) + movq 0x1510(%rsp), %rax + movq %rax, 0xa00(%rsp) + movq 0x1518(%rsp), %rax + movq %rax, 0xa10(%rsp) + movq 0x1520(%rsp), %rax + movq %rax, 0xa20(%rsp) + movq 0x1528(%rsp), %rax + movq %rax, 0xa30(%rsp) + movq 0x1530(%rsp), %rax + movq %rax, 0xa40(%rsp) + movq 0x1538(%rsp), %rax + movq %rax, 0xa50(%rsp) + movq 0x1540(%rsp), %rax + movq %rax, 0xa60(%rsp) + movq 0x1548(%rsp), %rax + movq %rax, 0xa70(%rsp) + movq 0x1550(%rsp), %rax + movq %rax, 0xa80(%rsp) + movq 0x1558(%rsp), %rax + movq %rax, 0xa90(%rsp) + movq 0x1560(%rsp), %rax + movq %rax, 0xaa0(%rsp) + movq 0x1568(%rsp), %rax + movq %rax, 0xab0(%rsp) + movq 0x1570(%rsp), %rax + movq %rax, 0xac0(%rsp) + movq 0x1578(%rsp), %rax + movq %rax, 0xad0(%rsp) + movq 0x1580(%rsp), %rax + movq %rax, 0xae0(%rsp) + movq 0x1588(%rsp), %rax + movq %rax, 0xaf0(%rsp) + movq 0x1590(%rsp), %rax + movq %rax, 0xb00(%rsp) + movq 0x1598(%rsp), %rax + movq %rax, 0xb10(%rsp) + movq 0x15a0(%rsp), %rax + movq %rax, 0xb20(%rsp) + movq 0x15a8(%rsp), %rax + movq %rax, 0xb30(%rsp) + movq 0x15b0(%rsp), %rax + movq %rax, 0xb40(%rsp) + movq 0x15b8(%rsp), %rax + movq %rax, 0xb50(%rsp) + movq 0x15c0(%rsp), %rax + movq %rax, 0xb60(%rsp) + movq 0x15c8(%rsp), %rax + movq %rax, 0xb70(%rsp) + movq 0x15d0(%rsp), %rax + movq %rax, 0xb80(%rsp) + movq 0x15d8(%rsp), %rax + movq %rax, 0xb90(%rsp) + movq 0x15e0(%rsp), %rax + movq %rax, 0xba0(%rsp) + movq 0x15e8(%rsp), %rax + movq %rax, 0xbb0(%rsp) + movq 0x15f0(%rsp), %rax + movq %rax, 0xbc0(%rsp) + movq 0x15f8(%rsp), %rax + movq %rax, 0xbd0(%rsp) + movq 0x1600(%rsp), %rax + movq %rax, 0xbe0(%rsp) + movq 0x1608(%rsp), %rax + movq %rax, 0xbf0(%rsp) + movq 0x1610(%rsp), %rax + movq %rax, 0xc00(%rsp) + movq 0x1618(%rsp), %rax + movq %rax, 0xc10(%rsp) + movq 0x1620(%rsp), %rax + movq %rax, 0xc20(%rsp) + movq 0x1628(%rsp), %rax + movq %rax, 0xc30(%rsp) + movq 0x1630(%rsp), %rax + movq %rax, 0xc40(%rsp) + movq 0x1638(%rsp), %rax + movq %rax, 0xc50(%rsp) + movq 0x1640(%rsp), %rax + movq %rax, 0xc60(%rsp) + movq 0x1648(%rsp), %rax + movq %rax, 0xc70(%rsp) + movq 0x1650(%rsp), %rax + movq %rax, 0xc80(%rsp) + movq 0x1658(%rsp), %rax + movq %rax, 0xc90(%rsp) + movq 0x1660(%rsp), %rax + movq %rax, 0xca0(%rsp) + movq 0x1668(%rsp), %rax + movq %rax, 0xcb0(%rsp) + movq 0x1670(%rsp), %rax + movq %rax, 0xcc0(%rsp) + movq 0x1678(%rsp), %rax + movq %rax, 0xcd0(%rsp) + movq 0x1680(%rsp), %rax + movq %rax, 0xce0(%rsp) + movq 0x1688(%rsp), %rax + movq %rax, 0xcf0(%rsp) + movq 0x1690(%rsp), %rax + movq %rax, 0xd00(%rsp) + movq 0x1698(%rsp), %rax + movq %rax, 0xd10(%rsp) + movq 0x16a0(%rsp), %rax + movq %rax, 0xd20(%rsp) + movq 0x16a8(%rsp), %rax + movq %rax, 0xd30(%rsp) + movq 0x16b0(%rsp), %rax + movq %rax, 0xd40(%rsp) + movq 0x16b8(%rsp), %rax + movq %rax, 0xd50(%rsp) + movq 0x16c0(%rsp), %rax + movq %rax, 0xd60(%rsp) + movq 0x16c8(%rsp), %rax + movq %rax, 0xd70(%rsp) + movq 0x16d0(%rsp), %rax + movq %rax, 0xd80(%rsp) + movq 0x16d8(%rsp), %rax + movq %rax, 0xd90(%rsp) + movq 0x16e0(%rsp), %rax + movq %rax, 0xda0(%rsp) + movq 0x16e8(%rsp), %rax + movq %rax, 0xdb0(%rsp) + movq 0x16f0(%rsp), %rax + movq %rax, 0xdc0(%rsp) + movq 0x16f8(%rsp), %rax + movq %rax, 0xdd0(%rsp) + movq 0x1700(%rsp), %rax + movq %rax, 0xde0(%rsp) + movq 0x1708(%rsp), %rax + movq %rax, 0xdf0(%rsp) + movq 0x1710(%rsp), %rax + movq %rax, 0xe00(%rsp) + movq 0x1718(%rsp), %rax + movq %rax, 0xe10(%rsp) + movq 0x1720(%rsp), %rax + movq %rax, 0xe20(%rsp) + movq 0x1728(%rsp), %rax + movq %rax, 0xe30(%rsp) + movq 0x1730(%rsp), %rax + movq %rax, 0xe40(%rsp) + movq 0x1738(%rsp), %rax + movq %rax, 0xe50(%rsp) + movq 0x1740(%rsp), %rax + movq %rax, 0xe60(%rsp) + movq 0x1748(%rsp), %rax + movq %rax, 0xe70(%rsp) + movq 0x1750(%rsp), %rax + movq %rax, 0xe80(%rsp) + movq 0x1758(%rsp), %rax + movq %rax, 0xe90(%rsp) + movq 0x1760(%rsp), %rax + movq %rax, 0xea0(%rsp) + movq 0x1768(%rsp), %rax + movq %rax, 0xeb0(%rsp) + movq 0x1770(%rsp), %rax + movq %rax, 0xec0(%rsp) + movq 0x1778(%rsp), %rax + movq %rax, 0xed0(%rsp) + movq 0x1780(%rsp), %rax + movq %rax, 0xee0(%rsp) + movq 0x1788(%rsp), %rax + movq %rax, 0xef0(%rsp) + movq 0x1790(%rsp), %rax + movq %rax, 0xf00(%rsp) + movq 0x1798(%rsp), %rax + movq %rax, 0xf10(%rsp) + movq 0x17a0(%rsp), %rax + movq %rax, 0xf20(%rsp) + movq 0x17a8(%rsp), %rax + movq %rax, 0xf30(%rsp) + movq 0x17b0(%rsp), %rax + movq %rax, 0xf40(%rsp) + movq 0x17b8(%rsp), %rax + movq %rax, 0xf50(%rsp) + movq 0x17c0(%rsp), %rax + movq %rax, 0xf60(%rsp) + movq 0x17c8(%rsp), %rax + movq %rax, 0xf70(%rsp) + movq 0x17d0(%rsp), %rax + movq %rax, 0xf80(%rsp) + movq 0x17d8(%rsp), %rax + movq %rax, 0xf90(%rsp) + movq 0x17e0(%rsp), %rax + movq %rax, 0xfa0(%rsp) + movq 0x17e8(%rsp), %rax + movq %rax, 0xfb0(%rsp) + movq 0x17f0(%rsp), %rax + movq %rax, 0xfc0(%rsp) + movq 0x17f8(%rsp), %rax + movq %rax, 0xfd0(%rsp) + movq 0x1800(%rsp), %rax + movq %rax, 0xfe0(%rsp) + movq 0x1808(%rsp), %rax + movq %rax, 0xff0(%rsp) + movq 0x1810(%rsp), %rax + movq %rax, 0x1000(%rsp) + movq 0x1818(%rsp), %rax + movq %rax, 0x1010(%rsp) + movq 0x1820(%rsp), %rax + movq %rax, 0x1020(%rsp) + movq 0x1828(%rsp), %rax + movq %rax, 0x1030(%rsp) + pushq %r10 + pushq %rbp + movq %rsp, %rbp + subq $0x20, %rsp + movq %rbx, (%rsp) + xorq %rax, %rax + addq %rdi, %rax + addq %rsi, %rax + addq %rdx, %rax + addq %rcx, %rax + addq %r8, %rax + addq %r9, %rax + movq 0x70(%rbp), %rcx + addq %rcx, %rax + movq 0x80(%rbp), %rcx + addq %rcx, %rax + movq 0x90(%rbp), %rcx + addq %rcx, %rax + movq 0xa0(%rbp), %rcx + addq %rcx, %rax + movq 0xb0(%rbp), %rcx + addq %rcx, %rax + movq 0xc0(%rbp), %rcx + addq %rcx, %rax + movq 0xd0(%rbp), %rcx + addq %rcx, %rax + movq 0xe0(%rbp), %rcx + addq %rcx, %rax + movq 0xf0(%rbp), %rcx + addq %rcx, %rax + movq 0x100(%rbp), %rcx + addq %rcx, %rax + movq 0x110(%rbp), %rcx + addq %rcx, %rax + movq 0x120(%rbp), %rcx + addq %rcx, %rax + movq 0x130(%rbp), %rcx + addq %rcx, %rax + movq 0x140(%rbp), %rcx + addq %rcx, %rax + movq 0x150(%rbp), %rcx + addq %rcx, %rax + movq 0x160(%rbp), %rcx + addq %rcx, %rax + movq 0x170(%rbp), %rcx + addq %rcx, %rax + movq 0x180(%rbp), %rcx + addq %rcx, %rax + movq 0x190(%rbp), %rcx + addq %rcx, %rax + movq 0x1a0(%rbp), %rcx + addq %rcx, %rax + movq 0x1b0(%rbp), %rcx + addq %rcx, %rax + movq 0x1c0(%rbp), %rcx + addq %rcx, %rax + movq 0x1d0(%rbp), %rcx + addq %rcx, %rax + movq 0x1e0(%rbp), %rcx + addq %rcx, %rax + movq 0x1f0(%rbp), %rcx + addq %rcx, %rax + movq 0x200(%rbp), %rcx + addq %rcx, %rax + movq 0x210(%rbp), %rcx + addq %rcx, %rax + movq 0x220(%rbp), %rcx + addq %rcx, %rax + movq 0x230(%rbp), %rcx + addq %rcx, %rax + movq 0x240(%rbp), %rcx + addq %rcx, %rax + movq 0x250(%rbp), %rcx + addq %rcx, %rax + movq 0x260(%rbp), %rcx + addq %rcx, %rax + movq 0x270(%rbp), %rcx + addq %rcx, %rax + movq 0x280(%rbp), %rcx + addq %rcx, %rax + movq 0x290(%rbp), %rcx + addq %rcx, %rax + movq 0x2a0(%rbp), %rcx + addq %rcx, %rax + movq 0x2b0(%rbp), %rcx + addq %rcx, %rax + movq 0x2c0(%rbp), %rcx + addq %rcx, %rax + movq 0x2d0(%rbp), %rcx + addq %rcx, %rax + movq 0x2e0(%rbp), %rcx + addq %rcx, %rax + movq 0x2f0(%rbp), %rcx + addq %rcx, %rax + movq 0x300(%rbp), %rcx + addq %rcx, %rax + movq 0x310(%rbp), %rcx + addq %rcx, %rax + movq 0x320(%rbp), %rcx + addq %rcx, %rax + movq 0x330(%rbp), %rcx + addq %rcx, %rax + movq 0x340(%rbp), %rcx + addq %rcx, %rax + movq 0x350(%rbp), %rcx + addq %rcx, %rax + movq 0x360(%rbp), %rcx + addq %rcx, %rax + movq 0x370(%rbp), %rcx + addq %rcx, %rax + movq 0x380(%rbp), %rcx + addq %rcx, %rax + movq 0x390(%rbp), %rcx + addq %rcx, %rax + movq 0x3a0(%rbp), %rcx + addq %rcx, %rax + movq 0x3b0(%rbp), %rcx + addq %rcx, %rax + movq 0x3c0(%rbp), %rcx + addq %rcx, %rax + movq 0x3d0(%rbp), %rcx + addq %rcx, %rax + movq 0x3e0(%rbp), %rcx + addq %rcx, %rax + movq 0x3f0(%rbp), %rcx + addq %rcx, %rax + movq 0x400(%rbp), %rcx + addq %rcx, %rax + movq 0x410(%rbp), %rcx + addq %rcx, %rax + movq 0x420(%rbp), %rcx + addq %rcx, %rax + movq 0x430(%rbp), %rcx + addq %rcx, %rax + movq 0x440(%rbp), %rcx + addq %rcx, %rax + movq 0x450(%rbp), %rcx + addq %rcx, %rax + movq 0x460(%rbp), %rcx + addq %rcx, %rax + movq 0x470(%rbp), %rcx + addq %rcx, %rax + movq 0x480(%rbp), %rcx + addq %rcx, %rax + movq 0x490(%rbp), %rcx + addq %rcx, %rax + movq 0x4a0(%rbp), %rcx + addq %rcx, %rax + movq 0x4b0(%rbp), %rcx + addq %rcx, %rax + movq 0x4c0(%rbp), %rcx + addq %rcx, %rax + movq 0x4d0(%rbp), %rcx + addq %rcx, %rax + movq 0x4e0(%rbp), %rcx + addq %rcx, %rax + movq 0x4f0(%rbp), %rcx + addq %rcx, %rax + movq 0x500(%rbp), %rcx + addq %rcx, %rax + movq 0x510(%rbp), %rcx + addq %rcx, %rax + movq 0x520(%rbp), %rcx + addq %rcx, %rax + movq 0x530(%rbp), %rcx + addq %rcx, %rax + movq 0x540(%rbp), %rcx + addq %rcx, %rax + movq 0x550(%rbp), %rcx + addq %rcx, %rax + movq 0x560(%rbp), %rcx + addq %rcx, %rax + movq 0x570(%rbp), %rcx + addq %rcx, %rax + movq 0x580(%rbp), %rcx + addq %rcx, %rax + movq 0x590(%rbp), %rcx + addq %rcx, %rax + movq 0x5a0(%rbp), %rcx + addq %rcx, %rax + movq 0x5b0(%rbp), %rcx + addq %rcx, %rax + movq 0x5c0(%rbp), %rcx + addq %rcx, %rax + movq 0x5d0(%rbp), %rcx + addq %rcx, %rax + movq 0x5e0(%rbp), %rcx + addq %rcx, %rax + movq 0x5f0(%rbp), %rcx + addq %rcx, %rax + movq 0x600(%rbp), %rcx + addq %rcx, %rax + movq 0x610(%rbp), %rcx + addq %rcx, %rax + movq 0x620(%rbp), %rcx + addq %rcx, %rax + movq 0x630(%rbp), %rcx + addq %rcx, %rax + movq 0x640(%rbp), %rcx + addq %rcx, %rax + movq 0x650(%rbp), %rcx + addq %rcx, %rax + movq 0x660(%rbp), %rcx + addq %rcx, %rax + movq 0x670(%rbp), %rcx + addq %rcx, %rax + movq 0x680(%rbp), %rcx + addq %rcx, %rax + movq 0x690(%rbp), %rcx + addq %rcx, %rax + movq 0x6a0(%rbp), %rcx + addq %rcx, %rax + movq 0x6b0(%rbp), %rcx + addq %rcx, %rax + movq 0x6c0(%rbp), %rcx + addq %rcx, %rax + movq 0x6d0(%rbp), %rcx + addq %rcx, %rax + movq 0x6e0(%rbp), %rcx + addq %rcx, %rax + movq 0x6f0(%rbp), %rcx + addq %rcx, %rax + movq 0x700(%rbp), %rcx + addq %rcx, %rax + movq 0x710(%rbp), %rcx + addq %rcx, %rax + movq 0x720(%rbp), %rcx + addq %rcx, %rax + movq 0x730(%rbp), %rcx + addq %rcx, %rax + movq 0x740(%rbp), %rcx + addq %rcx, %rax + movq 0x750(%rbp), %rcx + addq %rcx, %rax + movq 0x760(%rbp), %rcx + addq %rcx, %rax + movq 0x770(%rbp), %rcx + addq %rcx, %rax + movq 0x780(%rbp), %rcx + addq %rcx, %rax + movq 0x790(%rbp), %rcx + addq %rcx, %rax + movq 0x7a0(%rbp), %rcx + addq %rcx, %rax + movq 0x7b0(%rbp), %rcx + addq %rcx, %rax + movq 0x7c0(%rbp), %rcx + addq %rcx, %rax + movq 0x7d0(%rbp), %rcx + addq %rcx, %rax + movq 0x7e0(%rbp), %rcx + addq %rcx, %rax + movq 0x7f0(%rbp), %rcx + addq %rcx, %rax + movq 0x800(%rbp), %rcx + addq %rcx, %rax + movq 0x810(%rbp), %rcx + addq %rcx, %rax + movq 0x820(%rbp), %rcx + addq %rcx, %rax + movq 0x830(%rbp), %rcx + addq %rcx, %rax + movq 0x840(%rbp), %rcx + addq %rcx, %rax + movq 0x850(%rbp), %rcx + addq %rcx, %rax + movq 0x860(%rbp), %rcx + addq %rcx, %rax + movq 0x870(%rbp), %rcx + addq %rcx, %rax + movq 0x880(%rbp), %rcx + addq %rcx, %rax + movq 0x890(%rbp), %rcx + addq %rcx, %rax + movq 0x8a0(%rbp), %rcx + addq %rcx, %rax + movq 0x8b0(%rbp), %rcx + addq %rcx, %rax + movq 0x8c0(%rbp), %rcx + addq %rcx, %rax + movq 0x8d0(%rbp), %rcx + addq %rcx, %rax + movq 0x8e0(%rbp), %rcx + addq %rcx, %rax + movq 0x8f0(%rbp), %rcx + addq %rcx, %rax + movq 0x900(%rbp), %rcx + addq %rcx, %rax + movq 0x910(%rbp), %rcx + addq %rcx, %rax + movq 0x920(%rbp), %rcx + addq %rcx, %rax + movq 0x930(%rbp), %rcx + addq %rcx, %rax + movq 0x940(%rbp), %rcx + addq %rcx, %rax + movq 0x950(%rbp), %rcx + addq %rcx, %rax + movq 0x960(%rbp), %rcx + addq %rcx, %rax + movq 0x970(%rbp), %rcx + addq %rcx, %rax + movq 0x980(%rbp), %rcx + addq %rcx, %rax + movq 0x990(%rbp), %rcx + addq %rcx, %rax + movq 0x9a0(%rbp), %rcx + addq %rcx, %rax + movq 0x9b0(%rbp), %rcx + addq %rcx, %rax + movq 0x9c0(%rbp), %rcx + addq %rcx, %rax + movq 0x9d0(%rbp), %rcx + addq %rcx, %rax + movq 0x9e0(%rbp), %rcx + addq %rcx, %rax + movq 0x9f0(%rbp), %rcx + addq %rcx, %rax + movq 0xa00(%rbp), %rcx + addq %rcx, %rax + movq 0xa10(%rbp), %rcx + addq %rcx, %rax + movq 0xa20(%rbp), %rcx + addq %rcx, %rax + movq 0xa30(%rbp), %rcx + addq %rcx, %rax + movq 0xa40(%rbp), %rcx + addq %rcx, %rax + movq 0xa50(%rbp), %rcx + addq %rcx, %rax + movq 0xa60(%rbp), %rcx + addq %rcx, %rax + movq 0xa70(%rbp), %rcx + addq %rcx, %rax + movq 0xa80(%rbp), %rcx + addq %rcx, %rax + movq 0xa90(%rbp), %rcx + addq %rcx, %rax + movq 0xaa0(%rbp), %rcx + addq %rcx, %rax + movq 0xab0(%rbp), %rcx + addq %rcx, %rax + movq 0xac0(%rbp), %rcx + addq %rcx, %rax + movq 0xad0(%rbp), %rcx + addq %rcx, %rax + movq 0xae0(%rbp), %rcx + addq %rcx, %rax + movq 0xaf0(%rbp), %rcx + addq %rcx, %rax + movq 0xb00(%rbp), %rcx + addq %rcx, %rax + movq 0xb10(%rbp), %rcx + addq %rcx, %rax + movq 0xb20(%rbp), %rcx + addq %rcx, %rax + movq 0xb30(%rbp), %rcx + addq %rcx, %rax + movq 0xb40(%rbp), %rcx + addq %rcx, %rax + movq 0xb50(%rbp), %rcx + addq %rcx, %rax + movq 0xb60(%rbp), %rcx + addq %rcx, %rax + movq 0xb70(%rbp), %rcx + addq %rcx, %rax + movq 0xb80(%rbp), %rcx + addq %rcx, %rax + movq 0xb90(%rbp), %rcx + addq %rcx, %rax + movq 0xba0(%rbp), %rcx + addq %rcx, %rax + movq 0xbb0(%rbp), %rcx + addq %rcx, %rax + movq 0xbc0(%rbp), %rcx + addq %rcx, %rax + movq 0xbd0(%rbp), %rcx + addq %rcx, %rax + movq 0xbe0(%rbp), %rcx + addq %rcx, %rax + movq 0xbf0(%rbp), %rcx + addq %rcx, %rax + movq 0xc00(%rbp), %rcx + addq %rcx, %rax + movq 0xc10(%rbp), %rcx + addq %rcx, %rax + movq 0xc20(%rbp), %rcx + addq %rcx, %rax + movq 0xc30(%rbp), %rcx + addq %rcx, %rax + movq 0xc40(%rbp), %rcx + addq %rcx, %rax + movq 0xc50(%rbp), %rcx + addq %rcx, %rax + movq 0xc60(%rbp), %rcx + addq %rcx, %rax + movq 0xc70(%rbp), %rcx + addq %rcx, %rax + movq 0xc80(%rbp), %rcx + addq %rcx, %rax + movq 0xc90(%rbp), %rcx + addq %rcx, %rax + movq 0xca0(%rbp), %rcx + addq %rcx, %rax + movq 0xcb0(%rbp), %rcx + addq %rcx, %rax + movq 0xcc0(%rbp), %rcx + addq %rcx, %rax + movq 0xcd0(%rbp), %rcx + addq %rcx, %rax + movq 0xce0(%rbp), %rcx + addq %rcx, %rax + movq 0xcf0(%rbp), %rcx + addq %rcx, %rax + movq 0xd00(%rbp), %rcx + addq %rcx, %rax + movq 0xd10(%rbp), %rcx + addq %rcx, %rax + movq 0xd20(%rbp), %rcx + addq %rcx, %rax + movq 0xd30(%rbp), %rcx + addq %rcx, %rax + movq 0xd40(%rbp), %rcx + addq %rcx, %rax + movq 0xd50(%rbp), %rcx + addq %rcx, %rax + movq 0xd60(%rbp), %rcx + addq %rcx, %rax + movq 0xd70(%rbp), %rcx + addq %rcx, %rax + movq 0xd80(%rbp), %rcx + addq %rcx, %rax + movq 0xd90(%rbp), %rcx + addq %rcx, %rax + movq 0xda0(%rbp), %rcx + addq %rcx, %rax + movq 0xdb0(%rbp), %rcx + addq %rcx, %rax + movq 0xdc0(%rbp), %rcx + addq %rcx, %rax + movq 0xdd0(%rbp), %rcx + addq %rcx, %rax + movq 0xde0(%rbp), %rcx + addq %rcx, %rax + movq 0xdf0(%rbp), %rcx + addq %rcx, %rax + movq 0xe00(%rbp), %rcx + addq %rcx, %rax + movq 0xe10(%rbp), %rcx + addq %rcx, %rax + movq 0xe20(%rbp), %rcx + addq %rcx, %rax + movq 0xe30(%rbp), %rcx + addq %rcx, %rax + movq 0xe40(%rbp), %rcx + addq %rcx, %rax + movq 0xe50(%rbp), %rcx + addq %rcx, %rax + movq 0xe60(%rbp), %rcx + addq %rcx, %rax + movq 0xe70(%rbp), %rcx + addq %rcx, %rax + movq 0xe80(%rbp), %rcx + addq %rcx, %rax + movq 0xe90(%rbp), %rcx + addq %rcx, %rax + movq 0xea0(%rbp), %rcx + addq %rcx, %rax + movq 0xeb0(%rbp), %rcx + addq %rcx, %rax + movq 0xec0(%rbp), %rcx + addq %rcx, %rax + movq 0xed0(%rbp), %rcx + addq %rcx, %rax + movq 0xee0(%rbp), %rcx + addq %rcx, %rax + movq 0xef0(%rbp), %rcx + addq %rcx, %rax + movq 0xf00(%rbp), %rcx + addq %rcx, %rax + movq 0xf10(%rbp), %rcx + addq %rcx, %rax + movq 0xf20(%rbp), %rcx + addq %rcx, %rax + movq 0xf30(%rbp), %rcx + addq %rcx, %rax + movq 0xf40(%rbp), %rcx + addq %rcx, %rax + movq 0xf50(%rbp), %rcx + addq %rcx, %rax + movq 0xf60(%rbp), %rcx + addq %rcx, %rax + movq 0xf70(%rbp), %rcx + addq %rcx, %rax + movq 0xf80(%rbp), %rcx + addq %rcx, %rax + movq 0xf90(%rbp), %rcx + addq %rcx, %rax + movq 0xfa0(%rbp), %rcx + addq %rcx, %rax + movq 0xfb0(%rbp), %rcx + addq %rcx, %rax + movq 0xfc0(%rbp), %rcx + addq %rcx, %rax + movq 0xfd0(%rbp), %rcx + addq %rcx, %rax + movq 0xfe0(%rbp), %rcx + addq %rcx, %rax + movq 0xff0(%rbp), %rcx + addq %rcx, %rax + movq 0x1000(%rbp), %rcx + addq %rcx, %rax + movq 0x1010(%rbp), %rcx + addq %rcx, %rax + movq 0x1020(%rbp), %rcx + addq %rcx, %rax + movq 0x1030(%rbp), %rcx + addq %rcx, %rax + movq 0x1040(%rbp), %rcx + addq %rcx, %rax + movq (%rsp), %rbx + addq $0x20, %rsp + popq %rbp + popq %r11 + addq $0x1040, %rsp # imm = 0x1040 + pushq %r11 + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x1050, %rsp # imm = 0x1050 + movq %rbx, (%rsp) + movq %r12, 0x8(%rsp) + movq %r13, 0x10(%rsp) + movq %r14, 0x18(%rsp) + movq %r15, 0x20(%rsp) + leaq -, %rbx # + leaq -, %r12 # + xorq %rcx, %rcx + cmpq $0x105, %rcx # imm = 0x105 + jge + jmp + incq %rcx + jmp + leaq , %rax + movq %rcx, %rdx + shlq $0x4, %rdx + addq %rax, %rdx + movq %rcx, (%rdx) + movq %rcx, %rdx + shlq $0x4, %rdx + addq %rdx, %rax + movq %rcx, %rdx + shlq $0x1, %rdx + movq %rdx, 0x8(%rax) + jmp + leaq , %rdi + leaq 0x10(%rdi), %rsi + leaq 0x20(%rdi), %rdx + leaq 0x30(%rdi), %rcx + leaq 0x40(%rdi), %r8 + leaq 0x50(%rdi), %r9 + leaq 0x60(%rdi), %rax + leaq 0x70(%rdi), %r13 + leaq 0x80(%rdi), %r14 + leaq 0x90(%rdi), %r15 + leaq 0xa0(%rdi), %r10 + movq %r10, 0x808(%rsp) + leaq 0xb0(%rdi), %r10 + movq %r10, 0x800(%rsp) + leaq 0xc0(%rdi), %r10 + movq %r10, 0x7f8(%rsp) + leaq 0xd0(%rdi), %r10 + movq %r10, 0x7f0(%rsp) + leaq 0xe0(%rdi), %r10 + movq %r10, 0x7e8(%rsp) + leaq 0xf0(%rdi), %r10 + movq %r10, 0x7e0(%rsp) + leaq 0x100(%rdi), %r10 + movq %r10, 0x7d8(%rsp) + leaq 0x110(%rdi), %r10 + movq %r10, 0x7d0(%rsp) + leaq 0x120(%rdi), %r10 + movq %r10, 0x7c8(%rsp) + leaq 0x130(%rdi), %r10 + movq %r10, 0x7c0(%rsp) + leaq 0x140(%rdi), %r10 + movq %r10, 0x7b8(%rsp) + leaq 0x150(%rdi), %r10 + movq %r10, 0x7b0(%rsp) + leaq 0x160(%rdi), %r10 + movq %r10, 0x7a8(%rsp) + leaq 0x170(%rdi), %r10 + movq %r10, 0x7a0(%rsp) + leaq 0x180(%rdi), %r10 + movq %r10, 0x798(%rsp) + leaq 0x190(%rdi), %r10 + movq %r10, 0x790(%rsp) + leaq 0x1a0(%rdi), %r10 + movq %r10, 0x788(%rsp) + leaq 0x1b0(%rdi), %r10 + movq %r10, 0x780(%rsp) + leaq 0x1c0(%rdi), %r10 + movq %r10, 0x778(%rsp) + leaq 0x1d0(%rdi), %r10 + movq %r10, 0x770(%rsp) + leaq 0x1e0(%rdi), %r10 + movq %r10, 0x768(%rsp) + leaq 0x1f0(%rdi), %r10 + movq %r10, 0x760(%rsp) + leaq 0x200(%rdi), %r10 + movq %r10, 0x758(%rsp) + leaq 0x210(%rdi), %r10 + movq %r10, 0x750(%rsp) + leaq 0x220(%rdi), %r10 + movq %r10, 0x748(%rsp) + leaq 0x230(%rdi), %r10 + movq %r10, 0x740(%rsp) + leaq 0x240(%rdi), %r10 + movq %r10, 0x738(%rsp) + leaq 0x250(%rdi), %r10 + movq %r10, 0x730(%rsp) + leaq 0x260(%rdi), %r10 + movq %r10, 0x728(%rsp) + leaq 0x270(%rdi), %r10 + movq %r10, 0x720(%rsp) + leaq 0x280(%rdi), %r10 + movq %r10, 0x718(%rsp) + leaq 0x290(%rdi), %r10 + movq %r10, 0x710(%rsp) + leaq 0x2a0(%rdi), %r10 + movq %r10, 0x708(%rsp) + leaq 0x2b0(%rdi), %r10 + movq %r10, 0x700(%rsp) + leaq 0x2c0(%rdi), %r10 + movq %r10, 0x6f8(%rsp) + leaq 0x2d0(%rdi), %r10 + movq %r10, 0x6f0(%rsp) + leaq 0x2e0(%rdi), %r10 + movq %r10, 0x6e8(%rsp) + leaq 0x2f0(%rdi), %r10 + movq %r10, 0x6e0(%rsp) + leaq 0x300(%rdi), %r10 + movq %r10, 0x6d8(%rsp) + leaq 0x310(%rdi), %r10 + movq %r10, 0x6d0(%rsp) + leaq 0x320(%rdi), %r10 + movq %r10, 0x6c8(%rsp) + leaq 0x330(%rdi), %r10 + movq %r10, 0x6c0(%rsp) + leaq 0x340(%rdi), %r10 + movq %r10, 0x6b8(%rsp) + leaq 0x350(%rdi), %r10 + movq %r10, 0x6b0(%rsp) + leaq 0x360(%rdi), %r10 + movq %r10, 0x6a8(%rsp) + leaq 0x370(%rdi), %r10 + movq %r10, 0x6a0(%rsp) + leaq 0x380(%rdi), %r10 + movq %r10, 0x698(%rsp) + leaq 0x390(%rdi), %r10 + movq %r10, 0x690(%rsp) + leaq 0x3a0(%rdi), %r10 + movq %r10, 0x688(%rsp) + leaq 0x3b0(%rdi), %r10 + movq %r10, 0x680(%rsp) + leaq 0x3c0(%rdi), %r10 + movq %r10, 0x678(%rsp) + leaq 0x3d0(%rdi), %r10 + movq %r10, 0x670(%rsp) + leaq 0x3e0(%rdi), %r10 + movq %r10, 0x668(%rsp) + leaq 0x3f0(%rdi), %r10 + movq %r10, 0x660(%rsp) + leaq 0x400(%rdi), %r10 + movq %r10, 0x658(%rsp) + leaq 0x410(%rdi), %r10 + movq %r10, 0x650(%rsp) + leaq 0x420(%rdi), %r10 + movq %r10, 0x648(%rsp) + leaq 0x430(%rdi), %r10 + movq %r10, 0x640(%rsp) + leaq 0x440(%rdi), %r10 + movq %r10, 0x638(%rsp) + leaq 0x450(%rdi), %r10 + movq %r10, 0x630(%rsp) + leaq 0x460(%rdi), %r10 + movq %r10, 0x628(%rsp) + leaq 0x470(%rdi), %r10 + movq %r10, 0x620(%rsp) + leaq 0x480(%rdi), %r10 + movq %r10, 0x618(%rsp) + leaq 0x490(%rdi), %r10 + movq %r10, 0x610(%rsp) + leaq 0x4a0(%rdi), %r10 + movq %r10, 0x608(%rsp) + leaq 0x4b0(%rdi), %r10 + movq %r10, 0x600(%rsp) + leaq 0x4c0(%rdi), %r10 + movq %r10, 0x5f8(%rsp) + leaq 0x4d0(%rdi), %r10 + movq %r10, 0x5f0(%rsp) + leaq 0x4e0(%rdi), %r10 + movq %r10, 0x5e8(%rsp) + leaq 0x4f0(%rdi), %r10 + movq %r10, 0x5e0(%rsp) + leaq 0x500(%rdi), %r10 + movq %r10, 0x5d8(%rsp) + leaq 0x510(%rdi), %r10 + movq %r10, 0x5d0(%rsp) + leaq 0x520(%rdi), %r10 + movq %r10, 0x5c8(%rsp) + leaq 0x530(%rdi), %r10 + movq %r10, 0x5c0(%rsp) + leaq 0x540(%rdi), %r10 + movq %r10, 0x5b8(%rsp) + leaq 0x550(%rdi), %r10 + movq %r10, 0x5b0(%rsp) + leaq 0x560(%rdi), %r10 + movq %r10, 0x5a8(%rsp) + leaq 0x570(%rdi), %r10 + movq %r10, 0x5a0(%rsp) + leaq 0x580(%rdi), %r10 + movq %r10, 0x598(%rsp) + leaq 0x590(%rdi), %r10 + movq %r10, 0x590(%rsp) + leaq 0x5a0(%rdi), %r10 + movq %r10, 0x588(%rsp) + leaq 0x5b0(%rdi), %r10 + movq %r10, 0x580(%rsp) + leaq 0x5c0(%rdi), %r10 + movq %r10, 0x578(%rsp) + leaq 0x5d0(%rdi), %r10 + movq %r10, 0x570(%rsp) + leaq 0x5e0(%rdi), %r10 + movq %r10, 0x568(%rsp) + leaq 0x5f0(%rdi), %r10 + movq %r10, 0x560(%rsp) + leaq 0x600(%rdi), %r10 + movq %r10, 0x558(%rsp) + leaq 0x610(%rdi), %r10 + movq %r10, 0x550(%rsp) + leaq 0x620(%rdi), %r10 + movq %r10, 0x548(%rsp) + leaq 0x630(%rdi), %r10 + movq %r10, 0x540(%rsp) + leaq 0x640(%rdi), %r10 + movq %r10, 0x538(%rsp) + leaq 0x650(%rdi), %r10 + movq %r10, 0x530(%rsp) + leaq 0x660(%rdi), %r10 + movq %r10, 0x528(%rsp) + leaq 0x670(%rdi), %r10 + movq %r10, 0x520(%rsp) + leaq 0x680(%rdi), %r10 + movq %r10, 0x518(%rsp) + leaq 0x690(%rdi), %r10 + movq %r10, 0x510(%rsp) + leaq 0x6a0(%rdi), %r10 + movq %r10, 0x508(%rsp) + leaq 0x6b0(%rdi), %r10 + movq %r10, 0x500(%rsp) + leaq 0x6c0(%rdi), %r10 + movq %r10, 0x4f8(%rsp) + leaq 0x6d0(%rdi), %r10 + movq %r10, 0x4f0(%rsp) + leaq 0x6e0(%rdi), %r10 + movq %r10, 0x4e8(%rsp) + leaq 0x6f0(%rdi), %r10 + movq %r10, 0x4e0(%rsp) + leaq 0x700(%rdi), %r10 + movq %r10, 0x4d8(%rsp) + leaq 0x710(%rdi), %r10 + movq %r10, 0x4d0(%rsp) + leaq 0x720(%rdi), %r10 + movq %r10, 0x4c8(%rsp) + leaq 0x730(%rdi), %r10 + movq %r10, 0x4c0(%rsp) + leaq 0x740(%rdi), %r10 + movq %r10, 0x4b8(%rsp) + leaq 0x750(%rdi), %r10 + movq %r10, 0x4b0(%rsp) + leaq 0x760(%rdi), %r10 + movq %r10, 0x4a8(%rsp) + leaq 0x770(%rdi), %r10 + movq %r10, 0x4a0(%rsp) + leaq 0x780(%rdi), %r10 + movq %r10, 0x498(%rsp) + leaq 0x790(%rdi), %r10 + movq %r10, 0x490(%rsp) + leaq 0x7a0(%rdi), %r10 + movq %r10, 0x488(%rsp) + leaq 0x7b0(%rdi), %r10 + movq %r10, 0x480(%rsp) + leaq 0x7c0(%rdi), %r10 + movq %r10, 0x478(%rsp) + leaq 0x7d0(%rdi), %r10 + movq %r10, 0x470(%rsp) + leaq 0x7e0(%rdi), %r10 + movq %r10, 0x468(%rsp) + leaq 0x7f0(%rdi), %r10 + movq %r10, 0x460(%rsp) + leaq 0x800(%rdi), %r10 + movq %r10, 0x458(%rsp) + leaq 0x810(%rdi), %r10 + movq %r10, 0x450(%rsp) + leaq 0x820(%rdi), %r10 + movq %r10, 0x448(%rsp) + leaq 0x830(%rdi), %r10 + movq %r10, 0x440(%rsp) + leaq 0x840(%rdi), %r10 + movq %r10, 0x438(%rsp) + leaq 0x850(%rdi), %r10 + movq %r10, 0x430(%rsp) + leaq 0x860(%rdi), %r10 + movq %r10, 0x428(%rsp) + leaq 0x870(%rdi), %r10 + movq %r10, 0x420(%rsp) + leaq 0x880(%rdi), %r10 + movq %r10, 0x418(%rsp) + leaq 0x890(%rdi), %r10 + movq %r10, 0x410(%rsp) + leaq 0x8a0(%rdi), %r10 + movq %r10, 0x408(%rsp) + leaq 0x8b0(%rdi), %r10 + movq %r10, 0x400(%rsp) + leaq 0x8c0(%rdi), %r10 + movq %r10, 0x3f8(%rsp) + leaq 0x8d0(%rdi), %r10 + movq %r10, 0x3f0(%rsp) + leaq 0x8e0(%rdi), %r10 + movq %r10, 0x3e8(%rsp) + leaq 0x8f0(%rdi), %r10 + movq %r10, 0x3e0(%rsp) + leaq 0x900(%rdi), %r10 + movq %r10, 0x3d8(%rsp) + leaq 0x910(%rdi), %r10 + movq %r10, 0x3d0(%rsp) + leaq 0x920(%rdi), %r10 + movq %r10, 0x3c8(%rsp) + leaq 0x930(%rdi), %r10 + movq %r10, 0x3c0(%rsp) + leaq 0x940(%rdi), %r10 + movq %r10, 0x3b8(%rsp) + leaq 0x950(%rdi), %r10 + movq %r10, 0x3b0(%rsp) + leaq 0x960(%rdi), %r10 + movq %r10, 0x3a8(%rsp) + leaq 0x970(%rdi), %r10 + movq %r10, 0x3a0(%rsp) + leaq 0x980(%rdi), %r10 + movq %r10, 0x398(%rsp) + leaq 0x990(%rdi), %r10 + movq %r10, 0x390(%rsp) + leaq 0x9a0(%rdi), %r10 + movq %r10, 0x388(%rsp) + leaq 0x9b0(%rdi), %r10 + movq %r10, 0x380(%rsp) + leaq 0x9c0(%rdi), %r10 + movq %r10, 0x378(%rsp) + leaq 0x9d0(%rdi), %r10 + movq %r10, 0x370(%rsp) + leaq 0x9e0(%rdi), %r10 + movq %r10, 0x368(%rsp) + leaq 0x9f0(%rdi), %r10 + movq %r10, 0x360(%rsp) + leaq 0xa00(%rdi), %r10 + movq %r10, 0x358(%rsp) + leaq 0xa10(%rdi), %r10 + movq %r10, 0x350(%rsp) + leaq 0xa20(%rdi), %r10 + movq %r10, 0x348(%rsp) + leaq 0xa30(%rdi), %r10 + movq %r10, 0x340(%rsp) + leaq 0xa40(%rdi), %r10 + movq %r10, 0x338(%rsp) + leaq 0xa50(%rdi), %r10 + movq %r10, 0x330(%rsp) + leaq 0xa60(%rdi), %r10 + movq %r10, 0x328(%rsp) + leaq 0xa70(%rdi), %r10 + movq %r10, 0x320(%rsp) + leaq 0xa80(%rdi), %r10 + movq %r10, 0x318(%rsp) + leaq 0xa90(%rdi), %r10 + movq %r10, 0x310(%rsp) + leaq 0xaa0(%rdi), %r10 + movq %r10, 0x308(%rsp) + leaq 0xab0(%rdi), %r10 + movq %r10, 0x300(%rsp) + leaq 0xac0(%rdi), %r10 + movq %r10, 0x2f8(%rsp) + leaq 0xad0(%rdi), %r10 + movq %r10, 0x2f0(%rsp) + leaq 0xae0(%rdi), %r10 + movq %r10, 0x2e8(%rsp) + leaq 0xaf0(%rdi), %r10 + movq %r10, 0x2e0(%rsp) + leaq 0xb00(%rdi), %r10 + movq %r10, 0x2d8(%rsp) + leaq 0xb10(%rdi), %r10 + movq %r10, 0x2d0(%rsp) + leaq 0xb20(%rdi), %r10 + movq %r10, 0x2c8(%rsp) + leaq 0xb30(%rdi), %r10 + movq %r10, 0x2c0(%rsp) + leaq 0xb40(%rdi), %r10 + movq %r10, 0x2b8(%rsp) + leaq 0xb50(%rdi), %r10 + movq %r10, 0x2b0(%rsp) + leaq 0xb60(%rdi), %r10 + movq %r10, 0x2a8(%rsp) + leaq 0xb70(%rdi), %r10 + movq %r10, 0x2a0(%rsp) + leaq 0xb80(%rdi), %r10 + movq %r10, 0x298(%rsp) + leaq 0xb90(%rdi), %r10 + movq %r10, 0x290(%rsp) + leaq 0xba0(%rdi), %r10 + movq %r10, 0x288(%rsp) + leaq 0xbb0(%rdi), %r10 + movq %r10, 0x280(%rsp) + leaq 0xbc0(%rdi), %r10 + movq %r10, 0x278(%rsp) + leaq 0xbd0(%rdi), %r10 + movq %r10, 0x270(%rsp) + leaq 0xbe0(%rdi), %r10 + movq %r10, 0x268(%rsp) + leaq 0xbf0(%rdi), %r10 + movq %r10, 0x260(%rsp) + leaq 0xc00(%rdi), %r10 + movq %r10, 0x258(%rsp) + leaq 0xc10(%rdi), %r10 + movq %r10, 0x250(%rsp) + leaq 0xc20(%rdi), %r10 + movq %r10, 0x248(%rsp) + leaq 0xc30(%rdi), %r10 + movq %r10, 0x240(%rsp) + leaq 0xc40(%rdi), %r10 + movq %r10, 0x238(%rsp) + leaq 0xc50(%rdi), %r10 + movq %r10, 0x230(%rsp) + leaq 0xc60(%rdi), %r10 + movq %r10, 0x228(%rsp) + leaq 0xc70(%rdi), %r10 + movq %r10, 0x220(%rsp) + leaq 0xc80(%rdi), %r10 + movq %r10, 0x218(%rsp) + leaq 0xc90(%rdi), %r10 + movq %r10, 0x210(%rsp) + leaq 0xca0(%rdi), %r10 + movq %r10, 0x208(%rsp) + leaq 0xcb0(%rdi), %r10 + movq %r10, 0x200(%rsp) + leaq 0xcc0(%rdi), %r10 + movq %r10, 0x1f8(%rsp) + leaq 0xcd0(%rdi), %r10 + movq %r10, 0x1f0(%rsp) + leaq 0xce0(%rdi), %r10 + movq %r10, 0x1e8(%rsp) + leaq 0xcf0(%rdi), %r10 + movq %r10, 0x1e0(%rsp) + leaq 0xd00(%rdi), %r10 + movq %r10, 0x1d8(%rsp) + leaq 0xd10(%rdi), %r10 + movq %r10, 0x1d0(%rsp) + leaq 0xd20(%rdi), %r10 + movq %r10, 0x1c8(%rsp) + leaq 0xd30(%rdi), %r10 + movq %r10, 0x1c0(%rsp) + leaq 0xd40(%rdi), %r10 + movq %r10, 0x1b8(%rsp) + leaq 0xd50(%rdi), %r10 + movq %r10, 0x1b0(%rsp) + leaq 0xd60(%rdi), %r10 + movq %r10, 0x1a8(%rsp) + leaq 0xd70(%rdi), %r10 + movq %r10, 0x1a0(%rsp) + leaq 0xd80(%rdi), %r10 + movq %r10, 0x198(%rsp) + leaq 0xd90(%rdi), %r10 + movq %r10, 0x190(%rsp) + leaq 0xda0(%rdi), %r10 + movq %r10, 0x188(%rsp) + leaq 0xdb0(%rdi), %r10 + movq %r10, 0x180(%rsp) + leaq 0xdc0(%rdi), %r10 + movq %r10, 0x178(%rsp) + leaq 0xdd0(%rdi), %r10 + movq %r10, 0x170(%rsp) + leaq 0xde0(%rdi), %r10 + movq %r10, 0x168(%rsp) + leaq 0xdf0(%rdi), %r10 + movq %r10, 0x160(%rsp) + leaq 0xe00(%rdi), %r10 + movq %r10, 0x158(%rsp) + leaq 0xe10(%rdi), %r10 + movq %r10, 0x150(%rsp) + leaq 0xe20(%rdi), %r10 + movq %r10, 0x148(%rsp) + leaq 0xe30(%rdi), %r10 + movq %r10, 0x140(%rsp) + leaq 0xe40(%rdi), %r10 + movq %r10, 0x138(%rsp) + leaq 0xe50(%rdi), %r10 + movq %r10, 0x130(%rsp) + leaq 0xe60(%rdi), %r10 + movq %r10, 0x128(%rsp) + leaq 0xe70(%rdi), %r10 + movq %r10, 0x120(%rsp) + leaq 0xe80(%rdi), %r10 + movq %r10, 0x118(%rsp) + leaq 0xe90(%rdi), %r10 + movq %r10, 0x110(%rsp) + leaq 0xea0(%rdi), %r10 + movq %r10, 0x108(%rsp) + leaq 0xeb0(%rdi), %r10 + movq %r10, 0x100(%rsp) + leaq 0xec0(%rdi), %r10 + movq %r10, 0xf8(%rsp) + leaq 0xed0(%rdi), %r10 + movq %r10, 0xf0(%rsp) + leaq 0xee0(%rdi), %r10 + movq %r10, 0xe8(%rsp) + leaq 0xef0(%rdi), %r10 + movq %r10, 0xe0(%rsp) + leaq 0xf00(%rdi), %r10 + movq %r10, 0xd8(%rsp) + leaq 0xf10(%rdi), %r10 + movq %r10, 0xd0(%rsp) + leaq 0xf20(%rdi), %r10 + movq %r10, 0xc8(%rsp) + leaq 0xf30(%rdi), %r10 + movq %r10, 0xc0(%rsp) + leaq 0xf40(%rdi), %r10 + movq %r10, 0xb8(%rsp) + leaq 0xf50(%rdi), %r10 + movq %r10, 0xb0(%rsp) + leaq 0xf60(%rdi), %r10 + movq %r10, 0xa8(%rsp) + leaq 0xf70(%rdi), %r10 + movq %r10, 0xa0(%rsp) + leaq 0xf80(%rdi), %r10 + movq %r10, 0x98(%rsp) + leaq 0xf90(%rdi), %r10 + movq %r10, 0x90(%rsp) + leaq 0xfa0(%rdi), %r10 + movq %r10, 0x88(%rsp) + leaq 0xfb0(%rdi), %r10 + movq %r10, 0x80(%rsp) + leaq 0xfc0(%rdi), %r10 + movq %r10, 0x78(%rsp) + leaq 0xfd0(%rdi), %r10 + movq %r10, 0x70(%rsp) + leaq 0xfe0(%rdi), %r10 + movq %r10, 0x68(%rsp) + leaq 0xff0(%rdi), %r10 + movq %r10, 0x60(%rsp) + leaq 0x1000(%rdi), %r10 + movq %r10, 0x58(%rsp) + leaq 0x1010(%rdi), %r10 + movq %r10, 0x50(%rsp) + leaq 0x1020(%rdi), %r10 + movq %r10, 0x48(%rsp) + leaq 0x1030(%rdi), %r10 + movq %r10, 0x40(%rsp) + leaq 0x1040(%rdi), %r10 + movq %r10, 0x38(%rsp) + subq $0x1020, %rsp # imm = 0x1020 + movq %rcx, %r10 + movq (%r10), %r11 + movq %r11, (%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8(%rsp) + movq %r8, %r10 + movq (%r10), %r11 + movq %r11, 0x10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x18(%rsp) + movq %r9, %r10 + movq (%r10), %r11 + movq %r11, 0x20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x28(%rsp) + movq %rax, %r10 + movq (%r10), %r11 + movq %r11, 0x30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x38(%rsp) + movq %r13, %r10 + movq (%r10), %r11 + movq %r11, 0x40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x48(%rsp) + movq %r14, %r10 + movq (%r10), %r11 + movq %r11, 0x50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x58(%rsp) + movq %r15, %r10 + movq (%r10), %r11 + movq %r11, 0x60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x68(%rsp) + movq 0x1828(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x78(%rsp) + movq 0x1820(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x88(%rsp) + movq 0x1818(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x98(%rsp) + movq 0x1810(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa8(%rsp) + movq 0x1808(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb8(%rsp) + movq 0x1800(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc8(%rsp) + movq 0x17f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd8(%rsp) + movq 0x17f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe8(%rsp) + movq 0x17e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf8(%rsp) + movq 0x17e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x100(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x108(%rsp) + movq 0x17d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x110(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x118(%rsp) + movq 0x17d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x120(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x128(%rsp) + movq 0x17c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x130(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x138(%rsp) + movq 0x17c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x140(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x148(%rsp) + movq 0x17b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x150(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x158(%rsp) + movq 0x17b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x160(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x168(%rsp) + movq 0x17a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x170(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x178(%rsp) + movq 0x17a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x180(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x188(%rsp) + movq 0x1798(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x190(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x198(%rsp) + movq 0x1790(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1a8(%rsp) + movq 0x1788(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1b8(%rsp) + movq 0x1780(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1c8(%rsp) + movq 0x1778(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1d8(%rsp) + movq 0x1770(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1e8(%rsp) + movq 0x1768(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1f8(%rsp) + movq 0x1760(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x200(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x208(%rsp) + movq 0x1758(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x210(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x218(%rsp) + movq 0x1750(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x220(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x228(%rsp) + movq 0x1748(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x230(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x238(%rsp) + movq 0x1740(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x240(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x248(%rsp) + movq 0x1738(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x250(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x258(%rsp) + movq 0x1730(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x260(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x268(%rsp) + movq 0x1728(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x270(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x278(%rsp) + movq 0x1720(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x280(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x288(%rsp) + movq 0x1718(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x290(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x298(%rsp) + movq 0x1710(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x2a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x2a8(%rsp) + movq 0x1708(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x2b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x2b8(%rsp) + movq 0x1700(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x2c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x2c8(%rsp) + movq 0x16f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x2d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x2d8(%rsp) + movq 0x16f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x2e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x2e8(%rsp) + movq 0x16e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x2f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x2f8(%rsp) + movq 0x16e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x300(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x308(%rsp) + movq 0x16d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x310(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x318(%rsp) + movq 0x16d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x320(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x328(%rsp) + movq 0x16c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x330(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x338(%rsp) + movq 0x16c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x340(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x348(%rsp) + movq 0x16b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x350(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x358(%rsp) + movq 0x16b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x360(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x368(%rsp) + movq 0x16a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x370(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x378(%rsp) + movq 0x16a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x380(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x388(%rsp) + movq 0x1698(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x390(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x398(%rsp) + movq 0x1690(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x3a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x3a8(%rsp) + movq 0x1688(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x3b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x3b8(%rsp) + movq 0x1680(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x3c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x3c8(%rsp) + movq 0x1678(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x3d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x3d8(%rsp) + movq 0x1670(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x3e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x3e8(%rsp) + movq 0x1668(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x3f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x3f8(%rsp) + movq 0x1660(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x400(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x408(%rsp) + movq 0x1658(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x410(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x418(%rsp) + movq 0x1650(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x420(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x428(%rsp) + movq 0x1648(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x430(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x438(%rsp) + movq 0x1640(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x440(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x448(%rsp) + movq 0x1638(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x450(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x458(%rsp) + movq 0x1630(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x460(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x468(%rsp) + movq 0x1628(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x470(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x478(%rsp) + movq 0x1620(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x480(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x488(%rsp) + movq 0x1618(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x490(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x498(%rsp) + movq 0x1610(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x4a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x4a8(%rsp) + movq 0x1608(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x4b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x4b8(%rsp) + movq 0x1600(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x4c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x4c8(%rsp) + movq 0x15f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x4d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x4d8(%rsp) + movq 0x15f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x4e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x4e8(%rsp) + movq 0x15e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x4f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x4f8(%rsp) + movq 0x15e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x500(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x508(%rsp) + movq 0x15d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x510(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x518(%rsp) + movq 0x15d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x520(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x528(%rsp) + movq 0x15c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x530(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x538(%rsp) + movq 0x15c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x540(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x548(%rsp) + movq 0x15b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x550(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x558(%rsp) + movq 0x15b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x560(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x568(%rsp) + movq 0x15a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x570(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x578(%rsp) + movq 0x15a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x580(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x588(%rsp) + movq 0x1598(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x590(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x598(%rsp) + movq 0x1590(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x5a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x5a8(%rsp) + movq 0x1588(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x5b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x5b8(%rsp) + movq 0x1580(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x5c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x5c8(%rsp) + movq 0x1578(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x5d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x5d8(%rsp) + movq 0x1570(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x5e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x5e8(%rsp) + movq 0x1568(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x5f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x5f8(%rsp) + movq 0x1560(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x600(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x608(%rsp) + movq 0x1558(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x610(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x618(%rsp) + movq 0x1550(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x620(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x628(%rsp) + movq 0x1548(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x630(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x638(%rsp) + movq 0x1540(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x640(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x648(%rsp) + movq 0x1538(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x650(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x658(%rsp) + movq 0x1530(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x660(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x668(%rsp) + movq 0x1528(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x670(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x678(%rsp) + movq 0x1520(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x680(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x688(%rsp) + movq 0x1518(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x690(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x698(%rsp) + movq 0x1510(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x6a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x6a8(%rsp) + movq 0x1508(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x6b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x6b8(%rsp) + movq 0x1500(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x6c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x6c8(%rsp) + movq 0x14f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x6d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x6d8(%rsp) + movq 0x14f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x6e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x6e8(%rsp) + movq 0x14e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x6f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x6f8(%rsp) + movq 0x14e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x700(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x708(%rsp) + movq 0x14d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x710(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x718(%rsp) + movq 0x14d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x720(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x728(%rsp) + movq 0x14c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x730(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x738(%rsp) + movq 0x14c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x740(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x748(%rsp) + movq 0x14b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x750(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x758(%rsp) + movq 0x14b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x760(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x768(%rsp) + movq 0x14a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x770(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x778(%rsp) + movq 0x14a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x780(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x788(%rsp) + movq 0x1498(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x790(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x798(%rsp) + movq 0x1490(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x7a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x7a8(%rsp) + movq 0x1488(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x7b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x7b8(%rsp) + movq 0x1480(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x7c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x7c8(%rsp) + movq 0x1478(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x7d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x7d8(%rsp) + movq 0x1470(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x7e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x7e8(%rsp) + movq 0x1468(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x7f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x7f8(%rsp) + movq 0x1460(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x800(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x808(%rsp) + movq 0x1458(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x810(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x818(%rsp) + movq 0x1450(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x820(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x828(%rsp) + movq 0x1448(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x830(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x838(%rsp) + movq 0x1440(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x840(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x848(%rsp) + movq 0x1438(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x850(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x858(%rsp) + movq 0x1430(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x860(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x868(%rsp) + movq 0x1428(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x870(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x878(%rsp) + movq 0x1420(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x880(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x888(%rsp) + movq 0x1418(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x890(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x898(%rsp) + movq 0x1410(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x8a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8a8(%rsp) + movq 0x1408(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x8b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8b8(%rsp) + movq 0x1400(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x8c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8c8(%rsp) + movq 0x13f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x8d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8d8(%rsp) + movq 0x13f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x8e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8e8(%rsp) + movq 0x13e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x8f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8f8(%rsp) + movq 0x13e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x900(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x908(%rsp) + movq 0x13d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x910(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x918(%rsp) + movq 0x13d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x920(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x928(%rsp) + movq 0x13c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x930(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x938(%rsp) + movq 0x13c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x940(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x948(%rsp) + movq 0x13b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x950(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x958(%rsp) + movq 0x13b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x960(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x968(%rsp) + movq 0x13a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x970(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x978(%rsp) + movq 0x13a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x980(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x988(%rsp) + movq 0x1398(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x990(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x998(%rsp) + movq 0x1390(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x9a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x9a8(%rsp) + movq 0x1388(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x9b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x9b8(%rsp) + movq 0x1380(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x9c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x9c8(%rsp) + movq 0x1378(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x9d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x9d8(%rsp) + movq 0x1370(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x9e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x9e8(%rsp) + movq 0x1368(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x9f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x9f8(%rsp) + movq 0x1360(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa00(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa08(%rsp) + movq 0x1358(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa18(%rsp) + movq 0x1350(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa28(%rsp) + movq 0x1348(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa38(%rsp) + movq 0x1340(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa48(%rsp) + movq 0x1338(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa58(%rsp) + movq 0x1330(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa68(%rsp) + movq 0x1328(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa78(%rsp) + movq 0x1320(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa88(%rsp) + movq 0x1318(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa98(%rsp) + movq 0x1310(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xaa0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xaa8(%rsp) + movq 0x1308(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xab0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xab8(%rsp) + movq 0x1300(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xac0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xac8(%rsp) + movq 0x12f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xad0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xad8(%rsp) + movq 0x12f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xae0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xae8(%rsp) + movq 0x12e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xaf0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xaf8(%rsp) + movq 0x12e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb00(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb08(%rsp) + movq 0x12d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb18(%rsp) + movq 0x12d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb28(%rsp) + movq 0x12c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb38(%rsp) + movq 0x12c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb48(%rsp) + movq 0x12b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb58(%rsp) + movq 0x12b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb68(%rsp) + movq 0x12a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb78(%rsp) + movq 0x12a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb88(%rsp) + movq 0x1298(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb98(%rsp) + movq 0x1290(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xba0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xba8(%rsp) + movq 0x1288(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xbb0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xbb8(%rsp) + movq 0x1280(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xbc0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xbc8(%rsp) + movq 0x1278(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xbd0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xbd8(%rsp) + movq 0x1270(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xbe0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xbe8(%rsp) + movq 0x1268(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xbf0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xbf8(%rsp) + movq 0x1260(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc00(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc08(%rsp) + movq 0x1258(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc18(%rsp) + movq 0x1250(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc28(%rsp) + movq 0x1248(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc38(%rsp) + movq 0x1240(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc48(%rsp) + movq 0x1238(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc58(%rsp) + movq 0x1230(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc68(%rsp) + movq 0x1228(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc78(%rsp) + movq 0x1220(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc88(%rsp) + movq 0x1218(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc98(%rsp) + movq 0x1210(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xca0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xca8(%rsp) + movq 0x1208(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xcb0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xcb8(%rsp) + movq 0x1200(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xcc0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xcc8(%rsp) + movq 0x11f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xcd0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xcd8(%rsp) + movq 0x11f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xce0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xce8(%rsp) + movq 0x11e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xcf0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xcf8(%rsp) + movq 0x11e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd00(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd08(%rsp) + movq 0x11d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd18(%rsp) + movq 0x11d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd28(%rsp) + movq 0x11c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd38(%rsp) + movq 0x11c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd48(%rsp) + movq 0x11b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd58(%rsp) + movq 0x11b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd68(%rsp) + movq 0x11a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd78(%rsp) + movq 0x11a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd88(%rsp) + movq 0x1198(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd98(%rsp) + movq 0x1190(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xda0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xda8(%rsp) + movq 0x1188(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xdb0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xdb8(%rsp) + movq 0x1180(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xdc0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xdc8(%rsp) + movq 0x1178(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xdd0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xdd8(%rsp) + movq 0x1170(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xde0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xde8(%rsp) + movq 0x1168(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xdf0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xdf8(%rsp) + movq 0x1160(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe00(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe08(%rsp) + movq 0x1158(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe18(%rsp) + movq 0x1150(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe28(%rsp) + movq 0x1148(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe38(%rsp) + movq 0x1140(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe48(%rsp) + movq 0x1138(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe58(%rsp) + movq 0x1130(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe68(%rsp) + movq 0x1128(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe78(%rsp) + movq 0x1120(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe88(%rsp) + movq 0x1118(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe98(%rsp) + movq 0x1110(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xea0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xea8(%rsp) + movq 0x1108(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xeb0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xeb8(%rsp) + movq 0x1100(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xec0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xec8(%rsp) + movq 0x10f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xed0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xed8(%rsp) + movq 0x10f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xee0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xee8(%rsp) + movq 0x10e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xef0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xef8(%rsp) + movq 0x10e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf00(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf08(%rsp) + movq 0x10d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf18(%rsp) + movq 0x10d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf28(%rsp) + movq 0x10c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf38(%rsp) + movq 0x10c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf48(%rsp) + movq 0x10b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf58(%rsp) + movq 0x10b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf68(%rsp) + movq 0x10a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf78(%rsp) + movq 0x10a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf88(%rsp) + movq 0x1098(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf98(%rsp) + movq 0x1090(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xfa0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xfa8(%rsp) + movq 0x1088(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xfb0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xfb8(%rsp) + movq 0x1080(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xfc0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xfc8(%rsp) + movq 0x1078(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xfd0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xfd8(%rsp) + movq 0x1070(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xfe0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xfe8(%rsp) + movq 0x1068(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xff0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xff8(%rsp) + movq 0x1060(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1000(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1008(%rsp) + movq 0x1058(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1010(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1018(%rsp) + movq %rdx, %r8 + movq %rsi, %rdx + movq 0x8(%rdi), %rsi + movq (%rdi), %rdi + movq 0x8(%rdx), %rcx + movq (%rdx), %rdx + movq 0x8(%r8), %r9 + movq (%r8), %r8 + callq + addq $0x1020, %rsp # imm = 0x1020 + cmpq $0x18d9e, %rax # imm = 0x18D9E + je + movl $0x1, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + movq 0x18(%rsp), %r14 + movq 0x20(%rsp), %r15 + addq $0x1050, %rsp # imm = 0x1050 + popq %rbp + retq + movl $0x1, %edi + movl $0x2, %esi + movl $0x3, %edx + movl $0x4, %ecx + movl $0x5, %r8d + movl $0x6, %r9d + movl $0x7, %eax + movl $0x8, %r13d + movl $0x9, %r14d + movl $0xa, %r15d + movl $0xb, %r10d + movq %r10, 0x808(%rsp) + movl $0xc, %r10d + movq %r10, 0x800(%rsp) + movl $0xd, %r10d + movq %r10, 0x7f8(%rsp) + movl $0xe, %r10d + movq %r10, 0x7f0(%rsp) + movl $0xf, %r10d + movq %r10, 0x7e8(%rsp) + movl $0x10, %r10d + movq %r10, 0x7e0(%rsp) + movl $0x11, %r10d + movq %r10, 0x7d8(%rsp) + movl $0x12, %r10d + movq %r10, 0x7d0(%rsp) + movl $0x13, %r10d + movq %r10, 0x7c8(%rsp) + movl $0x14, %r10d + movq %r10, 0x7c0(%rsp) + movl $0x15, %r10d + movq %r10, 0x7b8(%rsp) + movl $0x16, %r10d + movq %r10, 0x7b0(%rsp) + movl $0x17, %r10d + movq %r10, 0x7a8(%rsp) + movl $0x18, %r10d + movq %r10, 0x7a0(%rsp) + movl $0x19, %r10d + movq %r10, 0x798(%rsp) + movl $0x1a, %r10d + movq %r10, 0x790(%rsp) + movl $0x1b, %r10d + movq %r10, 0x788(%rsp) + movl $0x1c, %r10d + movq %r10, 0x780(%rsp) + movl $0x1d, %r10d + movq %r10, 0x778(%rsp) + movl $0x1e, %r10d + movq %r10, 0x770(%rsp) + movl $0x1f, %r10d + movq %r10, 0x768(%rsp) + movl $0x20, %r10d + movq %r10, 0x760(%rsp) + movl $0x21, %r10d + movq %r10, 0x758(%rsp) + movl $0x22, %r10d + movq %r10, 0x750(%rsp) + movl $0x23, %r10d + movq %r10, 0x748(%rsp) + movl $0x24, %r10d + movq %r10, 0x740(%rsp) + movl $0x25, %r10d + movq %r10, 0x738(%rsp) + movl $0x26, %r10d + movq %r10, 0x730(%rsp) + movl $0x27, %r10d + movq %r10, 0x728(%rsp) + movl $0x28, %r10d + movq %r10, 0x720(%rsp) + movl $0x29, %r10d + movq %r10, 0x718(%rsp) + movl $0x2a, %r10d + movq %r10, 0x710(%rsp) + movl $0x2b, %r10d + movq %r10, 0x708(%rsp) + movl $0x2c, %r10d + movq %r10, 0x700(%rsp) + movl $0x2d, %r10d + movq %r10, 0x6f8(%rsp) + movl $0x2e, %r10d + movq %r10, 0x6f0(%rsp) + movl $0x2f, %r10d + movq %r10, 0x6e8(%rsp) + movl $0x30, %r10d + movq %r10, 0x6e0(%rsp) + movl $0x31, %r10d + movq %r10, 0x6d8(%rsp) + movl $0x32, %r10d + movq %r10, 0x6d0(%rsp) + movl $0x33, %r10d + movq %r10, 0x6c8(%rsp) + movl $0x34, %r10d + movq %r10, 0x6c0(%rsp) + movl $0x35, %r10d + movq %r10, 0x6b8(%rsp) + movl $0x36, %r10d + movq %r10, 0x6b0(%rsp) + movl $0x37, %r10d + movq %r10, 0x6a8(%rsp) + movl $0x38, %r10d + movq %r10, 0x6a0(%rsp) + movl $0x39, %r10d + movq %r10, 0x698(%rsp) + movl $0x3a, %r10d + movq %r10, 0x690(%rsp) + movl $0x3b, %r10d + movq %r10, 0x688(%rsp) + movl $0x3c, %r10d + movq %r10, 0x680(%rsp) + movl $0x3d, %r10d + movq %r10, 0x678(%rsp) + movl $0x3e, %r10d + movq %r10, 0x670(%rsp) + movl $0x3f, %r10d + movq %r10, 0x668(%rsp) + movl $0x40, %r10d + movq %r10, 0x660(%rsp) + movl $0x41, %r10d + movq %r10, 0x658(%rsp) + movl $0x42, %r10d + movq %r10, 0x650(%rsp) + movl $0x43, %r10d + movq %r10, 0x648(%rsp) + movl $0x44, %r10d + movq %r10, 0x640(%rsp) + movl $0x45, %r10d + movq %r10, 0x638(%rsp) + movl $0x46, %r10d + movq %r10, 0x630(%rsp) + movl $0x47, %r10d + movq %r10, 0x628(%rsp) + movl $0x48, %r10d + movq %r10, 0x620(%rsp) + movl $0x49, %r10d + movq %r10, 0x618(%rsp) + movl $0x4a, %r10d + movq %r10, 0x610(%rsp) + movl $0x4b, %r10d + movq %r10, 0x608(%rsp) + movl $0x4c, %r10d + movq %r10, 0x600(%rsp) + movl $0x4d, %r10d + movq %r10, 0x5f8(%rsp) + movl $0x4e, %r10d + movq %r10, 0x5f0(%rsp) + movl $0x4f, %r10d + movq %r10, 0x5e8(%rsp) + movl $0x50, %r10d + movq %r10, 0x5e0(%rsp) + movl $0x51, %r10d + movq %r10, 0x5d8(%rsp) + movl $0x52, %r10d + movq %r10, 0x5d0(%rsp) + movl $0x53, %r10d + movq %r10, 0x5c8(%rsp) + movl $0x54, %r10d + movq %r10, 0x5c0(%rsp) + movl $0x55, %r10d + movq %r10, 0x5b8(%rsp) + movl $0x56, %r10d + movq %r10, 0x5b0(%rsp) + movl $0x57, %r10d + movq %r10, 0x5a8(%rsp) + movl $0x58, %r10d + movq %r10, 0x5a0(%rsp) + movl $0x59, %r10d + movq %r10, 0x598(%rsp) + movl $0x5a, %r10d + movq %r10, 0x590(%rsp) + movl $0x5b, %r10d + movq %r10, 0x588(%rsp) + movl $0x5c, %r10d + movq %r10, 0x580(%rsp) + movl $0x5d, %r10d + movq %r10, 0x578(%rsp) + movl $0x5e, %r10d + movq %r10, 0x570(%rsp) + movl $0x5f, %r10d + movq %r10, 0x568(%rsp) + movl $0x60, %r10d + movq %r10, 0x560(%rsp) + movl $0x61, %r10d + movq %r10, 0x558(%rsp) + movl $0x62, %r10d + movq %r10, 0x550(%rsp) + movl $0x63, %r10d + movq %r10, 0x548(%rsp) + movl $0x64, %r10d + movq %r10, 0x540(%rsp) + movl $0x65, %r10d + movq %r10, 0x538(%rsp) + movl $0x66, %r10d + movq %r10, 0x530(%rsp) + movl $0x67, %r10d + movq %r10, 0x528(%rsp) + movl $0x68, %r10d + movq %r10, 0x520(%rsp) + movl $0x69, %r10d + movq %r10, 0x518(%rsp) + movl $0x6a, %r10d + movq %r10, 0x510(%rsp) + movl $0x6b, %r10d + movq %r10, 0x508(%rsp) + movl $0x6c, %r10d + movq %r10, 0x500(%rsp) + movl $0x6d, %r10d + movq %r10, 0x4f8(%rsp) + movl $0x6e, %r10d + movq %r10, 0x4f0(%rsp) + movl $0x6f, %r10d + movq %r10, 0x4e8(%rsp) + movl $0x70, %r10d + movq %r10, 0x4e0(%rsp) + movl $0x71, %r10d + movq %r10, 0x4d8(%rsp) + movl $0x72, %r10d + movq %r10, 0x4d0(%rsp) + movl $0x73, %r10d + movq %r10, 0x4c8(%rsp) + movl $0x74, %r10d + movq %r10, 0x4c0(%rsp) + movl $0x75, %r10d + movq %r10, 0x4b8(%rsp) + movl $0x76, %r10d + movq %r10, 0x4b0(%rsp) + movl $0x77, %r10d + movq %r10, 0x4a8(%rsp) + movl $0x78, %r10d + movq %r10, 0x4a0(%rsp) + movl $0x79, %r10d + movq %r10, 0x498(%rsp) + movl $0x7a, %r10d + movq %r10, 0x490(%rsp) + movl $0x7b, %r10d + movq %r10, 0x488(%rsp) + movl $0x7c, %r10d + movq %r10, 0x480(%rsp) + movl $0x7d, %r10d + movq %r10, 0x478(%rsp) + movl $0x7e, %r10d + movq %r10, 0x470(%rsp) + movl $0x7f, %r10d + movq %r10, 0x468(%rsp) + movl $0x80, %r10d + movq %r10, 0x460(%rsp) + movl $0x81, %r10d + movq %r10, 0x458(%rsp) + movl $0x82, %r10d + movq %r10, 0x450(%rsp) + movl $0x83, %r10d + movq %r10, 0x448(%rsp) + movl $0x84, %r10d + movq %r10, 0x440(%rsp) + movl $0x85, %r10d + movq %r10, 0x438(%rsp) + movl $0x86, %r10d + movq %r10, 0x430(%rsp) + movl $0x87, %r10d + movq %r10, 0x428(%rsp) + movl $0x88, %r10d + movq %r10, 0x420(%rsp) + movl $0x89, %r10d + movq %r10, 0x418(%rsp) + movl $0x8a, %r10d + movq %r10, 0x410(%rsp) + movl $0x8b, %r10d + movq %r10, 0x408(%rsp) + movl $0x8c, %r10d + movq %r10, 0x400(%rsp) + movl $0x8d, %r10d + movq %r10, 0x3f8(%rsp) + movl $0x8e, %r10d + movq %r10, 0x3f0(%rsp) + movl $0x8f, %r10d + movq %r10, 0x3e8(%rsp) + movl $0x90, %r10d + movq %r10, 0x3e0(%rsp) + movl $0x91, %r10d + movq %r10, 0x3d8(%rsp) + movl $0x92, %r10d + movq %r10, 0x3d0(%rsp) + movl $0x93, %r10d + movq %r10, 0x3c8(%rsp) + movl $0x94, %r10d + movq %r10, 0x3c0(%rsp) + movl $0x95, %r10d + movq %r10, 0x3b8(%rsp) + movl $0x96, %r10d + movq %r10, 0x3b0(%rsp) + movl $0x97, %r10d + movq %r10, 0x3a8(%rsp) + movl $0x98, %r10d + movq %r10, 0x3a0(%rsp) + movl $0x99, %r10d + movq %r10, 0x398(%rsp) + movl $0x9a, %r10d + movq %r10, 0x390(%rsp) + movl $0x9b, %r10d + movq %r10, 0x388(%rsp) + movl $0x9c, %r10d + movq %r10, 0x380(%rsp) + movl $0x9d, %r10d + movq %r10, 0x378(%rsp) + movl $0x9e, %r10d + movq %r10, 0x370(%rsp) + movl $0x9f, %r10d + movq %r10, 0x368(%rsp) + movl $0xa0, %r10d + movq %r10, 0x360(%rsp) + movl $0xa1, %r10d + movq %r10, 0x358(%rsp) + movl $0xa2, %r10d + movq %r10, 0x350(%rsp) + movl $0xa3, %r10d + movq %r10, 0x348(%rsp) + movl $0xa4, %r10d + movq %r10, 0x340(%rsp) + movl $0xa5, %r10d + movq %r10, 0x338(%rsp) + movl $0xa6, %r10d + movq %r10, 0x330(%rsp) + movl $0xa7, %r10d + movq %r10, 0x328(%rsp) + movl $0xa8, %r10d + movq %r10, 0x320(%rsp) + movl $0xa9, %r10d + movq %r10, 0x318(%rsp) + movl $0xaa, %r10d + movq %r10, 0x310(%rsp) + movl $0xab, %r10d + movq %r10, 0x308(%rsp) + movl $0xac, %r10d + movq %r10, 0x300(%rsp) + movl $0xad, %r10d + movq %r10, 0x2f8(%rsp) + movl $0xae, %r10d + movq %r10, 0x2f0(%rsp) + movl $0xaf, %r10d + movq %r10, 0x2e8(%rsp) + movl $0xb0, %r10d + movq %r10, 0x2e0(%rsp) + movl $0xb1, %r10d + movq %r10, 0x2d8(%rsp) + movl $0xb2, %r10d + movq %r10, 0x2d0(%rsp) + movl $0xb3, %r10d + movq %r10, 0x2c8(%rsp) + movl $0xb4, %r10d + movq %r10, 0x2c0(%rsp) + movl $0xb5, %r10d + movq %r10, 0x2b8(%rsp) + movl $0xb6, %r10d + movq %r10, 0x2b0(%rsp) + movl $0xb7, %r10d + movq %r10, 0x2a8(%rsp) + movl $0xb8, %r10d + movq %r10, 0x2a0(%rsp) + movl $0xb9, %r10d + movq %r10, 0x298(%rsp) + movl $0xba, %r10d + movq %r10, 0x290(%rsp) + movl $0xbb, %r10d + movq %r10, 0x288(%rsp) + movl $0xbc, %r10d + movq %r10, 0x280(%rsp) + movl $0xbd, %r10d + movq %r10, 0x278(%rsp) + movl $0xbe, %r10d + movq %r10, 0x270(%rsp) + movl $0xbf, %r10d + movq %r10, 0x268(%rsp) + movl $0xc0, %r10d + movq %r10, 0x260(%rsp) + movl $0xc1, %r10d + movq %r10, 0x258(%rsp) + movl $0xc2, %r10d + movq %r10, 0x250(%rsp) + movl $0xc3, %r10d + movq %r10, 0x248(%rsp) + movl $0xc4, %r10d + movq %r10, 0x240(%rsp) + movl $0xc5, %r10d + movq %r10, 0x238(%rsp) + movl $0xc6, %r10d + movq %r10, 0x230(%rsp) + movl $0xc7, %r10d + movq %r10, 0x228(%rsp) + movl $0xc8, %r10d + movq %r10, 0x220(%rsp) + movl $0xc9, %r10d + movq %r10, 0x218(%rsp) + movl $0xca, %r10d + movq %r10, 0x210(%rsp) + movl $0xcb, %r10d + movq %r10, 0x208(%rsp) + movl $0xcc, %r10d + movq %r10, 0x200(%rsp) + movl $0xcd, %r10d + movq %r10, 0x1f8(%rsp) + movl $0xce, %r10d + movq %r10, 0x1f0(%rsp) + movl $0xcf, %r10d + movq %r10, 0x1e8(%rsp) + movl $0xd0, %r10d + movq %r10, 0x1e0(%rsp) + movl $0xd1, %r10d + movq %r10, 0x1d8(%rsp) + movl $0xd2, %r10d + movq %r10, 0x1d0(%rsp) + movl $0xd3, %r10d + movq %r10, 0x1c8(%rsp) + movl $0xd4, %r10d + movq %r10, 0x1c0(%rsp) + movl $0xd5, %r10d + movq %r10, 0x1b8(%rsp) + movl $0xd6, %r10d + movq %r10, 0x1b0(%rsp) + movl $0xd7, %r10d + movq %r10, 0x1a8(%rsp) + movl $0xd8, %r10d + movq %r10, 0x1a0(%rsp) + movl $0xd9, %r10d + movq %r10, 0x198(%rsp) + movl $0xda, %r10d + movq %r10, 0x190(%rsp) + movl $0xdb, %r10d + movq %r10, 0x188(%rsp) + movl $0xdc, %r10d + movq %r10, 0x180(%rsp) + movl $0xdd, %r10d + movq %r10, 0x178(%rsp) + movl $0xde, %r10d + movq %r10, 0x170(%rsp) + movl $0xdf, %r10d + movq %r10, 0x168(%rsp) + movl $0xe0, %r10d + movq %r10, 0x160(%rsp) + movl $0xe1, %r10d + movq %r10, 0x158(%rsp) + movl $0xe2, %r10d + movq %r10, 0x150(%rsp) + movl $0xe3, %r10d + movq %r10, 0x148(%rsp) + movl $0xe4, %r10d + movq %r10, 0x140(%rsp) + movl $0xe5, %r10d + movq %r10, 0x138(%rsp) + movl $0xe6, %r10d + movq %r10, 0x130(%rsp) + movl $0xe7, %r10d + movq %r10, 0x128(%rsp) + movl $0xe8, %r10d + movq %r10, 0x120(%rsp) + movl $0xe9, %r10d + movq %r10, 0x118(%rsp) + movl $0xea, %r10d + movq %r10, 0x110(%rsp) + movl $0xeb, %r10d + movq %r10, 0x108(%rsp) + movl $0xec, %r10d + movq %r10, 0x100(%rsp) + movl $0xed, %r10d + movq %r10, 0xf8(%rsp) + movl $0xee, %r10d + movq %r10, 0xf0(%rsp) + movl $0xef, %r10d + movq %r10, 0xe8(%rsp) + movl $0xf0, %r10d + movq %r10, 0xe0(%rsp) + movl $0xf1, %r10d + movq %r10, 0xd8(%rsp) + movl $0xf2, %r10d + movq %r10, 0xd0(%rsp) + movl $0xf3, %r10d + movq %r10, 0xc8(%rsp) + movl $0xf4, %r10d + movq %r10, 0xc0(%rsp) + movl $0xf5, %r10d + movq %r10, 0xb8(%rsp) + movl $0xf6, %r10d + movq %r10, 0xb0(%rsp) + movl $0xf7, %r10d + movq %r10, 0xa8(%rsp) + movl $0xf8, %r10d + movq %r10, 0xa0(%rsp) + movl $0xf9, %r10d + movq %r10, 0x98(%rsp) + movl $0xfa, %r10d + movq %r10, 0x90(%rsp) + movl $0xfb, %r10d + movq %r10, 0x88(%rsp) + movl $0xfc, %r10d + movq %r10, 0x80(%rsp) + movl $0xfd, %r10d + movq %r10, 0x78(%rsp) + movl $0xfe, %r10d + movq %r10, 0x70(%rsp) + movl $0xff, %r10d + movq %r10, 0x68(%rsp) + movl $0x100, %r10d # imm = 0x100 + movq %r10, 0x60(%rsp) + movl $0x101, %r10d # imm = 0x101 + movq %r10, 0x58(%rsp) + movl $0x102, %r10d # imm = 0x102 + movq %r10, 0x50(%rsp) + movl $0x103, %r10d # imm = 0x103 + movq %r10, 0x48(%rsp) + movl $0x104, %r10d # imm = 0x104 + movq %r10, 0x40(%rsp) + subq $0x10, %rsp + movq %rbx, (%rsp) + subq $0x7f0, %rsp # imm = 0x7F0 + movq %rax, (%rsp) + movq %r13, 0x8(%rsp) + movq %r14, 0x10(%rsp) + movq %r15, 0x18(%rsp) + movq 0x1008(%rsp), %r10 + movq %r10, 0x20(%rsp) + movq 0x1000(%rsp), %r10 + movq %r10, 0x28(%rsp) + movq 0xff8(%rsp), %r10 + movq %r10, 0x30(%rsp) + movq 0xff0(%rsp), %r10 + movq %r10, 0x38(%rsp) + movq 0xfe8(%rsp), %r10 + movq %r10, 0x40(%rsp) + movq 0xfe0(%rsp), %r10 + movq %r10, 0x48(%rsp) + movq 0xfd8(%rsp), %r10 + movq %r10, 0x50(%rsp) + movq 0xfd0(%rsp), %r10 + movq %r10, 0x58(%rsp) + movq 0xfc8(%rsp), %r10 + movq %r10, 0x60(%rsp) + movq 0xfc0(%rsp), %r10 + movq %r10, 0x68(%rsp) + movq 0xfb8(%rsp), %r10 + movq %r10, 0x70(%rsp) + movq 0xfb0(%rsp), %r10 + movq %r10, 0x78(%rsp) + movq 0xfa8(%rsp), %r10 + movq %r10, 0x80(%rsp) + movq 0xfa0(%rsp), %r10 + movq %r10, 0x88(%rsp) + movq 0xf98(%rsp), %r10 + movq %r10, 0x90(%rsp) + movq 0xf90(%rsp), %r10 + movq %r10, 0x98(%rsp) + movq 0xf88(%rsp), %r10 + movq %r10, 0xa0(%rsp) + movq 0xf80(%rsp), %r10 + movq %r10, 0xa8(%rsp) + movq 0xf78(%rsp), %r10 + movq %r10, 0xb0(%rsp) + movq 0xf70(%rsp), %r10 + movq %r10, 0xb8(%rsp) + movq 0xf68(%rsp), %r10 + movq %r10, 0xc0(%rsp) + movq 0xf60(%rsp), %r10 + movq %r10, 0xc8(%rsp) + movq 0xf58(%rsp), %r10 + movq %r10, 0xd0(%rsp) + movq 0xf50(%rsp), %r10 + movq %r10, 0xd8(%rsp) + movq 0xf48(%rsp), %r10 + movq %r10, 0xe0(%rsp) + movq 0xf40(%rsp), %r10 + movq %r10, 0xe8(%rsp) + movq 0xf38(%rsp), %r10 + movq %r10, 0xf0(%rsp) + movq 0xf30(%rsp), %r10 + movq %r10, 0xf8(%rsp) + movq 0xf28(%rsp), %r10 + movq %r10, 0x100(%rsp) + movq 0xf20(%rsp), %r10 + movq %r10, 0x108(%rsp) + movq 0xf18(%rsp), %r10 + movq %r10, 0x110(%rsp) + movq 0xf10(%rsp), %r10 + movq %r10, 0x118(%rsp) + movq 0xf08(%rsp), %r10 + movq %r10, 0x120(%rsp) + movq 0xf00(%rsp), %r10 + movq %r10, 0x128(%rsp) + movq 0xef8(%rsp), %r10 + movq %r10, 0x130(%rsp) + movq 0xef0(%rsp), %r10 + movq %r10, 0x138(%rsp) + movq 0xee8(%rsp), %r10 + movq %r10, 0x140(%rsp) + movq 0xee0(%rsp), %r10 + movq %r10, 0x148(%rsp) + movq 0xed8(%rsp), %r10 + movq %r10, 0x150(%rsp) + movq 0xed0(%rsp), %r10 + movq %r10, 0x158(%rsp) + movq 0xec8(%rsp), %r10 + movq %r10, 0x160(%rsp) + movq 0xec0(%rsp), %r10 + movq %r10, 0x168(%rsp) + movq 0xeb8(%rsp), %r10 + movq %r10, 0x170(%rsp) + movq 0xeb0(%rsp), %r10 + movq %r10, 0x178(%rsp) + movq 0xea8(%rsp), %r10 + movq %r10, 0x180(%rsp) + movq 0xea0(%rsp), %r10 + movq %r10, 0x188(%rsp) + movq 0xe98(%rsp), %r10 + movq %r10, 0x190(%rsp) + movq 0xe90(%rsp), %r10 + movq %r10, 0x198(%rsp) + movq 0xe88(%rsp), %r10 + movq %r10, 0x1a0(%rsp) + movq 0xe80(%rsp), %r10 + movq %r10, 0x1a8(%rsp) + movq 0xe78(%rsp), %r10 + movq %r10, 0x1b0(%rsp) + movq 0xe70(%rsp), %r10 + movq %r10, 0x1b8(%rsp) + movq 0xe68(%rsp), %r10 + movq %r10, 0x1c0(%rsp) + movq 0xe60(%rsp), %r10 + movq %r10, 0x1c8(%rsp) + movq 0xe58(%rsp), %r10 + movq %r10, 0x1d0(%rsp) + movq 0xe50(%rsp), %r10 + movq %r10, 0x1d8(%rsp) + movq 0xe48(%rsp), %r10 + movq %r10, 0x1e0(%rsp) + movq 0xe40(%rsp), %r10 + movq %r10, 0x1e8(%rsp) + movq 0xe38(%rsp), %r10 + movq %r10, 0x1f0(%rsp) + movq 0xe30(%rsp), %r10 + movq %r10, 0x1f8(%rsp) + movq 0xe28(%rsp), %r10 + movq %r10, 0x200(%rsp) + movq 0xe20(%rsp), %r10 + movq %r10, 0x208(%rsp) + movq 0xe18(%rsp), %r10 + movq %r10, 0x210(%rsp) + movq 0xe10(%rsp), %r10 + movq %r10, 0x218(%rsp) + movq 0xe08(%rsp), %r10 + movq %r10, 0x220(%rsp) + movq 0xe00(%rsp), %r10 + movq %r10, 0x228(%rsp) + movq 0xdf8(%rsp), %r10 + movq %r10, 0x230(%rsp) + movq 0xdf0(%rsp), %r10 + movq %r10, 0x238(%rsp) + movq 0xde8(%rsp), %r10 + movq %r10, 0x240(%rsp) + movq 0xde0(%rsp), %r10 + movq %r10, 0x248(%rsp) + movq 0xdd8(%rsp), %r10 + movq %r10, 0x250(%rsp) + movq 0xdd0(%rsp), %r10 + movq %r10, 0x258(%rsp) + movq 0xdc8(%rsp), %r10 + movq %r10, 0x260(%rsp) + movq 0xdc0(%rsp), %r10 + movq %r10, 0x268(%rsp) + movq 0xdb8(%rsp), %r10 + movq %r10, 0x270(%rsp) + movq 0xdb0(%rsp), %r10 + movq %r10, 0x278(%rsp) + movq 0xda8(%rsp), %r10 + movq %r10, 0x280(%rsp) + movq 0xda0(%rsp), %r10 + movq %r10, 0x288(%rsp) + movq 0xd98(%rsp), %r10 + movq %r10, 0x290(%rsp) + movq 0xd90(%rsp), %r10 + movq %r10, 0x298(%rsp) + movq 0xd88(%rsp), %r10 + movq %r10, 0x2a0(%rsp) + movq 0xd80(%rsp), %r10 + movq %r10, 0x2a8(%rsp) + movq 0xd78(%rsp), %r10 + movq %r10, 0x2b0(%rsp) + movq 0xd70(%rsp), %r10 + movq %r10, 0x2b8(%rsp) + movq 0xd68(%rsp), %r10 + movq %r10, 0x2c0(%rsp) + movq 0xd60(%rsp), %r10 + movq %r10, 0x2c8(%rsp) + movq 0xd58(%rsp), %r10 + movq %r10, 0x2d0(%rsp) + movq 0xd50(%rsp), %r10 + movq %r10, 0x2d8(%rsp) + movq 0xd48(%rsp), %r10 + movq %r10, 0x2e0(%rsp) + movq 0xd40(%rsp), %r10 + movq %r10, 0x2e8(%rsp) + movq 0xd38(%rsp), %r10 + movq %r10, 0x2f0(%rsp) + movq 0xd30(%rsp), %r10 + movq %r10, 0x2f8(%rsp) + movq 0xd28(%rsp), %r10 + movq %r10, 0x300(%rsp) + movq 0xd20(%rsp), %r10 + movq %r10, 0x308(%rsp) + movq 0xd18(%rsp), %r10 + movq %r10, 0x310(%rsp) + movq 0xd10(%rsp), %r10 + movq %r10, 0x318(%rsp) + movq 0xd08(%rsp), %r10 + movq %r10, 0x320(%rsp) + movq 0xd00(%rsp), %r10 + movq %r10, 0x328(%rsp) + movq 0xcf8(%rsp), %r10 + movq %r10, 0x330(%rsp) + movq 0xcf0(%rsp), %r10 + movq %r10, 0x338(%rsp) + movq 0xce8(%rsp), %r10 + movq %r10, 0x340(%rsp) + movq 0xce0(%rsp), %r10 + movq %r10, 0x348(%rsp) + movq 0xcd8(%rsp), %r10 + movq %r10, 0x350(%rsp) + movq 0xcd0(%rsp), %r10 + movq %r10, 0x358(%rsp) + movq 0xcc8(%rsp), %r10 + movq %r10, 0x360(%rsp) + movq 0xcc0(%rsp), %r10 + movq %r10, 0x368(%rsp) + movq 0xcb8(%rsp), %r10 + movq %r10, 0x370(%rsp) + movq 0xcb0(%rsp), %r10 + movq %r10, 0x378(%rsp) + movq 0xca8(%rsp), %r10 + movq %r10, 0x380(%rsp) + movq 0xca0(%rsp), %r10 + movq %r10, 0x388(%rsp) + movq 0xc98(%rsp), %r10 + movq %r10, 0x390(%rsp) + movq 0xc90(%rsp), %r10 + movq %r10, 0x398(%rsp) + movq 0xc88(%rsp), %r10 + movq %r10, 0x3a0(%rsp) + movq 0xc80(%rsp), %r10 + movq %r10, 0x3a8(%rsp) + movq 0xc78(%rsp), %r10 + movq %r10, 0x3b0(%rsp) + movq 0xc70(%rsp), %r10 + movq %r10, 0x3b8(%rsp) + movq 0xc68(%rsp), %r10 + movq %r10, 0x3c0(%rsp) + movq 0xc60(%rsp), %r10 + movq %r10, 0x3c8(%rsp) + movq 0xc58(%rsp), %r10 + movq %r10, 0x3d0(%rsp) + movq 0xc50(%rsp), %r10 + movq %r10, 0x3d8(%rsp) + movq 0xc48(%rsp), %r10 + movq %r10, 0x3e0(%rsp) + movq 0xc40(%rsp), %r10 + movq %r10, 0x3e8(%rsp) + movq 0xc38(%rsp), %r10 + movq %r10, 0x3f0(%rsp) + movq 0xc30(%rsp), %r10 + movq %r10, 0x3f8(%rsp) + movq 0xc28(%rsp), %r10 + movq %r10, 0x400(%rsp) + movq 0xc20(%rsp), %r10 + movq %r10, 0x408(%rsp) + movq 0xc18(%rsp), %r10 + movq %r10, 0x410(%rsp) + movq 0xc10(%rsp), %r10 + movq %r10, 0x418(%rsp) + movq 0xc08(%rsp), %r10 + movq %r10, 0x420(%rsp) + movq 0xc00(%rsp), %r10 + movq %r10, 0x428(%rsp) + movq 0xbf8(%rsp), %r10 + movq %r10, 0x430(%rsp) + movq 0xbf0(%rsp), %r10 + movq %r10, 0x438(%rsp) + movq 0xbe8(%rsp), %r10 + movq %r10, 0x440(%rsp) + movq 0xbe0(%rsp), %r10 + movq %r10, 0x448(%rsp) + movq 0xbd8(%rsp), %r10 + movq %r10, 0x450(%rsp) + movq 0xbd0(%rsp), %r10 + movq %r10, 0x458(%rsp) + movq 0xbc8(%rsp), %r10 + movq %r10, 0x460(%rsp) + movq 0xbc0(%rsp), %r10 + movq %r10, 0x468(%rsp) + movq 0xbb8(%rsp), %r10 + movq %r10, 0x470(%rsp) + movq 0xbb0(%rsp), %r10 + movq %r10, 0x478(%rsp) + movq 0xba8(%rsp), %r10 + movq %r10, 0x480(%rsp) + movq 0xba0(%rsp), %r10 + movq %r10, 0x488(%rsp) + movq 0xb98(%rsp), %r10 + movq %r10, 0x490(%rsp) + movq 0xb90(%rsp), %r10 + movq %r10, 0x498(%rsp) + movq 0xb88(%rsp), %r10 + movq %r10, 0x4a0(%rsp) + movq 0xb80(%rsp), %r10 + movq %r10, 0x4a8(%rsp) + movq 0xb78(%rsp), %r10 + movq %r10, 0x4b0(%rsp) + movq 0xb70(%rsp), %r10 + movq %r10, 0x4b8(%rsp) + movq 0xb68(%rsp), %r10 + movq %r10, 0x4c0(%rsp) + movq 0xb60(%rsp), %r10 + movq %r10, 0x4c8(%rsp) + movq 0xb58(%rsp), %r10 + movq %r10, 0x4d0(%rsp) + movq 0xb50(%rsp), %r10 + movq %r10, 0x4d8(%rsp) + movq 0xb48(%rsp), %r10 + movq %r10, 0x4e0(%rsp) + movq 0xb40(%rsp), %r10 + movq %r10, 0x4e8(%rsp) + movq 0xb38(%rsp), %r10 + movq %r10, 0x4f0(%rsp) + movq 0xb30(%rsp), %r10 + movq %r10, 0x4f8(%rsp) + movq 0xb28(%rsp), %r10 + movq %r10, 0x500(%rsp) + movq 0xb20(%rsp), %r10 + movq %r10, 0x508(%rsp) + movq 0xb18(%rsp), %r10 + movq %r10, 0x510(%rsp) + movq 0xb10(%rsp), %r10 + movq %r10, 0x518(%rsp) + movq 0xb08(%rsp), %r10 + movq %r10, 0x520(%rsp) + movq 0xb00(%rsp), %r10 + movq %r10, 0x528(%rsp) + movq 0xaf8(%rsp), %r10 + movq %r10, 0x530(%rsp) + movq 0xaf0(%rsp), %r10 + movq %r10, 0x538(%rsp) + movq 0xae8(%rsp), %r10 + movq %r10, 0x540(%rsp) + movq 0xae0(%rsp), %r10 + movq %r10, 0x548(%rsp) + movq 0xad8(%rsp), %r10 + movq %r10, 0x550(%rsp) + movq 0xad0(%rsp), %r10 + movq %r10, 0x558(%rsp) + movq 0xac8(%rsp), %r10 + movq %r10, 0x560(%rsp) + movq 0xac0(%rsp), %r10 + movq %r10, 0x568(%rsp) + movq 0xab8(%rsp), %r10 + movq %r10, 0x570(%rsp) + movq 0xab0(%rsp), %r10 + movq %r10, 0x578(%rsp) + movq 0xaa8(%rsp), %r10 + movq %r10, 0x580(%rsp) + movq 0xaa0(%rsp), %r10 + movq %r10, 0x588(%rsp) + movq 0xa98(%rsp), %r10 + movq %r10, 0x590(%rsp) + movq 0xa90(%rsp), %r10 + movq %r10, 0x598(%rsp) + movq 0xa88(%rsp), %r10 + movq %r10, 0x5a0(%rsp) + movq 0xa80(%rsp), %r10 + movq %r10, 0x5a8(%rsp) + movq 0xa78(%rsp), %r10 + movq %r10, 0x5b0(%rsp) + movq 0xa70(%rsp), %r10 + movq %r10, 0x5b8(%rsp) + movq 0xa68(%rsp), %r10 + movq %r10, 0x5c0(%rsp) + movq 0xa60(%rsp), %r10 + movq %r10, 0x5c8(%rsp) + movq 0xa58(%rsp), %r10 + movq %r10, 0x5d0(%rsp) + movq 0xa50(%rsp), %r10 + movq %r10, 0x5d8(%rsp) + movq 0xa48(%rsp), %r10 + movq %r10, 0x5e0(%rsp) + movq 0xa40(%rsp), %r10 + movq %r10, 0x5e8(%rsp) + movq 0xa38(%rsp), %r10 + movq %r10, 0x5f0(%rsp) + movq 0xa30(%rsp), %r10 + movq %r10, 0x5f8(%rsp) + movq 0xa28(%rsp), %r10 + movq %r10, 0x600(%rsp) + movq 0xa20(%rsp), %r10 + movq %r10, 0x608(%rsp) + movq 0xa18(%rsp), %r10 + movq %r10, 0x610(%rsp) + movq 0xa10(%rsp), %r10 + movq %r10, 0x618(%rsp) + movq 0xa08(%rsp), %r10 + movq %r10, 0x620(%rsp) + movq 0xa00(%rsp), %r10 + movq %r10, 0x628(%rsp) + movq 0x9f8(%rsp), %r10 + movq %r10, 0x630(%rsp) + movq 0x9f0(%rsp), %r10 + movq %r10, 0x638(%rsp) + movq 0x9e8(%rsp), %r10 + movq %r10, 0x640(%rsp) + movq 0x9e0(%rsp), %r10 + movq %r10, 0x648(%rsp) + movq 0x9d8(%rsp), %r10 + movq %r10, 0x650(%rsp) + movq 0x9d0(%rsp), %r10 + movq %r10, 0x658(%rsp) + movq 0x9c8(%rsp), %r10 + movq %r10, 0x660(%rsp) + movq 0x9c0(%rsp), %r10 + movq %r10, 0x668(%rsp) + movq 0x9b8(%rsp), %r10 + movq %r10, 0x670(%rsp) + movq 0x9b0(%rsp), %r10 + movq %r10, 0x678(%rsp) + movq 0x9a8(%rsp), %r10 + movq %r10, 0x680(%rsp) + movq 0x9a0(%rsp), %r10 + movq %r10, 0x688(%rsp) + movq 0x998(%rsp), %r10 + movq %r10, 0x690(%rsp) + movq 0x990(%rsp), %r10 + movq %r10, 0x698(%rsp) + movq 0x988(%rsp), %r10 + movq %r10, 0x6a0(%rsp) + movq 0x980(%rsp), %r10 + movq %r10, 0x6a8(%rsp) + movq 0x978(%rsp), %r10 + movq %r10, 0x6b0(%rsp) + movq 0x970(%rsp), %r10 + movq %r10, 0x6b8(%rsp) + movq 0x968(%rsp), %r10 + movq %r10, 0x6c0(%rsp) + movq 0x960(%rsp), %r10 + movq %r10, 0x6c8(%rsp) + movq 0x958(%rsp), %r10 + movq %r10, 0x6d0(%rsp) + movq 0x950(%rsp), %r10 + movq %r10, 0x6d8(%rsp) + movq 0x948(%rsp), %r10 + movq %r10, 0x6e0(%rsp) + movq 0x940(%rsp), %r10 + movq %r10, 0x6e8(%rsp) + movq 0x938(%rsp), %r10 + movq %r10, 0x6f0(%rsp) + movq 0x930(%rsp), %r10 + movq %r10, 0x6f8(%rsp) + movq 0x928(%rsp), %r10 + movq %r10, 0x700(%rsp) + movq 0x920(%rsp), %r10 + movq %r10, 0x708(%rsp) + movq 0x918(%rsp), %r10 + movq %r10, 0x710(%rsp) + movq 0x910(%rsp), %r10 + movq %r10, 0x718(%rsp) + movq 0x908(%rsp), %r10 + movq %r10, 0x720(%rsp) + movq 0x900(%rsp), %r10 + movq %r10, 0x728(%rsp) + movq 0x8f8(%rsp), %r10 + movq %r10, 0x730(%rsp) + movq 0x8f0(%rsp), %r10 + movq %r10, 0x738(%rsp) + movq 0x8e8(%rsp), %r10 + movq %r10, 0x740(%rsp) + movq 0x8e0(%rsp), %r10 + movq %r10, 0x748(%rsp) + movq 0x8d8(%rsp), %r10 + movq %r10, 0x750(%rsp) + movq 0x8d0(%rsp), %r10 + movq %r10, 0x758(%rsp) + movq 0x8c8(%rsp), %r10 + movq %r10, 0x760(%rsp) + movq 0x8c0(%rsp), %r10 + movq %r10, 0x768(%rsp) + movq 0x8b8(%rsp), %r10 + movq %r10, 0x770(%rsp) + movq 0x8b0(%rsp), %r10 + movq %r10, 0x778(%rsp) + movq 0x8a8(%rsp), %r10 + movq %r10, 0x780(%rsp) + movq 0x8a0(%rsp), %r10 + movq %r10, 0x788(%rsp) + movq 0x898(%rsp), %r10 + movq %r10, 0x790(%rsp) + movq 0x890(%rsp), %r10 + movq %r10, 0x798(%rsp) + movq 0x888(%rsp), %r10 + movq %r10, 0x7a0(%rsp) + movq 0x880(%rsp), %r10 + movq %r10, 0x7a8(%rsp) + movq 0x878(%rsp), %r10 + movq %r10, 0x7b0(%rsp) + movq 0x870(%rsp), %r10 + movq %r10, 0x7b8(%rsp) + movq 0x868(%rsp), %r10 + movq %r10, 0x7c0(%rsp) + movq 0x860(%rsp), %r10 + movq %r10, 0x7c8(%rsp) + movq 0x858(%rsp), %r10 + movq %r10, 0x7d0(%rsp) + movq 0x850(%rsp), %r10 + movq %r10, 0x7d8(%rsp) + movq 0x848(%rsp), %r10 + movq %r10, 0x7e0(%rsp) + movq 0x840(%rsp), %r10 + movq %r10, 0x7e8(%rsp) + movq 0x7f0(%rsp), %r10 + callq *%r10 + addq $0x7f0, %rsp # imm = 0x7F0 + addq $0x10, %rsp + cmpq $0x848a, %rax # imm = 0x848A + je + movl $0x2, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + movq 0x18(%rsp), %r14 + movq 0x20(%rsp), %r15 + addq $0x1050, %rsp # imm = 0x1050 + popq %rbp + retq + leaq , %rdi + leaq 0x10(%rdi), %rsi + leaq 0x20(%rdi), %rdx + leaq 0x30(%rdi), %rcx + leaq 0x40(%rdi), %r8 + leaq 0x50(%rdi), %r9 + leaq 0x60(%rdi), %rax + leaq 0x70(%rdi), %rbx + leaq 0x80(%rdi), %r13 + leaq 0x90(%rdi), %r14 + leaq 0xa0(%rdi), %r15 + leaq 0xb0(%rdi), %r10 + movq %r10, 0x808(%rsp) + leaq 0xc0(%rdi), %r10 + movq %r10, 0x800(%rsp) + leaq 0xd0(%rdi), %r10 + movq %r10, 0x7f8(%rsp) + leaq 0xe0(%rdi), %r10 + movq %r10, 0x7f0(%rsp) + leaq 0xf0(%rdi), %r10 + movq %r10, 0x7e8(%rsp) + leaq 0x100(%rdi), %r10 + movq %r10, 0x7e0(%rsp) + leaq 0x110(%rdi), %r10 + movq %r10, 0x7d8(%rsp) + leaq 0x120(%rdi), %r10 + movq %r10, 0x7d0(%rsp) + leaq 0x130(%rdi), %r10 + movq %r10, 0x7c8(%rsp) + leaq 0x140(%rdi), %r10 + movq %r10, 0x7c0(%rsp) + leaq 0x150(%rdi), %r10 + movq %r10, 0x7b8(%rsp) + leaq 0x160(%rdi), %r10 + movq %r10, 0x7b0(%rsp) + leaq 0x170(%rdi), %r10 + movq %r10, 0x7a8(%rsp) + leaq 0x180(%rdi), %r10 + movq %r10, 0x7a0(%rsp) + leaq 0x190(%rdi), %r10 + movq %r10, 0x798(%rsp) + leaq 0x1a0(%rdi), %r10 + movq %r10, 0x790(%rsp) + leaq 0x1b0(%rdi), %r10 + movq %r10, 0x788(%rsp) + leaq 0x1c0(%rdi), %r10 + movq %r10, 0x780(%rsp) + leaq 0x1d0(%rdi), %r10 + movq %r10, 0x778(%rsp) + leaq 0x1e0(%rdi), %r10 + movq %r10, 0x770(%rsp) + leaq 0x1f0(%rdi), %r10 + movq %r10, 0x768(%rsp) + leaq 0x200(%rdi), %r10 + movq %r10, 0x760(%rsp) + leaq 0x210(%rdi), %r10 + movq %r10, 0x758(%rsp) + leaq 0x220(%rdi), %r10 + movq %r10, 0x750(%rsp) + leaq 0x230(%rdi), %r10 + movq %r10, 0x748(%rsp) + leaq 0x240(%rdi), %r10 + movq %r10, 0x740(%rsp) + leaq 0x250(%rdi), %r10 + movq %r10, 0x738(%rsp) + leaq 0x260(%rdi), %r10 + movq %r10, 0x730(%rsp) + leaq 0x270(%rdi), %r10 + movq %r10, 0x728(%rsp) + leaq 0x280(%rdi), %r10 + movq %r10, 0x720(%rsp) + leaq 0x290(%rdi), %r10 + movq %r10, 0x718(%rsp) + leaq 0x2a0(%rdi), %r10 + movq %r10, 0x710(%rsp) + leaq 0x2b0(%rdi), %r10 + movq %r10, 0x708(%rsp) + leaq 0x2c0(%rdi), %r10 + movq %r10, 0x700(%rsp) + leaq 0x2d0(%rdi), %r10 + movq %r10, 0x6f8(%rsp) + leaq 0x2e0(%rdi), %r10 + movq %r10, 0x6f0(%rsp) + leaq 0x2f0(%rdi), %r10 + movq %r10, 0x6e8(%rsp) + leaq 0x300(%rdi), %r10 + movq %r10, 0x6e0(%rsp) + leaq 0x310(%rdi), %r10 + movq %r10, 0x6d8(%rsp) + leaq 0x320(%rdi), %r10 + movq %r10, 0x6d0(%rsp) + leaq 0x330(%rdi), %r10 + movq %r10, 0x6c8(%rsp) + leaq 0x340(%rdi), %r10 + movq %r10, 0x6c0(%rsp) + leaq 0x350(%rdi), %r10 + movq %r10, 0x6b8(%rsp) + leaq 0x360(%rdi), %r10 + movq %r10, 0x6b0(%rsp) + leaq 0x370(%rdi), %r10 + movq %r10, 0x6a8(%rsp) + leaq 0x380(%rdi), %r10 + movq %r10, 0x6a0(%rsp) + leaq 0x390(%rdi), %r10 + movq %r10, 0x698(%rsp) + leaq 0x3a0(%rdi), %r10 + movq %r10, 0x690(%rsp) + leaq 0x3b0(%rdi), %r10 + movq %r10, 0x688(%rsp) + leaq 0x3c0(%rdi), %r10 + movq %r10, 0x680(%rsp) + leaq 0x3d0(%rdi), %r10 + movq %r10, 0x678(%rsp) + leaq 0x3e0(%rdi), %r10 + movq %r10, 0x670(%rsp) + leaq 0x3f0(%rdi), %r10 + movq %r10, 0x668(%rsp) + leaq 0x400(%rdi), %r10 + movq %r10, 0x660(%rsp) + leaq 0x410(%rdi), %r10 + movq %r10, 0x658(%rsp) + leaq 0x420(%rdi), %r10 + movq %r10, 0x650(%rsp) + leaq 0x430(%rdi), %r10 + movq %r10, 0x648(%rsp) + leaq 0x440(%rdi), %r10 + movq %r10, 0x640(%rsp) + leaq 0x450(%rdi), %r10 + movq %r10, 0x638(%rsp) + leaq 0x460(%rdi), %r10 + movq %r10, 0x630(%rsp) + leaq 0x470(%rdi), %r10 + movq %r10, 0x628(%rsp) + leaq 0x480(%rdi), %r10 + movq %r10, 0x620(%rsp) + leaq 0x490(%rdi), %r10 + movq %r10, 0x618(%rsp) + leaq 0x4a0(%rdi), %r10 + movq %r10, 0x610(%rsp) + leaq 0x4b0(%rdi), %r10 + movq %r10, 0x608(%rsp) + leaq 0x4c0(%rdi), %r10 + movq %r10, 0x600(%rsp) + leaq 0x4d0(%rdi), %r10 + movq %r10, 0x5f8(%rsp) + leaq 0x4e0(%rdi), %r10 + movq %r10, 0x5f0(%rsp) + leaq 0x4f0(%rdi), %r10 + movq %r10, 0x5e8(%rsp) + leaq 0x500(%rdi), %r10 + movq %r10, 0x5e0(%rsp) + leaq 0x510(%rdi), %r10 + movq %r10, 0x5d8(%rsp) + leaq 0x520(%rdi), %r10 + movq %r10, 0x5d0(%rsp) + leaq 0x530(%rdi), %r10 + movq %r10, 0x5c8(%rsp) + leaq 0x540(%rdi), %r10 + movq %r10, 0x5c0(%rsp) + leaq 0x550(%rdi), %r10 + movq %r10, 0x5b8(%rsp) + leaq 0x560(%rdi), %r10 + movq %r10, 0x5b0(%rsp) + leaq 0x570(%rdi), %r10 + movq %r10, 0x5a8(%rsp) + leaq 0x580(%rdi), %r10 + movq %r10, 0x5a0(%rsp) + leaq 0x590(%rdi), %r10 + movq %r10, 0x598(%rsp) + leaq 0x5a0(%rdi), %r10 + movq %r10, 0x590(%rsp) + leaq 0x5b0(%rdi), %r10 + movq %r10, 0x588(%rsp) + leaq 0x5c0(%rdi), %r10 + movq %r10, 0x580(%rsp) + leaq 0x5d0(%rdi), %r10 + movq %r10, 0x578(%rsp) + leaq 0x5e0(%rdi), %r10 + movq %r10, 0x570(%rsp) + leaq 0x5f0(%rdi), %r10 + movq %r10, 0x568(%rsp) + leaq 0x600(%rdi), %r10 + movq %r10, 0x560(%rsp) + leaq 0x610(%rdi), %r10 + movq %r10, 0x558(%rsp) + leaq 0x620(%rdi), %r10 + movq %r10, 0x550(%rsp) + leaq 0x630(%rdi), %r10 + movq %r10, 0x548(%rsp) + leaq 0x640(%rdi), %r10 + movq %r10, 0x540(%rsp) + leaq 0x650(%rdi), %r10 + movq %r10, 0x538(%rsp) + leaq 0x660(%rdi), %r10 + movq %r10, 0x530(%rsp) + leaq 0x670(%rdi), %r10 + movq %r10, 0x528(%rsp) + leaq 0x680(%rdi), %r10 + movq %r10, 0x520(%rsp) + leaq 0x690(%rdi), %r10 + movq %r10, 0x518(%rsp) + leaq 0x6a0(%rdi), %r10 + movq %r10, 0x510(%rsp) + leaq 0x6b0(%rdi), %r10 + movq %r10, 0x508(%rsp) + leaq 0x6c0(%rdi), %r10 + movq %r10, 0x500(%rsp) + leaq 0x6d0(%rdi), %r10 + movq %r10, 0x4f8(%rsp) + leaq 0x6e0(%rdi), %r10 + movq %r10, 0x4f0(%rsp) + leaq 0x6f0(%rdi), %r10 + movq %r10, 0x4e8(%rsp) + leaq 0x700(%rdi), %r10 + movq %r10, 0x4e0(%rsp) + leaq 0x710(%rdi), %r10 + movq %r10, 0x4d8(%rsp) + leaq 0x720(%rdi), %r10 + movq %r10, 0x4d0(%rsp) + leaq 0x730(%rdi), %r10 + movq %r10, 0x4c8(%rsp) + leaq 0x740(%rdi), %r10 + movq %r10, 0x4c0(%rsp) + leaq 0x750(%rdi), %r10 + movq %r10, 0x4b8(%rsp) + leaq 0x760(%rdi), %r10 + movq %r10, 0x4b0(%rsp) + leaq 0x770(%rdi), %r10 + movq %r10, 0x4a8(%rsp) + leaq 0x780(%rdi), %r10 + movq %r10, 0x4a0(%rsp) + leaq 0x790(%rdi), %r10 + movq %r10, 0x498(%rsp) + leaq 0x7a0(%rdi), %r10 + movq %r10, 0x490(%rsp) + leaq 0x7b0(%rdi), %r10 + movq %r10, 0x488(%rsp) + leaq 0x7c0(%rdi), %r10 + movq %r10, 0x480(%rsp) + leaq 0x7d0(%rdi), %r10 + movq %r10, 0x478(%rsp) + leaq 0x7e0(%rdi), %r10 + movq %r10, 0x470(%rsp) + leaq 0x7f0(%rdi), %r10 + movq %r10, 0x468(%rsp) + leaq 0x800(%rdi), %r10 + movq %r10, 0x460(%rsp) + leaq 0x810(%rdi), %r10 + movq %r10, 0x458(%rsp) + leaq 0x820(%rdi), %r10 + movq %r10, 0x450(%rsp) + leaq 0x830(%rdi), %r10 + movq %r10, 0x448(%rsp) + leaq 0x840(%rdi), %r10 + movq %r10, 0x440(%rsp) + leaq 0x850(%rdi), %r10 + movq %r10, 0x438(%rsp) + leaq 0x860(%rdi), %r10 + movq %r10, 0x430(%rsp) + leaq 0x870(%rdi), %r10 + movq %r10, 0x428(%rsp) + leaq 0x880(%rdi), %r10 + movq %r10, 0x420(%rsp) + leaq 0x890(%rdi), %r10 + movq %r10, 0x418(%rsp) + leaq 0x8a0(%rdi), %r10 + movq %r10, 0x410(%rsp) + leaq 0x8b0(%rdi), %r10 + movq %r10, 0x408(%rsp) + leaq 0x8c0(%rdi), %r10 + movq %r10, 0x400(%rsp) + leaq 0x8d0(%rdi), %r10 + movq %r10, 0x3f8(%rsp) + leaq 0x8e0(%rdi), %r10 + movq %r10, 0x3f0(%rsp) + leaq 0x8f0(%rdi), %r10 + movq %r10, 0x3e8(%rsp) + leaq 0x900(%rdi), %r10 + movq %r10, 0x3e0(%rsp) + leaq 0x910(%rdi), %r10 + movq %r10, 0x3d8(%rsp) + leaq 0x920(%rdi), %r10 + movq %r10, 0x3d0(%rsp) + leaq 0x930(%rdi), %r10 + movq %r10, 0x3c8(%rsp) + leaq 0x940(%rdi), %r10 + movq %r10, 0x3c0(%rsp) + leaq 0x950(%rdi), %r10 + movq %r10, 0x3b8(%rsp) + leaq 0x960(%rdi), %r10 + movq %r10, 0x3b0(%rsp) + leaq 0x970(%rdi), %r10 + movq %r10, 0x3a8(%rsp) + leaq 0x980(%rdi), %r10 + movq %r10, 0x3a0(%rsp) + leaq 0x990(%rdi), %r10 + movq %r10, 0x398(%rsp) + leaq 0x9a0(%rdi), %r10 + movq %r10, 0x390(%rsp) + leaq 0x9b0(%rdi), %r10 + movq %r10, 0x388(%rsp) + leaq 0x9c0(%rdi), %r10 + movq %r10, 0x380(%rsp) + leaq 0x9d0(%rdi), %r10 + movq %r10, 0x378(%rsp) + leaq 0x9e0(%rdi), %r10 + movq %r10, 0x370(%rsp) + leaq 0x9f0(%rdi), %r10 + movq %r10, 0x368(%rsp) + leaq 0xa00(%rdi), %r10 + movq %r10, 0x360(%rsp) + leaq 0xa10(%rdi), %r10 + movq %r10, 0x358(%rsp) + leaq 0xa20(%rdi), %r10 + movq %r10, 0x350(%rsp) + leaq 0xa30(%rdi), %r10 + movq %r10, 0x348(%rsp) + leaq 0xa40(%rdi), %r10 + movq %r10, 0x340(%rsp) + leaq 0xa50(%rdi), %r10 + movq %r10, 0x338(%rsp) + leaq 0xa60(%rdi), %r10 + movq %r10, 0x330(%rsp) + leaq 0xa70(%rdi), %r10 + movq %r10, 0x328(%rsp) + leaq 0xa80(%rdi), %r10 + movq %r10, 0x320(%rsp) + leaq 0xa90(%rdi), %r10 + movq %r10, 0x318(%rsp) + leaq 0xaa0(%rdi), %r10 + movq %r10, 0x310(%rsp) + leaq 0xab0(%rdi), %r10 + movq %r10, 0x308(%rsp) + leaq 0xac0(%rdi), %r10 + movq %r10, 0x300(%rsp) + leaq 0xad0(%rdi), %r10 + movq %r10, 0x2f8(%rsp) + leaq 0xae0(%rdi), %r10 + movq %r10, 0x2f0(%rsp) + leaq 0xaf0(%rdi), %r10 + movq %r10, 0x2e8(%rsp) + leaq 0xb00(%rdi), %r10 + movq %r10, 0x2e0(%rsp) + leaq 0xb10(%rdi), %r10 + movq %r10, 0x2d8(%rsp) + leaq 0xb20(%rdi), %r10 + movq %r10, 0x2d0(%rsp) + leaq 0xb30(%rdi), %r10 + movq %r10, 0x2c8(%rsp) + leaq 0xb40(%rdi), %r10 + movq %r10, 0x2c0(%rsp) + leaq 0xb50(%rdi), %r10 + movq %r10, 0x2b8(%rsp) + leaq 0xb60(%rdi), %r10 + movq %r10, 0x2b0(%rsp) + leaq 0xb70(%rdi), %r10 + movq %r10, 0x2a8(%rsp) + leaq 0xb80(%rdi), %r10 + movq %r10, 0x2a0(%rsp) + leaq 0xb90(%rdi), %r10 + movq %r10, 0x298(%rsp) + leaq 0xba0(%rdi), %r10 + movq %r10, 0x290(%rsp) + leaq 0xbb0(%rdi), %r10 + movq %r10, 0x288(%rsp) + leaq 0xbc0(%rdi), %r10 + movq %r10, 0x280(%rsp) + leaq 0xbd0(%rdi), %r10 + movq %r10, 0x278(%rsp) + leaq 0xbe0(%rdi), %r10 + movq %r10, 0x270(%rsp) + leaq 0xbf0(%rdi), %r10 + movq %r10, 0x268(%rsp) + leaq 0xc00(%rdi), %r10 + movq %r10, 0x260(%rsp) + leaq 0xc10(%rdi), %r10 + movq %r10, 0x258(%rsp) + leaq 0xc20(%rdi), %r10 + movq %r10, 0x250(%rsp) + leaq 0xc30(%rdi), %r10 + movq %r10, 0x248(%rsp) + leaq 0xc40(%rdi), %r10 + movq %r10, 0x240(%rsp) + leaq 0xc50(%rdi), %r10 + movq %r10, 0x238(%rsp) + leaq 0xc60(%rdi), %r10 + movq %r10, 0x230(%rsp) + leaq 0xc70(%rdi), %r10 + movq %r10, 0x228(%rsp) + leaq 0xc80(%rdi), %r10 + movq %r10, 0x220(%rsp) + leaq 0xc90(%rdi), %r10 + movq %r10, 0x218(%rsp) + leaq 0xca0(%rdi), %r10 + movq %r10, 0x210(%rsp) + leaq 0xcb0(%rdi), %r10 + movq %r10, 0x208(%rsp) + leaq 0xcc0(%rdi), %r10 + movq %r10, 0x200(%rsp) + leaq 0xcd0(%rdi), %r10 + movq %r10, 0x1f8(%rsp) + leaq 0xce0(%rdi), %r10 + movq %r10, 0x1f0(%rsp) + leaq 0xcf0(%rdi), %r10 + movq %r10, 0x1e8(%rsp) + leaq 0xd00(%rdi), %r10 + movq %r10, 0x1e0(%rsp) + leaq 0xd10(%rdi), %r10 + movq %r10, 0x1d8(%rsp) + leaq 0xd20(%rdi), %r10 + movq %r10, 0x1d0(%rsp) + leaq 0xd30(%rdi), %r10 + movq %r10, 0x1c8(%rsp) + leaq 0xd40(%rdi), %r10 + movq %r10, 0x1c0(%rsp) + leaq 0xd50(%rdi), %r10 + movq %r10, 0x1b8(%rsp) + leaq 0xd60(%rdi), %r10 + movq %r10, 0x1b0(%rsp) + leaq 0xd70(%rdi), %r10 + movq %r10, 0x1a8(%rsp) + leaq 0xd80(%rdi), %r10 + movq %r10, 0x1a0(%rsp) + leaq 0xd90(%rdi), %r10 + movq %r10, 0x198(%rsp) + leaq 0xda0(%rdi), %r10 + movq %r10, 0x190(%rsp) + leaq 0xdb0(%rdi), %r10 + movq %r10, 0x188(%rsp) + leaq 0xdc0(%rdi), %r10 + movq %r10, 0x180(%rsp) + leaq 0xdd0(%rdi), %r10 + movq %r10, 0x178(%rsp) + leaq 0xde0(%rdi), %r10 + movq %r10, 0x170(%rsp) + leaq 0xdf0(%rdi), %r10 + movq %r10, 0x168(%rsp) + leaq 0xe00(%rdi), %r10 + movq %r10, 0x160(%rsp) + leaq 0xe10(%rdi), %r10 + movq %r10, 0x158(%rsp) + leaq 0xe20(%rdi), %r10 + movq %r10, 0x150(%rsp) + leaq 0xe30(%rdi), %r10 + movq %r10, 0x148(%rsp) + leaq 0xe40(%rdi), %r10 + movq %r10, 0x140(%rsp) + leaq 0xe50(%rdi), %r10 + movq %r10, 0x138(%rsp) + leaq 0xe60(%rdi), %r10 + movq %r10, 0x130(%rsp) + leaq 0xe70(%rdi), %r10 + movq %r10, 0x128(%rsp) + leaq 0xe80(%rdi), %r10 + movq %r10, 0x120(%rsp) + leaq 0xe90(%rdi), %r10 + movq %r10, 0x118(%rsp) + leaq 0xea0(%rdi), %r10 + movq %r10, 0x110(%rsp) + leaq 0xeb0(%rdi), %r10 + movq %r10, 0x108(%rsp) + leaq 0xec0(%rdi), %r10 + movq %r10, 0x100(%rsp) + leaq 0xed0(%rdi), %r10 + movq %r10, 0xf8(%rsp) + leaq 0xee0(%rdi), %r10 + movq %r10, 0xf0(%rsp) + leaq 0xef0(%rdi), %r10 + movq %r10, 0xe8(%rsp) + leaq 0xf00(%rdi), %r10 + movq %r10, 0xe0(%rsp) + leaq 0xf10(%rdi), %r10 + movq %r10, 0xd8(%rsp) + leaq 0xf20(%rdi), %r10 + movq %r10, 0xd0(%rsp) + leaq 0xf30(%rdi), %r10 + movq %r10, 0xc8(%rsp) + leaq 0xf40(%rdi), %r10 + movq %r10, 0xc0(%rsp) + leaq 0xf50(%rdi), %r10 + movq %r10, 0xb8(%rsp) + leaq 0xf60(%rdi), %r10 + movq %r10, 0xb0(%rsp) + leaq 0xf70(%rdi), %r10 + movq %r10, 0xa8(%rsp) + leaq 0xf80(%rdi), %r10 + movq %r10, 0xa0(%rsp) + leaq 0xf90(%rdi), %r10 + movq %r10, 0x98(%rsp) + leaq 0xfa0(%rdi), %r10 + movq %r10, 0x90(%rsp) + leaq 0xfb0(%rdi), %r10 + movq %r10, 0x88(%rsp) + leaq 0xfc0(%rdi), %r10 + movq %r10, 0x80(%rsp) + leaq 0xfd0(%rdi), %r10 + movq %r10, 0x78(%rsp) + leaq 0xfe0(%rdi), %r10 + movq %r10, 0x70(%rsp) + leaq 0xff0(%rdi), %r10 + movq %r10, 0x68(%rsp) + leaq 0x1000(%rdi), %r10 + movq %r10, 0x60(%rsp) + leaq 0x1010(%rdi), %r10 + movq %r10, 0x58(%rsp) + leaq 0x1020(%rdi), %r10 + movq %r10, 0x50(%rsp) + leaq 0x1030(%rdi), %r10 + movq %r10, 0x48(%rsp) + leaq 0x1040(%rdi), %r10 + movq %r10, 0x40(%rsp) + subq $0x10, %rsp + movq %r12, (%rsp) + subq $0x1020, %rsp # imm = 0x1020 + movq %rcx, %r10 + movq (%r10), %r11 + movq %r11, (%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8(%rsp) + movq %r8, %r10 + movq (%r10), %r11 + movq %r11, 0x10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x18(%rsp) + movq %r9, %r10 + movq (%r10), %r11 + movq %r11, 0x20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x28(%rsp) + movq %rax, %r10 + movq (%r10), %r11 + movq %r11, 0x30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x38(%rsp) + movq %rbx, %r10 + movq (%r10), %r11 + movq %r11, 0x40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x48(%rsp) + movq %r13, %r10 + movq (%r10), %r11 + movq %r11, 0x50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x58(%rsp) + movq %r14, %r10 + movq (%r10), %r11 + movq %r11, 0x60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x68(%rsp) + movq %r15, %r10 + movq (%r10), %r11 + movq %r11, 0x70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x78(%rsp) + movq 0x1838(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x88(%rsp) + movq 0x1830(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x98(%rsp) + movq 0x1828(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa8(%rsp) + movq 0x1820(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb8(%rsp) + movq 0x1818(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc8(%rsp) + movq 0x1810(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd8(%rsp) + movq 0x1808(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe8(%rsp) + movq 0x1800(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf8(%rsp) + movq 0x17f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x100(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x108(%rsp) + movq 0x17f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x110(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x118(%rsp) + movq 0x17e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x120(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x128(%rsp) + movq 0x17e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x130(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x138(%rsp) + movq 0x17d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x140(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x148(%rsp) + movq 0x17d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x150(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x158(%rsp) + movq 0x17c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x160(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x168(%rsp) + movq 0x17c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x170(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x178(%rsp) + movq 0x17b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x180(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x188(%rsp) + movq 0x17b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x190(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x198(%rsp) + movq 0x17a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1a8(%rsp) + movq 0x17a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1b8(%rsp) + movq 0x1798(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1c8(%rsp) + movq 0x1790(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1d8(%rsp) + movq 0x1788(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1e8(%rsp) + movq 0x1780(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1f8(%rsp) + movq 0x1778(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x200(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x208(%rsp) + movq 0x1770(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x210(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x218(%rsp) + movq 0x1768(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x220(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x228(%rsp) + movq 0x1760(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x230(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x238(%rsp) + movq 0x1758(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x240(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x248(%rsp) + movq 0x1750(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x250(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x258(%rsp) + movq 0x1748(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x260(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x268(%rsp) + movq 0x1740(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x270(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x278(%rsp) + movq 0x1738(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x280(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x288(%rsp) + movq 0x1730(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x290(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x298(%rsp) + movq 0x1728(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x2a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x2a8(%rsp) + movq 0x1720(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x2b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x2b8(%rsp) + movq 0x1718(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x2c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x2c8(%rsp) + movq 0x1710(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x2d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x2d8(%rsp) + movq 0x1708(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x2e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x2e8(%rsp) + movq 0x1700(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x2f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x2f8(%rsp) + movq 0x16f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x300(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x308(%rsp) + movq 0x16f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x310(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x318(%rsp) + movq 0x16e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x320(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x328(%rsp) + movq 0x16e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x330(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x338(%rsp) + movq 0x16d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x340(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x348(%rsp) + movq 0x16d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x350(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x358(%rsp) + movq 0x16c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x360(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x368(%rsp) + movq 0x16c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x370(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x378(%rsp) + movq 0x16b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x380(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x388(%rsp) + movq 0x16b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x390(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x398(%rsp) + movq 0x16a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x3a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x3a8(%rsp) + movq 0x16a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x3b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x3b8(%rsp) + movq 0x1698(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x3c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x3c8(%rsp) + movq 0x1690(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x3d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x3d8(%rsp) + movq 0x1688(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x3e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x3e8(%rsp) + movq 0x1680(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x3f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x3f8(%rsp) + movq 0x1678(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x400(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x408(%rsp) + movq 0x1670(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x410(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x418(%rsp) + movq 0x1668(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x420(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x428(%rsp) + movq 0x1660(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x430(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x438(%rsp) + movq 0x1658(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x440(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x448(%rsp) + movq 0x1650(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x450(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x458(%rsp) + movq 0x1648(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x460(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x468(%rsp) + movq 0x1640(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x470(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x478(%rsp) + movq 0x1638(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x480(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x488(%rsp) + movq 0x1630(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x490(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x498(%rsp) + movq 0x1628(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x4a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x4a8(%rsp) + movq 0x1620(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x4b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x4b8(%rsp) + movq 0x1618(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x4c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x4c8(%rsp) + movq 0x1610(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x4d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x4d8(%rsp) + movq 0x1608(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x4e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x4e8(%rsp) + movq 0x1600(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x4f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x4f8(%rsp) + movq 0x15f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x500(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x508(%rsp) + movq 0x15f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x510(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x518(%rsp) + movq 0x15e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x520(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x528(%rsp) + movq 0x15e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x530(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x538(%rsp) + movq 0x15d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x540(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x548(%rsp) + movq 0x15d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x550(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x558(%rsp) + movq 0x15c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x560(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x568(%rsp) + movq 0x15c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x570(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x578(%rsp) + movq 0x15b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x580(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x588(%rsp) + movq 0x15b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x590(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x598(%rsp) + movq 0x15a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x5a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x5a8(%rsp) + movq 0x15a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x5b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x5b8(%rsp) + movq 0x1598(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x5c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x5c8(%rsp) + movq 0x1590(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x5d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x5d8(%rsp) + movq 0x1588(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x5e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x5e8(%rsp) + movq 0x1580(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x5f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x5f8(%rsp) + movq 0x1578(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x600(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x608(%rsp) + movq 0x1570(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x610(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x618(%rsp) + movq 0x1568(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x620(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x628(%rsp) + movq 0x1560(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x630(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x638(%rsp) + movq 0x1558(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x640(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x648(%rsp) + movq 0x1550(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x650(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x658(%rsp) + movq 0x1548(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x660(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x668(%rsp) + movq 0x1540(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x670(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x678(%rsp) + movq 0x1538(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x680(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x688(%rsp) + movq 0x1530(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x690(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x698(%rsp) + movq 0x1528(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x6a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x6a8(%rsp) + movq 0x1520(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x6b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x6b8(%rsp) + movq 0x1518(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x6c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x6c8(%rsp) + movq 0x1510(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x6d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x6d8(%rsp) + movq 0x1508(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x6e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x6e8(%rsp) + movq 0x1500(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x6f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x6f8(%rsp) + movq 0x14f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x700(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x708(%rsp) + movq 0x14f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x710(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x718(%rsp) + movq 0x14e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x720(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x728(%rsp) + movq 0x14e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x730(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x738(%rsp) + movq 0x14d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x740(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x748(%rsp) + movq 0x14d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x750(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x758(%rsp) + movq 0x14c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x760(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x768(%rsp) + movq 0x14c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x770(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x778(%rsp) + movq 0x14b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x780(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x788(%rsp) + movq 0x14b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x790(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x798(%rsp) + movq 0x14a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x7a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x7a8(%rsp) + movq 0x14a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x7b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x7b8(%rsp) + movq 0x1498(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x7c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x7c8(%rsp) + movq 0x1490(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x7d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x7d8(%rsp) + movq 0x1488(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x7e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x7e8(%rsp) + movq 0x1480(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x7f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x7f8(%rsp) + movq 0x1478(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x800(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x808(%rsp) + movq 0x1470(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x810(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x818(%rsp) + movq 0x1468(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x820(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x828(%rsp) + movq 0x1460(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x830(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x838(%rsp) + movq 0x1458(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x840(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x848(%rsp) + movq 0x1450(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x850(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x858(%rsp) + movq 0x1448(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x860(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x868(%rsp) + movq 0x1440(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x870(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x878(%rsp) + movq 0x1438(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x880(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x888(%rsp) + movq 0x1430(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x890(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x898(%rsp) + movq 0x1428(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x8a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8a8(%rsp) + movq 0x1420(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x8b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8b8(%rsp) + movq 0x1418(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x8c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8c8(%rsp) + movq 0x1410(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x8d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8d8(%rsp) + movq 0x1408(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x8e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8e8(%rsp) + movq 0x1400(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x8f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8f8(%rsp) + movq 0x13f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x900(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x908(%rsp) + movq 0x13f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x910(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x918(%rsp) + movq 0x13e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x920(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x928(%rsp) + movq 0x13e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x930(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x938(%rsp) + movq 0x13d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x940(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x948(%rsp) + movq 0x13d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x950(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x958(%rsp) + movq 0x13c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x960(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x968(%rsp) + movq 0x13c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x970(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x978(%rsp) + movq 0x13b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x980(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x988(%rsp) + movq 0x13b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x990(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x998(%rsp) + movq 0x13a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x9a0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x9a8(%rsp) + movq 0x13a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x9b0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x9b8(%rsp) + movq 0x1398(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x9c0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x9c8(%rsp) + movq 0x1390(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x9d0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x9d8(%rsp) + movq 0x1388(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x9e0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x9e8(%rsp) + movq 0x1380(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x9f0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x9f8(%rsp) + movq 0x1378(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa00(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa08(%rsp) + movq 0x1370(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa18(%rsp) + movq 0x1368(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa28(%rsp) + movq 0x1360(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa38(%rsp) + movq 0x1358(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa48(%rsp) + movq 0x1350(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa58(%rsp) + movq 0x1348(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa68(%rsp) + movq 0x1340(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa78(%rsp) + movq 0x1338(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa88(%rsp) + movq 0x1330(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa98(%rsp) + movq 0x1328(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xaa0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xaa8(%rsp) + movq 0x1320(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xab0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xab8(%rsp) + movq 0x1318(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xac0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xac8(%rsp) + movq 0x1310(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xad0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xad8(%rsp) + movq 0x1308(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xae0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xae8(%rsp) + movq 0x1300(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xaf0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xaf8(%rsp) + movq 0x12f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb00(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb08(%rsp) + movq 0x12f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb18(%rsp) + movq 0x12e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb28(%rsp) + movq 0x12e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb38(%rsp) + movq 0x12d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb48(%rsp) + movq 0x12d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb58(%rsp) + movq 0x12c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb68(%rsp) + movq 0x12c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb78(%rsp) + movq 0x12b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb88(%rsp) + movq 0x12b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb98(%rsp) + movq 0x12a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xba0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xba8(%rsp) + movq 0x12a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xbb0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xbb8(%rsp) + movq 0x1298(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xbc0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xbc8(%rsp) + movq 0x1290(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xbd0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xbd8(%rsp) + movq 0x1288(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xbe0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xbe8(%rsp) + movq 0x1280(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xbf0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xbf8(%rsp) + movq 0x1278(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc00(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc08(%rsp) + movq 0x1270(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc18(%rsp) + movq 0x1268(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc28(%rsp) + movq 0x1260(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc38(%rsp) + movq 0x1258(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc48(%rsp) + movq 0x1250(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc58(%rsp) + movq 0x1248(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc68(%rsp) + movq 0x1240(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc78(%rsp) + movq 0x1238(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc88(%rsp) + movq 0x1230(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc98(%rsp) + movq 0x1228(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xca0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xca8(%rsp) + movq 0x1220(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xcb0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xcb8(%rsp) + movq 0x1218(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xcc0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xcc8(%rsp) + movq 0x1210(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xcd0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xcd8(%rsp) + movq 0x1208(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xce0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xce8(%rsp) + movq 0x1200(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xcf0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xcf8(%rsp) + movq 0x11f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd00(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd08(%rsp) + movq 0x11f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd18(%rsp) + movq 0x11e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd28(%rsp) + movq 0x11e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd38(%rsp) + movq 0x11d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd48(%rsp) + movq 0x11d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd58(%rsp) + movq 0x11c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd68(%rsp) + movq 0x11c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd78(%rsp) + movq 0x11b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd88(%rsp) + movq 0x11b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xd90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xd98(%rsp) + movq 0x11a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xda0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xda8(%rsp) + movq 0x11a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xdb0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xdb8(%rsp) + movq 0x1198(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xdc0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xdc8(%rsp) + movq 0x1190(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xdd0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xdd8(%rsp) + movq 0x1188(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xde0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xde8(%rsp) + movq 0x1180(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xdf0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xdf8(%rsp) + movq 0x1178(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe00(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe08(%rsp) + movq 0x1170(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe18(%rsp) + movq 0x1168(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe28(%rsp) + movq 0x1160(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe38(%rsp) + movq 0x1158(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe48(%rsp) + movq 0x1150(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe58(%rsp) + movq 0x1148(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe68(%rsp) + movq 0x1140(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe78(%rsp) + movq 0x1138(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe88(%rsp) + movq 0x1130(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xe90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xe98(%rsp) + movq 0x1128(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xea0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xea8(%rsp) + movq 0x1120(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xeb0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xeb8(%rsp) + movq 0x1118(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xec0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xec8(%rsp) + movq 0x1110(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xed0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xed8(%rsp) + movq 0x1108(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xee0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xee8(%rsp) + movq 0x1100(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xef0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xef8(%rsp) + movq 0x10f8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf00(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf08(%rsp) + movq 0x10f0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf18(%rsp) + movq 0x10e8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf28(%rsp) + movq 0x10e0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf38(%rsp) + movq 0x10d8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf48(%rsp) + movq 0x10d0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf58(%rsp) + movq 0x10c8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf68(%rsp) + movq 0x10c0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf78(%rsp) + movq 0x10b8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf88(%rsp) + movq 0x10b0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xf90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xf98(%rsp) + movq 0x10a8(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xfa0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xfa8(%rsp) + movq 0x10a0(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xfb0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xfb8(%rsp) + movq 0x1098(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xfc0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xfc8(%rsp) + movq 0x1090(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xfd0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xfd8(%rsp) + movq 0x1088(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xfe0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xfe8(%rsp) + movq 0x1080(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xff0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xff8(%rsp) + movq 0x1078(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1000(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1008(%rsp) + movq 0x1070(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x1010(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x1018(%rsp) + movq %rdx, %r8 + movq %rsi, %rdx + movq 0x8(%rdi), %rsi + movq (%rdi), %rdi + movq 0x8(%rdx), %rcx + movq (%rdx), %rdx + movq 0x8(%r8), %r9 + movq (%r8), %r8 + movq 0x1020(%rsp), %r10 + callq *%r10 + addq $0x1020, %rsp # imm = 0x1020 + addq $0x10, %rsp + cmpq $0x18d9e, %rax # imm = 0x18D9E + je + movl $0x3, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + movq 0x18(%rsp), %r14 + movq 0x20(%rsp), %r15 + addq $0x1050, %rsp # imm = 0x1050 + popq %rbp + retq + xorq %rax, %rax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + movq 0x18(%rsp), %r14 + movq 0x20(%rsp), %r15 + addq $0x1050, %rsp # imm = 0x1050 + popq %rbp + retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/cast_fn_ptr_call.aarch64.asm b/tests/snapshots/asm/cast_fn_ptr_call.aarch64.asm index e51519a52..e535e4b82 100644 --- a/tests/snapshots/asm/cast_fn_ptr_call.aarch64.asm +++ b/tests/snapshots/asm/cast_fn_ptr_call.aarch64.asm @@ -28,8 +28,8 @@ Disassembly of section .text: adrp x20, add x20, x20, mov x0, #0x29 // =41 - mov x9, x20 str x0, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -43,8 +43,8 @@ Disassembly of section .text: ldp x29, x30, [sp], #0x10 ret mov x0, #0x7 // =7 - mov x9, x20 str x0, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -60,8 +60,8 @@ Disassembly of section .text: adrp x0, add x0, x0, mov x1, #0x15 // =21 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/cast_fn_typedef_ptr_in_initializer.aarch64.asm b/tests/snapshots/asm/cast_fn_typedef_ptr_in_initializer.aarch64.asm index 147826384..6492c2a0f 100644 --- a/tests/snapshots/asm/cast_fn_typedef_ptr_in_initializer.aarch64.asm +++ b/tests/snapshots/asm/cast_fn_typedef_ptr_in_initializer.aarch64.asm @@ -26,9 +26,9 @@ Disassembly of section .text: ldr x0, [x0] mov x1, #0x2 // =2 mov x2, #0x3 // =3 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/dlopen_atoi.aarch64.asm b/tests/snapshots/asm/dlopen_atoi.aarch64.asm index 2cdfd5a5c..36b1294bd 100644 --- a/tests/snapshots/asm/dlopen_atoi.aarch64.asm +++ b/tests/snapshots/asm/dlopen_atoi.aarch64.asm @@ -48,8 +48,8 @@ Disassembly of section .text: ret adrp x0, add x0, x0, - mov x9, x21 str x0, [sp, #-0x10]! + mov x9, x21 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/dlopen_strlen.aarch64.asm b/tests/snapshots/asm/dlopen_strlen.aarch64.asm index 3ca80adf2..c3f5435bd 100644 --- a/tests/snapshots/asm/dlopen_strlen.aarch64.asm +++ b/tests/snapshots/asm/dlopen_strlen.aarch64.asm @@ -22,8 +22,8 @@ Disassembly of section .text: bl adrp x1, add x1, x1, - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/float_arith_in_static_init.aarch64.asm b/tests/snapshots/asm/float_arith_in_static_init.aarch64.asm index cc1d48671..faed97e86 100644 --- a/tests/snapshots/asm/float_arith_in_static_init.aarch64.asm +++ b/tests/snapshots/asm/float_arith_in_static_init.aarch64.asm @@ -26,8 +26,7 @@ Disassembly of section .text: add sp, sp, #0x10 ldp x29, x30, [sp], #0x10 ret - add x1, x0, #0x4 - ldr s0, [x1] + ldr s0, [x0, #0x4] mov x1, #0x4004000000000000 // =4612811918334230528 fmov d16, x1 fneg d1, d16 @@ -39,8 +38,7 @@ Disassembly of section .text: add sp, sp, #0x10 ldp x29, x30, [sp], #0x10 ret - add x0, x0, #0x8 - ldr s0, [x0] + ldr s0, [x0, #0x8] mov x0, #0x4028000000000000 // =4622945017495814144 fcvt d0, s0 fmov d17, x0 @@ -79,8 +77,7 @@ Disassembly of section .text: ret adrp x0, add x0, x0, - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x0, #0x3fe8000000000000 // =4604930618986332160 fmov d16, x0 fneg d1, d16 diff --git a/tests/snapshots/asm/float_arith_in_static_init.x64.asm b/tests/snapshots/asm/float_arith_in_static_init.x64.asm index 6f5827631..d58817a1d 100644 --- a/tests/snapshots/asm/float_arith_in_static_init.x64.asm +++ b/tests/snapshots/asm/float_arith_in_static_init.x64.asm @@ -31,8 +31,7 @@ Disassembly of section .text: addq $0x10, %rsp popq %rbp retq - leaq 0x4(%rax), %rcx - movss (%rcx,%riz), %xmm0 + movss 0x4(%rax,%riz), %xmm0 movabsq $0x4004000000000000, %rcx # imm = 0x4004000000000000 movq %rcx, %xmm1 movabsq $-0x8000000000000000, %r10 # imm = 0x8000000000000000 @@ -51,8 +50,7 @@ Disassembly of section .text: addq $0x10, %rsp popq %rbp retq - addq $0x8, %rax - movss (%rax,%riz), %xmm0 + movss 0x8(%rax,%riz), %xmm0 movabsq $0x4028000000000000, %rax # imm = 0x4028000000000000 cvtss2sd %xmm0, %xmm0 movq %rax, %xmm15 @@ -94,8 +92,7 @@ Disassembly of section .text: popq %rbp retq leaq , %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x3fe8000000000000, %rax # imm = 0x3FE8000000000000 movq %rax, %xmm1 movabsq $-0x8000000000000000, %r10 # imm = 0x8000000000000000 @@ -118,5 +115,3 @@ Disassembly of section .text: popq %rbp retq jmp - addb %al, (%rax) - addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/float_increment_decrement.aarch64.asm b/tests/snapshots/asm/float_increment_decrement.aarch64.asm index 14909594c..10bb7e4dd 100644 --- a/tests/snapshots/asm/float_increment_decrement.aarch64.asm +++ b/tests/snapshots/asm/float_increment_decrement.aarch64.asm @@ -175,12 +175,11 @@ Disassembly of section .text: fcvt s0, d0 str s0, [x0] sub x0, x29, #0x60 - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x1, #-0x4010000000000000 // =-4616189618054758400 fmov d17, x1 fadd d0, d0, d17 - str d0, [x0] + str d0, [x0, #0x8] sub x0, x29, #0x60 ldr s0, [x0] mov x0, #0x4004000000000000 // =4612811918334230528 @@ -190,8 +189,7 @@ Disassembly of section .text: cset x1, ne cbnz x1, sub x0, x29, #0x60 - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x0, #0x3ff8000000000000 // =4609434218613702656 fmov d17, x0 fcmp d0, d17 @@ -234,30 +232,26 @@ Disassembly of section .text: str x10, [x0, #0x10] ldr x10, [sp], #0x10 sub x0, x29, #0x78 - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x1, #0x3ff0000000000000 // =4607182418800017408 fmov d17, x1 fadd d0, d0, d17 - str d0, [x0] + str d0, [x0, #0x8] sub x0, x29, #0x78 - add x0, x0, #0x10 - ldr d0, [x0] + ldr d0, [x0, #0x10] mov x1, #-0x4010000000000000 // =-4616189618054758400 fmov d17, x1 fadd d0, d0, d17 - str d0, [x0] + str d0, [x0, #0x10] sub x0, x29, #0x78 - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x0, #0x4000000000000000 // =4611686018427387904 fmov d17, x0 fcmp d0, d17 cset x1, ne cbnz x1, sub x0, x29, #0x78 - add x0, x0, #0x10 - ldr d0, [x0] + ldr d0, [x0, #0x10] mov x0, #0x3ff0000000000000 // =4607182418800017408 fmov d17, x0 fcmp d0, d17 diff --git a/tests/snapshots/asm/float_increment_decrement.x64.asm b/tests/snapshots/asm/float_increment_decrement.x64.asm index 6577ea860..e3d4a4920 100644 --- a/tests/snapshots/asm/float_increment_decrement.x64.asm +++ b/tests/snapshots/asm/float_increment_decrement.x64.asm @@ -207,12 +207,11 @@ Disassembly of section .text: cvtsd2ss %xmm0, %xmm0 movss %xmm0, (%rax,%riz) leaq -0x60(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $-0x4010000000000000, %rcx # imm = 0xBFF0000000000000 movq %rcx, %xmm15 addsd %xmm15, %xmm0 - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x8(%rax,%riz) leaq -0x60(%rbp), %rax movss (%rax,%riz), %xmm0 movabsq $0x4004000000000000, %rax # imm = 0x4004000000000000 @@ -227,8 +226,7 @@ Disassembly of section .text: testq %rcx, %rcx jne leaq -0x60(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x3ff8000000000000, %rax # imm = 0x3FF8000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -279,22 +277,19 @@ Disassembly of section .text: movq %rdx, 0x10(%rax) popq %rdx leaq -0x78(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x3ff0000000000000, %rcx # imm = 0x3FF0000000000000 movq %rcx, %xmm15 addsd %xmm15, %xmm0 - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x8(%rax,%riz) leaq -0x78(%rbp), %rax - addq $0x10, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x10(%rax,%riz), %xmm0 movabsq $-0x4010000000000000, %rcx # imm = 0xBFF0000000000000 movq %rcx, %xmm15 addsd %xmm15, %xmm0 - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x10(%rax,%riz) leaq -0x78(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x4000000000000000, %rax # imm = 0x4000000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -306,8 +301,7 @@ Disassembly of section .text: testq %rcx, %rcx jne leaq -0x78(%rbp), %rax - addq $0x10, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x10(%rax,%riz), %xmm0 movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -359,5 +353,4 @@ Disassembly of section .text: jmp jmp jmp - addb %al, (%rax) addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/float_is_four_bytes.aarch64.asm b/tests/snapshots/asm/float_is_four_bytes.aarch64.asm index b8233ec2a..9c028eee0 100644 --- a/tests/snapshots/asm/float_is_four_bytes.aarch64.asm +++ b/tests/snapshots/asm/float_is_four_bytes.aarch64.asm @@ -130,8 +130,7 @@ Disassembly of section .text: mov x20, #0x7 // =7 adrp x0, add x0, x0, - add x0, x0, #0x4 - ldr s0, [x0] + ldr s0, [x0, #0x4] mov x0, #0x4004000000000000 // =4612811918334230528 fcvt d0, s0 fmov d17, x0 @@ -142,16 +141,14 @@ Disassembly of section .text: add x0, x0, adrp x1, add x1, x1, - add x1, x1, #0x4 - ldr s0, [x1] + ldr s0, [x1, #0x4] fcvt d0, s0 bl sxtw x0, w0 mov x20, #0x8 // =8 adrp x0, add x0, x0, - add x0, x0, #0x8 - ldr s0, [x0] + ldr s0, [x0, #0x8] mov x0, #0x400c000000000000 // =4615063718147915776 fcvt d0, s0 fmov d17, x0 @@ -162,16 +159,14 @@ Disassembly of section .text: add x0, x0, adrp x1, add x1, x1, - add x1, x1, #0x8 - ldr s0, [x1] + ldr s0, [x1, #0x8] fcvt d0, s0 bl sxtw x0, w0 mov x20, #0x9 // =9 adrp x0, add x0, x0, - add x0, x0, #0xc - ldr s0, [x0] + ldr s0, [x0, #0xc] mov x0, #0x4012000000000000 // =4616752568008179712 fcvt d0, s0 fmov d17, x0 @@ -182,8 +177,7 @@ Disassembly of section .text: add x0, x0, adrp x1, add x1, x1, - add x1, x1, #0xc - ldr s0, [x1] + ldr s0, [x1, #0xc] fcvt d0, s0 bl sxtw x0, w0 diff --git a/tests/snapshots/asm/float_is_four_bytes.x64.asm b/tests/snapshots/asm/float_is_four_bytes.x64.asm index 0389887f4..309c468c1 100644 --- a/tests/snapshots/asm/float_is_four_bytes.x64.asm +++ b/tests/snapshots/asm/float_is_four_bytes.x64.asm @@ -127,8 +127,7 @@ Disassembly of section .text: movslq %eax, %rax movl $0x7, %ebx leaq , %rax - addq $0x4, %rax - movss (%rax,%riz), %xmm0 + movss 0x4(%rax,%riz), %xmm0 movabsq $0x4004000000000000, %rax # imm = 0x4004000000000000 cvtss2sd %xmm0, %xmm0 movq %rax, %xmm15 @@ -142,16 +141,14 @@ Disassembly of section .text: je leaq , %rdi leaq , %rax - addq $0x4, %rax - movss (%rax,%riz), %xmm0 + movss 0x4(%rax,%riz), %xmm0 cvtss2sd %xmm0, %xmm0 movb $0x1, %al callq movslq %eax, %rax movl $0x8, %ebx leaq , %rax - addq $0x8, %rax - movss (%rax,%riz), %xmm0 + movss 0x8(%rax,%riz), %xmm0 movabsq $0x400c000000000000, %rax # imm = 0x400C000000000000 cvtss2sd %xmm0, %xmm0 movq %rax, %xmm15 @@ -165,16 +162,14 @@ Disassembly of section .text: je leaq , %rdi leaq , %rax - addq $0x8, %rax - movss (%rax,%riz), %xmm0 + movss 0x8(%rax,%riz), %xmm0 cvtss2sd %xmm0, %xmm0 movb $0x1, %al callq movslq %eax, %rax movl $0x9, %ebx leaq , %rax - addq $0xc, %rax - movss (%rax,%riz), %xmm0 + movss 0xc(%rax,%riz), %xmm0 movabsq $0x4012000000000000, %rax # imm = 0x4012000000000000 cvtss2sd %xmm0, %xmm0 movq %rax, %xmm15 @@ -188,8 +183,7 @@ Disassembly of section .text: je leaq , %rdi leaq , %rax - addq $0xc, %rax - movss (%rax,%riz), %xmm0 + movss 0xc(%rax,%riz), %xmm0 cvtss2sd %xmm0, %xmm0 movb $0x1, %al callq @@ -356,5 +350,4 @@ Disassembly of section .text: jmp jmp jmp - addb %al, (%rax) addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/fma_numeric_kernels.aarch64.asm b/tests/snapshots/asm/fma_numeric_kernels.aarch64.asm index 3f795f3bc..303448f11 100644 --- a/tests/snapshots/asm/fma_numeric_kernels.aarch64.asm +++ b/tests/snapshots/asm/fma_numeric_kernels.aarch64.asm @@ -138,25 +138,21 @@ Disassembly of section .text: fmov d16, x1 str d16, [x0] sub x0, x29, #0x28 - add x0, x0, #0x8 mov x2, #0x4000000000000000 // =4611686018427387904 fmov d16, x2 - str d16, [x0] + str d16, [x0, #0x8] sub x0, x29, #0x28 - add x0, x0, #0x10 mov x1, #0x4008000000000000 // =4613937818241073152 fmov d16, x1 - str d16, [x0] + str d16, [x0, #0x10] sub x0, x29, #0x28 - add x0, x0, #0x18 mov x1, #0x4010000000000000 // =4616189618054758400 fmov d16, x1 - str d16, [x0] + str d16, [x0, #0x18] sub x0, x29, #0x28 - add x0, x0, #0x20 mov x1, #0x4014000000000000 // =4617315517961601024 fmov d16, x1 - str d16, [x0] + str d16, [x0, #0x20] sub x0, x29, #0x28 mov x1, #0x5 // =5 fmov d0, x2 diff --git a/tests/snapshots/asm/fma_numeric_kernels.x64.asm b/tests/snapshots/asm/fma_numeric_kernels.x64.asm index 8b28194af..d6838c151 100644 --- a/tests/snapshots/asm/fma_numeric_kernels.x64.asm +++ b/tests/snapshots/asm/fma_numeric_kernels.x64.asm @@ -168,25 +168,21 @@ Disassembly of section .text: movq %rcx, %xmm14 movsd %xmm14, (%rax,%riz) leaq -0x28(%rbp), %rax - addq $0x8, %rax movabsq $0x4000000000000000, %rdx # imm = 0x4000000000000000 movq %rdx, %xmm14 - movsd %xmm14, (%rax,%riz) + movsd %xmm14, 0x8(%rax,%riz) leaq -0x28(%rbp), %rax - addq $0x10, %rax movabsq $0x4008000000000000, %rcx # imm = 0x4008000000000000 movq %rcx, %xmm14 - movsd %xmm14, (%rax,%riz) + movsd %xmm14, 0x10(%rax,%riz) leaq -0x28(%rbp), %rax - addq $0x18, %rax movabsq $0x4010000000000000, %rcx # imm = 0x4010000000000000 movq %rcx, %xmm14 - movsd %xmm14, (%rax,%riz) + movsd %xmm14, 0x18(%rax,%riz) leaq -0x28(%rbp), %rax - addq $0x20, %rax movabsq $0x4014000000000000, %rcx # imm = 0x4014000000000000 movq %rcx, %xmm14 - movsd %xmm14, (%rax,%riz) + movsd %xmm14, 0x20(%rax,%riz) leaq -0x28(%rbp), %rdi movl $0x5, %esi movq %rdx, %xmm0 diff --git a/tests/snapshots/asm/fn_ptr_decay_inside_block.aarch64.asm b/tests/snapshots/asm/fn_ptr_decay_inside_block.aarch64.asm index 86fff3d75..183981708 100644 --- a/tests/snapshots/asm/fn_ptr_decay_inside_block.aarch64.asm +++ b/tests/snapshots/asm/fn_ptr_decay_inside_block.aarch64.asm @@ -38,15 +38,15 @@ Disassembly of section .text: adrp x21, add x21, x21, mov x0, #0x1 // =1 - mov x9, x21 str x0, [sp, #-0x10]! + mov x9, x21 ldr x0, [sp] blr x9 add sp, sp, #0x10 add x20, x20, x0 mov x0, #0x2 // =2 - mov x9, x21 str x0, [sp, #-0x10]! + mov x9, x21 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -58,8 +58,8 @@ Disassembly of section .text: mov x1, #0x0 // =0 b mov x0, #0x3 // =3 - mov x9, x1 str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -71,8 +71,8 @@ Disassembly of section .text: sub x0, x29, #0x48 ldr x0, [x0] mov x1, #0x4 // =4 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/fn_ptr_explicit_deref.aarch64.asm b/tests/snapshots/asm/fn_ptr_explicit_deref.aarch64.asm index 47f4f915e..b441ff29a 100644 --- a/tests/snapshots/asm/fn_ptr_explicit_deref.aarch64.asm +++ b/tests/snapshots/asm/fn_ptr_explicit_deref.aarch64.asm @@ -25,8 +25,8 @@ Disassembly of section .text: stur x0, [x29, #-0x8] mov x0, #0x28 // =40 ldur x1, [x29, #-0x8] - mov x9, x1 str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -41,8 +41,8 @@ Disassembly of section .text: ret mov x0, #0x28 // =40 ldur x1, [x29, #-0x8] - mov x9, x1 str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -58,8 +58,8 @@ Disassembly of section .text: sub x20, x29, #0x8 ldr x0, [x20] mov x1, #0x28 // =40 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -74,8 +74,8 @@ Disassembly of section .text: ret ldr x0, [x20] mov x1, #0x28 // =40 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/fn_ptr_float_arg.aarch64.asm b/tests/snapshots/asm/fn_ptr_float_arg.aarch64.asm index 91aeccaec..3f5f29da9 100644 --- a/tests/snapshots/asm/fn_ptr_float_arg.aarch64.asm +++ b/tests/snapshots/asm/fn_ptr_float_arg.aarch64.asm @@ -40,10 +40,10 @@ Disassembly of section .text: sub sp, sp, #0x30 str x19, [sp] sxtw x0, w0 - mov x9, x1 fmov x16, d0 str x16, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] ldr d0, [sp, #0x10] blr x9 @@ -77,9 +77,9 @@ Disassembly of section .text: mov x0, #0x4004000000000000 // =4612811918334230528 fmov d16, x0 fcvt s0, d16 - mov x9, x20 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x20 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -98,10 +98,10 @@ Disassembly of section .text: mov x2, #0x4012000000000000 // =4616752568008179712 fmov d16, x2 fcvt s0, d16 - mov x9, x0 fmov x16, d0 str x16, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr d0, [sp, #0x10] blr x9 @@ -133,9 +133,9 @@ Disassembly of section .text: mov x0, #0x400c000000000000 // =4615063718147915776 fmov d16, x0 fcvt s0, d16 - mov x9, x20 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x20 ldr d0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/fn_ptr_float_arg_narrow.aarch64.asm b/tests/snapshots/asm/fn_ptr_float_arg_narrow.aarch64.asm index 6eddddaf6..fd5140825 100644 --- a/tests/snapshots/asm/fn_ptr_float_arg_narrow.aarch64.asm +++ b/tests/snapshots/asm/fn_ptr_float_arg_narrow.aarch64.asm @@ -60,9 +60,9 @@ Disassembly of section .text: mov x1, #0x4008000000000000 // =4613937818241073152 fmov d16, x1 fcvt s0, d16 - mov x9, x0 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -83,9 +83,9 @@ Disassembly of section .text: mov x20, #0x4008000000000000 // =4613937818241073152 fmov d16, x20 fcvt s0, d16 - mov x9, x0 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -107,9 +107,9 @@ Disassembly of section .text: mov x1, #0x4010000000000000 // =4616189618054758400 fmov d16, x1 fcvt s0, d16 - mov x9, x0 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -140,11 +140,11 @@ Disassembly of section .text: mov x1, #0x4000000000000000 // =4611686018427387904 fmov d16, x1 fcvt s1, d16 - mov x9, x0 fmov x16, d1 str x16, [sp, #-0x10]! fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] ldr d1, [sp, #0x10] blr x9 @@ -166,9 +166,9 @@ Disassembly of section .text: mov x1, #0x4014000000000000 // =4617315517961601024 fmov d16, x1 fcvt s0, d16 - mov x9, x0 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -189,9 +189,9 @@ Disassembly of section .text: fcvt s0, d16 sub x0, x29, #0x10 ldr x0, [x0] - mov x9, x0 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -222,9 +222,9 @@ Disassembly of section .text: mov x1, #0x4008000000000000 // =4613937818241073152 fmov d16, x1 fcvt s0, d16 - mov x9, x0 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -244,9 +244,9 @@ Disassembly of section .text: mov x1, #0x4008000000000000 // =4613937818241073152 fmov d16, x1 fcvt s0, d16 - mov x9, x0 fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -269,11 +269,11 @@ Disassembly of section .text: mov x1, #0x4000000000000000 // =4611686018427387904 fmov d16, x1 fcvt s1, d16 - mov x9, x0 fmov x16, d1 str x16, [sp, #-0x10]! fmov x16, d0 str x16, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] ldr d1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/fn_ptr_float_return.aarch64.asm b/tests/snapshots/asm/fn_ptr_float_return.aarch64.asm index 3af29b9a5..206e7029b 100644 --- a/tests/snapshots/asm/fn_ptr_float_return.aarch64.asm +++ b/tests/snapshots/asm/fn_ptr_float_return.aarch64.asm @@ -64,8 +64,8 @@ Disassembly of section .text: adrp x0, add x0, x0, mov x1, #0xa // =10 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -84,8 +84,8 @@ Disassembly of section .text: adrp x0, add x0, x0, mov x1, #0x4000000000000000 // =4611686018427387904 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr d0, [sp] blr x9 add sp, sp, #0x10 @@ -118,8 +118,8 @@ Disassembly of section .text: adrp x0, add x0, x0, mov x1, #0x8 // =8 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/fn_ptr_multi_deref.aarch64.asm b/tests/snapshots/asm/fn_ptr_multi_deref.aarch64.asm index 58cf0ac12..eca3e6117 100644 --- a/tests/snapshots/asm/fn_ptr_multi_deref.aarch64.asm +++ b/tests/snapshots/asm/fn_ptr_multi_deref.aarch64.asm @@ -38,9 +38,9 @@ Disassembly of section .text: add x20, x20, mov x1, #0x4 // =4 mov x2, #0x5 // =5 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -56,9 +56,9 @@ Disassembly of section .text: ret mov x0, #0x6 // =6 mov x1, #0x7 // =7 - mov x9, x20 str x1, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/fn_ptr_struct_return.aarch64.asm b/tests/snapshots/asm/fn_ptr_struct_return.aarch64.asm index 50d48c953..6a4d7e5fd 100644 --- a/tests/snapshots/asm/fn_ptr_struct_return.aarch64.asm +++ b/tests/snapshots/asm/fn_ptr_struct_return.aarch64.asm @@ -25,8 +25,8 @@ Disassembly of section .text: adrp x20, add x20, x20, ldr x1, [x20] - mov x9, x1 str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -41,8 +41,8 @@ Disassembly of section .text: ret ldr x0, [x20] mov x1, #0x0 // =0 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -57,8 +57,8 @@ Disassembly of section .text: ret ldr x0, [x20] mov x1, #0x0 // =0 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -74,8 +74,8 @@ Disassembly of section .text: adrp x21, add x21, x21, mov x0, #0x0 // =0 - mov x9, x21 str x0, [sp, #-0x10]! + mov x9, x21 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -89,8 +89,8 @@ Disassembly of section .text: ldp x29, x30, [sp], #0x10 ret mov x0, #0x0 // =0 - mov x9, x21 str x0, [sp, #-0x10]! + mov x9, x21 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -105,8 +105,8 @@ Disassembly of section .text: ret ldr x0, [x20] mov x1, #0x0 // =0 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/fn_ptr_ternary_call_return.aarch64.asm b/tests/snapshots/asm/fn_ptr_ternary_call_return.aarch64.asm index 7fdd5db90..998365d77 100644 --- a/tests/snapshots/asm/fn_ptr_ternary_call_return.aarch64.asm +++ b/tests/snapshots/asm/fn_ptr_ternary_call_return.aarch64.asm @@ -39,8 +39,8 @@ Disassembly of section .text: b adrp x1, add x1, x1, - mov x9, x1 str x20, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -53,8 +53,8 @@ Disassembly of section .text: mov x0, #0x7890 // =30864 movk x0, #0x3456, lsl #16 movk x0, #0x12, lsl #32 - mov x9, x1 str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/fn_ptr_typedef_multi_declarator.aarch64.asm b/tests/snapshots/asm/fn_ptr_typedef_multi_declarator.aarch64.asm index 6fc1b8d36..5a7f5d34b 100644 --- a/tests/snapshots/asm/fn_ptr_typedef_multi_declarator.aarch64.asm +++ b/tests/snapshots/asm/fn_ptr_typedef_multi_declarator.aarch64.asm @@ -62,8 +62,8 @@ Disassembly of section .text: adrp x21, add x21, x21, sub x0, x29, #0x28 - mov x9, x21 str x0, [sp, #-0x10]! + mov x9, x21 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -78,8 +78,8 @@ Disassembly of section .text: ldp x29, x30, [sp], #0x10 ret sub x0, x29, #0x28 - mov x9, x21 str x0, [sp, #-0x10]! + mov x9, x21 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/fn_returning_fn_ptr.aarch64.asm b/tests/snapshots/asm/fn_returning_fn_ptr.aarch64.asm index 6963c8d18..825fff43e 100644 --- a/tests/snapshots/asm/fn_returning_fn_ptr.aarch64.asm +++ b/tests/snapshots/asm/fn_returning_fn_ptr.aarch64.asm @@ -38,9 +38,9 @@ Disassembly of section .text: bl mov x1, #0x7 // =7 mov x2, #0x3 // =3 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -57,9 +57,9 @@ Disassembly of section .text: bl mov x1, #0xa // =10 mov x2, #0x6 // =6 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -85,9 +85,9 @@ Disassembly of section .text: bl mov x1, #0x9 // =9 mov x2, #0x2 // =2 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/fnptr_param_indirection.aarch64.asm b/tests/snapshots/asm/fnptr_param_indirection.aarch64.asm index 8b2cb04c5..4f5a7d96c 100644 --- a/tests/snapshots/asm/fnptr_param_indirection.aarch64.asm +++ b/tests/snapshots/asm/fnptr_param_indirection.aarch64.asm @@ -54,8 +54,8 @@ Disassembly of section .text: ret mov x0, #0xa // =10 ldur x1, [x29, #-0x8] - mov x9, x1 str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -82,8 +82,8 @@ Disassembly of section .text: ldp x29, x30, [sp], #0x10 ret mov x0, #0xa // =10 - mov x9, x1 str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -106,8 +106,8 @@ Disassembly of section .text: cbnz x1, mov x0, #0x3 // =3 ldur x1, [x29, #-0x20] - mov x9, x1 str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/fnptr_typedef_return_proto.aarch64.asm b/tests/snapshots/asm/fnptr_typedef_return_proto.aarch64.asm index 34ae33cc4..a444ea863 100644 --- a/tests/snapshots/asm/fnptr_typedef_return_proto.aarch64.asm +++ b/tests/snapshots/asm/fnptr_typedef_return_proto.aarch64.asm @@ -33,9 +33,9 @@ Disassembly of section .text: add x0, x0, mov x1, #0x14 // =20 mov x2, #0x16 // =22 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/forge_code_pointer.aarch64.asm b/tests/snapshots/asm/forge_code_pointer.aarch64.asm index 42d96a3c5..c1779ed6b 100644 --- a/tests/snapshots/asm/forge_code_pointer.aarch64.asm +++ b/tests/snapshots/asm/forge_code_pointer.aarch64.asm @@ -16,8 +16,8 @@ Disassembly of section .text: str x19, [sp] mov x0, #0x2a // =42 mov x1, #0x0 // =0 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/forward_fn_ptr_in_static_init.aarch64.asm b/tests/snapshots/asm/forward_fn_ptr_in_static_init.aarch64.asm index 216c79f54..58e057527 100644 --- a/tests/snapshots/asm/forward_fn_ptr_in_static_init.aarch64.asm +++ b/tests/snapshots/asm/forward_fn_ptr_in_static_init.aarch64.asm @@ -35,8 +35,8 @@ Disassembly of section .text: adrp x2, add x2, x2, ldr x0, [x2, x0, lsl #3] - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/fp_load_folded_disp.aarch64.asm b/tests/snapshots/asm/fp_load_folded_disp.aarch64.asm new file mode 100644 index 000000000..e27ae1726 --- /dev/null +++ b/tests/snapshots/asm/fp_load_folded_disp.aarch64.asm @@ -0,0 +1,114 @@ + +fp_load_folded_disp.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + ldr s0, [x0, #0x8] + ret + +: + ldr d0, [x0, #0x10] + ret + +: + ldr s0, [x0, #0x20] + ret + +: + ldr d0, [x0, #0x10] + mov x1, #0x3fe0000000000000 // =4602678819172646912 + fmov d17, x1 + fadd d0, d0, d17 + str d0, [x0, #0x10] + mov x0, #0x0 // =0 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x30 + sub x0, x29, #0x28 + mov x1, #0xffff // =65535 + movk x1, #0xffff, lsl #16 + movk x1, #0xffff, lsl #32 + movk x1, #0xffff, lsl #48 + str x1, [x0] + sub x0, x29, #0x28 + mov x1, #0x3ff4000000000000 // =4608308318706860032 + fmov d16, x1 + fcvt s0, d16 + str s0, [x0, #0x8] + sub x0, x29, #0x28 + mov x2, #0x4004000000000000 // =4612811918334230528 + fmov d16, x2 + str d16, [x0, #0x10] + sub x0, x29, #0x28 + mov x2, #0x0 // =0 + fmov d16, x2 + fcvt s0, d16 + str s0, [x0, #0x18] + sub x0, x29, #0x28 + str s0, [x0, #0x1c] + sub x0, x29, #0x28 + mov x2, #0x4013000000000000 // =4617034042984890368 + fmov d16, x2 + fcvt s0, d16 + str s0, [x0, #0x20] + sub x0, x29, #0x28 + ldr s0, [x0, #0x8] + fcvt d0, s0 + fmov d17, x1 + fcmp d0, d17 + cset x0, ne + cbz x0, + mov x0, #0x1 // =1 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x28 + ldr d0, [x0, #0x10] + mov x0, #0x4004000000000000 // =4612811918334230528 + fmov d17, x0 + fcmp d0, d17 + cset x0, ne + cbz x0, + mov x0, #0x2 // =2 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x28 + ldr s0, [x0, #0x20] + mov x0, #0x4013000000000000 // =4617034042984890368 + fcvt d0, s0 + fmov d17, x0 + fcmp d0, d17 + cset x0, ne + cbz x0, + mov x0, #0x3 // =3 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + sub x0, x29, #0x28 + bl + sub x0, x29, #0x28 + ldr d0, [x0, #0x10] + mov x0, #0x4008000000000000 // =4613937818241073152 + fmov d17, x0 + fcmp d0, d17 + cset x0, ne + cbz x0, + mov x0, #0x4 // =4 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + add sp, sp, #0x30 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/fp_load_folded_disp.x64.asm b/tests/snapshots/asm/fp_load_folded_disp.x64.asm new file mode 100644 index 000000000..e20c64f57 --- /dev/null +++ b/tests/snapshots/asm/fp_load_folded_disp.x64.asm @@ -0,0 +1,134 @@ + +fp_load_folded_disp.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + movss 0x8(%rdi,%riz), %xmm0 + retq + +: + movsd 0x10(%rdi,%riz), %xmm0 + retq + +: + movss 0x20(%rdi,%riz), %xmm0 + retq + +: + movsd 0x10(%rdi,%riz), %xmm0 + movabsq $0x3fe0000000000000, %rax # imm = 0x3FE0000000000000 + movq %rax, %xmm15 + addsd %xmm15, %xmm0 + movsd %xmm0, 0x10(%rdi,%riz) + xorq %rax, %rax + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x30, %rsp + leaq -0x28(%rbp), %rax + movabsq $-0x1, %rcx + movq %rcx, (%rax) + leaq -0x28(%rbp), %rax + movabsq $0x3ff4000000000000, %rcx # imm = 0x3FF4000000000000 + movq %rcx, %xmm14 + cvtsd2ss %xmm14, %xmm0 + movss %xmm0, 0x8(%rax,%riz) + leaq -0x28(%rbp), %rax + movabsq $0x4004000000000000, %rdx # imm = 0x4004000000000000 + movq %rdx, %xmm14 + movsd %xmm14, 0x10(%rax,%riz) + leaq -0x28(%rbp), %rax + xorq %rdx, %rdx + movq %rdx, %xmm14 + cvtsd2ss %xmm14, %xmm0 + movss %xmm0, 0x18(%rax,%riz) + leaq -0x28(%rbp), %rax + movss %xmm0, 0x1c(%rax,%riz) + leaq -0x28(%rbp), %rax + movabsq $0x4013000000000000, %rdx # imm = 0x4013000000000000 + movq %rdx, %xmm14 + cvtsd2ss %xmm14, %xmm0 + movss %xmm0, 0x20(%rax,%riz) + leaq -0x28(%rbp), %rax + movss 0x8(%rax,%riz), %xmm0 + cvtss2sd %xmm0, %xmm0 + movq %rcx, %xmm15 + ucomisd %xmm15, %xmm0 + setne %al + movzbq %al, %rax + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rax + testq %rax, %rax + je + movl $0x1, %eax + addq $0x30, %rsp + popq %rbp + retq + leaq -0x28(%rbp), %rax + movsd 0x10(%rax,%riz), %xmm0 + movabsq $0x4004000000000000, %rax # imm = 0x4004000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %al + movzbq %al, %rax + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rax + testq %rax, %rax + je + movl $0x2, %eax + addq $0x30, %rsp + popq %rbp + retq + leaq -0x28(%rbp), %rax + movss 0x20(%rax,%riz), %xmm0 + movabsq $0x4013000000000000, %rax # imm = 0x4013000000000000 + cvtss2sd %xmm0, %xmm0 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %al + movzbq %al, %rax + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rax + testq %rax, %rax + je + movl $0x3, %eax + addq $0x30, %rsp + popq %rbp + retq + leaq -0x28(%rbp), %rdi + callq + leaq -0x28(%rbp), %rax + movsd 0x10(%rax,%riz), %xmm0 + movabsq $0x4008000000000000, %rax # imm = 0x4008000000000000 + movq %rax, %xmm15 + ucomisd %xmm15, %xmm0 + setne %al + movzbq %al, %rax + setp %r10b + movzbq %r10b, %r10 + orq %r10, %rax + testq %rax, %rax + je + movl $0x4, %eax + addq $0x30, %rsp + popq %rbp + retq + xorq %rax, %rax + addq $0x30, %rsp + popq %rbp + retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/funcptr_global_addressof_init.aarch64.asm b/tests/snapshots/asm/funcptr_global_addressof_init.aarch64.asm index 57fe85763..6075eb157 100644 --- a/tests/snapshots/asm/funcptr_global_addressof_init.aarch64.asm +++ b/tests/snapshots/asm/funcptr_global_addressof_init.aarch64.asm @@ -24,8 +24,8 @@ Disassembly of section .text: adrp x20, add x20, x20, ldr x1, [x20] - mov x9, x1 str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -42,8 +42,8 @@ Disassembly of section .text: adrp x1, add x1, x1, ldr x1, [x1] - mov x9, x1 str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/function_pointer_typedefs.aarch64.asm b/tests/snapshots/asm/function_pointer_typedefs.aarch64.asm index d1c38636e..772792cfe 100644 --- a/tests/snapshots/asm/function_pointer_typedefs.aarch64.asm +++ b/tests/snapshots/asm/function_pointer_typedefs.aarch64.asm @@ -43,9 +43,9 @@ Disassembly of section .text: str x19, [sp] sxtw x1, w1 sxtw x2, w2 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -66,9 +66,9 @@ Disassembly of section .text: add x20, x20, mov x0, #0x3 // =3 mov x1, #0x5 // =5 - mov x9, x20 str x1, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -88,9 +88,9 @@ Disassembly of section .text: ret mov x0, #0x7 // =7 mov x1, #0x2 // =2 - mov x9, x20 str x1, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -105,9 +105,9 @@ Disassembly of section .text: ldp x29, x30, [sp], #0x10 ret mov x0, #0x4 // =4 - mov x9, x20 str x0, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -135,9 +135,9 @@ Disassembly of section .text: ldr x0, [x0] mov x1, #0x2 // =2 mov x2, #0x3 // =3 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -155,9 +155,9 @@ Disassembly of section .text: ldr x0, [x0, #0x8] mov x1, #0xa // =10 mov x2, #0x4 // =4 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -175,9 +175,9 @@ Disassembly of section .text: ldr x0, [x0, #0x10] mov x1, #0x1 // =1 mov x2, #0x2 // =2 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/function_pointers.aarch64.asm b/tests/snapshots/asm/function_pointers.aarch64.asm index 8057b11a8..ffdb6acfc 100644 --- a/tests/snapshots/asm/function_pointers.aarch64.asm +++ b/tests/snapshots/asm/function_pointers.aarch64.asm @@ -30,9 +30,9 @@ Disassembly of section .text: add x0, x0, mov x20, #0xa // =10 mov x1, #0x14 // =20 - mov x9, x0 str x1, [sp, #-0x10]! str x20, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -41,9 +41,9 @@ Disassembly of section .text: adrp x0, add x0, x0, mov x1, #0x5 // =5 - mov x9, x0 str x1, [sp, #-0x10]! str x20, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/function_type_typedef.aarch64.asm b/tests/snapshots/asm/function_type_typedef.aarch64.asm index bca69ae28..9ed73b202 100644 --- a/tests/snapshots/asm/function_type_typedef.aarch64.asm +++ b/tests/snapshots/asm/function_type_typedef.aarch64.asm @@ -26,9 +26,9 @@ Disassembly of section .text: str x19, [sp] sxtw x1, w1 sxtw x2, w2 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -45,9 +45,9 @@ Disassembly of section .text: str x19, [sp] sxtw x1, w1 sxtw x2, w2 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/function_type_typedef_declaration.aarch64.asm b/tests/snapshots/asm/function_type_typedef_declaration.aarch64.asm index 3737d9b69..8efb6f443 100644 --- a/tests/snapshots/asm/function_type_typedef_declaration.aarch64.asm +++ b/tests/snapshots/asm/function_type_typedef_declaration.aarch64.asm @@ -26,9 +26,9 @@ Disassembly of section .text: str x19, [sp] sxtw x1, w1 sxtw x2, w2 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -70,9 +70,9 @@ Disassembly of section .text: add x0, x0, mov x1, #0x2 // =2 mov x2, #0x5 // =5 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -101,9 +101,9 @@ Disassembly of section .text: add x0, x0, mov x1, #0x8 // =8 mov x2, #0x3 // =3 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/function_typed_parameter.aarch64.asm b/tests/snapshots/asm/function_typed_parameter.aarch64.asm index 3b0db2829..3cba0747e 100644 --- a/tests/snapshots/asm/function_typed_parameter.aarch64.asm +++ b/tests/snapshots/asm/function_typed_parameter.aarch64.asm @@ -15,8 +15,8 @@ Disassembly of section .text: sub sp, sp, #0x10 str x19, [sp] sxtw x1, w1 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -32,8 +32,8 @@ Disassembly of section .text: sub sp, sp, #0x10 str x19, [sp] sxtw x1, w1 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -49,8 +49,8 @@ Disassembly of section .text: sub sp, sp, #0x10 str x19, [sp] sxtw x1, w1 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/hfa_param_interleave.aarch64.asm b/tests/snapshots/asm/hfa_param_interleave.aarch64.asm index 1c70192c3..2f9edcf26 100644 --- a/tests/snapshots/asm/hfa_param_interleave.aarch64.asm +++ b/tests/snapshots/asm/hfa_param_interleave.aarch64.asm @@ -34,29 +34,25 @@ Disassembly of section .text: sub x0, x29, #0x8 ldr s1, [x0] sub x0, x29, #0x8 - add x0, x0, #0x4 - ldr s2, [x0] + ldr s2, [x0, #0x4] fadd s1, s1, s2 sub x0, x29, #0x10 ldr s2, [x0] fadd s1, s1, s2 sub x0, x29, #0x10 - add x0, x0, #0x4 - ldr s2, [x0] + ldr s2, [x0, #0x4] fadd s1, s1, s2 sub x0, x29, #0x18 ldr s2, [x0] fadd s1, s1, s2 sub x0, x29, #0x18 - add x0, x0, #0x4 - ldr s2, [x0] + ldr s2, [x0, #0x4] fadd s1, s1, s2 sub x0, x29, #0x20 ldr s2, [x0] fadd s1, s1, s2 sub x0, x29, #0x20 - add x0, x0, #0x4 - ldr s2, [x0] + ldr s2, [x0, #0x4] fadd s1, s1, s2 fadd s0, s1, s0 sub x0, x29, #0x28 diff --git a/tests/snapshots/asm/hfa_param_interleave.x64.asm b/tests/snapshots/asm/hfa_param_interleave.x64.asm index 31d4a7626..f7058c209 100644 --- a/tests/snapshots/asm/hfa_param_interleave.x64.asm +++ b/tests/snapshots/asm/hfa_param_interleave.x64.asm @@ -26,29 +26,25 @@ Disassembly of section .text: leaq -0x8(%rbp), %rax movss (%rax,%riz), %xmm1 leaq -0x8(%rbp), %rax - addq $0x4, %rax - movss (%rax,%riz), %xmm2 + movss 0x4(%rax,%riz), %xmm2 addss %xmm2, %xmm1 leaq -0x10(%rbp), %rax movss (%rax,%riz), %xmm2 addss %xmm2, %xmm1 leaq -0x10(%rbp), %rax - addq $0x4, %rax - movss (%rax,%riz), %xmm2 + movss 0x4(%rax,%riz), %xmm2 addss %xmm2, %xmm1 leaq -0x18(%rbp), %rax movss (%rax,%riz), %xmm2 addss %xmm2, %xmm1 leaq -0x18(%rbp), %rax - addq $0x4, %rax - movss (%rax,%riz), %xmm2 + movss 0x4(%rax,%riz), %xmm2 addss %xmm2, %xmm1 leaq -0x20(%rbp), %rax movss (%rax,%riz), %xmm2 addss %xmm2, %xmm1 leaq -0x20(%rbp), %rax - addq $0x4, %rax - movss (%rax,%riz), %xmm2 + movss 0x4(%rax,%riz), %xmm2 addss %xmm2, %xmm1 movapd %xmm0, %xmm15 movapd %xmm1, %xmm0 diff --git a/tests/snapshots/asm/hfa_struct_return.aarch64.asm b/tests/snapshots/asm/hfa_struct_return.aarch64.asm index ff867c81b..0fcdc0bb9 100644 --- a/tests/snapshots/asm/hfa_struct_return.aarch64.asm +++ b/tests/snapshots/asm/hfa_struct_return.aarch64.asm @@ -29,8 +29,7 @@ Disassembly of section .text: sub x0, x29, #0x10 str d0, [x0] sub x0, x29, #0x10 - add x0, x0, #0x8 - str d1, [x0] + str d1, [x0, #0x8] sub x0, x29, #0x10 mov x16, x0 ldr d0, [x16] @@ -46,11 +45,9 @@ Disassembly of section .text: sub x0, x29, #0x18 str d0, [x0] sub x0, x29, #0x18 - add x0, x0, #0x8 - str d1, [x0] + str d1, [x0, #0x8] sub x0, x29, #0x18 - add x0, x0, #0x10 - str d2, [x0] + str d2, [x0, #0x10] sub x0, x29, #0x18 mov x16, x0 ldr d0, [x16] @@ -67,14 +64,11 @@ Disassembly of section .text: sub x0, x29, #0x20 str d0, [x0] sub x0, x29, #0x20 - add x0, x0, #0x8 - str d1, [x0] + str d1, [x0, #0x8] sub x0, x29, #0x20 - add x0, x0, #0x10 - str d2, [x0] + str d2, [x0, #0x10] sub x0, x29, #0x20 - add x0, x0, #0x18 - str d3, [x0] + str d3, [x0, #0x18] sub x0, x29, #0x20 mov x16, x0 ldr d0, [x16] @@ -92,8 +86,7 @@ Disassembly of section .text: sub x0, x29, #0x18 str s0, [x0] sub x0, x29, #0x18 - add x0, x0, #0x4 - str s1, [x0] + str s1, [x0, #0x4] sub x0, x29, #0x18 mov x16, x0 ldr s0, [x16] @@ -113,8 +106,7 @@ Disassembly of section .text: sub x0, x29, #0x10 ldr d0, [x0] sub x0, x29, #0x10 - add x0, x0, #0x8 - ldr d1, [x0] + ldr d1, [x0, #0x8] fadd d0, d0, d1 add sp, sp, #0x10 ldp x29, x30, [sp], #0x10 @@ -134,16 +126,13 @@ Disassembly of section .text: sub x0, x29, #0x20 ldr d0, [x0] sub x0, x29, #0x20 - add x0, x0, #0x8 - ldr d1, [x0] + ldr d1, [x0, #0x8] fadd d0, d0, d1 sub x0, x29, #0x20 - add x0, x0, #0x10 - ldr d1, [x0] + ldr d1, [x0, #0x10] fadd d0, d0, d1 sub x0, x29, #0x20 - add x0, x0, #0x18 - ldr d1, [x0] + ldr d1, [x0, #0x18] fadd d0, d0, d1 add sp, sp, #0x20 ldp x29, x30, [sp], #0x10 @@ -163,16 +152,13 @@ Disassembly of section .text: sub x0, x29, #0x10 ldr s0, [x0] sub x0, x29, #0x10 - add x0, x0, #0x4 - ldr s1, [x0] + ldr s1, [x0, #0x4] fadd s0, s0, s1 sub x0, x29, #0x10 - add x0, x0, #0x8 - ldr s1, [x0] + ldr s1, [x0, #0x8] fadd s0, s0, s1 sub x0, x29, #0x10 - add x0, x0, #0xc - ldr s1, [x0] + ldr s1, [x0, #0xc] fadd s0, s0, s1 add sp, sp, #0x10 ldp x29, x30, [sp], #0x10 @@ -233,8 +219,7 @@ Disassembly of section .text: cset x20, ne cbnz x20, sub x0, x29, #0x20 - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x0, #0x3fe0000000000000 // =4602678819172646912 fmov d17, x0 fcmp d0, d17 @@ -276,8 +261,7 @@ Disassembly of section .text: mov x20, #0x1 // =1 cbnz x0, sub x0, x29, #0x48 - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x0, #0x4000000000000000 // =4611686018427387904 fmov d17, x0 fcmp d0, d17 @@ -286,8 +270,7 @@ Disassembly of section .text: cset x20, ne cbnz x20, sub x0, x29, #0x48 - add x0, x0, #0x10 - ldr d0, [x0] + ldr d0, [x0, #0x10] mov x0, #0x4008000000000000 // =4613937818241073152 fmov d17, x0 fcmp d0, d17 @@ -334,8 +317,7 @@ Disassembly of section .text: mov x20, #0x1 // =1 cbnz x0, sub x0, x29, #0x80 - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x0, #0x4034000000000000 // =4626322717216342016 fmov d17, x0 fcmp d0, d17 @@ -345,8 +327,7 @@ Disassembly of section .text: mov x21, #0x1 // =1 cbnz x20, sub x0, x29, #0x80 - add x0, x0, #0x10 - ldr d0, [x0] + ldr d0, [x0, #0x10] mov x0, #0x403e000000000000 // =4629137466983448576 fmov d17, x0 fcmp d0, d17 @@ -355,8 +336,7 @@ Disassembly of section .text: cset x21, ne cbnz x21, sub x0, x29, #0x80 - add x0, x0, #0x18 - ldr d0, [x0] + ldr d0, [x0, #0x18] mov x0, #0x4044000000000000 // =4630826316843712512 fmov d17, x0 fcmp d0, d17 @@ -393,8 +373,7 @@ Disassembly of section .text: cset x20, ne cbnz x20, sub x0, x29, #0xa8 - add x0, x0, #0x4 - ldr s0, [x0] + ldr s0, [x0, #0x4] mov x0, #0x4004000000000000 // =4612811918334230528 fcvt d0, s0 fmov d17, x0 diff --git a/tests/snapshots/asm/hfa_struct_return.x64.asm b/tests/snapshots/asm/hfa_struct_return.x64.asm index 924cbae06..eae9f0c0b 100644 --- a/tests/snapshots/asm/hfa_struct_return.x64.asm +++ b/tests/snapshots/asm/hfa_struct_return.x64.asm @@ -30,8 +30,7 @@ Disassembly of section .text: leaq -0x10(%rbp), %rax movsd %xmm0, (%rax,%riz) leaq -0x10(%rbp), %rax - addq $0x8, %rax - movsd %xmm1, (%rax,%riz) + movsd %xmm1, 0x8(%rax,%riz) leaq -0x10(%rbp), %rax movq %rax, %rcx movsd (%rcx,%riz), %xmm0 @@ -55,13 +54,11 @@ Disassembly of section .text: movsd 0x20(%rbp,%riz), %xmm0 movsd %xmm0, (%rax,%riz) leaq -0x18(%rbp), %rax - addq $0x8, %rax movsd 0x30(%rbp,%riz), %xmm0 - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x8(%rax,%riz) leaq -0x18(%rbp), %rax - addq $0x10, %rax movsd 0x40(%rbp,%riz), %xmm0 - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x10(%rax,%riz) movq 0x10(%rbp), %rax leaq -0x18(%rbp), %rcx pushq %rdx @@ -96,17 +93,14 @@ Disassembly of section .text: movsd 0x20(%rbp,%riz), %xmm0 movsd %xmm0, (%rax,%riz) leaq -0x20(%rbp), %rax - addq $0x8, %rax movsd 0x30(%rbp,%riz), %xmm0 - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x8(%rax,%riz) leaq -0x20(%rbp), %rax - addq $0x10, %rax movsd 0x40(%rbp,%riz), %xmm0 - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x10(%rax,%riz) leaq -0x20(%rbp), %rax - addq $0x18, %rax movsd 0x50(%rbp,%riz), %xmm0 - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x18(%rax,%riz) movq 0x10(%rbp), %rax leaq -0x20(%rbp), %rcx pushq %rdx @@ -134,8 +128,7 @@ Disassembly of section .text: leaq -0x18(%rbp), %rax movss %xmm0, (%rax,%riz) leaq -0x18(%rbp), %rax - addq $0x4, %rax - movss %xmm1, (%rax,%riz) + movss %xmm1, 0x4(%rax,%riz) leaq -0x18(%rbp), %rax movq %rax, %rcx movsd (%rcx,%riz), %xmm0 @@ -155,8 +148,7 @@ Disassembly of section .text: leaq -0x10(%rbp), %rax movsd (%rax,%riz), %xmm0 leaq -0x10(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm1 + movsd 0x8(%rax,%riz), %xmm1 addsd %xmm1, %xmm0 addq $0x10, %rsp popq %rbp @@ -183,16 +175,13 @@ Disassembly of section .text: leaq -0x20(%rbp), %rax movsd (%rax,%riz), %xmm0 leaq -0x20(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm1 + movsd 0x8(%rax,%riz), %xmm1 addsd %xmm1, %xmm0 leaq -0x20(%rbp), %rax - addq $0x10, %rax - movsd (%rax,%riz), %xmm1 + movsd 0x10(%rax,%riz), %xmm1 addsd %xmm1, %xmm0 leaq -0x20(%rbp), %rax - addq $0x18, %rax - movsd (%rax,%riz), %xmm1 + movsd 0x18(%rax,%riz), %xmm1 addsd %xmm1, %xmm0 addq $0x20, %rsp popq %rbp @@ -213,16 +202,13 @@ Disassembly of section .text: leaq -0x10(%rbp), %rax movss (%rax,%riz), %xmm0 leaq -0x10(%rbp), %rax - addq $0x4, %rax - movss (%rax,%riz), %xmm1 + movss 0x4(%rax,%riz), %xmm1 addss %xmm1, %xmm0 leaq -0x10(%rbp), %rax - addq $0x8, %rax - movss (%rax,%riz), %xmm1 + movss 0x8(%rax,%riz), %xmm1 addss %xmm1, %xmm0 leaq -0x10(%rbp), %rax - addq $0xc, %rax - movss (%rax,%riz), %xmm1 + movss 0xc(%rax,%riz), %xmm1 addss %xmm1, %xmm0 addq $0x10, %rsp popq %rbp @@ -293,8 +279,7 @@ Disassembly of section .text: testq %rbx, %rbx jne leaq -0x20(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x3fe0000000000000, %rax # imm = 0x3FE0000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -341,8 +326,7 @@ Disassembly of section .text: testq %rax, %rax jne leaq -0x48(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x4000000000000000, %rax # imm = 0x4000000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -357,8 +341,7 @@ Disassembly of section .text: testq %rbx, %rbx jne leaq -0x48(%rbp), %rax - addq $0x10, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x10(%rax,%riz), %xmm0 movabsq $0x4008000000000000, %rax # imm = 0x4008000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -408,8 +391,7 @@ Disassembly of section .text: testq %rax, %rax jne leaq -0x80(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x4034000000000000, %rax # imm = 0x4034000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -425,8 +407,7 @@ Disassembly of section .text: testq %rbx, %rbx jne leaq -0x80(%rbp), %rax - addq $0x10, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x10(%rax,%riz), %xmm0 movabsq $0x403e000000000000, %rax # imm = 0x403E000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -441,8 +422,7 @@ Disassembly of section .text: testq %r12, %r12 jne leaq -0x80(%rbp), %rax - addq $0x18, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x18(%rax,%riz), %xmm0 movabsq $0x4044000000000000, %rax # imm = 0x4044000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -487,8 +467,7 @@ Disassembly of section .text: testq %rbx, %rbx jne leaq -0xa8(%rbp), %rax - addq $0x4, %rax - movss (%rax,%riz), %xmm0 + movss 0x4(%rax,%riz), %xmm0 movabsq $0x4004000000000000, %rax # imm = 0x4004000000000000 cvtss2sd %xmm0, %xmm0 movq %rax, %xmm15 @@ -599,4 +578,3 @@ Disassembly of section .text: jmp jmp jmp - addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/indirect_call_six_args_spilled_target.aarch64.asm b/tests/snapshots/asm/indirect_call_six_args_spilled_target.aarch64.asm index cf46a3943..cb0bf9aad 100644 --- a/tests/snapshots/asm/indirect_call_six_args_spilled_target.aarch64.asm +++ b/tests/snapshots/asm/indirect_call_six_args_spilled_target.aarch64.asm @@ -34,13 +34,13 @@ Disassembly of section .text: sub x6, x29, #0x8 add x1, x1, #0x10 add x3, x3, #0x10 - mov x9, x5 str x4, [sp, #-0x10]! str x3, [sp, #-0x10]! str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! str x6, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x5 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] diff --git a/tests/snapshots/asm/indirect_call_target_scratch_exhausted.aarch64.asm b/tests/snapshots/asm/indirect_call_target_scratch_exhausted.aarch64.asm new file mode 100644 index 000000000..2cf53c42d --- /dev/null +++ b/tests/snapshots/asm/indirect_call_target_scratch_exhausted.aarch64.asm @@ -0,0 +1,476 @@ + +indirect_call_target_scratch_exhausted.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + sub sp, sp, #0x90 + ldr x16, [sp, #0x90] + str x16, [sp] + ldr x16, [sp, #0x98] + str x16, [sp, #0x10] + ldr x16, [sp, #0xa0] + str x16, [sp, #0x20] + ldr x16, [sp, #0xa8] + str x16, [sp, #0x30] + ldr x16, [sp, #0xb0] + str x16, [sp, #0x40] + ldr x16, [sp, #0xb8] + str x16, [sp, #0x50] + ldr x16, [sp, #0xc0] + str x16, [sp, #0x60] + ldr x16, [sp, #0xc8] + str x16, [sp, #0x70] + ldr x16, [sp, #0xd0] + str x16, [sp, #0x80] + sub sp, sp, #0x80 + stp x29, x30, [sp, #-0x10]! + mov x29, sp + add x0, x0, x1 + add x0, x0, x2 + add x0, x0, x3 + add x0, x0, x4 + add x0, x0, x5 + add x0, x0, x6 + add x0, x0, x7 + ldur x1, [x29, #0x90] + add x0, x0, x1 + ldur x1, [x29, #0xa0] + add x0, x0, x1 + ldur x1, [x29, #0xb0] + add x0, x0, x1 + ldur x1, [x29, #0xc0] + add x0, x0, x1 + ldur x1, [x29, #0xd0] + add x0, x0, x1 + ldur x1, [x29, #0xe0] + add x0, x0, x1 + ldur x1, [x29, #0xf0] + add x0, x0, x1 + add x16, x29, #0x100 + ldr x1, [x16] + add x0, x0, x1 + add x16, x29, #0x110 + ldr x1, [x16] + add x0, x0, x1 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0x110 + ret + +: + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + sub sp, sp, #0x10 + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x100 + sub x16, x29, #0x10 + str x0, [x16] + str x1, [x16, #0x8] + sub x16, x29, #0x20 + str x2, [x16] + str x3, [x16, #0x8] + sub x16, x29, #0x30 + str x4, [x16] + str x5, [x16, #0x8] + sub x16, x29, #0x40 + str x6, [x16] + str x7, [x16, #0x8] + sub x16, x29, #0x50 + ldr x17, [x29, #0x110] + str x17, [x16] + ldr x17, [x29, #0x118] + str x17, [x16, #0x8] + sub x16, x29, #0x60 + ldr x17, [x29, #0x120] + str x17, [x16] + ldr x17, [x29, #0x128] + str x17, [x16, #0x8] + sub x16, x29, #0x70 + ldr x17, [x29, #0x130] + str x17, [x16] + ldr x17, [x29, #0x138] + str x17, [x16, #0x8] + sub x16, x29, #0x80 + ldr x17, [x29, #0x140] + str x17, [x16] + ldr x17, [x29, #0x148] + str x17, [x16, #0x8] + sub x16, x29, #0x90 + ldr x17, [x29, #0x150] + str x17, [x16] + ldr x17, [x29, #0x158] + str x17, [x16, #0x8] + sub x16, x29, #0xa0 + ldr x17, [x29, #0x160] + str x17, [x16] + ldr x17, [x29, #0x168] + str x17, [x16, #0x8] + sub x16, x29, #0xb0 + ldr x17, [x29, #0x170] + str x17, [x16] + ldr x17, [x29, #0x178] + str x17, [x16, #0x8] + sub x16, x29, #0xc0 + ldr x17, [x29, #0x180] + str x17, [x16] + ldr x17, [x29, #0x188] + str x17, [x16, #0x8] + sub x16, x29, #0xd0 + ldr x17, [x29, #0x190] + str x17, [x16] + ldr x17, [x29, #0x198] + str x17, [x16, #0x8] + sub x16, x29, #0xe0 + ldr x17, [x29, #0x1a0] + str x17, [x16] + ldr x17, [x29, #0x1a8] + str x17, [x16, #0x8] + sub x16, x29, #0xf0 + ldr x17, [x29, #0x1b0] + str x17, [x16] + ldr x17, [x29, #0x1b8] + str x17, [x16, #0x8] + sub x16, x29, #0x100 + ldr x17, [x29, #0x1c0] + str x17, [x16] + ldr x17, [x29, #0x1c8] + str x17, [x16, #0x8] + sub x0, x29, #0x10 + ldr x0, [x0] + sub x1, x29, #0x10 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0x20 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0x20 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0x30 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0x30 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0x40 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0x40 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0x50 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0x50 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0x60 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0x60 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0x70 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0x70 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0x80 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0x80 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0x90 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0x90 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0xa0 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0xa0 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0xb0 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0xb0 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0xc0 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0xc0 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0xd0 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0xd0 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0xe0 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0xe0 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0xf0 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0xf0 + ldr x1, [x1, #0x8] + add x0, x0, x1 + sub x1, x29, #0x100 + ldr x1, [x1] + add x0, x0, x1 + sub x1, x29, #0x100 + ldr x1, [x1, #0x8] + add x0, x0, x1 + add sp, sp, #0x100 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0x100 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0xd0 + str x20, [sp] + str x21, [sp, #0x8] + str x22, [sp, #0x10] + str x23, [sp, #0x18] + str x19, [sp, #0x20] + adrp x0, + add x0, x0, + adrp x20, + add x20, x20, + mov x2, #0x0 // =0 + cmp x2, #0x10 + b.ge + b + add x2, x2, #0x1 + b + adrp x1, + add x1, x1, + lsl x3, x2, #4 + add x3, x1, x3 + str x2, [x3] + lsl x3, x2, #4 + add x1, x1, x3 + lsl x3, x2, #1 + str x3, [x1, #0x8] + b + mov x1, #0x1 // =1 + mov x2, #0x2 // =2 + mov x3, #0x3 // =3 + mov x4, #0x4 // =4 + mov x5, #0x5 // =5 + mov x6, #0x6 // =6 + mov x7, #0x7 // =7 + mov x8, #0x8 // =8 + mov x9, #0x9 // =9 + mov x10, #0xa // =10 + mov x11, #0xb // =11 + mov x12, #0xc // =12 + mov x13, #0xd // =13 + mov x14, #0xe // =14 + mov x15, #0xf // =15 + mov x21, #0x10 // =16 + mov x22, #0x11 // =17 + str x22, [sp, #-0x10]! + str x21, [sp, #-0x10]! + str x15, [sp, #-0x10]! + str x14, [sp, #-0x10]! + str x13, [sp, #-0x10]! + str x12, [sp, #-0x10]! + str x11, [sp, #-0x10]! + str x10, [sp, #-0x10]! + str x9, [sp, #-0x10]! + str x8, [sp, #-0x10]! + str x7, [sp, #-0x10]! + str x6, [sp, #-0x10]! + str x5, [sp, #-0x10]! + str x4, [sp, #-0x10]! + str x3, [sp, #-0x10]! + str x2, [sp, #-0x10]! + str x1, [sp, #-0x10]! + mov x9, x0 + sub sp, sp, #0x50 + ldr x0, [sp, #0x50] + ldr x1, [sp, #0x60] + ldr x2, [sp, #0x70] + ldr x3, [sp, #0x80] + ldr x4, [sp, #0x90] + ldr x5, [sp, #0xa0] + ldr x6, [sp, #0xb0] + ldr x7, [sp, #0xc0] + ldr x16, [sp, #0xd0] + str x16, [sp] + ldr x16, [sp, #0xe0] + str x16, [sp, #0x8] + ldr x16, [sp, #0xf0] + str x16, [sp, #0x10] + ldr x16, [sp, #0x100] + str x16, [sp, #0x18] + ldr x16, [sp, #0x110] + str x16, [sp, #0x20] + ldr x16, [sp, #0x120] + str x16, [sp, #0x28] + ldr x16, [sp, #0x130] + str x16, [sp, #0x30] + ldr x16, [sp, #0x140] + str x16, [sp, #0x38] + ldr x16, [sp, #0x150] + str x16, [sp, #0x40] + blr x9 + add sp, sp, #0x50 + add sp, sp, #0x110 + cmp x0, #0x99 + b.eq + mov x0, #0x1 // =1 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + ldr x23, [sp, #0x18] + ldr x19, [sp, #0x20] + add sp, sp, #0xd0 + ldp x29, x30, [sp], #0x10 + ret + adrp x0, + add x0, x0, + add x1, x0, #0x10 + add x2, x0, #0x20 + add x3, x0, #0x30 + add x4, x0, #0x40 + add x5, x0, #0x50 + add x6, x0, #0x60 + add x7, x0, #0x70 + add x8, x0, #0x80 + add x9, x0, #0x90 + add x10, x0, #0xa0 + add x11, x0, #0xb0 + add x12, x0, #0xc0 + add x13, x0, #0xd0 + add x14, x0, #0xe0 + add x15, x0, #0xf0 + mov x16, x20 + sub sp, sp, #0xd0 + str x16, [sp, #0xc0] + mov x16, x4 + ldr x17, [x16] + str x17, [sp] + ldr x17, [x16, #0x8] + str x17, [sp, #0x8] + mov x16, x5 + ldr x17, [x16] + str x17, [sp, #0x10] + ldr x17, [x16, #0x8] + str x17, [sp, #0x18] + mov x16, x6 + ldr x17, [x16] + str x17, [sp, #0x20] + ldr x17, [x16, #0x8] + str x17, [sp, #0x28] + mov x16, x7 + ldr x17, [x16] + str x17, [sp, #0x30] + ldr x17, [x16, #0x8] + str x17, [sp, #0x38] + mov x16, x8 + ldr x17, [x16] + str x17, [sp, #0x40] + ldr x17, [x16, #0x8] + str x17, [sp, #0x48] + mov x16, x9 + ldr x17, [x16] + str x17, [sp, #0x50] + ldr x17, [x16, #0x8] + str x17, [sp, #0x58] + mov x16, x10 + ldr x17, [x16] + str x17, [sp, #0x60] + ldr x17, [x16, #0x8] + str x17, [sp, #0x68] + mov x16, x11 + ldr x17, [x16] + str x17, [sp, #0x70] + ldr x17, [x16, #0x8] + str x17, [sp, #0x78] + mov x16, x12 + ldr x17, [x16] + str x17, [sp, #0x80] + ldr x17, [x16, #0x8] + str x17, [sp, #0x88] + mov x16, x13 + ldr x17, [x16] + str x17, [sp, #0x90] + ldr x17, [x16, #0x8] + str x17, [sp, #0x98] + mov x16, x14 + ldr x17, [x16] + str x17, [sp, #0xa0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xa8] + mov x16, x15 + ldr x17, [x16] + str x17, [sp, #0xb0] + ldr x17, [x16, #0x8] + str x17, [sp, #0xb8] + mov x4, x2 + mov x6, x3 + mov x2, x1 + ldr x1, [x0, #0x8] + ldr x0, [x0] + ldr x3, [x2, #0x8] + ldr x2, [x2] + ldr x5, [x4, #0x8] + ldr x4, [x4] + ldr x7, [x6, #0x8] + ldr x6, [x6] + ldr x9, [sp, #0xc0] + blr x9 + add sp, sp, #0xd0 + cmp x0, #0x168 + b.eq + mov x0, #0x2 // =2 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + ldr x23, [sp, #0x18] + ldr x19, [sp, #0x20] + add sp, sp, #0xd0 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldr x20, [sp] + ldr x21, [sp, #0x8] + ldr x22, [sp, #0x10] + ldr x23, [sp, #0x18] + ldr x19, [sp, #0x20] + add sp, sp, #0xd0 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/indirect_call_target_scratch_exhausted.x64.asm b/tests/snapshots/asm/indirect_call_target_scratch_exhausted.x64.asm new file mode 100644 index 000000000..a8a519a42 --- /dev/null +++ b/tests/snapshots/asm/indirect_call_target_scratch_exhausted.x64.asm @@ -0,0 +1,447 @@ + +indirect_call_target_scratch_exhausted.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + popq %r10 + subq $0x110, %rsp # imm = 0x110 + movq 0x110(%rsp), %rax + movq %rax, 0x60(%rsp) + movq 0x118(%rsp), %rax + movq %rax, 0x70(%rsp) + movq 0x120(%rsp), %rax + movq %rax, 0x80(%rsp) + movq 0x128(%rsp), %rax + movq %rax, 0x90(%rsp) + movq 0x130(%rsp), %rax + movq %rax, 0xa0(%rsp) + movq 0x138(%rsp), %rax + movq %rax, 0xb0(%rsp) + movq 0x140(%rsp), %rax + movq %rax, 0xc0(%rsp) + movq 0x148(%rsp), %rax + movq %rax, 0xd0(%rsp) + movq 0x150(%rsp), %rax + movq %rax, 0xe0(%rsp) + movq 0x158(%rsp), %rax + movq %rax, 0xf0(%rsp) + movq 0x160(%rsp), %rax + movq %rax, 0x100(%rsp) + pushq %r10 + pushq %rbp + movq %rsp, %rbp + leaq (%rdi,%rsi), %rax + addq %rdx, %rax + addq %rcx, %rax + addq %r8, %rax + addq %r9, %rax + movq 0x70(%rbp), %rcx + addq %rcx, %rax + movq 0x80(%rbp), %rcx + addq %rcx, %rax + movq 0x90(%rbp), %rcx + addq %rcx, %rax + movq 0xa0(%rbp), %rcx + addq %rcx, %rax + movq 0xb0(%rbp), %rcx + addq %rcx, %rax + movq 0xc0(%rbp), %rcx + addq %rcx, %rax + movq 0xd0(%rbp), %rcx + addq %rcx, %rax + movq 0xe0(%rbp), %rcx + addq %rcx, %rax + movq 0xf0(%rbp), %rcx + addq %rcx, %rax + movq 0x100(%rbp), %rcx + addq %rcx, %rax + movq 0x110(%rbp), %rcx + addq %rcx, %rax + popq %rbp + popq %r11 + addq $0x110, %rsp # imm = 0x110 + pushq %r11 + retq + +: + popq %r10 + subq $0x100, %rsp # imm = 0x100 + pushq %r10 + pushq %rbp + movq %rsp, %rbp + subq $0x100, %rsp # imm = 0x100 + movq %rdi, -0x10(%rbp) + movq %rsi, -0x8(%rbp) + movq %rdx, -0x20(%rbp) + movq %rcx, -0x18(%rbp) + movq %r8, -0x30(%rbp) + movq %r9, -0x28(%rbp) + movq 0x110(%rbp), %r10 + movq %r10, -0x40(%rbp) + movq 0x118(%rbp), %r10 + movq %r10, -0x38(%rbp) + movq 0x120(%rbp), %r10 + movq %r10, -0x50(%rbp) + movq 0x128(%rbp), %r10 + movq %r10, -0x48(%rbp) + movq 0x130(%rbp), %r10 + movq %r10, -0x60(%rbp) + movq 0x138(%rbp), %r10 + movq %r10, -0x58(%rbp) + movq 0x140(%rbp), %r10 + movq %r10, -0x70(%rbp) + movq 0x148(%rbp), %r10 + movq %r10, -0x68(%rbp) + movq 0x150(%rbp), %r10 + movq %r10, -0x80(%rbp) + movq 0x158(%rbp), %r10 + movq %r10, -0x78(%rbp) + movq 0x160(%rbp), %r10 + movq %r10, -0x90(%rbp) + movq 0x168(%rbp), %r10 + movq %r10, -0x88(%rbp) + movq 0x170(%rbp), %r10 + movq %r10, -0xa0(%rbp) + movq 0x178(%rbp), %r10 + movq %r10, -0x98(%rbp) + movq 0x180(%rbp), %r10 + movq %r10, -0xb0(%rbp) + movq 0x188(%rbp), %r10 + movq %r10, -0xa8(%rbp) + movq 0x190(%rbp), %r10 + movq %r10, -0xc0(%rbp) + movq 0x198(%rbp), %r10 + movq %r10, -0xb8(%rbp) + movq 0x1a0(%rbp), %r10 + movq %r10, -0xd0(%rbp) + movq 0x1a8(%rbp), %r10 + movq %r10, -0xc8(%rbp) + movq 0x1b0(%rbp), %r10 + movq %r10, -0xe0(%rbp) + movq 0x1b8(%rbp), %r10 + movq %r10, -0xd8(%rbp) + movq 0x1c0(%rbp), %r10 + movq %r10, -0xf0(%rbp) + movq 0x1c8(%rbp), %r10 + movq %r10, -0xe8(%rbp) + movq 0x1d0(%rbp), %r10 + movq %r10, -0x100(%rbp) + movq 0x1d8(%rbp), %r10 + movq %r10, -0xf8(%rbp) + leaq -0x10(%rbp), %rax + movq (%rax), %rax + leaq -0x10(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0x20(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0x20(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0x30(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0x30(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0x40(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0x40(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0x50(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0x50(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0x60(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0x60(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0x70(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0x70(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0x80(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0x80(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0x90(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0x90(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0xa0(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0xa0(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0xb0(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0xb0(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0xc0(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0xc0(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0xd0(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0xd0(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0xe0(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0xe0(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0xf0(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0xf0(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + leaq -0x100(%rbp), %rcx + movq (%rcx), %rcx + addq %rcx, %rax + leaq -0x100(%rbp), %rcx + movq 0x8(%rcx), %rcx + addq %rcx, %rax + addq $0x100, %rsp # imm = 0x100 + popq %rbp + popq %r11 + addq $0x100, %rsp # imm = 0x100 + pushq %r11 + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x110, %rsp # imm = 0x110 + movq %rbx, (%rsp) + movq %r12, 0x8(%rsp) + movq %r13, 0x10(%rsp) + movq %r14, 0x18(%rsp) + movq %r15, 0x20(%rsp) + leaq -, %rax # + leaq -, %rbx # + xorq %rdx, %rdx + cmpq $0x10, %rdx + jge + jmp + incq %rdx + jmp + leaq , %rcx + movq %rdx, %rsi + shlq $0x4, %rsi + addq %rcx, %rsi + movq %rdx, (%rsi) + movq %rdx, %rsi + shlq $0x4, %rsi + addq %rsi, %rcx + movq %rdx, %rsi + shlq $0x1, %rsi + movq %rsi, 0x8(%rcx) + jmp + movl $0x1, %edi + movl $0x2, %esi + movl $0x3, %edx + movl $0x4, %ecx + movl $0x5, %r8d + movl $0x6, %r9d + movl $0x7, %r12d + movl $0x8, %r13d + movl $0x9, %r14d + movl $0xa, %r15d + movl $0xb, %r10d + movq %r10, 0x68(%rsp) + movl $0xc, %r10d + movq %r10, 0x60(%rsp) + movl $0xd, %r10d + movq %r10, 0x58(%rsp) + movl $0xe, %r10d + movq %r10, 0x50(%rsp) + movl $0xf, %r10d + movq %r10, 0x48(%rsp) + movl $0x10, %r10d + movq %r10, 0x40(%rsp) + movl $0x11, %r10d + movq %r10, 0x38(%rsp) + subq $0x60, %rsp + movq %r12, (%rsp) + movq %r13, 0x8(%rsp) + movq %r14, 0x10(%rsp) + movq %r15, 0x18(%rsp) + movq 0xc8(%rsp), %r10 + movq %r10, 0x20(%rsp) + movq 0xc0(%rsp), %r10 + movq %r10, 0x28(%rsp) + movq 0xb8(%rsp), %r10 + movq %r10, 0x30(%rsp) + movq 0xb0(%rsp), %r10 + movq %r10, 0x38(%rsp) + movq 0xa8(%rsp), %r10 + movq %r10, 0x40(%rsp) + movq 0xa0(%rsp), %r10 + movq %r10, 0x48(%rsp) + movq 0x98(%rsp), %r10 + movq %r10, 0x50(%rsp) + callq *%rax + addq $0x60, %rsp + cmpq $0x99, %rax + je + movl $0x1, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + movq 0x18(%rsp), %r14 + movq 0x20(%rsp), %r15 + addq $0x110, %rsp # imm = 0x110 + popq %rbp + retq + leaq , %rdi + leaq 0x10(%rdi), %rsi + leaq 0x20(%rdi), %rdx + leaq 0x30(%rdi), %rcx + leaq 0x40(%rdi), %r8 + leaq 0x50(%rdi), %r9 + leaq 0x60(%rdi), %rax + leaq 0x70(%rdi), %r12 + leaq 0x80(%rdi), %r13 + leaq 0x90(%rdi), %r14 + leaq 0xa0(%rdi), %r15 + leaq 0xb0(%rdi), %r10 + movq %r10, 0x68(%rsp) + leaq 0xc0(%rdi), %r10 + movq %r10, 0x60(%rsp) + leaq 0xd0(%rdi), %r10 + movq %r10, 0x58(%rsp) + leaq 0xe0(%rdi), %r10 + movq %r10, 0x50(%rsp) + leaq 0xf0(%rdi), %r10 + movq %r10, 0x48(%rsp) + subq $0x10, %rsp + movq %rbx, (%rsp) + subq $0xd0, %rsp + movq %rcx, %r10 + movq (%r10), %r11 + movq %r11, (%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x8(%rsp) + movq %r8, %r10 + movq (%r10), %r11 + movq %r11, 0x10(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x18(%rsp) + movq %r9, %r10 + movq (%r10), %r11 + movq %r11, 0x20(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x28(%rsp) + movq %rax, %r10 + movq (%r10), %r11 + movq %r11, 0x30(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x38(%rsp) + movq %r12, %r10 + movq (%r10), %r11 + movq %r11, 0x40(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x48(%rsp) + movq %r13, %r10 + movq (%r10), %r11 + movq %r11, 0x50(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x58(%rsp) + movq %r14, %r10 + movq (%r10), %r11 + movq %r11, 0x60(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x68(%rsp) + movq %r15, %r10 + movq (%r10), %r11 + movq %r11, 0x70(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x78(%rsp) + movq 0x148(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x80(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x88(%rsp) + movq 0x140(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0x90(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0x98(%rsp) + movq 0x138(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xa0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xa8(%rsp) + movq 0x130(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xb0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xb8(%rsp) + movq 0x128(%rsp), %r10 + movq (%r10), %r11 + movq %r11, 0xc0(%rsp) + movq 0x8(%r10), %r11 + movq %r11, 0xc8(%rsp) + movq %rdx, %r8 + movq %rsi, %rdx + movq 0x8(%rdi), %rsi + movq (%rdi), %rdi + movq 0x8(%rdx), %rcx + movq (%rdx), %rdx + movq 0x8(%r8), %r9 + movq (%r8), %r8 + movq 0xd0(%rsp), %r10 + callq *%r10 + addq $0xd0, %rsp + addq $0x10, %rsp + cmpq $0x168, %rax # imm = 0x168 + je + movl $0x2, %eax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + movq 0x18(%rsp), %r14 + movq 0x20(%rsp), %r15 + addq $0x110, %rsp # imm = 0x110 + popq %rbp + retq + xorq %rax, %rax + movq (%rsp), %rbx + movq 0x8(%rsp), %r12 + movq 0x10(%rsp), %r13 + movq 0x18(%rsp), %r14 + movq 0x20(%rsp), %r15 + addq $0x110, %rsp # imm = 0x110 + popq %rbp + retq + addb %al, (%rax) diff --git a/tests/snapshots/asm/indirect_call_through_global_fn_ptr.aarch64.asm b/tests/snapshots/asm/indirect_call_through_global_fn_ptr.aarch64.asm index c3ca4cbc4..2ca837bb0 100644 --- a/tests/snapshots/asm/indirect_call_through_global_fn_ptr.aarch64.asm +++ b/tests/snapshots/asm/indirect_call_through_global_fn_ptr.aarch64.asm @@ -36,10 +36,10 @@ Disassembly of section .text: adrp x0, add x0, x0, ldr x0, [x0] - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! str x20, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] diff --git a/tests/snapshots/asm/init_float_to_int.aarch64.asm b/tests/snapshots/asm/init_float_to_int.aarch64.asm index d2fd75b14..2745bdb42 100644 --- a/tests/snapshots/asm/init_float_to_int.aarch64.asm +++ b/tests/snapshots/asm/init_float_to_int.aarch64.asm @@ -80,8 +80,7 @@ Disassembly of section .text: cbnz x1, adrp x0, add x0, x0, - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x0, #0x4000000000000000 // =4611686018427387904 fmov d17, x0 fcmp d0, d17 diff --git a/tests/snapshots/asm/init_float_to_int.x64.asm b/tests/snapshots/asm/init_float_to_int.x64.asm index b5f32f434..a4db111ad 100644 --- a/tests/snapshots/asm/init_float_to_int.x64.asm +++ b/tests/snapshots/asm/init_float_to_int.x64.asm @@ -82,8 +82,7 @@ Disassembly of section .text: testq %rcx, %rcx jne leaq , %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x4000000000000000, %rax # imm = 0x4000000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -107,4 +106,3 @@ Disassembly of section .text: jmp jmp addb %al, (%rax) - addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/init_scalar_conversion.aarch64.asm b/tests/snapshots/asm/init_scalar_conversion.aarch64.asm index f3bb30119..e43a47c5d 100644 --- a/tests/snapshots/asm/init_scalar_conversion.aarch64.asm +++ b/tests/snapshots/asm/init_scalar_conversion.aarch64.asm @@ -27,8 +27,7 @@ Disassembly of section .text: cset x0, eq cbz x0, sub x0, x29, #0x20 - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x0, #0x0 // =0 fmov d17, x0 fcmp d0, d17 @@ -38,8 +37,7 @@ Disassembly of section .text: mov x1, #0x0 // =0 cbz x2, sub x0, x29, #0x20 - add x0, x0, #0x10 - ldr d0, [x0] + ldr d0, [x0, #0x10] mov x0, #0x400000000000 // =70368744177664 movk x0, #0x408a, lsl #48 fmov d17, x0 @@ -50,8 +48,7 @@ Disassembly of section .text: mov x2, #0x0 // =0 cbz x1, sub x0, x29, #0x20 - add x0, x0, #0x18 - ldr d0, [x0] + ldr d0, [x0, #0x18] mov x0, #0xe00000000000 // =246290604621824 movk x0, #0x4080, lsl #48 fmov d17, x0 @@ -91,8 +88,7 @@ Disassembly of section .text: str d0, [x0] scvtf d0, x21 sub x0, x29, #0x20 - add x0, x0, #0x8 - str d0, [x0] + str d0, [x0, #0x8] sub x0, x29, #0x20 ldr d0, [x0] mov x0, #0x400000000000 // =70368744177664 @@ -102,8 +98,7 @@ Disassembly of section .text: cset x22, ne cbnz x22, sub x0, x29, #0x20 - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x0, #0xe00000000000 // =246290604621824 movk x0, #0x4080, lsl #48 fmov d17, x0 @@ -135,19 +130,15 @@ Disassembly of section .text: sub x0, x29, #0x40 str d0, [x0] sub x0, x29, #0x40 - add x0, x0, #0x8 - str d0, [x0] + str d0, [x0, #0x8] scvtf d0, x20 sub x0, x29, #0x40 - add x0, x0, #0x10 - str d0, [x0] + str d0, [x0, #0x10] scvtf d0, x21 sub x0, x29, #0x40 - add x0, x0, #0x18 - str d0, [x0] + str d0, [x0, #0x18] sub x0, x29, #0x40 - add x0, x0, #0x10 - ldr d0, [x0] + ldr d0, [x0, #0x10] mov x0, #0x400000000000 // =70368744177664 movk x0, #0x408a, lsl #48 fmov d17, x0 @@ -155,8 +146,7 @@ Disassembly of section .text: cset x22, ne cbnz x22, sub x0, x29, #0x40 - add x0, x0, #0x18 - ldr d0, [x0] + ldr d0, [x0, #0x18] mov x0, #0xe00000000000 // =246290604621824 movk x0, #0x4080, lsl #48 fmov d17, x0 @@ -184,8 +174,7 @@ Disassembly of section .text: str d0, [x0] scvtf d0, x21 sub x0, x29, #0x50 - add x0, x0, #0x8 - str d0, [x0] + str d0, [x0, #0x8] sub x0, x29, #0x50 ldr d0, [x0] mov x0, #0x400000000000 // =70368744177664 @@ -195,8 +184,7 @@ Disassembly of section .text: cset x22, ne cbnz x22, sub x0, x29, #0x50 - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x0, #0xe00000000000 // =246290604621824 movk x0, #0x4080, lsl #48 fmov d17, x0 @@ -330,16 +318,13 @@ Disassembly of section .text: sub x0, x29, #0x98 str d0, [x0] sub x0, x29, #0x98 - add x0, x0, #0x8 - str d0, [x0] + str d0, [x0, #0x8] scvtf d0, x20 sub x0, x29, #0x98 - add x0, x0, #0x10 - str d0, [x0] + str d0, [x0, #0x10] scvtf d0, x21 sub x0, x29, #0x98 - add x0, x0, #0x18 - str d0, [x0] + str d0, [x0, #0x18] sub x0, x29, #0x98 ldr d0, [x0] ldr d1, [x0, #0x8] diff --git a/tests/snapshots/asm/init_scalar_conversion.x64.asm b/tests/snapshots/asm/init_scalar_conversion.x64.asm index 52bf2df7b..8e043c803 100644 --- a/tests/snapshots/asm/init_scalar_conversion.x64.asm +++ b/tests/snapshots/asm/init_scalar_conversion.x64.asm @@ -38,8 +38,7 @@ Disassembly of section .text: testq %rax, %rax je leaq -0x20(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 xorq %rax, %rax movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -55,8 +54,7 @@ Disassembly of section .text: testq %rdx, %rdx je leaq -0x20(%rbp), %rax - addq $0x10, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x10(%rax,%riz), %xmm0 movabsq $0x408a400000000000, %rax # imm = 0x408A400000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -72,8 +70,7 @@ Disassembly of section .text: testq %rcx, %rcx je leaq -0x20(%rbp), %rax - addq $0x18, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x18(%rax,%riz), %xmm0 movabsq $0x4080e00000000000, %rax # imm = 0x4080E00000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -118,8 +115,7 @@ Disassembly of section .text: movsd %xmm0, (%rax,%riz) cvtsi2sd %r12, %xmm0 leaq -0x20(%rbp), %rax - addq $0x8, %rax - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x8(%rax,%riz) leaq -0x20(%rbp), %rax movsd (%rax,%riz), %xmm0 movabsq $0x408a400000000000, %rax # imm = 0x408A400000000000 @@ -133,8 +129,7 @@ Disassembly of section .text: testq %r13, %r13 jne leaq -0x20(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x4080e00000000000, %rax # imm = 0x4080E00000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -169,19 +164,15 @@ Disassembly of section .text: leaq -0x40(%rbp), %rax movsd %xmm0, (%rax,%riz) leaq -0x40(%rbp), %rax - addq $0x8, %rax - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x8(%rax,%riz) cvtsi2sd %rbx, %xmm0 leaq -0x40(%rbp), %rax - addq $0x10, %rax - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x10(%rax,%riz) cvtsi2sd %r12, %xmm0 leaq -0x40(%rbp), %rax - addq $0x18, %rax - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x18(%rax,%riz) leaq -0x40(%rbp), %rax - addq $0x10, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x10(%rax,%riz), %xmm0 movabsq $0x408a400000000000, %rax # imm = 0x408A400000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -193,8 +184,7 @@ Disassembly of section .text: testq %r13, %r13 jne leaq -0x40(%rbp), %rax - addq $0x18, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x18(%rax,%riz), %xmm0 movabsq $0x4080e00000000000, %rax # imm = 0x4080E00000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -225,8 +215,7 @@ Disassembly of section .text: movsd %xmm0, (%rax,%riz) cvtsi2sd %r12, %xmm0 leaq -0x50(%rbp), %rax - addq $0x8, %rax - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x8(%rax,%riz) leaq -0x50(%rbp), %rax movsd (%rax,%riz), %xmm0 movabsq $0x408a400000000000, %rax # imm = 0x408A400000000000 @@ -240,8 +229,7 @@ Disassembly of section .text: testq %r13, %r13 jne leaq -0x50(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x4080e00000000000, %rax # imm = 0x4080E00000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -382,16 +370,13 @@ Disassembly of section .text: leaq -0x98(%rbp), %rax movsd %xmm0, (%rax,%riz) leaq -0x98(%rbp), %rax - addq $0x8, %rax - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x8(%rax,%riz) cvtsi2sd %rbx, %xmm0 leaq -0x98(%rbp), %rax - addq $0x10, %rax - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x10(%rax,%riz) cvtsi2sd %r12, %xmm0 leaq -0x98(%rbp), %rax - addq $0x18, %rax - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x18(%rax,%riz) leaq -0x98(%rbp), %rdi subq $0x20, %rsp movq %rdi, %r10 @@ -426,4 +411,4 @@ Disassembly of section .text: jmp jmp jmp - addb %al, 0x41(%rdx) + addb %al, (%rax) diff --git a/tests/snapshots/asm/libc_pread64_pwrite64.aarch64.asm b/tests/snapshots/asm/libc_pread64_pwrite64.aarch64.asm index d2d720de5..7770e85ea 100644 --- a/tests/snapshots/asm/libc_pread64_pwrite64.aarch64.asm +++ b/tests/snapshots/asm/libc_pread64_pwrite64.aarch64.asm @@ -118,11 +118,11 @@ Disassembly of section .text: sub x2, x29, #0x58 mov x3, #0x8 // =8 mov x4, #0x10 // =16 - mov x9, x1 str x4, [sp, #-0x10]! str x3, [sp, #-0x10]! str x2, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] @@ -150,11 +150,11 @@ Disassembly of section .text: sxtw x0, w20 sub x1, x29, #0x68 mov x2, #0x8 // =8 - mov x9, x21 str x22, [sp, #-0x10]! str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x21 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] diff --git a/tests/snapshots/asm/mem2reg_value_across_call.aarch64.asm b/tests/snapshots/asm/mem2reg_value_across_call.aarch64.asm index 044f1b855..12d288506 100644 --- a/tests/snapshots/asm/mem2reg_value_across_call.aarch64.asm +++ b/tests/snapshots/asm/mem2reg_value_across_call.aarch64.asm @@ -37,8 +37,8 @@ Disassembly of section .text: lsl x0, x22, #1 add x0, x0, #0x1 add x23, x23, x0 - mov x9, x21 str x22, [sp, #-0x10]! + mov x9, x21 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/mixed_sse_int_aggregate_args.aarch64.asm b/tests/snapshots/asm/mixed_sse_int_aggregate_args.aarch64.asm index 8f2a7c166..625369877 100644 --- a/tests/snapshots/asm/mixed_sse_int_aggregate_args.aarch64.asm +++ b/tests/snapshots/asm/mixed_sse_int_aggregate_args.aarch64.asm @@ -58,8 +58,7 @@ Disassembly of section .text: cset x1, ne cbnz x1, sub x0, x29, #0x20 - add x0, x0, #0x8 - ldr d1, [x0] + ldr d1, [x0, #0x8] mov x0, #0x3fe0000000000000 // =4602678819172646912 fmov d17, x0 fcmp d1, d17 @@ -88,8 +87,7 @@ Disassembly of section .text: cset x1, ne cbnz x1, sub x0, x29, #0x30 - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x0, #0x4012000000000000 // =4616752568008179712 fmov d17, x0 fcmp d0, d17 @@ -140,19 +138,17 @@ Disassembly of section .text: mov x1, #0xb // =11 str x1, [x0] sub x0, x29, #0x20 - add x0, x0, #0x8 mov x1, #0x3fe0000000000000 // =4602678819172646912 fmov d16, x1 - str d16, [x0] + str d16, [x0, #0x8] sub x0, x29, #0x30 mov x1, #0x400c000000000000 // =4615063718147915776 fmov d16, x1 str d16, [x0] sub x0, x29, #0x30 - add x0, x0, #0x8 mov x1, #0x4012000000000000 // =4616752568008179712 fmov d16, x1 - str d16, [x0] + str d16, [x0, #0x8] mov x0, #0x4 // =4 sub x1, x29, #0x10 sub x2, x29, #0x20 diff --git a/tests/snapshots/asm/mixed_sse_int_aggregate_args.x64.asm b/tests/snapshots/asm/mixed_sse_int_aggregate_args.x64.asm index c820f2bb6..a724e7101 100644 --- a/tests/snapshots/asm/mixed_sse_int_aggregate_args.x64.asm +++ b/tests/snapshots/asm/mixed_sse_int_aggregate_args.x64.asm @@ -67,8 +67,7 @@ Disassembly of section .text: testq %rcx, %rcx jne leaq -0x20(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm1 + movsd 0x8(%rax,%riz), %xmm1 movabsq $0x3fe0000000000000, %rax # imm = 0x3FE0000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm1 @@ -116,8 +115,7 @@ Disassembly of section .text: testq %rcx, %rcx jne leaq -0x30(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x4012000000000000, %rax # imm = 0x4012000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -177,19 +175,17 @@ Disassembly of section .text: movl $0xb, %ecx movq %rcx, (%rax) leaq -0x20(%rbp), %rax - addq $0x8, %rax movabsq $0x3fe0000000000000, %rcx # imm = 0x3FE0000000000000 movq %rcx, %xmm14 - movsd %xmm14, (%rax,%riz) + movsd %xmm14, 0x8(%rax,%riz) leaq -0x30(%rbp), %rax movabsq $0x400c000000000000, %rcx # imm = 0x400C000000000000 movq %rcx, %xmm14 movsd %xmm14, (%rax,%riz) leaq -0x30(%rbp), %rax - addq $0x8, %rax movabsq $0x4012000000000000, %rcx # imm = 0x4012000000000000 movq %rcx, %xmm14 - movsd %xmm14, (%rax,%riz) + movsd %xmm14, 0x8(%rax,%riz) movl $0x4, %edi leaq -0x10(%rbp), %rsi leaq -0x20(%rbp), %rdx diff --git a/tests/snapshots/asm/mixed_struct_gpr_abi.aarch64.asm b/tests/snapshots/asm/mixed_struct_gpr_abi.aarch64.asm index 5c087c8cb..0a8fa4e5a 100644 --- a/tests/snapshots/asm/mixed_struct_gpr_abi.aarch64.asm +++ b/tests/snapshots/asm/mixed_struct_gpr_abi.aarch64.asm @@ -24,8 +24,7 @@ Disassembly of section .text: ldr x0, [x0] scvtf d0, x0 sub x0, x29, #0x10 - add x0, x0, #0x8 - ldr d1, [x0] + ldr d1, [x0, #0x8] mov x0, #0x4000000000000000 // =4611686018427387904 fmov d17, x0 fmadd d0, d1, d17, d0 @@ -55,8 +54,7 @@ Disassembly of section .text: ldr x1, [x1] add x0, x0, x1 sub x1, x29, #0x10 - add x1, x1, #0x8 - ldr d0, [x1] + ldr d0, [x1, #0x8] fcvtzs x1, d0 add x0, x0, x1 add sp, sp, #0x10 @@ -82,8 +80,7 @@ Disassembly of section .text: sxtw x1, w1 ldr x2, [x0] scvtf d0, x2 - add x0, x0, #0x8 - ldr d1, [x0] + ldr d1, [x0, #0x8] mov x0, #0x4000000000000000 // =4611686018427387904 fmov d17, x0 fmadd d0, d1, d17, d0 @@ -110,8 +107,7 @@ Disassembly of section .text: sxtw x0, w0 ldr x1, [x6] add x0, x0, x1 - add x1, x6, #0x8 - ldr d0, [x1] + ldr d0, [x6, #0x8] fcvtzs x1, d0 add x0, x0, x1 cmp x0, #0x1c diff --git a/tests/snapshots/asm/mixed_struct_gpr_abi.x64.asm b/tests/snapshots/asm/mixed_struct_gpr_abi.x64.asm index 847596946..abb438fdf 100644 --- a/tests/snapshots/asm/mixed_struct_gpr_abi.x64.asm +++ b/tests/snapshots/asm/mixed_struct_gpr_abi.x64.asm @@ -24,8 +24,7 @@ Disassembly of section .text: movq (%rax), %rax cvtsi2sd %rax, %xmm0 leaq -0x10(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm1 + movsd 0x8(%rax,%riz), %xmm1 movabsq $0x4000000000000000, %rax # imm = 0x4000000000000000 movapd %xmm1, %xmm14 movq %rax, %xmm15 @@ -60,8 +59,7 @@ Disassembly of section .text: movq (%rcx), %rcx addq %rcx, %rax leaq -0x10(%rbp), %rcx - addq $0x8, %rcx - movsd (%rcx,%riz), %xmm0 + movsd 0x8(%rcx,%riz), %xmm0 cvttsd2si %xmm0, %rcx addq %rcx, %rax addq $0x10, %rsp @@ -119,3 +117,4 @@ Disassembly of section .text: addq $0x50, %rsp popq %rbp retq + addb %al, (%rax) diff --git a/tests/snapshots/asm/msvc_callconv.aarch64.asm b/tests/snapshots/asm/msvc_callconv.aarch64.asm index 9bb5f134d..f03aa77c1 100644 --- a/tests/snapshots/asm/msvc_callconv.aarch64.asm +++ b/tests/snapshots/asm/msvc_callconv.aarch64.asm @@ -46,9 +46,9 @@ Disassembly of section .text: add x20, x20, mov x1, #0x14 // =20 mov x2, #0x16 // =22 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -61,8 +61,8 @@ Disassembly of section .text: add x1, x1, x2 add x0, x0, x1 sxtw x21, w0 - mov x9, x20 str x21, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/negative_float_in_array_init.aarch64.asm b/tests/snapshots/asm/negative_float_in_array_init.aarch64.asm index 711893168..d105f69ba 100644 --- a/tests/snapshots/asm/negative_float_in_array_init.aarch64.asm +++ b/tests/snapshots/asm/negative_float_in_array_init.aarch64.asm @@ -25,8 +25,7 @@ Disassembly of section .text: add sp, sp, #0x10 ldp x29, x30, [sp], #0x10 ret - add x1, x0, #0x8 - ldr d0, [x1] + ldr d0, [x0, #0x8] mov x1, #0x4004000000000000 // =4612811918334230528 fmov d16, x1 fneg d1, d16 @@ -37,8 +36,7 @@ Disassembly of section .text: add sp, sp, #0x10 ldp x29, x30, [sp], #0x10 ret - add x1, x0, #0x10 - ldr d0, [x1] + ldr d0, [x0, #0x10] mov x1, #0x94000000 // =2483027968 movk x1, #0x449a, lsl #32 movk x1, #0x421e, lsl #48 @@ -52,11 +50,9 @@ Disassembly of section .text: ldp x29, x30, [sp], #0x10 ret ldr d0, [x0] - add x1, x0, #0x8 - ldr d1, [x1] + ldr d1, [x0, #0x8] fadd d0, d0, d1 - add x0, x0, #0x10 - ldr d1, [x0] + ldr d1, [x0, #0x10] fadd d0, d0, d1 mov x0, #0x94000000 // =2483027968 movk x0, #0x449a, lsl #32 diff --git a/tests/snapshots/asm/negative_float_in_array_init.x64.asm b/tests/snapshots/asm/negative_float_in_array_init.x64.asm index 6598bae3b..067bb05f4 100644 --- a/tests/snapshots/asm/negative_float_in_array_init.x64.asm +++ b/tests/snapshots/asm/negative_float_in_array_init.x64.asm @@ -30,8 +30,7 @@ Disassembly of section .text: addq $0x10, %rsp popq %rbp retq - leaq 0x8(%rax), %rcx - movsd (%rcx,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x4004000000000000, %rcx # imm = 0x4004000000000000 movq %rcx, %xmm1 movabsq $-0x8000000000000000, %r10 # imm = 0x8000000000000000 @@ -49,8 +48,7 @@ Disassembly of section .text: addq $0x10, %rsp popq %rbp retq - leaq 0x10(%rax), %rcx - movsd (%rcx,%riz), %xmm0 + movsd 0x10(%rax,%riz), %xmm0 movabsq $0x421e449a94000000, %rcx # imm = 0x421E449A94000000 movq %rcx, %xmm1 movabsq $-0x8000000000000000, %r10 # imm = 0x8000000000000000 @@ -69,11 +67,9 @@ Disassembly of section .text: popq %rbp retq movsd (%rax,%riz), %xmm0 - leaq 0x8(%rax), %rcx - movsd (%rcx,%riz), %xmm1 + movsd 0x8(%rax,%riz), %xmm1 addsd %xmm1, %xmm0 - addq $0x10, %rax - movsd (%rax,%riz), %xmm1 + movsd 0x10(%rax,%riz), %xmm1 addsd %xmm1, %xmm0 movabsq $0x421e449a94000000, %rax # imm = 0x421E449A94000000 movq %rax, %xmm1 @@ -113,4 +109,4 @@ Disassembly of section .text: popq %rbp retq jmp - addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/out_pointer_return_float_args.aarch64.asm b/tests/snapshots/asm/out_pointer_return_float_args.aarch64.asm index be641702a..bee1fb173 100644 --- a/tests/snapshots/asm/out_pointer_return_float_args.aarch64.asm +++ b/tests/snapshots/asm/out_pointer_return_float_args.aarch64.asm @@ -16,14 +16,11 @@ Disassembly of section .text: sub x0, x29, #0x30 str s0, [x0] sub x0, x29, #0x30 - add x0, x0, #0x4 - str s1, [x0] + str s1, [x0, #0x4] sub x0, x29, #0x30 - add x0, x0, #0x8 - str s2, [x0] + str s2, [x0, #0x8] sub x0, x29, #0x30 - add x0, x0, #0xc - str s3, [x0] + str s3, [x0, #0xc] sub x0, x29, #0x30 mov x16, x0 ldr s0, [x16] @@ -43,17 +40,13 @@ Disassembly of section .text: sub x0, x29, #0x40 str s0, [x0] sub x0, x29, #0x40 - add x0, x0, #0x4 - str s1, [x0] + str s1, [x0, #0x4] sub x0, x29, #0x40 - add x0, x0, #0x8 - str s2, [x0] + str s2, [x0, #0x8] sub x0, x29, #0x40 - add x0, x0, #0xc - str s3, [x0] + str s3, [x0, #0xc] sub x0, x29, #0x40 - add x0, x0, #0x10 - str s4, [x0] + str s4, [x0, #0x10] sub x0, x29, #0x40 mov x16, x0 sub x17, x29, #0x48 @@ -82,11 +75,9 @@ Disassembly of section .text: sub x0, x29, #0x18 str d0, [x0] sub x0, x29, #0x18 - add x0, x0, #0x8 - str d1, [x0] + str d1, [x0, #0x8] sub x0, x29, #0x18 - add x0, x0, #0x10 - str d2, [x0] + str d2, [x0, #0x10] sub x0, x29, #0x18 mov x16, x0 ldr d0, [x16] @@ -138,8 +129,7 @@ Disassembly of section .text: mov x20, #0x1 // =1 cbnz x0, sub x0, x29, #0x10 - add x0, x0, #0x4 - ldr s0, [x0] + ldr s0, [x0, #0x4] mov x0, #0x4000000000000000 // =4611686018427387904 fcvt d0, s0 fmov d17, x0 @@ -150,8 +140,7 @@ Disassembly of section .text: mov x21, #0x1 // =1 cbnz x20, sub x0, x29, #0x10 - add x0, x0, #0x8 - ldr s0, [x0] + ldr s0, [x0, #0x8] mov x0, #0x4008000000000000 // =4613937818241073152 fcvt d0, s0 fmov d17, x0 @@ -161,8 +150,7 @@ Disassembly of section .text: cset x21, ne cbnz x21, sub x0, x29, #0x10 - add x0, x0, #0xc - ldr s0, [x0] + ldr s0, [x0, #0xc] mov x0, #0x4010000000000000 // =4616189618054758400 fcvt d0, s0 fmov d17, x0 @@ -218,8 +206,7 @@ Disassembly of section .text: mov x20, #0x1 // =1 cbnz x0, sub x0, x29, #0x38 - add x0, x0, #0x4 - ldr s0, [x0] + ldr s0, [x0, #0x4] mov x0, #0x4004000000000000 // =4612811918334230528 fcvt d0, s0 fmov d17, x0 @@ -230,8 +217,7 @@ Disassembly of section .text: mov x21, #0x1 // =1 cbnz x20, sub x0, x29, #0x38 - add x0, x0, #0x8 - ldr s0, [x0] + ldr s0, [x0, #0x8] mov x0, #0x400c000000000000 // =4615063718147915776 fcvt d0, s0 fmov d17, x0 @@ -242,8 +228,7 @@ Disassembly of section .text: mov x20, #0x1 // =1 cbnz x21, sub x0, x29, #0x38 - add x0, x0, #0xc - ldr s0, [x0] + ldr s0, [x0, #0xc] mov x0, #0x4012000000000000 // =4616752568008179712 fcvt d0, s0 fmov d17, x0 @@ -253,8 +238,7 @@ Disassembly of section .text: cset x20, ne cbnz x20, sub x0, x29, #0x38 - add x0, x0, #0x10 - ldr s0, [x0] + ldr s0, [x0, #0x10] mov x0, #0x4016000000000000 // =4617878467915022336 fcvt d0, s0 fmov d17, x0 @@ -297,8 +281,7 @@ Disassembly of section .text: mov x2, #0x1 // =1 cbnz x0, sub x0, x29, #0x68 - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x0, #0x4034000000000000 // =4626322717216342016 fmov d17, x0 fcmp d0, d17 @@ -307,8 +290,7 @@ Disassembly of section .text: cset x2, ne cbnz x2, sub x0, x29, #0x68 - add x0, x0, #0x10 - ldr d0, [x0] + ldr d0, [x0, #0x10] mov x0, #0x403e000000000000 // =4629137466983448576 fmov d17, x0 fcmp d0, d17 diff --git a/tests/snapshots/asm/out_pointer_return_float_args.x64.asm b/tests/snapshots/asm/out_pointer_return_float_args.x64.asm index be302a423..b49b87843 100644 --- a/tests/snapshots/asm/out_pointer_return_float_args.x64.asm +++ b/tests/snapshots/asm/out_pointer_return_float_args.x64.asm @@ -17,14 +17,11 @@ Disassembly of section .text: leaq -0x30(%rbp), %rax movss %xmm0, (%rax,%riz) leaq -0x30(%rbp), %rax - addq $0x4, %rax - movss %xmm1, (%rax,%riz) + movss %xmm1, 0x4(%rax,%riz) leaq -0x30(%rbp), %rax - addq $0x8, %rax - movss %xmm2, (%rax,%riz) + movss %xmm2, 0x8(%rax,%riz) leaq -0x30(%rbp), %rax - addq $0xc, %rax - movss %xmm3, (%rax,%riz) + movss %xmm3, 0xc(%rax,%riz) leaq -0x30(%rbp), %rax movq %rax, %rcx movsd (%rcx,%riz), %xmm0 @@ -70,21 +67,17 @@ Disassembly of section .text: movss -0x8(%rbp,%riz), %xmm0 movss %xmm0, (%rax,%riz) leaq -0x40(%rbp), %rax - addq $0x4, %rax movss -0x10(%rbp,%riz), %xmm0 - movss %xmm0, (%rax,%riz) + movss %xmm0, 0x4(%rax,%riz) leaq -0x40(%rbp), %rax - addq $0x8, %rax movss -0x18(%rbp,%riz), %xmm0 - movss %xmm0, (%rax,%riz) + movss %xmm0, 0x8(%rax,%riz) leaq -0x40(%rbp), %rax - addq $0xc, %rax movss -0x20(%rbp,%riz), %xmm0 - movss %xmm0, (%rax,%riz) + movss %xmm0, 0xc(%rax,%riz) leaq -0x40(%rbp), %rax - addq $0x10, %rax movss -0x28(%rbp,%riz), %xmm0 - movss %xmm0, (%rax,%riz) + movss %xmm0, 0x10(%rax,%riz) movq 0x10(%rbp), %rax leaq -0x40(%rbp), %rcx pushq %rdx @@ -124,13 +117,11 @@ Disassembly of section .text: movsd 0x20(%rbp,%riz), %xmm0 movsd %xmm0, (%rax,%riz) leaq -0x18(%rbp), %rax - addq $0x8, %rax movsd 0x30(%rbp,%riz), %xmm0 - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x8(%rax,%riz) leaq -0x18(%rbp), %rax - addq $0x10, %rax movsd 0x40(%rbp,%riz), %xmm0 - movsd %xmm0, (%rax,%riz) + movsd %xmm0, 0x10(%rax,%riz) movq 0x10(%rbp), %rax leaq -0x18(%rbp), %rcx pushq %rdx @@ -193,8 +184,7 @@ Disassembly of section .text: testq %rax, %rax jne leaq -0x10(%rbp), %rax - addq $0x4, %rax - movss (%rax,%riz), %xmm0 + movss 0x4(%rax,%riz), %xmm0 movabsq $0x4000000000000000, %rax # imm = 0x4000000000000000 cvtss2sd %xmm0, %xmm0 movq %rax, %xmm15 @@ -211,8 +201,7 @@ Disassembly of section .text: testq %rbx, %rbx jne leaq -0x10(%rbp), %rax - addq $0x8, %rax - movss (%rax,%riz), %xmm0 + movss 0x8(%rax,%riz), %xmm0 movabsq $0x4008000000000000, %rax # imm = 0x4008000000000000 cvtss2sd %xmm0, %xmm0 movq %rax, %xmm15 @@ -228,8 +217,7 @@ Disassembly of section .text: testq %r12, %r12 jne leaq -0x10(%rbp), %rax - addq $0xc, %rax - movss (%rax,%riz), %xmm0 + movss 0xc(%rax,%riz), %xmm0 movabsq $0x4010000000000000, %rax # imm = 0x4010000000000000 cvtss2sd %xmm0, %xmm0 movq %rax, %xmm15 @@ -315,8 +303,7 @@ Disassembly of section .text: testq %rax, %rax jne leaq -0x38(%rbp), %rax - addq $0x4, %rax - movss (%rax,%riz), %xmm0 + movss 0x4(%rax,%riz), %xmm0 movabsq $0x4004000000000000, %rax # imm = 0x4004000000000000 cvtss2sd %xmm0, %xmm0 movq %rax, %xmm15 @@ -333,8 +320,7 @@ Disassembly of section .text: testq %rbx, %rbx jne leaq -0x38(%rbp), %rax - addq $0x8, %rax - movss (%rax,%riz), %xmm0 + movss 0x8(%rax,%riz), %xmm0 movabsq $0x400c000000000000, %rax # imm = 0x400C000000000000 cvtss2sd %xmm0, %xmm0 movq %rax, %xmm15 @@ -351,8 +337,7 @@ Disassembly of section .text: testq %r12, %r12 jne leaq -0x38(%rbp), %rax - addq $0xc, %rax - movss (%rax,%riz), %xmm0 + movss 0xc(%rax,%riz), %xmm0 movabsq $0x4012000000000000, %rax # imm = 0x4012000000000000 cvtss2sd %xmm0, %xmm0 movq %rax, %xmm15 @@ -368,8 +353,7 @@ Disassembly of section .text: testq %rbx, %rbx jne leaq -0x38(%rbp), %rax - addq $0x10, %rax - movss (%rax,%riz), %xmm0 + movss 0x10(%rax,%riz), %xmm0 movabsq $0x4016000000000000, %rax # imm = 0x4016000000000000 cvtss2sd %xmm0, %xmm0 movq %rax, %xmm15 @@ -417,8 +401,7 @@ Disassembly of section .text: testq %rax, %rax jne leaq -0x68(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x4034000000000000, %rax # imm = 0x4034000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -433,8 +416,7 @@ Disassembly of section .text: testq %rdx, %rdx jne leaq -0x68(%rbp), %rax - addq $0x10, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x10(%rax,%riz), %xmm0 movabsq $0x403e000000000000, %rax # imm = 0x403E000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -466,4 +448,3 @@ Disassembly of section .text: jmp jmp jmp - addb %al, (%rax) diff --git a/tests/snapshots/asm/pthread_create.aarch64.asm b/tests/snapshots/asm/pthread_create.aarch64.asm index 98283214a..400bf422c 100644 --- a/tests/snapshots/asm/pthread_create.aarch64.asm +++ b/tests/snapshots/asm/pthread_create.aarch64.asm @@ -39,11 +39,11 @@ Disassembly of section .text: sub x0, x29, #0x20 adrp x2, add x2, x2, - mov x9, x22 str x20, [sp, #-0x10]! str x2, [sp, #-0x10]! str x20, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x22 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] @@ -52,9 +52,9 @@ Disassembly of section .text: add sp, sp, #0x40 ldur x0, [x29, #-0x20] sub x1, x29, #0x28 - mov x9, x21 str x1, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x21 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/sqlite_min.aarch64.asm b/tests/snapshots/asm/sqlite_min.aarch64.asm index 1cb23980f..daa7312b1 100644 --- a/tests/snapshots/asm/sqlite_min.aarch64.asm +++ b/tests/snapshots/asm/sqlite_min.aarch64.asm @@ -30,10 +30,10 @@ Disassembly of section .text: add x0, x0, mov x2, #0x42 // =66 mov x3, #0x1a4 // =420 - mov x9, x1 str x3, [sp, #-0x10]! str x2, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] @@ -53,9 +53,9 @@ Disassembly of section .text: ldp x29, x30, [sp], #0x10 ret mov x1, #0x400 // =1024 - mov x9, x23 str x1, [sp, #-0x10]! str x24, [sp, #-0x10]! + mov x9, x23 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -74,9 +74,9 @@ Disassembly of section .text: ldp x29, x30, [sp], #0x10 ret sub x1, x29, #0xb8 - mov x9, x22 str x1, [sp, #-0x10]! str x24, [sp, #-0x10]! + mov x9, x22 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -112,8 +112,8 @@ Disassembly of section .text: add sp, sp, #0x110 ldp x29, x30, [sp], #0x10 ret - mov x9, x20 str x24, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/static_init_cast_funcptr.aarch64.asm b/tests/snapshots/asm/static_init_cast_funcptr.aarch64.asm index 6edf1481a..9043771ae 100644 --- a/tests/snapshots/asm/static_init_cast_funcptr.aarch64.asm +++ b/tests/snapshots/asm/static_init_cast_funcptr.aarch64.asm @@ -33,8 +33,8 @@ Disassembly of section .text: add x20, x20, ldr x0, [x20, #0x8] mov x1, #0x15 // =21 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -49,8 +49,8 @@ Disassembly of section .text: ret ldr x0, [x20, #0x20] mov x1, #0x7 // =7 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -70,8 +70,8 @@ Disassembly of section .text: ldr x0, [x20, #0x10] adrp x1, add x1, x1, - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -87,8 +87,8 @@ Disassembly of section .text: ldr x0, [x20, #0x28] adrp x1, add x1, x1, - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/static_init_paren_relocation.aarch64.asm b/tests/snapshots/asm/static_init_paren_relocation.aarch64.asm index df70a7eaf..c17c47c87 100644 --- a/tests/snapshots/asm/static_init_paren_relocation.aarch64.asm +++ b/tests/snapshots/asm/static_init_paren_relocation.aarch64.asm @@ -23,9 +23,9 @@ Disassembly of section .text: add x20, x20, mov x0, #0x0 // =0 ldr x1, [x20, #0x8] - mov x9, x1 str x0, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -73,9 +73,9 @@ Disassembly of section .text: adrp x1, add x1, x1, ldr x1, [x1] - mov x9, x1 str x0, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x1 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/static_init_struct_fp_call.aarch64.asm b/tests/snapshots/asm/static_init_struct_fp_call.aarch64.asm index 08cf60dd1..d82bcbcb7 100644 --- a/tests/snapshots/asm/static_init_struct_fp_call.aarch64.asm +++ b/tests/snapshots/asm/static_init_struct_fp_call.aarch64.asm @@ -30,9 +30,9 @@ Disassembly of section .text: ldr x0, [x20] mov x1, #0x2 // =2 mov x2, #0x3 // =3 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -49,9 +49,9 @@ Disassembly of section .text: ldr x0, [x20, #0x8] mov x1, #0xa // =10 mov x2, #0x4 // =4 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/static_neg_infinity_init.aarch64.asm b/tests/snapshots/asm/static_neg_infinity_init.aarch64.asm index 89834d649..914159967 100644 --- a/tests/snapshots/asm/static_neg_infinity_init.aarch64.asm +++ b/tests/snapshots/asm/static_neg_infinity_init.aarch64.asm @@ -52,8 +52,7 @@ Disassembly of section .text: ret adrp x0, add x0, x0, - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] bl cmp x0, #0x0 b.ne diff --git a/tests/snapshots/asm/static_neg_infinity_init.x64.asm b/tests/snapshots/asm/static_neg_infinity_init.x64.asm index 7259dac21..2ad932c0d 100644 --- a/tests/snapshots/asm/static_neg_infinity_init.x64.asm +++ b/tests/snapshots/asm/static_neg_infinity_init.x64.asm @@ -61,8 +61,7 @@ Disassembly of section .text: popq %rbp retq leaq , %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 callq testq %rax, %rax jne @@ -105,4 +104,4 @@ Disassembly of section .text: addq $0x10, %rsp popq %rbp retq - addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/struct_arg_indirect_subscript.aarch64.asm b/tests/snapshots/asm/struct_arg_indirect_subscript.aarch64.asm index 602611d9a..c3147bdf4 100644 --- a/tests/snapshots/asm/struct_arg_indirect_subscript.aarch64.asm +++ b/tests/snapshots/asm/struct_arg_indirect_subscript.aarch64.asm @@ -62,8 +62,7 @@ Disassembly of section .text: ldr d0, [x0] mov x0, #0x4010000000000000 // =4616189618054758400 sub x2, x29, #0x10 - add x2, x2, #0x8 - ldr d1, [x2] + ldr d1, [x2, #0x8] mov x2, #0x4000000000000000 // =4611686018427387904 fmov d17, x2 fmul d1, d1, d17 diff --git a/tests/snapshots/asm/struct_arg_indirect_subscript.x64.asm b/tests/snapshots/asm/struct_arg_indirect_subscript.x64.asm index 215b3b749..8573b6e09 100644 --- a/tests/snapshots/asm/struct_arg_indirect_subscript.x64.asm +++ b/tests/snapshots/asm/struct_arg_indirect_subscript.x64.asm @@ -64,8 +64,7 @@ Disassembly of section .text: movsd (%rax,%riz), %xmm0 movabsq $0x4010000000000000, %rax # imm = 0x4010000000000000 leaq -0x10(%rbp), %rcx - addq $0x8, %rcx - movsd (%rcx,%riz), %xmm1 + movsd 0x8(%rcx,%riz), %xmm1 movabsq $0x4000000000000000, %rcx # imm = 0x4000000000000000 movq %rcx, %xmm15 mulsd %xmm15, %xmm1 @@ -306,3 +305,5 @@ Disassembly of section .text: addq $0xd0, %rsp popq %rbp retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/struct_fn_ptr_field_deref_call.aarch64.asm b/tests/snapshots/asm/struct_fn_ptr_field_deref_call.aarch64.asm index f125dd10c..6c039fc4b 100644 --- a/tests/snapshots/asm/struct_fn_ptr_field_deref_call.aarch64.asm +++ b/tests/snapshots/asm/struct_fn_ptr_field_deref_call.aarch64.asm @@ -34,16 +34,16 @@ Disassembly of section .text: mov x1, #0x0 // =0 str w1, [x20, #0x8] mov x1, #0xa // =10 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 sxtw x21, w0 ldr x0, [x20] mov x1, #0x14 // =20 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -70,16 +70,16 @@ Disassembly of section .text: add x0, x0, str x0, [x20] mov x1, #0x64 // =100 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 sxtw x21, w0 ldr x0, [x20] mov x1, #0xc8 // =200 - mov x9, x0 str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/struct_initializers.aarch64.asm b/tests/snapshots/asm/struct_initializers.aarch64.asm index c9e883efd..cac20dd47 100644 --- a/tests/snapshots/asm/struct_initializers.aarch64.asm +++ b/tests/snapshots/asm/struct_initializers.aarch64.asm @@ -39,9 +39,9 @@ Disassembly of section .text: ldr x0, [x20, #0x8] mov x1, #0x2 // =2 mov x2, #0x3 // =3 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -58,9 +58,9 @@ Disassembly of section .text: ldr x0, [x20, #0x10] mov x1, #0xa // =10 mov x2, #0x4 // =4 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -103,9 +103,9 @@ Disassembly of section .text: ldr x0, [x0, #0x8] mov x1, #0x7 // =7 mov x2, #0x8 // =8 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -149,9 +149,9 @@ Disassembly of section .text: add x0, x0, ldr x0, [x0, #0x8] mov x1, #0x1 // =1 - mov x9, x0 str x1, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -170,9 +170,9 @@ Disassembly of section .text: ldr x0, [x0, #0x10] mov x1, #0x5 // =5 mov x2, #0x1 // =1 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/sys_addr_in_static_init.aarch64.asm b/tests/snapshots/asm/sys_addr_in_static_init.aarch64.asm index 7c52e79d6..e84e66bcc 100644 --- a/tests/snapshots/asm/sys_addr_in_static_init.aarch64.asm +++ b/tests/snapshots/asm/sys_addr_in_static_init.aarch64.asm @@ -23,9 +23,9 @@ Disassembly of section .text: adrp x1, add x1, x1, mov x2, #0x4 // =4 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -45,10 +45,10 @@ Disassembly of section .text: ldr x0, [x20, #0x8] adrp x2, add x2, x2, - mov x9, x0 str x1, [sp, #-0x10]! str x1, [sp, #-0x10]! str x2, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] @@ -68,10 +68,10 @@ Disassembly of section .text: ldr x0, [x20, #0x68] sub x1, x29, #0x48 mov x2, #0x4 // =4 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! str x21, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] @@ -79,8 +79,8 @@ Disassembly of section .text: add sp, sp, #0x30 sxtw x22, w0 ldr x0, [x20, #0x20] - mov x9, x0 str x21, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/thread_local_per_thread.aarch64.asm b/tests/snapshots/asm/thread_local_per_thread.aarch64.asm index 3864df980..cbbe5a7b3 100644 --- a/tests/snapshots/asm/thread_local_per_thread.aarch64.asm +++ b/tests/snapshots/asm/thread_local_per_thread.aarch64.asm @@ -71,11 +71,11 @@ Disassembly of section .text: sub x0, x29, #0x20 adrp x2, add x2, x2, - mov x9, x23 str x21, [sp, #-0x10]! str x2, [sp, #-0x10]! str x21, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x23 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] @@ -84,9 +84,9 @@ Disassembly of section .text: add sp, sp, #0x40 ldur x0, [x29, #-0x20] sub x1, x29, #0x28 - mov x9, x22 str x1, [sp, #-0x10]! str x0, [sp, #-0x10]! + mov x9, x22 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/two_d_float_array_partial_init.aarch64.asm b/tests/snapshots/asm/two_d_float_array_partial_init.aarch64.asm index f5ef2e85b..2291d318b 100644 --- a/tests/snapshots/asm/two_d_float_array_partial_init.aarch64.asm +++ b/tests/snapshots/asm/two_d_float_array_partial_init.aarch64.asm @@ -153,11 +153,9 @@ Disassembly of section .text: lsl x3, x3, #4 add x2, x2, x3 ldr s1, [x2] - add x3, x2, #0x4 - ldr s2, [x3] + ldr s2, [x2, #0x4] fadd s1, s1, s2 - add x2, x2, #0x8 - ldr s2, [x2] + ldr s2, [x2, #0x8] fadd s1, s1, s2 fadd s0, s0, s1 str s0, [x0] diff --git a/tests/snapshots/asm/two_d_float_array_partial_init.x64.asm b/tests/snapshots/asm/two_d_float_array_partial_init.x64.asm index 6f3b4ba4d..e92d89514 100644 --- a/tests/snapshots/asm/two_d_float_array_partial_init.x64.asm +++ b/tests/snapshots/asm/two_d_float_array_partial_init.x64.asm @@ -147,11 +147,9 @@ Disassembly of section .text: shlq $0x4, %rsi addq %rsi, %rdx movss (%rdx,%riz), %xmm1 - leaq 0x4(%rdx), %rsi - movss (%rsi,%riz), %xmm2 + movss 0x4(%rdx,%riz), %xmm2 addss %xmm2, %xmm1 - addq $0x8, %rdx - movss (%rdx,%riz), %xmm2 + movss 0x8(%rdx,%riz), %xmm2 addss %xmm2, %xmm1 addss %xmm1, %xmm0 movss %xmm0, (%rax,%riz) @@ -190,4 +188,3 @@ Disassembly of section .text: addq $0x50, %rsp popq %rbp retq - addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/two_d_stride_no_leak_across_exprs.aarch64.asm b/tests/snapshots/asm/two_d_stride_no_leak_across_exprs.aarch64.asm index 95ad55da3..457e43b43 100644 --- a/tests/snapshots/asm/two_d_stride_no_leak_across_exprs.aarch64.asm +++ b/tests/snapshots/asm/two_d_stride_no_leak_across_exprs.aarch64.asm @@ -54,8 +54,7 @@ Disassembly of section .text: str s0, [x0] b sub x0, x29, #0x508 - add x0, x0, #0x20 - ldr s0, [x0] + ldr s0, [x0, #0x20] mov x0, #0x4000000000000000 // =4611686018427387904 fcvt d0, s0 fmov d17, x0 diff --git a/tests/snapshots/asm/two_d_stride_no_leak_across_exprs.x64.asm b/tests/snapshots/asm/two_d_stride_no_leak_across_exprs.x64.asm index 3c53b4dd6..89100c389 100644 --- a/tests/snapshots/asm/two_d_stride_no_leak_across_exprs.x64.asm +++ b/tests/snapshots/asm/two_d_stride_no_leak_across_exprs.x64.asm @@ -56,8 +56,7 @@ Disassembly of section .text: movss %xmm0, (%rax,%riz) jmp leaq -0x508(%rbp), %rax - addq $0x20, %rax - movss (%rax,%riz), %xmm0 + movss 0x20(%rax,%riz), %xmm0 movabsq $0x4000000000000000, %rax # imm = 0x4000000000000000 cvtss2sd %xmm0, %xmm0 movq %rax, %xmm15 @@ -98,4 +97,3 @@ Disassembly of section .text: addq $0x520, %rsp # imm = 0x520 popq %rbp retq - addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/typedef_fn_ptr_struct_field.aarch64.asm b/tests/snapshots/asm/typedef_fn_ptr_struct_field.aarch64.asm index 91abf9f90..07e06d215 100644 --- a/tests/snapshots/asm/typedef_fn_ptr_struct_field.aarch64.asm +++ b/tests/snapshots/asm/typedef_fn_ptr_struct_field.aarch64.asm @@ -31,9 +31,9 @@ Disassembly of section .text: ldr x0, [x20] mov x1, #0x3 // =3 mov x2, #0x7 // =7 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -50,9 +50,9 @@ Disassembly of section .text: ldr x0, [x20] mov x1, #0x4 // =4 mov x2, #0x5 // =5 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -70,9 +70,9 @@ Disassembly of section .text: ldr x0, [x0] mov x1, #0x2 // =2 mov x2, #0x9 // =9 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -90,9 +90,9 @@ Disassembly of section .text: ldr x0, [x0] mov x1, #0x6 // =6 mov x2, #0x4 // =4 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 diff --git a/tests/snapshots/asm/unary_plus_init_and_param_shadow.aarch64.asm b/tests/snapshots/asm/unary_plus_init_and_param_shadow.aarch64.asm index ecc77ad57..60b3de606 100644 --- a/tests/snapshots/asm/unary_plus_init_and_param_shadow.aarch64.asm +++ b/tests/snapshots/asm/unary_plus_init_and_param_shadow.aarch64.asm @@ -65,8 +65,7 @@ Disassembly of section .text: add sp, sp, #0x40 ldp x29, x30, [sp], #0x10 ret - add x0, x20, #0x8 - ldr d0, [x0] + ldr d0, [x20, #0x8] mov x0, #0x6666 // =26214 movk x0, #0x6666, lsl #16 movk x0, #0x6666, lsl #32 @@ -80,8 +79,7 @@ Disassembly of section .text: add sp, sp, #0x40 ldp x29, x30, [sp], #0x10 ret - add x0, x20, #0x10 - ldr d0, [x0] + ldr d0, [x20, #0x10] mov x0, #0x3ff0000000000000 // =4607182418800017408 fmov d1, x0 bl @@ -92,8 +90,7 @@ Disassembly of section .text: add sp, sp, #0x40 ldp x29, x30, [sp], #0x10 ret - add x0, x20, #0x18 - ldr d0, [x0] + ldr d0, [x20, #0x18] mov x0, #0x4000000000000000 // =4611686018427387904 fmov d16, x0 fneg d1, d16 diff --git a/tests/snapshots/asm/unary_plus_init_and_param_shadow.x64.asm b/tests/snapshots/asm/unary_plus_init_and_param_shadow.x64.asm index 8a11f486a..a2869f73d 100644 --- a/tests/snapshots/asm/unary_plus_init_and_param_shadow.x64.asm +++ b/tests/snapshots/asm/unary_plus_init_and_param_shadow.x64.asm @@ -68,8 +68,7 @@ Disassembly of section .text: addq $0x40, %rsp popq %rbp retq - leaq 0x8(%rbx), %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rbx,%riz), %xmm0 movabsq $0x3fe6666666666666, %rdi # imm = 0x3FE6666666666666 movq %rdi, %xmm1 callq @@ -80,8 +79,7 @@ Disassembly of section .text: addq $0x40, %rsp popq %rbp retq - leaq 0x10(%rbx), %rax - movsd (%rax,%riz), %xmm0 + movsd 0x10(%rbx,%riz), %xmm0 movabsq $0x3ff0000000000000, %rdi # imm = 0x3FF0000000000000 movq %rdi, %xmm1 callq @@ -92,8 +90,7 @@ Disassembly of section .text: addq $0x40, %rsp popq %rbp retq - leaq 0x18(%rbx), %rax - movsd (%rax,%riz), %xmm0 + movsd 0x18(%rbx,%riz), %xmm0 movabsq $0x4000000000000000, %rax # imm = 0x4000000000000000 movq %rax, %xmm1 movabsq $-0x8000000000000000, %r10 # imm = 0x8000000000000000 diff --git a/tests/snapshots/asm/union_member_unbraced_init.aarch64.asm b/tests/snapshots/asm/union_member_unbraced_init.aarch64.asm index b41394ee6..24d4e7a16 100644 --- a/tests/snapshots/asm/union_member_unbraced_init.aarch64.asm +++ b/tests/snapshots/asm/union_member_unbraced_init.aarch64.asm @@ -112,8 +112,7 @@ Disassembly of section .text: ret adrp x0, add x0, x0, - add x0, x0, #0x18 - ldr d0, [x0] + ldr d0, [x0, #0x18] mov x0, #0x4010000000000000 // =4616189618054758400 fmov d17, x0 fcmp d0, d17 diff --git a/tests/snapshots/asm/union_member_unbraced_init.x64.asm b/tests/snapshots/asm/union_member_unbraced_init.x64.asm index dc52e1dac..af4978ecd 100644 --- a/tests/snapshots/asm/union_member_unbraced_init.x64.asm +++ b/tests/snapshots/asm/union_member_unbraced_init.x64.asm @@ -132,8 +132,7 @@ Disassembly of section .text: popq %rbp retq leaq , %rax - addq $0x18, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x18(%rax,%riz), %xmm0 movabsq $0x4010000000000000, %rax # imm = 0x4010000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -234,4 +233,3 @@ Disassembly of section .text: jmp jmp addb %al, (%rax) - addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/variadic_agg_return_classes.aarch64.asm b/tests/snapshots/asm/variadic_agg_return_classes.aarch64.asm index c4b18b346..576e0adb2 100644 --- a/tests/snapshots/asm/variadic_agg_return_classes.aarch64.asm +++ b/tests/snapshots/asm/variadic_agg_return_classes.aarch64.asm @@ -38,10 +38,9 @@ Disassembly of section .text: fmul d0, d16, d0 str d0, [x0] sub x0, x29, #0x10 - add x0, x0, #0x8 mov x1, #0x4002000000000000 // =4612248968380809216 fmov d16, x1 - str d16, [x0] + str d16, [x0, #0x8] sub x0, x29, #0x10 mov x16, x0 ldr d0, [x16] @@ -117,8 +116,7 @@ Disassembly of section .text: cset x20, ne cbnz x20, sub x0, x29, #0x10 - add x0, x0, #0x8 - ldr d0, [x0] + ldr d0, [x0, #0x8] mov x0, #0x4002000000000000 // =4612248968380809216 fmov d17, x0 fcmp d0, d17 diff --git a/tests/snapshots/asm/variadic_agg_return_classes.x64.asm b/tests/snapshots/asm/variadic_agg_return_classes.x64.asm index 9594d1014..29d7a6db8 100644 --- a/tests/snapshots/asm/variadic_agg_return_classes.x64.asm +++ b/tests/snapshots/asm/variadic_agg_return_classes.x64.asm @@ -39,10 +39,9 @@ Disassembly of section .text: mulsd %xmm15, %xmm0 movsd %xmm0, (%rax,%riz) leaq -0x10(%rbp), %rax - addq $0x8, %rax movabsq $0x4002000000000000, %rcx # imm = 0x4002000000000000 movq %rcx, %xmm14 - movsd %xmm14, (%rax,%riz) + movsd %xmm14, 0x8(%rax,%riz) leaq -0x10(%rbp), %rax movq %rax, %rcx movsd (%rcx,%riz), %xmm0 @@ -120,8 +119,7 @@ Disassembly of section .text: testq %rbx, %rbx jne leaq -0x10(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm0 + movsd 0x8(%rax,%riz), %xmm0 movabsq $0x4002000000000000, %rax # imm = 0x4002000000000000 movq %rax, %xmm15 ucomisd %xmm15, %xmm0 @@ -182,4 +180,3 @@ Disassembly of section .text: retq jmp jmp - addb %al, (%rax) diff --git a/tests/snapshots/asm/variadic_hfa_struct_arg.aarch64.asm b/tests/snapshots/asm/variadic_hfa_struct_arg.aarch64.asm index bd238b610..aa3007d4b 100644 --- a/tests/snapshots/asm/variadic_hfa_struct_arg.aarch64.asm +++ b/tests/snapshots/asm/variadic_hfa_struct_arg.aarch64.asm @@ -81,8 +81,7 @@ Disassembly of section .text: sub x0, x29, #0x30 ldr d0, [x0] sub x0, x29, #0x30 - add x0, x0, #0x8 - ldr d1, [x0] + ldr d1, [x0, #0x8] fadd d0, d0, d1 ldr x19, [sp] add sp, sp, #0x40 @@ -99,10 +98,9 @@ Disassembly of section .text: fmov d16, x1 str d16, [x0] sub x0, x29, #0x10 - add x0, x0, #0x8 mov x1, #0x4002000000000000 // =4612248968380809216 fmov d16, x1 - str d16, [x0] + str d16, [x0, #0x8] mov x0, #0x1 // =1 sub x1, x29, #0x10 ldr d0, [x1] diff --git a/tests/snapshots/asm/variadic_hfa_struct_arg.x64.asm b/tests/snapshots/asm/variadic_hfa_struct_arg.x64.asm index 2aa76bfde..c4ec0839c 100644 --- a/tests/snapshots/asm/variadic_hfa_struct_arg.x64.asm +++ b/tests/snapshots/asm/variadic_hfa_struct_arg.x64.asm @@ -61,8 +61,7 @@ Disassembly of section .text: leaq -0x28(%rbp), %rax movsd (%rax,%riz), %xmm0 leaq -0x28(%rbp), %rax - addq $0x8, %rax - movsd (%rax,%riz), %xmm1 + movsd 0x8(%rax,%riz), %xmm1 addsd %xmm1, %xmm0 addq $0xe0, %rsp popq %rbp @@ -77,10 +76,9 @@ Disassembly of section .text: movq %rcx, %xmm14 movsd %xmm14, (%rax,%riz) leaq -0x10(%rbp), %rax - addq $0x8, %rax movabsq $0x4002000000000000, %rcx # imm = 0x4002000000000000 movq %rcx, %xmm14 - movsd %xmm14, (%rax,%riz) + movsd %xmm14, 0x8(%rax,%riz) movl $0x1, %edi leaq -0x10(%rbp), %rsi movq %rsi, %r10 @@ -105,3 +103,4 @@ Disassembly of section .text: addq $0x30, %rsp popq %rbp retq + addb %al, (%rax) diff --git a/tests/snapshots/asm/void_function_produces_no_value.aarch64.asm b/tests/snapshots/asm/void_function_produces_no_value.aarch64.asm index dafa68e51..3949fcacb 100644 --- a/tests/snapshots/asm/void_function_produces_no_value.aarch64.asm +++ b/tests/snapshots/asm/void_function_produces_no_value.aarch64.asm @@ -37,9 +37,9 @@ Disassembly of section .text: add x0, x0, mov x1, #0x6 // =6 mov x2, #0x7 // =7 - mov x9, x0 str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] blr x9 @@ -63,8 +63,8 @@ Disassembly of section .text: movk x0, #0xffff, lsl #16 movk x0, #0xffff, lsl #32 movk x0, #0xffff, lsl #48 - mov x9, x20 str x0, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] blr x9 add sp, sp, #0x10 @@ -82,8 +82,8 @@ Disassembly of section .text: ldp x29, x30, [sp], #0x10 ret mov x0, #0x5 // =5 - mov x9, x20 str x0, [sp, #-0x10]! + mov x9, x20 ldr x0, [sp] blr x9 add sp, sp, #0x10 diff --git a/tests/snapshots/asm/vtable_back_to_back.aarch64.asm b/tests/snapshots/asm/vtable_back_to_back.aarch64.asm index 60ea6c321..4419dc45f 100644 --- a/tests/snapshots/asm/vtable_back_to_back.aarch64.asm +++ b/tests/snapshots/asm/vtable_back_to_back.aarch64.asm @@ -47,11 +47,11 @@ Disassembly of section .text: add x2, x2, mov x3, #0x2a // =42 mov x4, #0x8 // =8 - mov x9, x0 str x4, [sp, #-0x10]! str x3, [sp, #-0x10]! str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] @@ -64,10 +64,10 @@ Disassembly of section .text: sub x1, x29, #0x10 sub x2, x29, #0x40 mov x3, #0x1 // =1 - mov x9, x0 str x3, [sp, #-0x10]! str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] diff --git a/tests/snapshots/asm/vtable_back_to_back_4arg.aarch64.asm b/tests/snapshots/asm/vtable_back_to_back_4arg.aarch64.asm index 0399894c1..f155ae62f 100644 --- a/tests/snapshots/asm/vtable_back_to_back_4arg.aarch64.asm +++ b/tests/snapshots/asm/vtable_back_to_back_4arg.aarch64.asm @@ -49,11 +49,11 @@ Disassembly of section .text: add x2, x2, mov x20, #0x1 // =1 mov x3, #0x64 // =100 - mov x9, x0 str x3, [sp, #-0x10]! str x20, [sp, #-0x10]! str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] @@ -65,10 +65,10 @@ Disassembly of section .text: ldr x0, [x0, #0x8] sub x1, x29, #0x10 sub x2, x29, #0x40 - mov x9, x0 str x20, [sp, #-0x10]! str x2, [sp, #-0x10]! str x1, [sp, #-0x10]! + mov x9, x0 ldr x0, [sp] ldr x1, [sp, #0x10] ldr x2, [sp, #0x20] diff --git a/tests/snapshots/ssa/anonymous_aggregates.ssa b/tests/snapshots/ssa/anonymous_aggregates.ssa index 7c20bdd04..44e3b135b 100644 --- a/tests/snapshots/ssa/anonymous_aggregates.ssa +++ b/tests/snapshots/ssa/anonymous_aggregates.ssa @@ -123,9 +123,9 @@ fn ent_pc=1 n_params=0 variadic=false locals=11 terminator Return(v74) (exit_acc=v74) block 22 start_pc=0 v75 LocalAddr(-4) -> x0 - v76 BinopI { op=add, lhs=v75, rhs_imm=8 } -> x0 + v76 BinopI { op=add, lhs=v75, rhs_imm=8 } -> x1 v77 Imm(4614253070214989087) -> x1 - v78 Store { addr=v76, disp=0, value=v77, kind=F64 } -> - + v78 Store { addr=v75, disp=8, value=v77, kind=F64 } -> - v79 LocalAddr(-4) -> x0 v80 Load { addr=v79, disp=0, kind=I32 } -> x0 v81 BinopI { op=ne, lhs=v80, rhs_imm=1 } -> x0 diff --git a/tests/snapshots/ssa/array_2d_struct_init.ssa b/tests/snapshots/ssa/array_2d_struct_init.ssa index b735db69c..8633b6d5e 100644 --- a/tests/snapshots/ssa/array_2d_struct_init.ssa +++ b/tests/snapshots/ssa/array_2d_struct_init.ssa @@ -18,7 +18,7 @@ fn ent_pc=0 n_params=0 variadic=false locals=7 v10 Imm(16) -> x1 v11 BinopI { op=add, lhs=v1, rhs_imm=16 } -> x1 v12 BinopI { op=add, lhs=v1, rhs_imm=24 } -> x1 - v13 Load { addr=v12, disp=0, kind=F64 } -> d0 + v13 Load { addr=v1, disp=24, kind=F64 } -> d0 v14 Imm(4) -> x1 v15 FpCast { kind=IntToFp, value=v14 } -> d1 v16 Binop { op=fne, lhs=v13, rhs=v15 } -> x1 @@ -35,8 +35,8 @@ fn ent_pc=0 n_params=0 variadic=false locals=7 v23 ImmData(8) -> x1 v24 Imm(32) -> x1 v25 BinopI { op=add, lhs=v1, rhs_imm=32 } -> x1 - v26 Imm(0) -> x2 - v27 Load { addr=v25, disp=0, kind=F64 } -> d0 + v26 Imm(0) -> x1 + v27 Load { addr=v1, disp=32, kind=F64 } -> d0 v28 Imm(5) -> x1 v29 FpCast { kind=IntToFp, value=v28 } -> d1 v30 Binop { op=fne, lhs=v27, rhs=v29 } -> x1 @@ -54,8 +54,8 @@ fn ent_pc=0 n_params=0 variadic=false locals=7 v38 BinopI { op=add, lhs=v1, rhs_imm=32 } -> x1 v39 Imm(16) -> x1 v40 BinopI { op=add, lhs=v1, rhs_imm=48 } -> x1 - v41 BinopI { op=add, lhs=v1, rhs_imm=56 } -> x0 - v42 Load { addr=v41, disp=0, kind=F64 } -> d0 + v41 BinopI { op=add, lhs=v1, rhs_imm=56 } -> x1 + v42 Load { addr=v1, disp=56, kind=F64 } -> d0 v43 Imm(8) -> x0 v44 FpCast { kind=IntToFp, value=v43 } -> d1 v45 Binop { op=fne, lhs=v42, rhs=v44 } -> x2 @@ -85,8 +85,8 @@ fn ent_pc=0 n_params=0 variadic=false locals=7 v61 BinopI { op=add, lhs=v57, rhs_imm=96 } -> x1 v62 Imm(16) -> x1 v63 BinopI { op=add, lhs=v57, rhs_imm=112 } -> x1 - v64 BinopI { op=add, lhs=v57, rhs_imm=120 } -> x0 - v65 Load { addr=v64, disp=0, kind=F64 } -> d0 + v64 BinopI { op=add, lhs=v57, rhs_imm=120 } -> x1 + v65 Load { addr=v57, disp=120, kind=F64 } -> d0 v66 Imm(8) -> x0 v67 FpCast { kind=IntToFp, value=v66 } -> d1 v68 Binop { op=fne, lhs=v65, rhs=v67 } -> x0 @@ -104,8 +104,8 @@ fn ent_pc=0 n_params=0 variadic=false locals=7 v76 BinopI { op=add, lhs=v74, rhs_imm=64 } -> x1 v77 Imm(0) -> x1 v78 Imm(16) -> x1 - v79 BinopI { op=add, lhs=v74, rhs_imm=80 } -> x0 - v80 Load { addr=v79, disp=0, kind=F64 } -> d0 + v79 BinopI { op=add, lhs=v74, rhs_imm=80 } -> x1 + v80 Load { addr=v74, disp=80, kind=F64 } -> d0 v81 Imm(6) -> x0 v82 FpCast { kind=IntToFp, value=v81 } -> d1 v83 Binop { op=fne, lhs=v80, rhs=v82 } -> x2 @@ -134,8 +134,8 @@ fn ent_pc=0 n_params=0 variadic=false locals=7 v98 BinopI { op=add, lhs=v96, rhs_imm=32 } -> x1 v99 Imm(16) -> x1 v100 BinopI { op=add, lhs=v96, rhs_imm=48 } -> x2 - v101 BinopI { op=add, lhs=v96, rhs_imm=56 } -> x0 - v102 Load { addr=v101, disp=0, kind=F64 } -> d0 + v101 BinopI { op=add, lhs=v96, rhs_imm=56 } -> x2 + v102 Load { addr=v96, disp=56, kind=F64 } -> d0 v103 FpCast { kind=IntToFp, value=v99 } -> d1 v104 Binop { op=fne, lhs=v102, rhs=v103 } -> x0 v105 BinopI { op=ne, lhs=v104, rhs_imm=0 } -> x2 @@ -150,8 +150,8 @@ fn ent_pc=0 n_params=0 variadic=false locals=7 v110 ImmData(200) -> x0 v111 Imm(0) -> x1 v112 Imm(16) -> x1 - v113 BinopI { op=add, lhs=v110, rhs_imm=16 } -> x0 - v114 Load { addr=v113, disp=0, kind=F64 } -> d0 + v113 BinopI { op=add, lhs=v110, rhs_imm=16 } -> x1 + v114 Load { addr=v110, disp=16, kind=F64 } -> d0 v115 Imm(11) -> x0 v116 FpCast { kind=IntToFp, value=v115 } -> d1 v117 Binop { op=fne, lhs=v114, rhs=v116 } -> x2 diff --git a/tests/snapshots/ssa/call_sp_adjust_imm12_overflow.ssa b/tests/snapshots/ssa/call_sp_adjust_imm12_overflow.ssa new file mode 100644 index 000000000..f1e940f47 --- /dev/null +++ b/tests/snapshots/ssa/call_sp_adjust_imm12_overflow.ssa @@ -0,0 +1,4835 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=sum_pairs +fn ent_pc=0 n_params=261 variadic=false locals=523 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(0) -> x0 + v2 Imm(0) -> x1 + v3 LoadLocal { off=-523, kind=I64 } -> x1 + v4 LocalAddr(-2) -> x1 + v5 Load { addr=v4, disp=0, kind=I64 } -> x1 + v6 LocalAddr(-2) -> x2 + v7 BinopI { op=add, lhs=v6, rhs_imm=8 } -> x6 + v8 Load { addr=v6, disp=8, kind=I64 } -> x2 + v9 Binop { op=add, lhs=v5, rhs=v8 } -> x1 + v10 Binop { op=add, lhs=v1, rhs=v9 } -> x0 + v11 Imm(0) -> x1 + v12 LoadLocal { off=-523, kind=I64 } -> x1 + v13 LocalAddr(-4) -> x1 + v14 Load { addr=v13, disp=0, kind=I64 } -> x1 + v15 LocalAddr(-4) -> x2 + v16 BinopI { op=add, lhs=v15, rhs_imm=8 } -> x6 + v17 Load { addr=v15, disp=8, kind=I64 } -> x2 + v18 Binop { op=add, lhs=v14, rhs=v17 } -> x1 + v19 Binop { op=add, lhs=v10, rhs=v18 } -> x0 + v20 Imm(0) -> x1 + v21 LoadLocal { off=-523, kind=I64 } -> x1 + v22 LocalAddr(-6) -> x1 + v23 Load { addr=v22, disp=0, kind=I64 } -> x1 + v24 LocalAddr(-6) -> x2 + v25 BinopI { op=add, lhs=v24, rhs_imm=8 } -> x6 + v26 Load { addr=v24, disp=8, kind=I64 } -> x2 + v27 Binop { op=add, lhs=v23, rhs=v26 } -> x1 + v28 Binop { op=add, lhs=v19, rhs=v27 } -> x0 + v29 Imm(0) -> x1 + v30 LoadLocal { off=-523, kind=I64 } -> x1 + v31 LocalAddr(-8) -> x1 + v32 Load { addr=v31, disp=0, kind=I64 } -> x1 + v33 LocalAddr(-8) -> x2 + v34 BinopI { op=add, lhs=v33, rhs_imm=8 } -> x6 + v35 Load { addr=v33, disp=8, kind=I64 } -> x2 + v36 Binop { op=add, lhs=v32, rhs=v35 } -> x1 + v37 Binop { op=add, lhs=v28, rhs=v36 } -> x0 + v38 Imm(0) -> x1 + v39 LoadLocal { off=-523, kind=I64 } -> x1 + v40 LocalAddr(-10) -> x1 + v41 Load { addr=v40, disp=0, kind=I64 } -> x1 + v42 LocalAddr(-10) -> x2 + v43 BinopI { op=add, lhs=v42, rhs_imm=8 } -> x6 + v44 Load { addr=v42, disp=8, kind=I64 } -> x2 + v45 Binop { op=add, lhs=v41, rhs=v44 } -> x1 + v46 Binop { op=add, lhs=v37, rhs=v45 } -> x0 + v47 Imm(0) -> x1 + v48 LoadLocal { off=-523, kind=I64 } -> x1 + v49 LocalAddr(-12) -> x1 + v50 Load { addr=v49, disp=0, kind=I64 } -> x1 + v51 LocalAddr(-12) -> x2 + v52 BinopI { op=add, lhs=v51, rhs_imm=8 } -> x6 + v53 Load { addr=v51, disp=8, kind=I64 } -> x2 + v54 Binop { op=add, lhs=v50, rhs=v53 } -> x1 + v55 Binop { op=add, lhs=v46, rhs=v54 } -> x0 + v56 Imm(0) -> x1 + v57 LoadLocal { off=-523, kind=I64 } -> x1 + v58 LocalAddr(-14) -> x1 + v59 Load { addr=v58, disp=0, kind=I64 } -> x1 + v60 LocalAddr(-14) -> x2 + v61 BinopI { op=add, lhs=v60, rhs_imm=8 } -> x6 + v62 Load { addr=v60, disp=8, kind=I64 } -> x2 + v63 Binop { op=add, lhs=v59, rhs=v62 } -> x1 + v64 Binop { op=add, lhs=v55, rhs=v63 } -> x0 + v65 Imm(0) -> x1 + v66 LoadLocal { off=-523, kind=I64 } -> x1 + v67 LocalAddr(-16) -> x1 + v68 Load { addr=v67, disp=0, kind=I64 } -> x1 + v69 LocalAddr(-16) -> x2 + v70 BinopI { op=add, lhs=v69, rhs_imm=8 } -> x6 + v71 Load { addr=v69, disp=8, kind=I64 } -> x2 + v72 Binop { op=add, lhs=v68, rhs=v71 } -> x1 + v73 Binop { op=add, lhs=v64, rhs=v72 } -> x0 + v74 Imm(0) -> x1 + v75 LoadLocal { off=-523, kind=I64 } -> x1 + v76 LocalAddr(-18) -> x1 + v77 Load { addr=v76, disp=0, kind=I64 } -> x1 + v78 LocalAddr(-18) -> x2 + v79 BinopI { op=add, lhs=v78, rhs_imm=8 } -> x6 + v80 Load { addr=v78, disp=8, kind=I64 } -> x2 + v81 Binop { op=add, lhs=v77, rhs=v80 } -> x1 + v82 Binop { op=add, lhs=v73, rhs=v81 } -> x0 + v83 Imm(0) -> x1 + v84 LoadLocal { off=-523, kind=I64 } -> x1 + v85 LocalAddr(-20) -> x1 + v86 Load { addr=v85, disp=0, kind=I64 } -> x1 + v87 LocalAddr(-20) -> x2 + v88 BinopI { op=add, lhs=v87, rhs_imm=8 } -> x6 + v89 Load { addr=v87, disp=8, kind=I64 } -> x2 + v90 Binop { op=add, lhs=v86, rhs=v89 } -> x1 + v91 Binop { op=add, lhs=v82, rhs=v90 } -> x0 + v92 Imm(0) -> x1 + v93 LoadLocal { off=-523, kind=I64 } -> x1 + v94 LocalAddr(-22) -> x1 + v95 Load { addr=v94, disp=0, kind=I64 } -> x1 + v96 LocalAddr(-22) -> x2 + v97 BinopI { op=add, lhs=v96, rhs_imm=8 } -> x6 + v98 Load { addr=v96, disp=8, kind=I64 } -> x2 + v99 Binop { op=add, lhs=v95, rhs=v98 } -> x1 + v100 Binop { op=add, lhs=v91, rhs=v99 } -> x0 + v101 Imm(0) -> x1 + v102 LoadLocal { off=-523, kind=I64 } -> x1 + v103 LocalAddr(-24) -> x1 + v104 Load { addr=v103, disp=0, kind=I64 } -> x1 + v105 LocalAddr(-24) -> x2 + v106 BinopI { op=add, lhs=v105, rhs_imm=8 } -> x6 + v107 Load { addr=v105, disp=8, kind=I64 } -> x2 + v108 Binop { op=add, lhs=v104, rhs=v107 } -> x1 + v109 Binop { op=add, lhs=v100, rhs=v108 } -> x0 + v110 Imm(0) -> x1 + v111 LoadLocal { off=-523, kind=I64 } -> x1 + v112 LocalAddr(-26) -> x1 + v113 Load { addr=v112, disp=0, kind=I64 } -> x1 + v114 LocalAddr(-26) -> x2 + v115 BinopI { op=add, lhs=v114, rhs_imm=8 } -> x6 + v116 Load { addr=v114, disp=8, kind=I64 } -> x2 + v117 Binop { op=add, lhs=v113, rhs=v116 } -> x1 + v118 Binop { op=add, lhs=v109, rhs=v117 } -> x0 + v119 Imm(0) -> x1 + v120 LoadLocal { off=-523, kind=I64 } -> x1 + v121 LocalAddr(-28) -> x1 + v122 Load { addr=v121, disp=0, kind=I64 } -> x1 + v123 LocalAddr(-28) -> x2 + v124 BinopI { op=add, lhs=v123, rhs_imm=8 } -> x6 + v125 Load { addr=v123, disp=8, kind=I64 } -> x2 + v126 Binop { op=add, lhs=v122, rhs=v125 } -> x1 + v127 Binop { op=add, lhs=v118, rhs=v126 } -> x0 + v128 Imm(0) -> x1 + v129 LoadLocal { off=-523, kind=I64 } -> x1 + v130 LocalAddr(-30) -> x1 + v131 Load { addr=v130, disp=0, kind=I64 } -> x1 + v132 LocalAddr(-30) -> x2 + v133 BinopI { op=add, lhs=v132, rhs_imm=8 } -> x6 + v134 Load { addr=v132, disp=8, kind=I64 } -> x2 + v135 Binop { op=add, lhs=v131, rhs=v134 } -> x1 + v136 Binop { op=add, lhs=v127, rhs=v135 } -> x0 + v137 Imm(0) -> x1 + v138 LoadLocal { off=-523, kind=I64 } -> x1 + v139 LocalAddr(-32) -> x1 + v140 Load { addr=v139, disp=0, kind=I64 } -> x1 + v141 LocalAddr(-32) -> x2 + v142 BinopI { op=add, lhs=v141, rhs_imm=8 } -> x6 + v143 Load { addr=v141, disp=8, kind=I64 } -> x2 + v144 Binop { op=add, lhs=v140, rhs=v143 } -> x1 + v145 Binop { op=add, lhs=v136, rhs=v144 } -> x0 + v146 Imm(0) -> x1 + v147 LoadLocal { off=-523, kind=I64 } -> x1 + v148 LocalAddr(-34) -> x1 + v149 Load { addr=v148, disp=0, kind=I64 } -> x1 + v150 LocalAddr(-34) -> x2 + v151 BinopI { op=add, lhs=v150, rhs_imm=8 } -> x6 + v152 Load { addr=v150, disp=8, kind=I64 } -> x2 + v153 Binop { op=add, lhs=v149, rhs=v152 } -> x1 + v154 Binop { op=add, lhs=v145, rhs=v153 } -> x0 + v155 Imm(0) -> x1 + v156 LoadLocal { off=-523, kind=I64 } -> x1 + v157 LocalAddr(-36) -> x1 + v158 Load { addr=v157, disp=0, kind=I64 } -> x1 + v159 LocalAddr(-36) -> x2 + v160 BinopI { op=add, lhs=v159, rhs_imm=8 } -> x6 + v161 Load { addr=v159, disp=8, kind=I64 } -> x2 + v162 Binop { op=add, lhs=v158, rhs=v161 } -> x1 + v163 Binop { op=add, lhs=v154, rhs=v162 } -> x0 + v164 Imm(0) -> x1 + v165 LoadLocal { off=-523, kind=I64 } -> x1 + v166 LocalAddr(-38) -> x1 + v167 Load { addr=v166, disp=0, kind=I64 } -> x1 + v168 LocalAddr(-38) -> x2 + v169 BinopI { op=add, lhs=v168, rhs_imm=8 } -> x6 + v170 Load { addr=v168, disp=8, kind=I64 } -> x2 + v171 Binop { op=add, lhs=v167, rhs=v170 } -> x1 + v172 Binop { op=add, lhs=v163, rhs=v171 } -> x0 + v173 Imm(0) -> x1 + v174 LoadLocal { off=-523, kind=I64 } -> x1 + v175 LocalAddr(-40) -> x1 + v176 Load { addr=v175, disp=0, kind=I64 } -> x1 + v177 LocalAddr(-40) -> x2 + v178 BinopI { op=add, lhs=v177, rhs_imm=8 } -> x6 + v179 Load { addr=v177, disp=8, kind=I64 } -> x2 + v180 Binop { op=add, lhs=v176, rhs=v179 } -> x1 + v181 Binop { op=add, lhs=v172, rhs=v180 } -> x0 + v182 Imm(0) -> x1 + v183 LoadLocal { off=-523, kind=I64 } -> x1 + v184 LocalAddr(-42) -> x1 + v185 Load { addr=v184, disp=0, kind=I64 } -> x1 + v186 LocalAddr(-42) -> x2 + v187 BinopI { op=add, lhs=v186, rhs_imm=8 } -> x6 + v188 Load { addr=v186, disp=8, kind=I64 } -> x2 + v189 Binop { op=add, lhs=v185, rhs=v188 } -> x1 + v190 Binop { op=add, lhs=v181, rhs=v189 } -> x0 + v191 Imm(0) -> x1 + v192 LoadLocal { off=-523, kind=I64 } -> x1 + v193 LocalAddr(-44) -> x1 + v194 Load { addr=v193, disp=0, kind=I64 } -> x1 + v195 LocalAddr(-44) -> x2 + v196 BinopI { op=add, lhs=v195, rhs_imm=8 } -> x6 + v197 Load { addr=v195, disp=8, kind=I64 } -> x2 + v198 Binop { op=add, lhs=v194, rhs=v197 } -> x1 + v199 Binop { op=add, lhs=v190, rhs=v198 } -> x0 + v200 Imm(0) -> x1 + v201 LoadLocal { off=-523, kind=I64 } -> x1 + v202 LocalAddr(-46) -> x1 + v203 Load { addr=v202, disp=0, kind=I64 } -> x1 + v204 LocalAddr(-46) -> x2 + v205 BinopI { op=add, lhs=v204, rhs_imm=8 } -> x6 + v206 Load { addr=v204, disp=8, kind=I64 } -> x2 + v207 Binop { op=add, lhs=v203, rhs=v206 } -> x1 + v208 Binop { op=add, lhs=v199, rhs=v207 } -> x0 + v209 Imm(0) -> x1 + v210 LoadLocal { off=-523, kind=I64 } -> x1 + v211 LocalAddr(-48) -> x1 + v212 Load { addr=v211, disp=0, kind=I64 } -> x1 + v213 LocalAddr(-48) -> x2 + v214 BinopI { op=add, lhs=v213, rhs_imm=8 } -> x6 + v215 Load { addr=v213, disp=8, kind=I64 } -> x2 + v216 Binop { op=add, lhs=v212, rhs=v215 } -> x1 + v217 Binop { op=add, lhs=v208, rhs=v216 } -> x0 + v218 Imm(0) -> x1 + v219 LoadLocal { off=-523, kind=I64 } -> x1 + v220 LocalAddr(-50) -> x1 + v221 Load { addr=v220, disp=0, kind=I64 } -> x1 + v222 LocalAddr(-50) -> x2 + v223 BinopI { op=add, lhs=v222, rhs_imm=8 } -> x6 + v224 Load { addr=v222, disp=8, kind=I64 } -> x2 + v225 Binop { op=add, lhs=v221, rhs=v224 } -> x1 + v226 Binop { op=add, lhs=v217, rhs=v225 } -> x0 + v227 Imm(0) -> x1 + v228 LoadLocal { off=-523, kind=I64 } -> x1 + v229 LocalAddr(-52) -> x1 + v230 Load { addr=v229, disp=0, kind=I64 } -> x1 + v231 LocalAddr(-52) -> x2 + v232 BinopI { op=add, lhs=v231, rhs_imm=8 } -> x6 + v233 Load { addr=v231, disp=8, kind=I64 } -> x2 + v234 Binop { op=add, lhs=v230, rhs=v233 } -> x1 + v235 Binop { op=add, lhs=v226, rhs=v234 } -> x0 + v236 Imm(0) -> x1 + v237 LoadLocal { off=-523, kind=I64 } -> x1 + v238 LocalAddr(-54) -> x1 + v239 Load { addr=v238, disp=0, kind=I64 } -> x1 + v240 LocalAddr(-54) -> x2 + v241 BinopI { op=add, lhs=v240, rhs_imm=8 } -> x6 + v242 Load { addr=v240, disp=8, kind=I64 } -> x2 + v243 Binop { op=add, lhs=v239, rhs=v242 } -> x1 + v244 Binop { op=add, lhs=v235, rhs=v243 } -> x0 + v245 Imm(0) -> x1 + v246 LoadLocal { off=-523, kind=I64 } -> x1 + v247 LocalAddr(-56) -> x1 + v248 Load { addr=v247, disp=0, kind=I64 } -> x1 + v249 LocalAddr(-56) -> x2 + v250 BinopI { op=add, lhs=v249, rhs_imm=8 } -> x6 + v251 Load { addr=v249, disp=8, kind=I64 } -> x2 + v252 Binop { op=add, lhs=v248, rhs=v251 } -> x1 + v253 Binop { op=add, lhs=v244, rhs=v252 } -> x0 + v254 Imm(0) -> x1 + v255 LoadLocal { off=-523, kind=I64 } -> x1 + v256 LocalAddr(-58) -> x1 + v257 Load { addr=v256, disp=0, kind=I64 } -> x1 + v258 LocalAddr(-58) -> x2 + v259 BinopI { op=add, lhs=v258, rhs_imm=8 } -> x6 + v260 Load { addr=v258, disp=8, kind=I64 } -> x2 + v261 Binop { op=add, lhs=v257, rhs=v260 } -> x1 + v262 Binop { op=add, lhs=v253, rhs=v261 } -> x0 + v263 Imm(0) -> x1 + v264 LoadLocal { off=-523, kind=I64 } -> x1 + v265 LocalAddr(-60) -> x1 + v266 Load { addr=v265, disp=0, kind=I64 } -> x1 + v267 LocalAddr(-60) -> x2 + v268 BinopI { op=add, lhs=v267, rhs_imm=8 } -> x6 + v269 Load { addr=v267, disp=8, kind=I64 } -> x2 + v270 Binop { op=add, lhs=v266, rhs=v269 } -> x1 + v271 Binop { op=add, lhs=v262, rhs=v270 } -> x0 + v272 Imm(0) -> x1 + v273 LoadLocal { off=-523, kind=I64 } -> x1 + v274 LocalAddr(-62) -> x1 + v275 Load { addr=v274, disp=0, kind=I64 } -> x1 + v276 LocalAddr(-62) -> x2 + v277 BinopI { op=add, lhs=v276, rhs_imm=8 } -> x6 + v278 Load { addr=v276, disp=8, kind=I64 } -> x2 + v279 Binop { op=add, lhs=v275, rhs=v278 } -> x1 + v280 Binop { op=add, lhs=v271, rhs=v279 } -> x0 + v281 Imm(0) -> x1 + v282 LoadLocal { off=-523, kind=I64 } -> x1 + v283 LocalAddr(-64) -> x1 + v284 Load { addr=v283, disp=0, kind=I64 } -> x1 + v285 LocalAddr(-64) -> x2 + v286 BinopI { op=add, lhs=v285, rhs_imm=8 } -> x6 + v287 Load { addr=v285, disp=8, kind=I64 } -> x2 + v288 Binop { op=add, lhs=v284, rhs=v287 } -> x1 + v289 Binop { op=add, lhs=v280, rhs=v288 } -> x0 + v290 Imm(0) -> x1 + v291 LoadLocal { off=-523, kind=I64 } -> x1 + v292 LocalAddr(-66) -> x1 + v293 Load { addr=v292, disp=0, kind=I64 } -> x1 + v294 LocalAddr(-66) -> x2 + v295 BinopI { op=add, lhs=v294, rhs_imm=8 } -> x6 + v296 Load { addr=v294, disp=8, kind=I64 } -> x2 + v297 Binop { op=add, lhs=v293, rhs=v296 } -> x1 + v298 Binop { op=add, lhs=v289, rhs=v297 } -> x0 + v299 Imm(0) -> x1 + v300 LoadLocal { off=-523, kind=I64 } -> x1 + v301 LocalAddr(-68) -> x1 + v302 Load { addr=v301, disp=0, kind=I64 } -> x1 + v303 LocalAddr(-68) -> x2 + v304 BinopI { op=add, lhs=v303, rhs_imm=8 } -> x6 + v305 Load { addr=v303, disp=8, kind=I64 } -> x2 + v306 Binop { op=add, lhs=v302, rhs=v305 } -> x1 + v307 Binop { op=add, lhs=v298, rhs=v306 } -> x0 + v308 Imm(0) -> x1 + v309 LoadLocal { off=-523, kind=I64 } -> x1 + v310 LocalAddr(-70) -> x1 + v311 Load { addr=v310, disp=0, kind=I64 } -> x1 + v312 LocalAddr(-70) -> x2 + v313 BinopI { op=add, lhs=v312, rhs_imm=8 } -> x6 + v314 Load { addr=v312, disp=8, kind=I64 } -> x2 + v315 Binop { op=add, lhs=v311, rhs=v314 } -> x1 + v316 Binop { op=add, lhs=v307, rhs=v315 } -> x0 + v317 Imm(0) -> x1 + v318 LoadLocal { off=-523, kind=I64 } -> x1 + v319 LocalAddr(-72) -> x1 + v320 Load { addr=v319, disp=0, kind=I64 } -> x1 + v321 LocalAddr(-72) -> x2 + v322 BinopI { op=add, lhs=v321, rhs_imm=8 } -> x6 + v323 Load { addr=v321, disp=8, kind=I64 } -> x2 + v324 Binop { op=add, lhs=v320, rhs=v323 } -> x1 + v325 Binop { op=add, lhs=v316, rhs=v324 } -> x0 + v326 Imm(0) -> x1 + v327 LoadLocal { off=-523, kind=I64 } -> x1 + v328 LocalAddr(-74) -> x1 + v329 Load { addr=v328, disp=0, kind=I64 } -> x1 + v330 LocalAddr(-74) -> x2 + v331 BinopI { op=add, lhs=v330, rhs_imm=8 } -> x6 + v332 Load { addr=v330, disp=8, kind=I64 } -> x2 + v333 Binop { op=add, lhs=v329, rhs=v332 } -> x1 + v334 Binop { op=add, lhs=v325, rhs=v333 } -> x0 + v335 Imm(0) -> x1 + v336 LoadLocal { off=-523, kind=I64 } -> x1 + v337 LocalAddr(-76) -> x1 + v338 Load { addr=v337, disp=0, kind=I64 } -> x1 + v339 LocalAddr(-76) -> x2 + v340 BinopI { op=add, lhs=v339, rhs_imm=8 } -> x6 + v341 Load { addr=v339, disp=8, kind=I64 } -> x2 + v342 Binop { op=add, lhs=v338, rhs=v341 } -> x1 + v343 Binop { op=add, lhs=v334, rhs=v342 } -> x0 + v344 Imm(0) -> x1 + v345 LoadLocal { off=-523, kind=I64 } -> x1 + v346 LocalAddr(-78) -> x1 + v347 Load { addr=v346, disp=0, kind=I64 } -> x1 + v348 LocalAddr(-78) -> x2 + v349 BinopI { op=add, lhs=v348, rhs_imm=8 } -> x6 + v350 Load { addr=v348, disp=8, kind=I64 } -> x2 + v351 Binop { op=add, lhs=v347, rhs=v350 } -> x1 + v352 Binop { op=add, lhs=v343, rhs=v351 } -> x0 + v353 Imm(0) -> x1 + v354 LoadLocal { off=-523, kind=I64 } -> x1 + v355 LocalAddr(-80) -> x1 + v356 Load { addr=v355, disp=0, kind=I64 } -> x1 + v357 LocalAddr(-80) -> x2 + v358 BinopI { op=add, lhs=v357, rhs_imm=8 } -> x6 + v359 Load { addr=v357, disp=8, kind=I64 } -> x2 + v360 Binop { op=add, lhs=v356, rhs=v359 } -> x1 + v361 Binop { op=add, lhs=v352, rhs=v360 } -> x0 + v362 Imm(0) -> x1 + v363 LoadLocal { off=-523, kind=I64 } -> x1 + v364 LocalAddr(-82) -> x1 + v365 Load { addr=v364, disp=0, kind=I64 } -> x1 + v366 LocalAddr(-82) -> x2 + v367 BinopI { op=add, lhs=v366, rhs_imm=8 } -> x6 + v368 Load { addr=v366, disp=8, kind=I64 } -> x2 + v369 Binop { op=add, lhs=v365, rhs=v368 } -> x1 + v370 Binop { op=add, lhs=v361, rhs=v369 } -> x0 + v371 Imm(0) -> x1 + v372 LoadLocal { off=-523, kind=I64 } -> x1 + v373 LocalAddr(-84) -> x1 + v374 Load { addr=v373, disp=0, kind=I64 } -> x1 + v375 LocalAddr(-84) -> x2 + v376 BinopI { op=add, lhs=v375, rhs_imm=8 } -> x6 + v377 Load { addr=v375, disp=8, kind=I64 } -> x2 + v378 Binop { op=add, lhs=v374, rhs=v377 } -> x1 + v379 Binop { op=add, lhs=v370, rhs=v378 } -> x0 + v380 Imm(0) -> x1 + v381 LoadLocal { off=-523, kind=I64 } -> x1 + v382 LocalAddr(-86) -> x1 + v383 Load { addr=v382, disp=0, kind=I64 } -> x1 + v384 LocalAddr(-86) -> x2 + v385 BinopI { op=add, lhs=v384, rhs_imm=8 } -> x6 + v386 Load { addr=v384, disp=8, kind=I64 } -> x2 + v387 Binop { op=add, lhs=v383, rhs=v386 } -> x1 + v388 Binop { op=add, lhs=v379, rhs=v387 } -> x0 + v389 Imm(0) -> x1 + v390 LoadLocal { off=-523, kind=I64 } -> x1 + v391 LocalAddr(-88) -> x1 + v392 Load { addr=v391, disp=0, kind=I64 } -> x1 + v393 LocalAddr(-88) -> x2 + v394 BinopI { op=add, lhs=v393, rhs_imm=8 } -> x6 + v395 Load { addr=v393, disp=8, kind=I64 } -> x2 + v396 Binop { op=add, lhs=v392, rhs=v395 } -> x1 + v397 Binop { op=add, lhs=v388, rhs=v396 } -> x0 + v398 Imm(0) -> x1 + v399 LoadLocal { off=-523, kind=I64 } -> x1 + v400 LocalAddr(-90) -> x1 + v401 Load { addr=v400, disp=0, kind=I64 } -> x1 + v402 LocalAddr(-90) -> x2 + v403 BinopI { op=add, lhs=v402, rhs_imm=8 } -> x6 + v404 Load { addr=v402, disp=8, kind=I64 } -> x2 + v405 Binop { op=add, lhs=v401, rhs=v404 } -> x1 + v406 Binop { op=add, lhs=v397, rhs=v405 } -> x0 + v407 Imm(0) -> x1 + v408 LoadLocal { off=-523, kind=I64 } -> x1 + v409 LocalAddr(-92) -> x1 + v410 Load { addr=v409, disp=0, kind=I64 } -> x1 + v411 LocalAddr(-92) -> x2 + v412 BinopI { op=add, lhs=v411, rhs_imm=8 } -> x6 + v413 Load { addr=v411, disp=8, kind=I64 } -> x2 + v414 Binop { op=add, lhs=v410, rhs=v413 } -> x1 + v415 Binop { op=add, lhs=v406, rhs=v414 } -> x0 + v416 Imm(0) -> x1 + v417 LoadLocal { off=-523, kind=I64 } -> x1 + v418 LocalAddr(-94) -> x1 + v419 Load { addr=v418, disp=0, kind=I64 } -> x1 + v420 LocalAddr(-94) -> x2 + v421 BinopI { op=add, lhs=v420, rhs_imm=8 } -> x6 + v422 Load { addr=v420, disp=8, kind=I64 } -> x2 + v423 Binop { op=add, lhs=v419, rhs=v422 } -> x1 + v424 Binop { op=add, lhs=v415, rhs=v423 } -> x0 + v425 Imm(0) -> x1 + v426 LoadLocal { off=-523, kind=I64 } -> x1 + v427 LocalAddr(-96) -> x1 + v428 Load { addr=v427, disp=0, kind=I64 } -> x1 + v429 LocalAddr(-96) -> x2 + v430 BinopI { op=add, lhs=v429, rhs_imm=8 } -> x6 + v431 Load { addr=v429, disp=8, kind=I64 } -> x2 + v432 Binop { op=add, lhs=v428, rhs=v431 } -> x1 + v433 Binop { op=add, lhs=v424, rhs=v432 } -> x0 + v434 Imm(0) -> x1 + v435 LoadLocal { off=-523, kind=I64 } -> x1 + v436 LocalAddr(-98) -> x1 + v437 Load { addr=v436, disp=0, kind=I64 } -> x1 + v438 LocalAddr(-98) -> x2 + v439 BinopI { op=add, lhs=v438, rhs_imm=8 } -> x6 + v440 Load { addr=v438, disp=8, kind=I64 } -> x2 + v441 Binop { op=add, lhs=v437, rhs=v440 } -> x1 + v442 Binop { op=add, lhs=v433, rhs=v441 } -> x0 + v443 Imm(0) -> x1 + v444 LoadLocal { off=-523, kind=I64 } -> x1 + v445 LocalAddr(-100) -> x1 + v446 Load { addr=v445, disp=0, kind=I64 } -> x1 + v447 LocalAddr(-100) -> x2 + v448 BinopI { op=add, lhs=v447, rhs_imm=8 } -> x6 + v449 Load { addr=v447, disp=8, kind=I64 } -> x2 + v450 Binop { op=add, lhs=v446, rhs=v449 } -> x1 + v451 Binop { op=add, lhs=v442, rhs=v450 } -> x0 + v452 Imm(0) -> x1 + v453 LoadLocal { off=-523, kind=I64 } -> x1 + v454 LocalAddr(-102) -> x1 + v455 Load { addr=v454, disp=0, kind=I64 } -> x1 + v456 LocalAddr(-102) -> x2 + v457 BinopI { op=add, lhs=v456, rhs_imm=8 } -> x6 + v458 Load { addr=v456, disp=8, kind=I64 } -> x2 + v459 Binop { op=add, lhs=v455, rhs=v458 } -> x1 + v460 Binop { op=add, lhs=v451, rhs=v459 } -> x0 + v461 Imm(0) -> x1 + v462 LoadLocal { off=-523, kind=I64 } -> x1 + v463 LocalAddr(-104) -> x1 + v464 Load { addr=v463, disp=0, kind=I64 } -> x1 + v465 LocalAddr(-104) -> x2 + v466 BinopI { op=add, lhs=v465, rhs_imm=8 } -> x6 + v467 Load { addr=v465, disp=8, kind=I64 } -> x2 + v468 Binop { op=add, lhs=v464, rhs=v467 } -> x1 + v469 Binop { op=add, lhs=v460, rhs=v468 } -> x0 + v470 Imm(0) -> x1 + v471 LoadLocal { off=-523, kind=I64 } -> x1 + v472 LocalAddr(-106) -> x1 + v473 Load { addr=v472, disp=0, kind=I64 } -> x1 + v474 LocalAddr(-106) -> x2 + v475 BinopI { op=add, lhs=v474, rhs_imm=8 } -> x6 + v476 Load { addr=v474, disp=8, kind=I64 } -> x2 + v477 Binop { op=add, lhs=v473, rhs=v476 } -> x1 + v478 Binop { op=add, lhs=v469, rhs=v477 } -> x0 + v479 Imm(0) -> x1 + v480 LoadLocal { off=-523, kind=I64 } -> x1 + v481 LocalAddr(-108) -> x1 + v482 Load { addr=v481, disp=0, kind=I64 } -> x1 + v483 LocalAddr(-108) -> x2 + v484 BinopI { op=add, lhs=v483, rhs_imm=8 } -> x6 + v485 Load { addr=v483, disp=8, kind=I64 } -> x2 + v486 Binop { op=add, lhs=v482, rhs=v485 } -> x1 + v487 Binop { op=add, lhs=v478, rhs=v486 } -> x0 + v488 Imm(0) -> x1 + v489 LoadLocal { off=-523, kind=I64 } -> x1 + v490 LocalAddr(-110) -> x1 + v491 Load { addr=v490, disp=0, kind=I64 } -> x1 + v492 LocalAddr(-110) -> x2 + v493 BinopI { op=add, lhs=v492, rhs_imm=8 } -> x6 + v494 Load { addr=v492, disp=8, kind=I64 } -> x2 + v495 Binop { op=add, lhs=v491, rhs=v494 } -> x1 + v496 Binop { op=add, lhs=v487, rhs=v495 } -> x0 + v497 Imm(0) -> x1 + v498 LoadLocal { off=-523, kind=I64 } -> x1 + v499 LocalAddr(-112) -> x1 + v500 Load { addr=v499, disp=0, kind=I64 } -> x1 + v501 LocalAddr(-112) -> x2 + v502 BinopI { op=add, lhs=v501, rhs_imm=8 } -> x6 + v503 Load { addr=v501, disp=8, kind=I64 } -> x2 + v504 Binop { op=add, lhs=v500, rhs=v503 } -> x1 + v505 Binop { op=add, lhs=v496, rhs=v504 } -> x0 + v506 Imm(0) -> x1 + v507 LoadLocal { off=-523, kind=I64 } -> x1 + v508 LocalAddr(-114) -> x1 + v509 Load { addr=v508, disp=0, kind=I64 } -> x1 + v510 LocalAddr(-114) -> x2 + v511 BinopI { op=add, lhs=v510, rhs_imm=8 } -> x6 + v512 Load { addr=v510, disp=8, kind=I64 } -> x2 + v513 Binop { op=add, lhs=v509, rhs=v512 } -> x1 + v514 Binop { op=add, lhs=v505, rhs=v513 } -> x0 + v515 Imm(0) -> x1 + v516 LoadLocal { off=-523, kind=I64 } -> x1 + v517 LocalAddr(-116) -> x1 + v518 Load { addr=v517, disp=0, kind=I64 } -> x1 + v519 LocalAddr(-116) -> x2 + v520 BinopI { op=add, lhs=v519, rhs_imm=8 } -> x6 + v521 Load { addr=v519, disp=8, kind=I64 } -> x2 + v522 Binop { op=add, lhs=v518, rhs=v521 } -> x1 + v523 Binop { op=add, lhs=v514, rhs=v522 } -> x0 + v524 Imm(0) -> x1 + v525 LoadLocal { off=-523, kind=I64 } -> x1 + v526 LocalAddr(-118) -> x1 + v527 Load { addr=v526, disp=0, kind=I64 } -> x1 + v528 LocalAddr(-118) -> x2 + v529 BinopI { op=add, lhs=v528, rhs_imm=8 } -> x6 + v530 Load { addr=v528, disp=8, kind=I64 } -> x2 + v531 Binop { op=add, lhs=v527, rhs=v530 } -> x1 + v532 Binop { op=add, lhs=v523, rhs=v531 } -> x0 + v533 Imm(0) -> x1 + v534 LoadLocal { off=-523, kind=I64 } -> x1 + v535 LocalAddr(-120) -> x1 + v536 Load { addr=v535, disp=0, kind=I64 } -> x1 + v537 LocalAddr(-120) -> x2 + v538 BinopI { op=add, lhs=v537, rhs_imm=8 } -> x6 + v539 Load { addr=v537, disp=8, kind=I64 } -> x2 + v540 Binop { op=add, lhs=v536, rhs=v539 } -> x1 + v541 Binop { op=add, lhs=v532, rhs=v540 } -> x0 + v542 Imm(0) -> x1 + v543 LoadLocal { off=-523, kind=I64 } -> x1 + v544 LocalAddr(-122) -> x1 + v545 Load { addr=v544, disp=0, kind=I64 } -> x1 + v546 LocalAddr(-122) -> x2 + v547 BinopI { op=add, lhs=v546, rhs_imm=8 } -> x6 + v548 Load { addr=v546, disp=8, kind=I64 } -> x2 + v549 Binop { op=add, lhs=v545, rhs=v548 } -> x1 + v550 Binop { op=add, lhs=v541, rhs=v549 } -> x0 + v551 Imm(0) -> x1 + v552 LoadLocal { off=-523, kind=I64 } -> x1 + v553 LocalAddr(-124) -> x1 + v554 Load { addr=v553, disp=0, kind=I64 } -> x1 + v555 LocalAddr(-124) -> x2 + v556 BinopI { op=add, lhs=v555, rhs_imm=8 } -> x6 + v557 Load { addr=v555, disp=8, kind=I64 } -> x2 + v558 Binop { op=add, lhs=v554, rhs=v557 } -> x1 + v559 Binop { op=add, lhs=v550, rhs=v558 } -> x0 + v560 Imm(0) -> x1 + v561 LoadLocal { off=-523, kind=I64 } -> x1 + v562 LocalAddr(-126) -> x1 + v563 Load { addr=v562, disp=0, kind=I64 } -> x1 + v564 LocalAddr(-126) -> x2 + v565 BinopI { op=add, lhs=v564, rhs_imm=8 } -> x6 + v566 Load { addr=v564, disp=8, kind=I64 } -> x2 + v567 Binop { op=add, lhs=v563, rhs=v566 } -> x1 + v568 Binop { op=add, lhs=v559, rhs=v567 } -> x0 + v569 Imm(0) -> x1 + v570 LoadLocal { off=-523, kind=I64 } -> x1 + v571 LocalAddr(-128) -> x1 + v572 Load { addr=v571, disp=0, kind=I64 } -> x1 + v573 LocalAddr(-128) -> x2 + v574 BinopI { op=add, lhs=v573, rhs_imm=8 } -> x6 + v575 Load { addr=v573, disp=8, kind=I64 } -> x2 + v576 Binop { op=add, lhs=v572, rhs=v575 } -> x1 + v577 Binop { op=add, lhs=v568, rhs=v576 } -> x0 + v578 Imm(0) -> x1 + v579 LoadLocal { off=-523, kind=I64 } -> x1 + v580 LocalAddr(-130) -> x1 + v581 Load { addr=v580, disp=0, kind=I64 } -> x1 + v582 LocalAddr(-130) -> x2 + v583 BinopI { op=add, lhs=v582, rhs_imm=8 } -> x6 + v584 Load { addr=v582, disp=8, kind=I64 } -> x2 + v585 Binop { op=add, lhs=v581, rhs=v584 } -> x1 + v586 Binop { op=add, lhs=v577, rhs=v585 } -> x0 + v587 Imm(0) -> x1 + v588 LoadLocal { off=-523, kind=I64 } -> x1 + v589 LocalAddr(-132) -> x1 + v590 Load { addr=v589, disp=0, kind=I64 } -> x1 + v591 LocalAddr(-132) -> x2 + v592 BinopI { op=add, lhs=v591, rhs_imm=8 } -> x6 + v593 Load { addr=v591, disp=8, kind=I64 } -> x2 + v594 Binop { op=add, lhs=v590, rhs=v593 } -> x1 + v595 Binop { op=add, lhs=v586, rhs=v594 } -> x0 + v596 Imm(0) -> x1 + v597 LoadLocal { off=-523, kind=I64 } -> x1 + v598 LocalAddr(-134) -> x1 + v599 Load { addr=v598, disp=0, kind=I64 } -> x1 + v600 LocalAddr(-134) -> x2 + v601 BinopI { op=add, lhs=v600, rhs_imm=8 } -> x6 + v602 Load { addr=v600, disp=8, kind=I64 } -> x2 + v603 Binop { op=add, lhs=v599, rhs=v602 } -> x1 + v604 Binop { op=add, lhs=v595, rhs=v603 } -> x0 + v605 Imm(0) -> x1 + v606 LoadLocal { off=-523, kind=I64 } -> x1 + v607 LocalAddr(-136) -> x1 + v608 Load { addr=v607, disp=0, kind=I64 } -> x1 + v609 LocalAddr(-136) -> x2 + v610 BinopI { op=add, lhs=v609, rhs_imm=8 } -> x6 + v611 Load { addr=v609, disp=8, kind=I64 } -> x2 + v612 Binop { op=add, lhs=v608, rhs=v611 } -> x1 + v613 Binop { op=add, lhs=v604, rhs=v612 } -> x0 + v614 Imm(0) -> x1 + v615 LoadLocal { off=-523, kind=I64 } -> x1 + v616 LocalAddr(-138) -> x1 + v617 Load { addr=v616, disp=0, kind=I64 } -> x1 + v618 LocalAddr(-138) -> x2 + v619 BinopI { op=add, lhs=v618, rhs_imm=8 } -> x6 + v620 Load { addr=v618, disp=8, kind=I64 } -> x2 + v621 Binop { op=add, lhs=v617, rhs=v620 } -> x1 + v622 Binop { op=add, lhs=v613, rhs=v621 } -> x0 + v623 Imm(0) -> x1 + v624 LoadLocal { off=-523, kind=I64 } -> x1 + v625 LocalAddr(-140) -> x1 + v626 Load { addr=v625, disp=0, kind=I64 } -> x1 + v627 LocalAddr(-140) -> x2 + v628 BinopI { op=add, lhs=v627, rhs_imm=8 } -> x6 + v629 Load { addr=v627, disp=8, kind=I64 } -> x2 + v630 Binop { op=add, lhs=v626, rhs=v629 } -> x1 + v631 Binop { op=add, lhs=v622, rhs=v630 } -> x0 + v632 Imm(0) -> x1 + v633 LoadLocal { off=-523, kind=I64 } -> x1 + v634 LocalAddr(-142) -> x1 + v635 Load { addr=v634, disp=0, kind=I64 } -> x1 + v636 LocalAddr(-142) -> x2 + v637 BinopI { op=add, lhs=v636, rhs_imm=8 } -> x6 + v638 Load { addr=v636, disp=8, kind=I64 } -> x2 + v639 Binop { op=add, lhs=v635, rhs=v638 } -> x1 + v640 Binop { op=add, lhs=v631, rhs=v639 } -> x0 + v641 Imm(0) -> x1 + v642 LoadLocal { off=-523, kind=I64 } -> x1 + v643 LocalAddr(-144) -> x1 + v644 Load { addr=v643, disp=0, kind=I64 } -> x1 + v645 LocalAddr(-144) -> x2 + v646 BinopI { op=add, lhs=v645, rhs_imm=8 } -> x6 + v647 Load { addr=v645, disp=8, kind=I64 } -> x2 + v648 Binop { op=add, lhs=v644, rhs=v647 } -> x1 + v649 Binop { op=add, lhs=v640, rhs=v648 } -> x0 + v650 Imm(0) -> x1 + v651 LoadLocal { off=-523, kind=I64 } -> x1 + v652 LocalAddr(-146) -> x1 + v653 Load { addr=v652, disp=0, kind=I64 } -> x1 + v654 LocalAddr(-146) -> x2 + v655 BinopI { op=add, lhs=v654, rhs_imm=8 } -> x6 + v656 Load { addr=v654, disp=8, kind=I64 } -> x2 + v657 Binop { op=add, lhs=v653, rhs=v656 } -> x1 + v658 Binop { op=add, lhs=v649, rhs=v657 } -> x0 + v659 Imm(0) -> x1 + v660 LoadLocal { off=-523, kind=I64 } -> x1 + v661 LocalAddr(-148) -> x1 + v662 Load { addr=v661, disp=0, kind=I64 } -> x1 + v663 LocalAddr(-148) -> x2 + v664 BinopI { op=add, lhs=v663, rhs_imm=8 } -> x6 + v665 Load { addr=v663, disp=8, kind=I64 } -> x2 + v666 Binop { op=add, lhs=v662, rhs=v665 } -> x1 + v667 Binop { op=add, lhs=v658, rhs=v666 } -> x0 + v668 Imm(0) -> x1 + v669 LoadLocal { off=-523, kind=I64 } -> x1 + v670 LocalAddr(-150) -> x1 + v671 Load { addr=v670, disp=0, kind=I64 } -> x1 + v672 LocalAddr(-150) -> x2 + v673 BinopI { op=add, lhs=v672, rhs_imm=8 } -> x6 + v674 Load { addr=v672, disp=8, kind=I64 } -> x2 + v675 Binop { op=add, lhs=v671, rhs=v674 } -> x1 + v676 Binop { op=add, lhs=v667, rhs=v675 } -> x0 + v677 Imm(0) -> x1 + v678 LoadLocal { off=-523, kind=I64 } -> x1 + v679 LocalAddr(-152) -> x1 + v680 Load { addr=v679, disp=0, kind=I64 } -> x1 + v681 LocalAddr(-152) -> x2 + v682 BinopI { op=add, lhs=v681, rhs_imm=8 } -> x6 + v683 Load { addr=v681, disp=8, kind=I64 } -> x2 + v684 Binop { op=add, lhs=v680, rhs=v683 } -> x1 + v685 Binop { op=add, lhs=v676, rhs=v684 } -> x0 + v686 Imm(0) -> x1 + v687 LoadLocal { off=-523, kind=I64 } -> x1 + v688 LocalAddr(-154) -> x1 + v689 Load { addr=v688, disp=0, kind=I64 } -> x1 + v690 LocalAddr(-154) -> x2 + v691 BinopI { op=add, lhs=v690, rhs_imm=8 } -> x6 + v692 Load { addr=v690, disp=8, kind=I64 } -> x2 + v693 Binop { op=add, lhs=v689, rhs=v692 } -> x1 + v694 Binop { op=add, lhs=v685, rhs=v693 } -> x0 + v695 Imm(0) -> x1 + v696 LoadLocal { off=-523, kind=I64 } -> x1 + v697 LocalAddr(-156) -> x1 + v698 Load { addr=v697, disp=0, kind=I64 } -> x1 + v699 LocalAddr(-156) -> x2 + v700 BinopI { op=add, lhs=v699, rhs_imm=8 } -> x6 + v701 Load { addr=v699, disp=8, kind=I64 } -> x2 + v702 Binop { op=add, lhs=v698, rhs=v701 } -> x1 + v703 Binop { op=add, lhs=v694, rhs=v702 } -> x0 + v704 Imm(0) -> x1 + v705 LoadLocal { off=-523, kind=I64 } -> x1 + v706 LocalAddr(-158) -> x1 + v707 Load { addr=v706, disp=0, kind=I64 } -> x1 + v708 LocalAddr(-158) -> x2 + v709 BinopI { op=add, lhs=v708, rhs_imm=8 } -> x6 + v710 Load { addr=v708, disp=8, kind=I64 } -> x2 + v711 Binop { op=add, lhs=v707, rhs=v710 } -> x1 + v712 Binop { op=add, lhs=v703, rhs=v711 } -> x0 + v713 Imm(0) -> x1 + v714 LoadLocal { off=-523, kind=I64 } -> x1 + v715 LocalAddr(-160) -> x1 + v716 Load { addr=v715, disp=0, kind=I64 } -> x1 + v717 LocalAddr(-160) -> x2 + v718 BinopI { op=add, lhs=v717, rhs_imm=8 } -> x6 + v719 Load { addr=v717, disp=8, kind=I64 } -> x2 + v720 Binop { op=add, lhs=v716, rhs=v719 } -> x1 + v721 Binop { op=add, lhs=v712, rhs=v720 } -> x0 + v722 Imm(0) -> x1 + v723 LoadLocal { off=-523, kind=I64 } -> x1 + v724 LocalAddr(-162) -> x1 + v725 Load { addr=v724, disp=0, kind=I64 } -> x1 + v726 LocalAddr(-162) -> x2 + v727 BinopI { op=add, lhs=v726, rhs_imm=8 } -> x6 + v728 Load { addr=v726, disp=8, kind=I64 } -> x2 + v729 Binop { op=add, lhs=v725, rhs=v728 } -> x1 + v730 Binop { op=add, lhs=v721, rhs=v729 } -> x0 + v731 Imm(0) -> x1 + v732 LoadLocal { off=-523, kind=I64 } -> x1 + v733 LocalAddr(-164) -> x1 + v734 Load { addr=v733, disp=0, kind=I64 } -> x1 + v735 LocalAddr(-164) -> x2 + v736 BinopI { op=add, lhs=v735, rhs_imm=8 } -> x6 + v737 Load { addr=v735, disp=8, kind=I64 } -> x2 + v738 Binop { op=add, lhs=v734, rhs=v737 } -> x1 + v739 Binop { op=add, lhs=v730, rhs=v738 } -> x0 + v740 Imm(0) -> x1 + v741 LoadLocal { off=-523, kind=I64 } -> x1 + v742 LocalAddr(-166) -> x1 + v743 Load { addr=v742, disp=0, kind=I64 } -> x1 + v744 LocalAddr(-166) -> x2 + v745 BinopI { op=add, lhs=v744, rhs_imm=8 } -> x6 + v746 Load { addr=v744, disp=8, kind=I64 } -> x2 + v747 Binop { op=add, lhs=v743, rhs=v746 } -> x1 + v748 Binop { op=add, lhs=v739, rhs=v747 } -> x0 + v749 Imm(0) -> x1 + v750 LoadLocal { off=-523, kind=I64 } -> x1 + v751 LocalAddr(-168) -> x1 + v752 Load { addr=v751, disp=0, kind=I64 } -> x1 + v753 LocalAddr(-168) -> x2 + v754 BinopI { op=add, lhs=v753, rhs_imm=8 } -> x6 + v755 Load { addr=v753, disp=8, kind=I64 } -> x2 + v756 Binop { op=add, lhs=v752, rhs=v755 } -> x1 + v757 Binop { op=add, lhs=v748, rhs=v756 } -> x0 + v758 Imm(0) -> x1 + v759 LoadLocal { off=-523, kind=I64 } -> x1 + v760 LocalAddr(-170) -> x1 + v761 Load { addr=v760, disp=0, kind=I64 } -> x1 + v762 LocalAddr(-170) -> x2 + v763 BinopI { op=add, lhs=v762, rhs_imm=8 } -> x6 + v764 Load { addr=v762, disp=8, kind=I64 } -> x2 + v765 Binop { op=add, lhs=v761, rhs=v764 } -> x1 + v766 Binop { op=add, lhs=v757, rhs=v765 } -> x0 + v767 Imm(0) -> x1 + v768 LoadLocal { off=-523, kind=I64 } -> x1 + v769 LocalAddr(-172) -> x1 + v770 Load { addr=v769, disp=0, kind=I64 } -> x1 + v771 LocalAddr(-172) -> x2 + v772 BinopI { op=add, lhs=v771, rhs_imm=8 } -> x6 + v773 Load { addr=v771, disp=8, kind=I64 } -> x2 + v774 Binop { op=add, lhs=v770, rhs=v773 } -> x1 + v775 Binop { op=add, lhs=v766, rhs=v774 } -> x0 + v776 Imm(0) -> x1 + v777 LoadLocal { off=-523, kind=I64 } -> x1 + v778 LocalAddr(-174) -> x1 + v779 Load { addr=v778, disp=0, kind=I64 } -> x1 + v780 LocalAddr(-174) -> x2 + v781 BinopI { op=add, lhs=v780, rhs_imm=8 } -> x6 + v782 Load { addr=v780, disp=8, kind=I64 } -> x2 + v783 Binop { op=add, lhs=v779, rhs=v782 } -> x1 + v784 Binop { op=add, lhs=v775, rhs=v783 } -> x0 + v785 Imm(0) -> x1 + v786 LoadLocal { off=-523, kind=I64 } -> x1 + v787 LocalAddr(-176) -> x1 + v788 Load { addr=v787, disp=0, kind=I64 } -> x1 + v789 LocalAddr(-176) -> x2 + v790 BinopI { op=add, lhs=v789, rhs_imm=8 } -> x6 + v791 Load { addr=v789, disp=8, kind=I64 } -> x2 + v792 Binop { op=add, lhs=v788, rhs=v791 } -> x1 + v793 Binop { op=add, lhs=v784, rhs=v792 } -> x0 + v794 Imm(0) -> x1 + v795 LoadLocal { off=-523, kind=I64 } -> x1 + v796 LocalAddr(-178) -> x1 + v797 Load { addr=v796, disp=0, kind=I64 } -> x1 + v798 LocalAddr(-178) -> x2 + v799 BinopI { op=add, lhs=v798, rhs_imm=8 } -> x6 + v800 Load { addr=v798, disp=8, kind=I64 } -> x2 + v801 Binop { op=add, lhs=v797, rhs=v800 } -> x1 + v802 Binop { op=add, lhs=v793, rhs=v801 } -> x0 + v803 Imm(0) -> x1 + v804 LoadLocal { off=-523, kind=I64 } -> x1 + v805 LocalAddr(-180) -> x1 + v806 Load { addr=v805, disp=0, kind=I64 } -> x1 + v807 LocalAddr(-180) -> x2 + v808 BinopI { op=add, lhs=v807, rhs_imm=8 } -> x6 + v809 Load { addr=v807, disp=8, kind=I64 } -> x2 + v810 Binop { op=add, lhs=v806, rhs=v809 } -> x1 + v811 Binop { op=add, lhs=v802, rhs=v810 } -> x0 + v812 Imm(0) -> x1 + v813 LoadLocal { off=-523, kind=I64 } -> x1 + v814 LocalAddr(-182) -> x1 + v815 Load { addr=v814, disp=0, kind=I64 } -> x1 + v816 LocalAddr(-182) -> x2 + v817 BinopI { op=add, lhs=v816, rhs_imm=8 } -> x6 + v818 Load { addr=v816, disp=8, kind=I64 } -> x2 + v819 Binop { op=add, lhs=v815, rhs=v818 } -> x1 + v820 Binop { op=add, lhs=v811, rhs=v819 } -> x0 + v821 Imm(0) -> x1 + v822 LoadLocal { off=-523, kind=I64 } -> x1 + v823 LocalAddr(-184) -> x1 + v824 Load { addr=v823, disp=0, kind=I64 } -> x1 + v825 LocalAddr(-184) -> x2 + v826 BinopI { op=add, lhs=v825, rhs_imm=8 } -> x6 + v827 Load { addr=v825, disp=8, kind=I64 } -> x2 + v828 Binop { op=add, lhs=v824, rhs=v827 } -> x1 + v829 Binop { op=add, lhs=v820, rhs=v828 } -> x0 + v830 Imm(0) -> x1 + v831 LoadLocal { off=-523, kind=I64 } -> x1 + v832 LocalAddr(-186) -> x1 + v833 Load { addr=v832, disp=0, kind=I64 } -> x1 + v834 LocalAddr(-186) -> x2 + v835 BinopI { op=add, lhs=v834, rhs_imm=8 } -> x6 + v836 Load { addr=v834, disp=8, kind=I64 } -> x2 + v837 Binop { op=add, lhs=v833, rhs=v836 } -> x1 + v838 Binop { op=add, lhs=v829, rhs=v837 } -> x0 + v839 Imm(0) -> x1 + v840 LoadLocal { off=-523, kind=I64 } -> x1 + v841 LocalAddr(-188) -> x1 + v842 Load { addr=v841, disp=0, kind=I64 } -> x1 + v843 LocalAddr(-188) -> x2 + v844 BinopI { op=add, lhs=v843, rhs_imm=8 } -> x6 + v845 Load { addr=v843, disp=8, kind=I64 } -> x2 + v846 Binop { op=add, lhs=v842, rhs=v845 } -> x1 + v847 Binop { op=add, lhs=v838, rhs=v846 } -> x0 + v848 Imm(0) -> x1 + v849 LoadLocal { off=-523, kind=I64 } -> x1 + v850 LocalAddr(-190) -> x1 + v851 Load { addr=v850, disp=0, kind=I64 } -> x1 + v852 LocalAddr(-190) -> x2 + v853 BinopI { op=add, lhs=v852, rhs_imm=8 } -> x6 + v854 Load { addr=v852, disp=8, kind=I64 } -> x2 + v855 Binop { op=add, lhs=v851, rhs=v854 } -> x1 + v856 Binop { op=add, lhs=v847, rhs=v855 } -> x0 + v857 Imm(0) -> x1 + v858 LoadLocal { off=-523, kind=I64 } -> x1 + v859 LocalAddr(-192) -> x1 + v860 Load { addr=v859, disp=0, kind=I64 } -> x1 + v861 LocalAddr(-192) -> x2 + v862 BinopI { op=add, lhs=v861, rhs_imm=8 } -> x6 + v863 Load { addr=v861, disp=8, kind=I64 } -> x2 + v864 Binop { op=add, lhs=v860, rhs=v863 } -> x1 + v865 Binop { op=add, lhs=v856, rhs=v864 } -> x0 + v866 Imm(0) -> x1 + v867 LoadLocal { off=-523, kind=I64 } -> x1 + v868 LocalAddr(-194) -> x1 + v869 Load { addr=v868, disp=0, kind=I64 } -> x1 + v870 LocalAddr(-194) -> x2 + v871 BinopI { op=add, lhs=v870, rhs_imm=8 } -> x6 + v872 Load { addr=v870, disp=8, kind=I64 } -> x2 + v873 Binop { op=add, lhs=v869, rhs=v872 } -> x1 + v874 Binop { op=add, lhs=v865, rhs=v873 } -> x0 + v875 Imm(0) -> x1 + v876 LoadLocal { off=-523, kind=I64 } -> x1 + v877 LocalAddr(-196) -> x1 + v878 Load { addr=v877, disp=0, kind=I64 } -> x1 + v879 LocalAddr(-196) -> x2 + v880 BinopI { op=add, lhs=v879, rhs_imm=8 } -> x6 + v881 Load { addr=v879, disp=8, kind=I64 } -> x2 + v882 Binop { op=add, lhs=v878, rhs=v881 } -> x1 + v883 Binop { op=add, lhs=v874, rhs=v882 } -> x0 + v884 Imm(0) -> x1 + v885 LoadLocal { off=-523, kind=I64 } -> x1 + v886 LocalAddr(-198) -> x1 + v887 Load { addr=v886, disp=0, kind=I64 } -> x1 + v888 LocalAddr(-198) -> x2 + v889 BinopI { op=add, lhs=v888, rhs_imm=8 } -> x6 + v890 Load { addr=v888, disp=8, kind=I64 } -> x2 + v891 Binop { op=add, lhs=v887, rhs=v890 } -> x1 + v892 Binop { op=add, lhs=v883, rhs=v891 } -> x0 + v893 Imm(0) -> x1 + v894 LoadLocal { off=-523, kind=I64 } -> x1 + v895 LocalAddr(-200) -> x1 + v896 Load { addr=v895, disp=0, kind=I64 } -> x1 + v897 LocalAddr(-200) -> x2 + v898 BinopI { op=add, lhs=v897, rhs_imm=8 } -> x6 + v899 Load { addr=v897, disp=8, kind=I64 } -> x2 + v900 Binop { op=add, lhs=v896, rhs=v899 } -> x1 + v901 Binop { op=add, lhs=v892, rhs=v900 } -> x0 + v902 Imm(0) -> x1 + v903 LoadLocal { off=-523, kind=I64 } -> x1 + v904 LocalAddr(-202) -> x1 + v905 Load { addr=v904, disp=0, kind=I64 } -> x1 + v906 LocalAddr(-202) -> x2 + v907 BinopI { op=add, lhs=v906, rhs_imm=8 } -> x6 + v908 Load { addr=v906, disp=8, kind=I64 } -> x2 + v909 Binop { op=add, lhs=v905, rhs=v908 } -> x1 + v910 Binop { op=add, lhs=v901, rhs=v909 } -> x0 + v911 Imm(0) -> x1 + v912 LoadLocal { off=-523, kind=I64 } -> x1 + v913 LocalAddr(-204) -> x1 + v914 Load { addr=v913, disp=0, kind=I64 } -> x1 + v915 LocalAddr(-204) -> x2 + v916 BinopI { op=add, lhs=v915, rhs_imm=8 } -> x6 + v917 Load { addr=v915, disp=8, kind=I64 } -> x2 + v918 Binop { op=add, lhs=v914, rhs=v917 } -> x1 + v919 Binop { op=add, lhs=v910, rhs=v918 } -> x0 + v920 Imm(0) -> x1 + v921 LoadLocal { off=-523, kind=I64 } -> x1 + v922 LocalAddr(-206) -> x1 + v923 Load { addr=v922, disp=0, kind=I64 } -> x1 + v924 LocalAddr(-206) -> x2 + v925 BinopI { op=add, lhs=v924, rhs_imm=8 } -> x6 + v926 Load { addr=v924, disp=8, kind=I64 } -> x2 + v927 Binop { op=add, lhs=v923, rhs=v926 } -> x1 + v928 Binop { op=add, lhs=v919, rhs=v927 } -> x0 + v929 Imm(0) -> x1 + v930 LoadLocal { off=-523, kind=I64 } -> x1 + v931 LocalAddr(-208) -> x1 + v932 Load { addr=v931, disp=0, kind=I64 } -> x1 + v933 LocalAddr(-208) -> x2 + v934 BinopI { op=add, lhs=v933, rhs_imm=8 } -> x6 + v935 Load { addr=v933, disp=8, kind=I64 } -> x2 + v936 Binop { op=add, lhs=v932, rhs=v935 } -> x1 + v937 Binop { op=add, lhs=v928, rhs=v936 } -> x0 + v938 Imm(0) -> x1 + v939 LoadLocal { off=-523, kind=I64 } -> x1 + v940 LocalAddr(-210) -> x1 + v941 Load { addr=v940, disp=0, kind=I64 } -> x1 + v942 LocalAddr(-210) -> x2 + v943 BinopI { op=add, lhs=v942, rhs_imm=8 } -> x6 + v944 Load { addr=v942, disp=8, kind=I64 } -> x2 + v945 Binop { op=add, lhs=v941, rhs=v944 } -> x1 + v946 Binop { op=add, lhs=v937, rhs=v945 } -> x0 + v947 Imm(0) -> x1 + v948 LoadLocal { off=-523, kind=I64 } -> x1 + v949 LocalAddr(-212) -> x1 + v950 Load { addr=v949, disp=0, kind=I64 } -> x1 + v951 LocalAddr(-212) -> x2 + v952 BinopI { op=add, lhs=v951, rhs_imm=8 } -> x6 + v953 Load { addr=v951, disp=8, kind=I64 } -> x2 + v954 Binop { op=add, lhs=v950, rhs=v953 } -> x1 + v955 Binop { op=add, lhs=v946, rhs=v954 } -> x0 + v956 Imm(0) -> x1 + v957 LoadLocal { off=-523, kind=I64 } -> x1 + v958 LocalAddr(-214) -> x1 + v959 Load { addr=v958, disp=0, kind=I64 } -> x1 + v960 LocalAddr(-214) -> x2 + v961 BinopI { op=add, lhs=v960, rhs_imm=8 } -> x6 + v962 Load { addr=v960, disp=8, kind=I64 } -> x2 + v963 Binop { op=add, lhs=v959, rhs=v962 } -> x1 + v964 Binop { op=add, lhs=v955, rhs=v963 } -> x0 + v965 Imm(0) -> x1 + v966 LoadLocal { off=-523, kind=I64 } -> x1 + v967 LocalAddr(-216) -> x1 + v968 Load { addr=v967, disp=0, kind=I64 } -> x1 + v969 LocalAddr(-216) -> x2 + v970 BinopI { op=add, lhs=v969, rhs_imm=8 } -> x6 + v971 Load { addr=v969, disp=8, kind=I64 } -> x2 + v972 Binop { op=add, lhs=v968, rhs=v971 } -> x1 + v973 Binop { op=add, lhs=v964, rhs=v972 } -> x0 + v974 Imm(0) -> x1 + v975 LoadLocal { off=-523, kind=I64 } -> x1 + v976 LocalAddr(-218) -> x1 + v977 Load { addr=v976, disp=0, kind=I64 } -> x1 + v978 LocalAddr(-218) -> x2 + v979 BinopI { op=add, lhs=v978, rhs_imm=8 } -> x6 + v980 Load { addr=v978, disp=8, kind=I64 } -> x2 + v981 Binop { op=add, lhs=v977, rhs=v980 } -> x1 + v982 Binop { op=add, lhs=v973, rhs=v981 } -> x0 + v983 Imm(0) -> x1 + v984 LoadLocal { off=-523, kind=I64 } -> x1 + v985 LocalAddr(-220) -> x1 + v986 Load { addr=v985, disp=0, kind=I64 } -> x1 + v987 LocalAddr(-220) -> x2 + v988 BinopI { op=add, lhs=v987, rhs_imm=8 } -> x6 + v989 Load { addr=v987, disp=8, kind=I64 } -> x2 + v990 Binop { op=add, lhs=v986, rhs=v989 } -> x1 + v991 Binop { op=add, lhs=v982, rhs=v990 } -> x0 + v992 Imm(0) -> x1 + v993 LoadLocal { off=-523, kind=I64 } -> x1 + v994 LocalAddr(-222) -> x1 + v995 Load { addr=v994, disp=0, kind=I64 } -> x1 + v996 LocalAddr(-222) -> x2 + v997 BinopI { op=add, lhs=v996, rhs_imm=8 } -> x6 + v998 Load { addr=v996, disp=8, kind=I64 } -> x2 + v999 Binop { op=add, lhs=v995, rhs=v998 } -> x1 + v1000 Binop { op=add, lhs=v991, rhs=v999 } -> x0 + v1001 Imm(0) -> x1 + v1002 LoadLocal { off=-523, kind=I64 } -> x1 + v1003 LocalAddr(-224) -> x1 + v1004 Load { addr=v1003, disp=0, kind=I64 } -> x1 + v1005 LocalAddr(-224) -> x2 + v1006 BinopI { op=add, lhs=v1005, rhs_imm=8 } -> x6 + v1007 Load { addr=v1005, disp=8, kind=I64 } -> x2 + v1008 Binop { op=add, lhs=v1004, rhs=v1007 } -> x1 + v1009 Binop { op=add, lhs=v1000, rhs=v1008 } -> x0 + v1010 Imm(0) -> x1 + v1011 LoadLocal { off=-523, kind=I64 } -> x1 + v1012 LocalAddr(-226) -> x1 + v1013 Load { addr=v1012, disp=0, kind=I64 } -> x1 + v1014 LocalAddr(-226) -> x2 + v1015 BinopI { op=add, lhs=v1014, rhs_imm=8 } -> x6 + v1016 Load { addr=v1014, disp=8, kind=I64 } -> x2 + v1017 Binop { op=add, lhs=v1013, rhs=v1016 } -> x1 + v1018 Binop { op=add, lhs=v1009, rhs=v1017 } -> x0 + v1019 Imm(0) -> x1 + v1020 LoadLocal { off=-523, kind=I64 } -> x1 + v1021 LocalAddr(-228) -> x1 + v1022 Load { addr=v1021, disp=0, kind=I64 } -> x1 + v1023 LocalAddr(-228) -> x2 + v1024 BinopI { op=add, lhs=v1023, rhs_imm=8 } -> x6 + v1025 Load { addr=v1023, disp=8, kind=I64 } -> x2 + v1026 Binop { op=add, lhs=v1022, rhs=v1025 } -> x1 + v1027 Binop { op=add, lhs=v1018, rhs=v1026 } -> x0 + v1028 Imm(0) -> x1 + v1029 LoadLocal { off=-523, kind=I64 } -> x1 + v1030 LocalAddr(-230) -> x1 + v1031 Load { addr=v1030, disp=0, kind=I64 } -> x1 + v1032 LocalAddr(-230) -> x2 + v1033 BinopI { op=add, lhs=v1032, rhs_imm=8 } -> x6 + v1034 Load { addr=v1032, disp=8, kind=I64 } -> x2 + v1035 Binop { op=add, lhs=v1031, rhs=v1034 } -> x1 + v1036 Binop { op=add, lhs=v1027, rhs=v1035 } -> x0 + v1037 Imm(0) -> x1 + v1038 LoadLocal { off=-523, kind=I64 } -> x1 + v1039 LocalAddr(-232) -> x1 + v1040 Load { addr=v1039, disp=0, kind=I64 } -> x1 + v1041 LocalAddr(-232) -> x2 + v1042 BinopI { op=add, lhs=v1041, rhs_imm=8 } -> x6 + v1043 Load { addr=v1041, disp=8, kind=I64 } -> x2 + v1044 Binop { op=add, lhs=v1040, rhs=v1043 } -> x1 + v1045 Binop { op=add, lhs=v1036, rhs=v1044 } -> x0 + v1046 Imm(0) -> x1 + v1047 LoadLocal { off=-523, kind=I64 } -> x1 + v1048 LocalAddr(-234) -> x1 + v1049 Load { addr=v1048, disp=0, kind=I64 } -> x1 + v1050 LocalAddr(-234) -> x2 + v1051 BinopI { op=add, lhs=v1050, rhs_imm=8 } -> x6 + v1052 Load { addr=v1050, disp=8, kind=I64 } -> x2 + v1053 Binop { op=add, lhs=v1049, rhs=v1052 } -> x1 + v1054 Binop { op=add, lhs=v1045, rhs=v1053 } -> x0 + v1055 Imm(0) -> x1 + v1056 LoadLocal { off=-523, kind=I64 } -> x1 + v1057 LocalAddr(-236) -> x1 + v1058 Load { addr=v1057, disp=0, kind=I64 } -> x1 + v1059 LocalAddr(-236) -> x2 + v1060 BinopI { op=add, lhs=v1059, rhs_imm=8 } -> x6 + v1061 Load { addr=v1059, disp=8, kind=I64 } -> x2 + v1062 Binop { op=add, lhs=v1058, rhs=v1061 } -> x1 + v1063 Binop { op=add, lhs=v1054, rhs=v1062 } -> x0 + v1064 Imm(0) -> x1 + v1065 LoadLocal { off=-523, kind=I64 } -> x1 + v1066 LocalAddr(-238) -> x1 + v1067 Load { addr=v1066, disp=0, kind=I64 } -> x1 + v1068 LocalAddr(-238) -> x2 + v1069 BinopI { op=add, lhs=v1068, rhs_imm=8 } -> x6 + v1070 Load { addr=v1068, disp=8, kind=I64 } -> x2 + v1071 Binop { op=add, lhs=v1067, rhs=v1070 } -> x1 + v1072 Binop { op=add, lhs=v1063, rhs=v1071 } -> x0 + v1073 Imm(0) -> x1 + v1074 LoadLocal { off=-523, kind=I64 } -> x1 + v1075 LocalAddr(-240) -> x1 + v1076 Load { addr=v1075, disp=0, kind=I64 } -> x1 + v1077 LocalAddr(-240) -> x2 + v1078 BinopI { op=add, lhs=v1077, rhs_imm=8 } -> x6 + v1079 Load { addr=v1077, disp=8, kind=I64 } -> x2 + v1080 Binop { op=add, lhs=v1076, rhs=v1079 } -> x1 + v1081 Binop { op=add, lhs=v1072, rhs=v1080 } -> x0 + v1082 Imm(0) -> x1 + v1083 LoadLocal { off=-523, kind=I64 } -> x1 + v1084 LocalAddr(-242) -> x1 + v1085 Load { addr=v1084, disp=0, kind=I64 } -> x1 + v1086 LocalAddr(-242) -> x2 + v1087 BinopI { op=add, lhs=v1086, rhs_imm=8 } -> x6 + v1088 Load { addr=v1086, disp=8, kind=I64 } -> x2 + v1089 Binop { op=add, lhs=v1085, rhs=v1088 } -> x1 + v1090 Binop { op=add, lhs=v1081, rhs=v1089 } -> x0 + v1091 Imm(0) -> x1 + v1092 LoadLocal { off=-523, kind=I64 } -> x1 + v1093 LocalAddr(-244) -> x1 + v1094 Load { addr=v1093, disp=0, kind=I64 } -> x1 + v1095 LocalAddr(-244) -> x2 + v1096 BinopI { op=add, lhs=v1095, rhs_imm=8 } -> x6 + v1097 Load { addr=v1095, disp=8, kind=I64 } -> x2 + v1098 Binop { op=add, lhs=v1094, rhs=v1097 } -> x1 + v1099 Binop { op=add, lhs=v1090, rhs=v1098 } -> x0 + v1100 Imm(0) -> x1 + v1101 LoadLocal { off=-523, kind=I64 } -> x1 + v1102 LocalAddr(-246) -> x1 + v1103 Load { addr=v1102, disp=0, kind=I64 } -> x1 + v1104 LocalAddr(-246) -> x2 + v1105 BinopI { op=add, lhs=v1104, rhs_imm=8 } -> x6 + v1106 Load { addr=v1104, disp=8, kind=I64 } -> x2 + v1107 Binop { op=add, lhs=v1103, rhs=v1106 } -> x1 + v1108 Binop { op=add, lhs=v1099, rhs=v1107 } -> x0 + v1109 Imm(0) -> x1 + v1110 LoadLocal { off=-523, kind=I64 } -> x1 + v1111 LocalAddr(-248) -> x1 + v1112 Load { addr=v1111, disp=0, kind=I64 } -> x1 + v1113 LocalAddr(-248) -> x2 + v1114 BinopI { op=add, lhs=v1113, rhs_imm=8 } -> x6 + v1115 Load { addr=v1113, disp=8, kind=I64 } -> x2 + v1116 Binop { op=add, lhs=v1112, rhs=v1115 } -> x1 + v1117 Binop { op=add, lhs=v1108, rhs=v1116 } -> x0 + v1118 Imm(0) -> x1 + v1119 LoadLocal { off=-523, kind=I64 } -> x1 + v1120 LocalAddr(-250) -> x1 + v1121 Load { addr=v1120, disp=0, kind=I64 } -> x1 + v1122 LocalAddr(-250) -> x2 + v1123 BinopI { op=add, lhs=v1122, rhs_imm=8 } -> x6 + v1124 Load { addr=v1122, disp=8, kind=I64 } -> x2 + v1125 Binop { op=add, lhs=v1121, rhs=v1124 } -> x1 + v1126 Binop { op=add, lhs=v1117, rhs=v1125 } -> x0 + v1127 Imm(0) -> x1 + v1128 LoadLocal { off=-523, kind=I64 } -> x1 + v1129 LocalAddr(-252) -> x1 + v1130 Load { addr=v1129, disp=0, kind=I64 } -> x1 + v1131 LocalAddr(-252) -> x2 + v1132 BinopI { op=add, lhs=v1131, rhs_imm=8 } -> x6 + v1133 Load { addr=v1131, disp=8, kind=I64 } -> x2 + v1134 Binop { op=add, lhs=v1130, rhs=v1133 } -> x1 + v1135 Binop { op=add, lhs=v1126, rhs=v1134 } -> x0 + v1136 Imm(0) -> x1 + v1137 LoadLocal { off=-523, kind=I64 } -> x1 + v1138 LocalAddr(-254) -> x1 + v1139 Load { addr=v1138, disp=0, kind=I64 } -> x1 + v1140 LocalAddr(-254) -> x2 + v1141 BinopI { op=add, lhs=v1140, rhs_imm=8 } -> x6 + v1142 Load { addr=v1140, disp=8, kind=I64 } -> x2 + v1143 Binop { op=add, lhs=v1139, rhs=v1142 } -> x1 + v1144 Binop { op=add, lhs=v1135, rhs=v1143 } -> x0 + v1145 Imm(0) -> x1 + v1146 LoadLocal { off=-523, kind=I64 } -> x1 + v1147 LocalAddr(-256) -> x1 + v1148 Load { addr=v1147, disp=0, kind=I64 } -> x1 + v1149 LocalAddr(-256) -> x2 + v1150 BinopI { op=add, lhs=v1149, rhs_imm=8 } -> x6 + v1151 Load { addr=v1149, disp=8, kind=I64 } -> x2 + v1152 Binop { op=add, lhs=v1148, rhs=v1151 } -> x1 + v1153 Binop { op=add, lhs=v1144, rhs=v1152 } -> x0 + v1154 Imm(0) -> x1 + v1155 LoadLocal { off=-523, kind=I64 } -> x1 + v1156 LocalAddr(-258) -> x1 + v1157 Load { addr=v1156, disp=0, kind=I64 } -> x1 + v1158 LocalAddr(-258) -> x2 + v1159 BinopI { op=add, lhs=v1158, rhs_imm=8 } -> x6 + v1160 Load { addr=v1158, disp=8, kind=I64 } -> x2 + v1161 Binop { op=add, lhs=v1157, rhs=v1160 } -> x1 + v1162 Binop { op=add, lhs=v1153, rhs=v1161 } -> x0 + v1163 Imm(0) -> x1 + v1164 LoadLocal { off=-523, kind=I64 } -> x1 + v1165 LocalAddr(-260) -> x1 + v1166 Load { addr=v1165, disp=0, kind=I64 } -> x1 + v1167 LocalAddr(-260) -> x2 + v1168 BinopI { op=add, lhs=v1167, rhs_imm=8 } -> x6 + v1169 Load { addr=v1167, disp=8, kind=I64 } -> x2 + v1170 Binop { op=add, lhs=v1166, rhs=v1169 } -> x1 + v1171 Binop { op=add, lhs=v1162, rhs=v1170 } -> x0 + v1172 Imm(0) -> x1 + v1173 LoadLocal { off=-523, kind=I64 } -> x1 + v1174 LocalAddr(-262) -> x1 + v1175 Load { addr=v1174, disp=0, kind=I64 } -> x1 + v1176 LocalAddr(-262) -> x2 + v1177 BinopI { op=add, lhs=v1176, rhs_imm=8 } -> x6 + v1178 Load { addr=v1176, disp=8, kind=I64 } -> x2 + v1179 Binop { op=add, lhs=v1175, rhs=v1178 } -> x1 + v1180 Binop { op=add, lhs=v1171, rhs=v1179 } -> x0 + v1181 Imm(0) -> x1 + v1182 LoadLocal { off=-523, kind=I64 } -> x1 + v1183 LocalAddr(-264) -> x1 + v1184 Load { addr=v1183, disp=0, kind=I64 } -> x1 + v1185 LocalAddr(-264) -> x2 + v1186 BinopI { op=add, lhs=v1185, rhs_imm=8 } -> x6 + v1187 Load { addr=v1185, disp=8, kind=I64 } -> x2 + v1188 Binop { op=add, lhs=v1184, rhs=v1187 } -> x1 + v1189 Binop { op=add, lhs=v1180, rhs=v1188 } -> x0 + v1190 Imm(0) -> x1 + v1191 LoadLocal { off=-523, kind=I64 } -> x1 + v1192 LocalAddr(-266) -> x1 + v1193 Load { addr=v1192, disp=0, kind=I64 } -> x1 + v1194 LocalAddr(-266) -> x2 + v1195 BinopI { op=add, lhs=v1194, rhs_imm=8 } -> x6 + v1196 Load { addr=v1194, disp=8, kind=I64 } -> x2 + v1197 Binop { op=add, lhs=v1193, rhs=v1196 } -> x1 + v1198 Binop { op=add, lhs=v1189, rhs=v1197 } -> x0 + v1199 Imm(0) -> x1 + v1200 LoadLocal { off=-523, kind=I64 } -> x1 + v1201 LocalAddr(-268) -> x1 + v1202 Load { addr=v1201, disp=0, kind=I64 } -> x1 + v1203 LocalAddr(-268) -> x2 + v1204 BinopI { op=add, lhs=v1203, rhs_imm=8 } -> x6 + v1205 Load { addr=v1203, disp=8, kind=I64 } -> x2 + v1206 Binop { op=add, lhs=v1202, rhs=v1205 } -> x1 + v1207 Binop { op=add, lhs=v1198, rhs=v1206 } -> x0 + v1208 Imm(0) -> x1 + v1209 LoadLocal { off=-523, kind=I64 } -> x1 + v1210 LocalAddr(-270) -> x1 + v1211 Load { addr=v1210, disp=0, kind=I64 } -> x1 + v1212 LocalAddr(-270) -> x2 + v1213 BinopI { op=add, lhs=v1212, rhs_imm=8 } -> x6 + v1214 Load { addr=v1212, disp=8, kind=I64 } -> x2 + v1215 Binop { op=add, lhs=v1211, rhs=v1214 } -> x1 + v1216 Binop { op=add, lhs=v1207, rhs=v1215 } -> x0 + v1217 Imm(0) -> x1 + v1218 LoadLocal { off=-523, kind=I64 } -> x1 + v1219 LocalAddr(-272) -> x1 + v1220 Load { addr=v1219, disp=0, kind=I64 } -> x1 + v1221 LocalAddr(-272) -> x2 + v1222 BinopI { op=add, lhs=v1221, rhs_imm=8 } -> x6 + v1223 Load { addr=v1221, disp=8, kind=I64 } -> x2 + v1224 Binop { op=add, lhs=v1220, rhs=v1223 } -> x1 + v1225 Binop { op=add, lhs=v1216, rhs=v1224 } -> x0 + v1226 Imm(0) -> x1 + v1227 LoadLocal { off=-523, kind=I64 } -> x1 + v1228 LocalAddr(-274) -> x1 + v1229 Load { addr=v1228, disp=0, kind=I64 } -> x1 + v1230 LocalAddr(-274) -> x2 + v1231 BinopI { op=add, lhs=v1230, rhs_imm=8 } -> x6 + v1232 Load { addr=v1230, disp=8, kind=I64 } -> x2 + v1233 Binop { op=add, lhs=v1229, rhs=v1232 } -> x1 + v1234 Binop { op=add, lhs=v1225, rhs=v1233 } -> x0 + v1235 Imm(0) -> x1 + v1236 LoadLocal { off=-523, kind=I64 } -> x1 + v1237 LocalAddr(-276) -> x1 + v1238 Load { addr=v1237, disp=0, kind=I64 } -> x1 + v1239 LocalAddr(-276) -> x2 + v1240 BinopI { op=add, lhs=v1239, rhs_imm=8 } -> x6 + v1241 Load { addr=v1239, disp=8, kind=I64 } -> x2 + v1242 Binop { op=add, lhs=v1238, rhs=v1241 } -> x1 + v1243 Binop { op=add, lhs=v1234, rhs=v1242 } -> x0 + v1244 Imm(0) -> x1 + v1245 LoadLocal { off=-523, kind=I64 } -> x1 + v1246 LocalAddr(-278) -> x1 + v1247 Load { addr=v1246, disp=0, kind=I64 } -> x1 + v1248 LocalAddr(-278) -> x2 + v1249 BinopI { op=add, lhs=v1248, rhs_imm=8 } -> x6 + v1250 Load { addr=v1248, disp=8, kind=I64 } -> x2 + v1251 Binop { op=add, lhs=v1247, rhs=v1250 } -> x1 + v1252 Binop { op=add, lhs=v1243, rhs=v1251 } -> x0 + v1253 Imm(0) -> x1 + v1254 LoadLocal { off=-523, kind=I64 } -> x1 + v1255 LocalAddr(-280) -> x1 + v1256 Load { addr=v1255, disp=0, kind=I64 } -> x1 + v1257 LocalAddr(-280) -> x2 + v1258 BinopI { op=add, lhs=v1257, rhs_imm=8 } -> x6 + v1259 Load { addr=v1257, disp=8, kind=I64 } -> x2 + v1260 Binop { op=add, lhs=v1256, rhs=v1259 } -> x1 + v1261 Binop { op=add, lhs=v1252, rhs=v1260 } -> x0 + v1262 Imm(0) -> x1 + v1263 LoadLocal { off=-523, kind=I64 } -> x1 + v1264 LocalAddr(-282) -> x1 + v1265 Load { addr=v1264, disp=0, kind=I64 } -> x1 + v1266 LocalAddr(-282) -> x2 + v1267 BinopI { op=add, lhs=v1266, rhs_imm=8 } -> x6 + v1268 Load { addr=v1266, disp=8, kind=I64 } -> x2 + v1269 Binop { op=add, lhs=v1265, rhs=v1268 } -> x1 + v1270 Binop { op=add, lhs=v1261, rhs=v1269 } -> x0 + v1271 Imm(0) -> x1 + v1272 LoadLocal { off=-523, kind=I64 } -> x1 + v1273 LocalAddr(-284) -> x1 + v1274 Load { addr=v1273, disp=0, kind=I64 } -> x1 + v1275 LocalAddr(-284) -> x2 + v1276 BinopI { op=add, lhs=v1275, rhs_imm=8 } -> x6 + v1277 Load { addr=v1275, disp=8, kind=I64 } -> x2 + v1278 Binop { op=add, lhs=v1274, rhs=v1277 } -> x1 + v1279 Binop { op=add, lhs=v1270, rhs=v1278 } -> x0 + v1280 Imm(0) -> x1 + v1281 LoadLocal { off=-523, kind=I64 } -> x1 + v1282 LocalAddr(-286) -> x1 + v1283 Load { addr=v1282, disp=0, kind=I64 } -> x1 + v1284 LocalAddr(-286) -> x2 + v1285 BinopI { op=add, lhs=v1284, rhs_imm=8 } -> x6 + v1286 Load { addr=v1284, disp=8, kind=I64 } -> x2 + v1287 Binop { op=add, lhs=v1283, rhs=v1286 } -> x1 + v1288 Binop { op=add, lhs=v1279, rhs=v1287 } -> x0 + v1289 Imm(0) -> x1 + v1290 LoadLocal { off=-523, kind=I64 } -> x1 + v1291 LocalAddr(-288) -> x1 + v1292 Load { addr=v1291, disp=0, kind=I64 } -> x1 + v1293 LocalAddr(-288) -> x2 + v1294 BinopI { op=add, lhs=v1293, rhs_imm=8 } -> x6 + v1295 Load { addr=v1293, disp=8, kind=I64 } -> x2 + v1296 Binop { op=add, lhs=v1292, rhs=v1295 } -> x1 + v1297 Binop { op=add, lhs=v1288, rhs=v1296 } -> x0 + v1298 Imm(0) -> x1 + v1299 LoadLocal { off=-523, kind=I64 } -> x1 + v1300 LocalAddr(-290) -> x1 + v1301 Load { addr=v1300, disp=0, kind=I64 } -> x1 + v1302 LocalAddr(-290) -> x2 + v1303 BinopI { op=add, lhs=v1302, rhs_imm=8 } -> x6 + v1304 Load { addr=v1302, disp=8, kind=I64 } -> x2 + v1305 Binop { op=add, lhs=v1301, rhs=v1304 } -> x1 + v1306 Binop { op=add, lhs=v1297, rhs=v1305 } -> x0 + v1307 Imm(0) -> x1 + v1308 LoadLocal { off=-523, kind=I64 } -> x1 + v1309 LocalAddr(-292) -> x1 + v1310 Load { addr=v1309, disp=0, kind=I64 } -> x1 + v1311 LocalAddr(-292) -> x2 + v1312 BinopI { op=add, lhs=v1311, rhs_imm=8 } -> x6 + v1313 Load { addr=v1311, disp=8, kind=I64 } -> x2 + v1314 Binop { op=add, lhs=v1310, rhs=v1313 } -> x1 + v1315 Binop { op=add, lhs=v1306, rhs=v1314 } -> x0 + v1316 Imm(0) -> x1 + v1317 LoadLocal { off=-523, kind=I64 } -> x1 + v1318 LocalAddr(-294) -> x1 + v1319 Load { addr=v1318, disp=0, kind=I64 } -> x1 + v1320 LocalAddr(-294) -> x2 + v1321 BinopI { op=add, lhs=v1320, rhs_imm=8 } -> x6 + v1322 Load { addr=v1320, disp=8, kind=I64 } -> x2 + v1323 Binop { op=add, lhs=v1319, rhs=v1322 } -> x1 + v1324 Binop { op=add, lhs=v1315, rhs=v1323 } -> x0 + v1325 Imm(0) -> x1 + v1326 LoadLocal { off=-523, kind=I64 } -> x1 + v1327 LocalAddr(-296) -> x1 + v1328 Load { addr=v1327, disp=0, kind=I64 } -> x1 + v1329 LocalAddr(-296) -> x2 + v1330 BinopI { op=add, lhs=v1329, rhs_imm=8 } -> x6 + v1331 Load { addr=v1329, disp=8, kind=I64 } -> x2 + v1332 Binop { op=add, lhs=v1328, rhs=v1331 } -> x1 + v1333 Binop { op=add, lhs=v1324, rhs=v1332 } -> x0 + v1334 Imm(0) -> x1 + v1335 LoadLocal { off=-523, kind=I64 } -> x1 + v1336 LocalAddr(-298) -> x1 + v1337 Load { addr=v1336, disp=0, kind=I64 } -> x1 + v1338 LocalAddr(-298) -> x2 + v1339 BinopI { op=add, lhs=v1338, rhs_imm=8 } -> x6 + v1340 Load { addr=v1338, disp=8, kind=I64 } -> x2 + v1341 Binop { op=add, lhs=v1337, rhs=v1340 } -> x1 + v1342 Binop { op=add, lhs=v1333, rhs=v1341 } -> x0 + v1343 Imm(0) -> x1 + v1344 LoadLocal { off=-523, kind=I64 } -> x1 + v1345 LocalAddr(-300) -> x1 + v1346 Load { addr=v1345, disp=0, kind=I64 } -> x1 + v1347 LocalAddr(-300) -> x2 + v1348 BinopI { op=add, lhs=v1347, rhs_imm=8 } -> x6 + v1349 Load { addr=v1347, disp=8, kind=I64 } -> x2 + v1350 Binop { op=add, lhs=v1346, rhs=v1349 } -> x1 + v1351 Binop { op=add, lhs=v1342, rhs=v1350 } -> x0 + v1352 Imm(0) -> x1 + v1353 LoadLocal { off=-523, kind=I64 } -> x1 + v1354 LocalAddr(-302) -> x1 + v1355 Load { addr=v1354, disp=0, kind=I64 } -> x1 + v1356 LocalAddr(-302) -> x2 + v1357 BinopI { op=add, lhs=v1356, rhs_imm=8 } -> x6 + v1358 Load { addr=v1356, disp=8, kind=I64 } -> x2 + v1359 Binop { op=add, lhs=v1355, rhs=v1358 } -> x1 + v1360 Binop { op=add, lhs=v1351, rhs=v1359 } -> x0 + v1361 Imm(0) -> x1 + v1362 LoadLocal { off=-523, kind=I64 } -> x1 + v1363 LocalAddr(-304) -> x1 + v1364 Load { addr=v1363, disp=0, kind=I64 } -> x1 + v1365 LocalAddr(-304) -> x2 + v1366 BinopI { op=add, lhs=v1365, rhs_imm=8 } -> x6 + v1367 Load { addr=v1365, disp=8, kind=I64 } -> x2 + v1368 Binop { op=add, lhs=v1364, rhs=v1367 } -> x1 + v1369 Binop { op=add, lhs=v1360, rhs=v1368 } -> x0 + v1370 Imm(0) -> x1 + v1371 LoadLocal { off=-523, kind=I64 } -> x1 + v1372 LocalAddr(-306) -> x1 + v1373 Load { addr=v1372, disp=0, kind=I64 } -> x1 + v1374 LocalAddr(-306) -> x2 + v1375 BinopI { op=add, lhs=v1374, rhs_imm=8 } -> x6 + v1376 Load { addr=v1374, disp=8, kind=I64 } -> x2 + v1377 Binop { op=add, lhs=v1373, rhs=v1376 } -> x1 + v1378 Binop { op=add, lhs=v1369, rhs=v1377 } -> x0 + v1379 Imm(0) -> x1 + v1380 LoadLocal { off=-523, kind=I64 } -> x1 + v1381 LocalAddr(-308) -> x1 + v1382 Load { addr=v1381, disp=0, kind=I64 } -> x1 + v1383 LocalAddr(-308) -> x2 + v1384 BinopI { op=add, lhs=v1383, rhs_imm=8 } -> x6 + v1385 Load { addr=v1383, disp=8, kind=I64 } -> x2 + v1386 Binop { op=add, lhs=v1382, rhs=v1385 } -> x1 + v1387 Binop { op=add, lhs=v1378, rhs=v1386 } -> x0 + v1388 Imm(0) -> x1 + v1389 LoadLocal { off=-523, kind=I64 } -> x1 + v1390 LocalAddr(-310) -> x1 + v1391 Load { addr=v1390, disp=0, kind=I64 } -> x1 + v1392 LocalAddr(-310) -> x2 + v1393 BinopI { op=add, lhs=v1392, rhs_imm=8 } -> x6 + v1394 Load { addr=v1392, disp=8, kind=I64 } -> x2 + v1395 Binop { op=add, lhs=v1391, rhs=v1394 } -> x1 + v1396 Binop { op=add, lhs=v1387, rhs=v1395 } -> x0 + v1397 Imm(0) -> x1 + v1398 LoadLocal { off=-523, kind=I64 } -> x1 + v1399 LocalAddr(-312) -> x1 + v1400 Load { addr=v1399, disp=0, kind=I64 } -> x1 + v1401 LocalAddr(-312) -> x2 + v1402 BinopI { op=add, lhs=v1401, rhs_imm=8 } -> x6 + v1403 Load { addr=v1401, disp=8, kind=I64 } -> x2 + v1404 Binop { op=add, lhs=v1400, rhs=v1403 } -> x1 + v1405 Binop { op=add, lhs=v1396, rhs=v1404 } -> x0 + v1406 Imm(0) -> x1 + v1407 LoadLocal { off=-523, kind=I64 } -> x1 + v1408 LocalAddr(-314) -> x1 + v1409 Load { addr=v1408, disp=0, kind=I64 } -> x1 + v1410 LocalAddr(-314) -> x2 + v1411 BinopI { op=add, lhs=v1410, rhs_imm=8 } -> x6 + v1412 Load { addr=v1410, disp=8, kind=I64 } -> x2 + v1413 Binop { op=add, lhs=v1409, rhs=v1412 } -> x1 + v1414 Binop { op=add, lhs=v1405, rhs=v1413 } -> x0 + v1415 Imm(0) -> x1 + v1416 LoadLocal { off=-523, kind=I64 } -> x1 + v1417 LocalAddr(-316) -> x1 + v1418 Load { addr=v1417, disp=0, kind=I64 } -> x1 + v1419 LocalAddr(-316) -> x2 + v1420 BinopI { op=add, lhs=v1419, rhs_imm=8 } -> x6 + v1421 Load { addr=v1419, disp=8, kind=I64 } -> x2 + v1422 Binop { op=add, lhs=v1418, rhs=v1421 } -> x1 + v1423 Binop { op=add, lhs=v1414, rhs=v1422 } -> x0 + v1424 Imm(0) -> x1 + v1425 LoadLocal { off=-523, kind=I64 } -> x1 + v1426 LocalAddr(-318) -> x1 + v1427 Load { addr=v1426, disp=0, kind=I64 } -> x1 + v1428 LocalAddr(-318) -> x2 + v1429 BinopI { op=add, lhs=v1428, rhs_imm=8 } -> x6 + v1430 Load { addr=v1428, disp=8, kind=I64 } -> x2 + v1431 Binop { op=add, lhs=v1427, rhs=v1430 } -> x1 + v1432 Binop { op=add, lhs=v1423, rhs=v1431 } -> x0 + v1433 Imm(0) -> x1 + v1434 LoadLocal { off=-523, kind=I64 } -> x1 + v1435 LocalAddr(-320) -> x1 + v1436 Load { addr=v1435, disp=0, kind=I64 } -> x1 + v1437 LocalAddr(-320) -> x2 + v1438 BinopI { op=add, lhs=v1437, rhs_imm=8 } -> x6 + v1439 Load { addr=v1437, disp=8, kind=I64 } -> x2 + v1440 Binop { op=add, lhs=v1436, rhs=v1439 } -> x1 + v1441 Binop { op=add, lhs=v1432, rhs=v1440 } -> x0 + v1442 Imm(0) -> x1 + v1443 LoadLocal { off=-523, kind=I64 } -> x1 + v1444 LocalAddr(-322) -> x1 + v1445 Load { addr=v1444, disp=0, kind=I64 } -> x1 + v1446 LocalAddr(-322) -> x2 + v1447 BinopI { op=add, lhs=v1446, rhs_imm=8 } -> x6 + v1448 Load { addr=v1446, disp=8, kind=I64 } -> x2 + v1449 Binop { op=add, lhs=v1445, rhs=v1448 } -> x1 + v1450 Binop { op=add, lhs=v1441, rhs=v1449 } -> x0 + v1451 Imm(0) -> x1 + v1452 LoadLocal { off=-523, kind=I64 } -> x1 + v1453 LocalAddr(-324) -> x1 + v1454 Load { addr=v1453, disp=0, kind=I64 } -> x1 + v1455 LocalAddr(-324) -> x2 + v1456 BinopI { op=add, lhs=v1455, rhs_imm=8 } -> x6 + v1457 Load { addr=v1455, disp=8, kind=I64 } -> x2 + v1458 Binop { op=add, lhs=v1454, rhs=v1457 } -> x1 + v1459 Binop { op=add, lhs=v1450, rhs=v1458 } -> x0 + v1460 Imm(0) -> x1 + v1461 LoadLocal { off=-523, kind=I64 } -> x1 + v1462 LocalAddr(-326) -> x1 + v1463 Load { addr=v1462, disp=0, kind=I64 } -> x1 + v1464 LocalAddr(-326) -> x2 + v1465 BinopI { op=add, lhs=v1464, rhs_imm=8 } -> x6 + v1466 Load { addr=v1464, disp=8, kind=I64 } -> x2 + v1467 Binop { op=add, lhs=v1463, rhs=v1466 } -> x1 + v1468 Binop { op=add, lhs=v1459, rhs=v1467 } -> x0 + v1469 Imm(0) -> x1 + v1470 LoadLocal { off=-523, kind=I64 } -> x1 + v1471 LocalAddr(-328) -> x1 + v1472 Load { addr=v1471, disp=0, kind=I64 } -> x1 + v1473 LocalAddr(-328) -> x2 + v1474 BinopI { op=add, lhs=v1473, rhs_imm=8 } -> x6 + v1475 Load { addr=v1473, disp=8, kind=I64 } -> x2 + v1476 Binop { op=add, lhs=v1472, rhs=v1475 } -> x1 + v1477 Binop { op=add, lhs=v1468, rhs=v1476 } -> x0 + v1478 Imm(0) -> x1 + v1479 LoadLocal { off=-523, kind=I64 } -> x1 + v1480 LocalAddr(-330) -> x1 + v1481 Load { addr=v1480, disp=0, kind=I64 } -> x1 + v1482 LocalAddr(-330) -> x2 + v1483 BinopI { op=add, lhs=v1482, rhs_imm=8 } -> x6 + v1484 Load { addr=v1482, disp=8, kind=I64 } -> x2 + v1485 Binop { op=add, lhs=v1481, rhs=v1484 } -> x1 + v1486 Binop { op=add, lhs=v1477, rhs=v1485 } -> x0 + v1487 Imm(0) -> x1 + v1488 LoadLocal { off=-523, kind=I64 } -> x1 + v1489 LocalAddr(-332) -> x1 + v1490 Load { addr=v1489, disp=0, kind=I64 } -> x1 + v1491 LocalAddr(-332) -> x2 + v1492 BinopI { op=add, lhs=v1491, rhs_imm=8 } -> x6 + v1493 Load { addr=v1491, disp=8, kind=I64 } -> x2 + v1494 Binop { op=add, lhs=v1490, rhs=v1493 } -> x1 + v1495 Binop { op=add, lhs=v1486, rhs=v1494 } -> x0 + v1496 Imm(0) -> x1 + v1497 LoadLocal { off=-523, kind=I64 } -> x1 + v1498 LocalAddr(-334) -> x1 + v1499 Load { addr=v1498, disp=0, kind=I64 } -> x1 + v1500 LocalAddr(-334) -> x2 + v1501 BinopI { op=add, lhs=v1500, rhs_imm=8 } -> x6 + v1502 Load { addr=v1500, disp=8, kind=I64 } -> x2 + v1503 Binop { op=add, lhs=v1499, rhs=v1502 } -> x1 + v1504 Binop { op=add, lhs=v1495, rhs=v1503 } -> x0 + v1505 Imm(0) -> x1 + v1506 LoadLocal { off=-523, kind=I64 } -> x1 + v1507 LocalAddr(-336) -> x1 + v1508 Load { addr=v1507, disp=0, kind=I64 } -> x1 + v1509 LocalAddr(-336) -> x2 + v1510 BinopI { op=add, lhs=v1509, rhs_imm=8 } -> x6 + v1511 Load { addr=v1509, disp=8, kind=I64 } -> x2 + v1512 Binop { op=add, lhs=v1508, rhs=v1511 } -> x1 + v1513 Binop { op=add, lhs=v1504, rhs=v1512 } -> x0 + v1514 Imm(0) -> x1 + v1515 LoadLocal { off=-523, kind=I64 } -> x1 + v1516 LocalAddr(-338) -> x1 + v1517 Load { addr=v1516, disp=0, kind=I64 } -> x1 + v1518 LocalAddr(-338) -> x2 + v1519 BinopI { op=add, lhs=v1518, rhs_imm=8 } -> x6 + v1520 Load { addr=v1518, disp=8, kind=I64 } -> x2 + v1521 Binop { op=add, lhs=v1517, rhs=v1520 } -> x1 + v1522 Binop { op=add, lhs=v1513, rhs=v1521 } -> x0 + v1523 Imm(0) -> x1 + v1524 LoadLocal { off=-523, kind=I64 } -> x1 + v1525 LocalAddr(-340) -> x1 + v1526 Load { addr=v1525, disp=0, kind=I64 } -> x1 + v1527 LocalAddr(-340) -> x2 + v1528 BinopI { op=add, lhs=v1527, rhs_imm=8 } -> x6 + v1529 Load { addr=v1527, disp=8, kind=I64 } -> x2 + v1530 Binop { op=add, lhs=v1526, rhs=v1529 } -> x1 + v1531 Binop { op=add, lhs=v1522, rhs=v1530 } -> x0 + v1532 Imm(0) -> x1 + v1533 LoadLocal { off=-523, kind=I64 } -> x1 + v1534 LocalAddr(-342) -> x1 + v1535 Load { addr=v1534, disp=0, kind=I64 } -> x1 + v1536 LocalAddr(-342) -> x2 + v1537 BinopI { op=add, lhs=v1536, rhs_imm=8 } -> x6 + v1538 Load { addr=v1536, disp=8, kind=I64 } -> x2 + v1539 Binop { op=add, lhs=v1535, rhs=v1538 } -> x1 + v1540 Binop { op=add, lhs=v1531, rhs=v1539 } -> x0 + v1541 Imm(0) -> x1 + v1542 LoadLocal { off=-523, kind=I64 } -> x1 + v1543 LocalAddr(-344) -> x1 + v1544 Load { addr=v1543, disp=0, kind=I64 } -> x1 + v1545 LocalAddr(-344) -> x2 + v1546 BinopI { op=add, lhs=v1545, rhs_imm=8 } -> x6 + v1547 Load { addr=v1545, disp=8, kind=I64 } -> x2 + v1548 Binop { op=add, lhs=v1544, rhs=v1547 } -> x1 + v1549 Binop { op=add, lhs=v1540, rhs=v1548 } -> x0 + v1550 Imm(0) -> x1 + v1551 LoadLocal { off=-523, kind=I64 } -> x1 + v1552 LocalAddr(-346) -> x1 + v1553 Load { addr=v1552, disp=0, kind=I64 } -> x1 + v1554 LocalAddr(-346) -> x2 + v1555 BinopI { op=add, lhs=v1554, rhs_imm=8 } -> x6 + v1556 Load { addr=v1554, disp=8, kind=I64 } -> x2 + v1557 Binop { op=add, lhs=v1553, rhs=v1556 } -> x1 + v1558 Binop { op=add, lhs=v1549, rhs=v1557 } -> x0 + v1559 Imm(0) -> x1 + v1560 LoadLocal { off=-523, kind=I64 } -> x1 + v1561 LocalAddr(-348) -> x1 + v1562 Load { addr=v1561, disp=0, kind=I64 } -> x1 + v1563 LocalAddr(-348) -> x2 + v1564 BinopI { op=add, lhs=v1563, rhs_imm=8 } -> x6 + v1565 Load { addr=v1563, disp=8, kind=I64 } -> x2 + v1566 Binop { op=add, lhs=v1562, rhs=v1565 } -> x1 + v1567 Binop { op=add, lhs=v1558, rhs=v1566 } -> x0 + v1568 Imm(0) -> x1 + v1569 LoadLocal { off=-523, kind=I64 } -> x1 + v1570 LocalAddr(-350) -> x1 + v1571 Load { addr=v1570, disp=0, kind=I64 } -> x1 + v1572 LocalAddr(-350) -> x2 + v1573 BinopI { op=add, lhs=v1572, rhs_imm=8 } -> x6 + v1574 Load { addr=v1572, disp=8, kind=I64 } -> x2 + v1575 Binop { op=add, lhs=v1571, rhs=v1574 } -> x1 + v1576 Binop { op=add, lhs=v1567, rhs=v1575 } -> x0 + v1577 Imm(0) -> x1 + v1578 LoadLocal { off=-523, kind=I64 } -> x1 + v1579 LocalAddr(-352) -> x1 + v1580 Load { addr=v1579, disp=0, kind=I64 } -> x1 + v1581 LocalAddr(-352) -> x2 + v1582 BinopI { op=add, lhs=v1581, rhs_imm=8 } -> x6 + v1583 Load { addr=v1581, disp=8, kind=I64 } -> x2 + v1584 Binop { op=add, lhs=v1580, rhs=v1583 } -> x1 + v1585 Binop { op=add, lhs=v1576, rhs=v1584 } -> x0 + v1586 Imm(0) -> x1 + v1587 LoadLocal { off=-523, kind=I64 } -> x1 + v1588 LocalAddr(-354) -> x1 + v1589 Load { addr=v1588, disp=0, kind=I64 } -> x1 + v1590 LocalAddr(-354) -> x2 + v1591 BinopI { op=add, lhs=v1590, rhs_imm=8 } -> x6 + v1592 Load { addr=v1590, disp=8, kind=I64 } -> x2 + v1593 Binop { op=add, lhs=v1589, rhs=v1592 } -> x1 + v1594 Binop { op=add, lhs=v1585, rhs=v1593 } -> x0 + v1595 Imm(0) -> x1 + v1596 LoadLocal { off=-523, kind=I64 } -> x1 + v1597 LocalAddr(-356) -> x1 + v1598 Load { addr=v1597, disp=0, kind=I64 } -> x1 + v1599 LocalAddr(-356) -> x2 + v1600 BinopI { op=add, lhs=v1599, rhs_imm=8 } -> x6 + v1601 Load { addr=v1599, disp=8, kind=I64 } -> x2 + v1602 Binop { op=add, lhs=v1598, rhs=v1601 } -> x1 + v1603 Binop { op=add, lhs=v1594, rhs=v1602 } -> x0 + v1604 Imm(0) -> x1 + v1605 LoadLocal { off=-523, kind=I64 } -> x1 + v1606 LocalAddr(-358) -> x1 + v1607 Load { addr=v1606, disp=0, kind=I64 } -> x1 + v1608 LocalAddr(-358) -> x2 + v1609 BinopI { op=add, lhs=v1608, rhs_imm=8 } -> x6 + v1610 Load { addr=v1608, disp=8, kind=I64 } -> x2 + v1611 Binop { op=add, lhs=v1607, rhs=v1610 } -> x1 + v1612 Binop { op=add, lhs=v1603, rhs=v1611 } -> x0 + v1613 Imm(0) -> x1 + v1614 LoadLocal { off=-523, kind=I64 } -> x1 + v1615 LocalAddr(-360) -> x1 + v1616 Load { addr=v1615, disp=0, kind=I64 } -> x1 + v1617 LocalAddr(-360) -> x2 + v1618 BinopI { op=add, lhs=v1617, rhs_imm=8 } -> x6 + v1619 Load { addr=v1617, disp=8, kind=I64 } -> x2 + v1620 Binop { op=add, lhs=v1616, rhs=v1619 } -> x1 + v1621 Binop { op=add, lhs=v1612, rhs=v1620 } -> x0 + v1622 Imm(0) -> x1 + v1623 LoadLocal { off=-523, kind=I64 } -> x1 + v1624 LocalAddr(-362) -> x1 + v1625 Load { addr=v1624, disp=0, kind=I64 } -> x1 + v1626 LocalAddr(-362) -> x2 + v1627 BinopI { op=add, lhs=v1626, rhs_imm=8 } -> x6 + v1628 Load { addr=v1626, disp=8, kind=I64 } -> x2 + v1629 Binop { op=add, lhs=v1625, rhs=v1628 } -> x1 + v1630 Binop { op=add, lhs=v1621, rhs=v1629 } -> x0 + v1631 Imm(0) -> x1 + v1632 LoadLocal { off=-523, kind=I64 } -> x1 + v1633 LocalAddr(-364) -> x1 + v1634 Load { addr=v1633, disp=0, kind=I64 } -> x1 + v1635 LocalAddr(-364) -> x2 + v1636 BinopI { op=add, lhs=v1635, rhs_imm=8 } -> x6 + v1637 Load { addr=v1635, disp=8, kind=I64 } -> x2 + v1638 Binop { op=add, lhs=v1634, rhs=v1637 } -> x1 + v1639 Binop { op=add, lhs=v1630, rhs=v1638 } -> x0 + v1640 Imm(0) -> x1 + v1641 LoadLocal { off=-523, kind=I64 } -> x1 + v1642 LocalAddr(-366) -> x1 + v1643 Load { addr=v1642, disp=0, kind=I64 } -> x1 + v1644 LocalAddr(-366) -> x2 + v1645 BinopI { op=add, lhs=v1644, rhs_imm=8 } -> x6 + v1646 Load { addr=v1644, disp=8, kind=I64 } -> x2 + v1647 Binop { op=add, lhs=v1643, rhs=v1646 } -> x1 + v1648 Binop { op=add, lhs=v1639, rhs=v1647 } -> x0 + v1649 Imm(0) -> x1 + v1650 LoadLocal { off=-523, kind=I64 } -> x1 + v1651 LocalAddr(-368) -> x1 + v1652 Load { addr=v1651, disp=0, kind=I64 } -> x1 + v1653 LocalAddr(-368) -> x2 + v1654 BinopI { op=add, lhs=v1653, rhs_imm=8 } -> x6 + v1655 Load { addr=v1653, disp=8, kind=I64 } -> x2 + v1656 Binop { op=add, lhs=v1652, rhs=v1655 } -> x1 + v1657 Binop { op=add, lhs=v1648, rhs=v1656 } -> x0 + v1658 Imm(0) -> x1 + v1659 LoadLocal { off=-523, kind=I64 } -> x1 + v1660 LocalAddr(-370) -> x1 + v1661 Load { addr=v1660, disp=0, kind=I64 } -> x1 + v1662 LocalAddr(-370) -> x2 + v1663 BinopI { op=add, lhs=v1662, rhs_imm=8 } -> x6 + v1664 Load { addr=v1662, disp=8, kind=I64 } -> x2 + v1665 Binop { op=add, lhs=v1661, rhs=v1664 } -> x1 + v1666 Binop { op=add, lhs=v1657, rhs=v1665 } -> x0 + v1667 Imm(0) -> x1 + v1668 LoadLocal { off=-523, kind=I64 } -> x1 + v1669 LocalAddr(-372) -> x1 + v1670 Load { addr=v1669, disp=0, kind=I64 } -> x1 + v1671 LocalAddr(-372) -> x2 + v1672 BinopI { op=add, lhs=v1671, rhs_imm=8 } -> x6 + v1673 Load { addr=v1671, disp=8, kind=I64 } -> x2 + v1674 Binop { op=add, lhs=v1670, rhs=v1673 } -> x1 + v1675 Binop { op=add, lhs=v1666, rhs=v1674 } -> x0 + v1676 Imm(0) -> x1 + v1677 LoadLocal { off=-523, kind=I64 } -> x1 + v1678 LocalAddr(-374) -> x1 + v1679 Load { addr=v1678, disp=0, kind=I64 } -> x1 + v1680 LocalAddr(-374) -> x2 + v1681 BinopI { op=add, lhs=v1680, rhs_imm=8 } -> x6 + v1682 Load { addr=v1680, disp=8, kind=I64 } -> x2 + v1683 Binop { op=add, lhs=v1679, rhs=v1682 } -> x1 + v1684 Binop { op=add, lhs=v1675, rhs=v1683 } -> x0 + v1685 Imm(0) -> x1 + v1686 LoadLocal { off=-523, kind=I64 } -> x1 + v1687 LocalAddr(-376) -> x1 + v1688 Load { addr=v1687, disp=0, kind=I64 } -> x1 + v1689 LocalAddr(-376) -> x2 + v1690 BinopI { op=add, lhs=v1689, rhs_imm=8 } -> x6 + v1691 Load { addr=v1689, disp=8, kind=I64 } -> x2 + v1692 Binop { op=add, lhs=v1688, rhs=v1691 } -> x1 + v1693 Binop { op=add, lhs=v1684, rhs=v1692 } -> x0 + v1694 Imm(0) -> x1 + v1695 LoadLocal { off=-523, kind=I64 } -> x1 + v1696 LocalAddr(-378) -> x1 + v1697 Load { addr=v1696, disp=0, kind=I64 } -> x1 + v1698 LocalAddr(-378) -> x2 + v1699 BinopI { op=add, lhs=v1698, rhs_imm=8 } -> x6 + v1700 Load { addr=v1698, disp=8, kind=I64 } -> x2 + v1701 Binop { op=add, lhs=v1697, rhs=v1700 } -> x1 + v1702 Binop { op=add, lhs=v1693, rhs=v1701 } -> x0 + v1703 Imm(0) -> x1 + v1704 LoadLocal { off=-523, kind=I64 } -> x1 + v1705 LocalAddr(-380) -> x1 + v1706 Load { addr=v1705, disp=0, kind=I64 } -> x1 + v1707 LocalAddr(-380) -> x2 + v1708 BinopI { op=add, lhs=v1707, rhs_imm=8 } -> x6 + v1709 Load { addr=v1707, disp=8, kind=I64 } -> x2 + v1710 Binop { op=add, lhs=v1706, rhs=v1709 } -> x1 + v1711 Binop { op=add, lhs=v1702, rhs=v1710 } -> x0 + v1712 Imm(0) -> x1 + v1713 LoadLocal { off=-523, kind=I64 } -> x1 + v1714 LocalAddr(-382) -> x1 + v1715 Load { addr=v1714, disp=0, kind=I64 } -> x1 + v1716 LocalAddr(-382) -> x2 + v1717 BinopI { op=add, lhs=v1716, rhs_imm=8 } -> x6 + v1718 Load { addr=v1716, disp=8, kind=I64 } -> x2 + v1719 Binop { op=add, lhs=v1715, rhs=v1718 } -> x1 + v1720 Binop { op=add, lhs=v1711, rhs=v1719 } -> x0 + v1721 Imm(0) -> x1 + v1722 LoadLocal { off=-523, kind=I64 } -> x1 + v1723 LocalAddr(-384) -> x1 + v1724 Load { addr=v1723, disp=0, kind=I64 } -> x1 + v1725 LocalAddr(-384) -> x2 + v1726 BinopI { op=add, lhs=v1725, rhs_imm=8 } -> x6 + v1727 Load { addr=v1725, disp=8, kind=I64 } -> x2 + v1728 Binop { op=add, lhs=v1724, rhs=v1727 } -> x1 + v1729 Binop { op=add, lhs=v1720, rhs=v1728 } -> x0 + v1730 Imm(0) -> x1 + v1731 LoadLocal { off=-523, kind=I64 } -> x1 + v1732 LocalAddr(-386) -> x1 + v1733 Load { addr=v1732, disp=0, kind=I64 } -> x1 + v1734 LocalAddr(-386) -> x2 + v1735 BinopI { op=add, lhs=v1734, rhs_imm=8 } -> x6 + v1736 Load { addr=v1734, disp=8, kind=I64 } -> x2 + v1737 Binop { op=add, lhs=v1733, rhs=v1736 } -> x1 + v1738 Binop { op=add, lhs=v1729, rhs=v1737 } -> x0 + v1739 Imm(0) -> x1 + v1740 LoadLocal { off=-523, kind=I64 } -> x1 + v1741 LocalAddr(-388) -> x1 + v1742 Load { addr=v1741, disp=0, kind=I64 } -> x1 + v1743 LocalAddr(-388) -> x2 + v1744 BinopI { op=add, lhs=v1743, rhs_imm=8 } -> x6 + v1745 Load { addr=v1743, disp=8, kind=I64 } -> x2 + v1746 Binop { op=add, lhs=v1742, rhs=v1745 } -> x1 + v1747 Binop { op=add, lhs=v1738, rhs=v1746 } -> x0 + v1748 Imm(0) -> x1 + v1749 LoadLocal { off=-523, kind=I64 } -> x1 + v1750 LocalAddr(-390) -> x1 + v1751 Load { addr=v1750, disp=0, kind=I64 } -> x1 + v1752 LocalAddr(-390) -> x2 + v1753 BinopI { op=add, lhs=v1752, rhs_imm=8 } -> x6 + v1754 Load { addr=v1752, disp=8, kind=I64 } -> x2 + v1755 Binop { op=add, lhs=v1751, rhs=v1754 } -> x1 + v1756 Binop { op=add, lhs=v1747, rhs=v1755 } -> x0 + v1757 Imm(0) -> x1 + v1758 LoadLocal { off=-523, kind=I64 } -> x1 + v1759 LocalAddr(-392) -> x1 + v1760 Load { addr=v1759, disp=0, kind=I64 } -> x1 + v1761 LocalAddr(-392) -> x2 + v1762 BinopI { op=add, lhs=v1761, rhs_imm=8 } -> x6 + v1763 Load { addr=v1761, disp=8, kind=I64 } -> x2 + v1764 Binop { op=add, lhs=v1760, rhs=v1763 } -> x1 + v1765 Binop { op=add, lhs=v1756, rhs=v1764 } -> x0 + v1766 Imm(0) -> x1 + v1767 LoadLocal { off=-523, kind=I64 } -> x1 + v1768 LocalAddr(-394) -> x1 + v1769 Load { addr=v1768, disp=0, kind=I64 } -> x1 + v1770 LocalAddr(-394) -> x2 + v1771 BinopI { op=add, lhs=v1770, rhs_imm=8 } -> x6 + v1772 Load { addr=v1770, disp=8, kind=I64 } -> x2 + v1773 Binop { op=add, lhs=v1769, rhs=v1772 } -> x1 + v1774 Binop { op=add, lhs=v1765, rhs=v1773 } -> x0 + v1775 Imm(0) -> x1 + v1776 LoadLocal { off=-523, kind=I64 } -> x1 + v1777 LocalAddr(-396) -> x1 + v1778 Load { addr=v1777, disp=0, kind=I64 } -> x1 + v1779 LocalAddr(-396) -> x2 + v1780 BinopI { op=add, lhs=v1779, rhs_imm=8 } -> x6 + v1781 Load { addr=v1779, disp=8, kind=I64 } -> x2 + v1782 Binop { op=add, lhs=v1778, rhs=v1781 } -> x1 + v1783 Binop { op=add, lhs=v1774, rhs=v1782 } -> x0 + v1784 Imm(0) -> x1 + v1785 LoadLocal { off=-523, kind=I64 } -> x1 + v1786 LocalAddr(-398) -> x1 + v1787 Load { addr=v1786, disp=0, kind=I64 } -> x1 + v1788 LocalAddr(-398) -> x2 + v1789 BinopI { op=add, lhs=v1788, rhs_imm=8 } -> x6 + v1790 Load { addr=v1788, disp=8, kind=I64 } -> x2 + v1791 Binop { op=add, lhs=v1787, rhs=v1790 } -> x1 + v1792 Binop { op=add, lhs=v1783, rhs=v1791 } -> x0 + v1793 Imm(0) -> x1 + v1794 LoadLocal { off=-523, kind=I64 } -> x1 + v1795 LocalAddr(-400) -> x1 + v1796 Load { addr=v1795, disp=0, kind=I64 } -> x1 + v1797 LocalAddr(-400) -> x2 + v1798 BinopI { op=add, lhs=v1797, rhs_imm=8 } -> x6 + v1799 Load { addr=v1797, disp=8, kind=I64 } -> x2 + v1800 Binop { op=add, lhs=v1796, rhs=v1799 } -> x1 + v1801 Binop { op=add, lhs=v1792, rhs=v1800 } -> x0 + v1802 Imm(0) -> x1 + v1803 LoadLocal { off=-523, kind=I64 } -> x1 + v1804 LocalAddr(-402) -> x1 + v1805 Load { addr=v1804, disp=0, kind=I64 } -> x1 + v1806 LocalAddr(-402) -> x2 + v1807 BinopI { op=add, lhs=v1806, rhs_imm=8 } -> x6 + v1808 Load { addr=v1806, disp=8, kind=I64 } -> x2 + v1809 Binop { op=add, lhs=v1805, rhs=v1808 } -> x1 + v1810 Binop { op=add, lhs=v1801, rhs=v1809 } -> x0 + v1811 Imm(0) -> x1 + v1812 LoadLocal { off=-523, kind=I64 } -> x1 + v1813 LocalAddr(-404) -> x1 + v1814 Load { addr=v1813, disp=0, kind=I64 } -> x1 + v1815 LocalAddr(-404) -> x2 + v1816 BinopI { op=add, lhs=v1815, rhs_imm=8 } -> x6 + v1817 Load { addr=v1815, disp=8, kind=I64 } -> x2 + v1818 Binop { op=add, lhs=v1814, rhs=v1817 } -> x1 + v1819 Binop { op=add, lhs=v1810, rhs=v1818 } -> x0 + v1820 Imm(0) -> x1 + v1821 LoadLocal { off=-523, kind=I64 } -> x1 + v1822 LocalAddr(-406) -> x1 + v1823 Load { addr=v1822, disp=0, kind=I64 } -> x1 + v1824 LocalAddr(-406) -> x2 + v1825 BinopI { op=add, lhs=v1824, rhs_imm=8 } -> x6 + v1826 Load { addr=v1824, disp=8, kind=I64 } -> x2 + v1827 Binop { op=add, lhs=v1823, rhs=v1826 } -> x1 + v1828 Binop { op=add, lhs=v1819, rhs=v1827 } -> x0 + v1829 Imm(0) -> x1 + v1830 LoadLocal { off=-523, kind=I64 } -> x1 + v1831 LocalAddr(-408) -> x1 + v1832 Load { addr=v1831, disp=0, kind=I64 } -> x1 + v1833 LocalAddr(-408) -> x2 + v1834 BinopI { op=add, lhs=v1833, rhs_imm=8 } -> x6 + v1835 Load { addr=v1833, disp=8, kind=I64 } -> x2 + v1836 Binop { op=add, lhs=v1832, rhs=v1835 } -> x1 + v1837 Binop { op=add, lhs=v1828, rhs=v1836 } -> x0 + v1838 Imm(0) -> x1 + v1839 LoadLocal { off=-523, kind=I64 } -> x1 + v1840 LocalAddr(-410) -> x1 + v1841 Load { addr=v1840, disp=0, kind=I64 } -> x1 + v1842 LocalAddr(-410) -> x2 + v1843 BinopI { op=add, lhs=v1842, rhs_imm=8 } -> x6 + v1844 Load { addr=v1842, disp=8, kind=I64 } -> x2 + v1845 Binop { op=add, lhs=v1841, rhs=v1844 } -> x1 + v1846 Binop { op=add, lhs=v1837, rhs=v1845 } -> x0 + v1847 Imm(0) -> x1 + v1848 LoadLocal { off=-523, kind=I64 } -> x1 + v1849 LocalAddr(-412) -> x1 + v1850 Load { addr=v1849, disp=0, kind=I64 } -> x1 + v1851 LocalAddr(-412) -> x2 + v1852 BinopI { op=add, lhs=v1851, rhs_imm=8 } -> x6 + v1853 Load { addr=v1851, disp=8, kind=I64 } -> x2 + v1854 Binop { op=add, lhs=v1850, rhs=v1853 } -> x1 + v1855 Binop { op=add, lhs=v1846, rhs=v1854 } -> x0 + v1856 Imm(0) -> x1 + v1857 LoadLocal { off=-523, kind=I64 } -> x1 + v1858 LocalAddr(-414) -> x1 + v1859 Load { addr=v1858, disp=0, kind=I64 } -> x1 + v1860 LocalAddr(-414) -> x2 + v1861 BinopI { op=add, lhs=v1860, rhs_imm=8 } -> x6 + v1862 Load { addr=v1860, disp=8, kind=I64 } -> x2 + v1863 Binop { op=add, lhs=v1859, rhs=v1862 } -> x1 + v1864 Binop { op=add, lhs=v1855, rhs=v1863 } -> x0 + v1865 Imm(0) -> x1 + v1866 LoadLocal { off=-523, kind=I64 } -> x1 + v1867 LocalAddr(-416) -> x1 + v1868 Load { addr=v1867, disp=0, kind=I64 } -> x1 + v1869 LocalAddr(-416) -> x2 + v1870 BinopI { op=add, lhs=v1869, rhs_imm=8 } -> x6 + v1871 Load { addr=v1869, disp=8, kind=I64 } -> x2 + v1872 Binop { op=add, lhs=v1868, rhs=v1871 } -> x1 + v1873 Binop { op=add, lhs=v1864, rhs=v1872 } -> x0 + v1874 Imm(0) -> x1 + v1875 LoadLocal { off=-523, kind=I64 } -> x1 + v1876 LocalAddr(-418) -> x1 + v1877 Load { addr=v1876, disp=0, kind=I64 } -> x1 + v1878 LocalAddr(-418) -> x2 + v1879 BinopI { op=add, lhs=v1878, rhs_imm=8 } -> x6 + v1880 Load { addr=v1878, disp=8, kind=I64 } -> x2 + v1881 Binop { op=add, lhs=v1877, rhs=v1880 } -> x1 + v1882 Binop { op=add, lhs=v1873, rhs=v1881 } -> x0 + v1883 Imm(0) -> x1 + v1884 LoadLocal { off=-523, kind=I64 } -> x1 + v1885 LocalAddr(-420) -> x1 + v1886 Load { addr=v1885, disp=0, kind=I64 } -> x1 + v1887 LocalAddr(-420) -> x2 + v1888 BinopI { op=add, lhs=v1887, rhs_imm=8 } -> x6 + v1889 Load { addr=v1887, disp=8, kind=I64 } -> x2 + v1890 Binop { op=add, lhs=v1886, rhs=v1889 } -> x1 + v1891 Binop { op=add, lhs=v1882, rhs=v1890 } -> x0 + v1892 Imm(0) -> x1 + v1893 LoadLocal { off=-523, kind=I64 } -> x1 + v1894 LocalAddr(-422) -> x1 + v1895 Load { addr=v1894, disp=0, kind=I64 } -> x1 + v1896 LocalAddr(-422) -> x2 + v1897 BinopI { op=add, lhs=v1896, rhs_imm=8 } -> x6 + v1898 Load { addr=v1896, disp=8, kind=I64 } -> x2 + v1899 Binop { op=add, lhs=v1895, rhs=v1898 } -> x1 + v1900 Binop { op=add, lhs=v1891, rhs=v1899 } -> x0 + v1901 Imm(0) -> x1 + v1902 LoadLocal { off=-523, kind=I64 } -> x1 + v1903 LocalAddr(-424) -> x1 + v1904 Load { addr=v1903, disp=0, kind=I64 } -> x1 + v1905 LocalAddr(-424) -> x2 + v1906 BinopI { op=add, lhs=v1905, rhs_imm=8 } -> x6 + v1907 Load { addr=v1905, disp=8, kind=I64 } -> x2 + v1908 Binop { op=add, lhs=v1904, rhs=v1907 } -> x1 + v1909 Binop { op=add, lhs=v1900, rhs=v1908 } -> x0 + v1910 Imm(0) -> x1 + v1911 LoadLocal { off=-523, kind=I64 } -> x1 + v1912 LocalAddr(-426) -> x1 + v1913 Load { addr=v1912, disp=0, kind=I64 } -> x1 + v1914 LocalAddr(-426) -> x2 + v1915 BinopI { op=add, lhs=v1914, rhs_imm=8 } -> x6 + v1916 Load { addr=v1914, disp=8, kind=I64 } -> x2 + v1917 Binop { op=add, lhs=v1913, rhs=v1916 } -> x1 + v1918 Binop { op=add, lhs=v1909, rhs=v1917 } -> x0 + v1919 Imm(0) -> x1 + v1920 LoadLocal { off=-523, kind=I64 } -> x1 + v1921 LocalAddr(-428) -> x1 + v1922 Load { addr=v1921, disp=0, kind=I64 } -> x1 + v1923 LocalAddr(-428) -> x2 + v1924 BinopI { op=add, lhs=v1923, rhs_imm=8 } -> x6 + v1925 Load { addr=v1923, disp=8, kind=I64 } -> x2 + v1926 Binop { op=add, lhs=v1922, rhs=v1925 } -> x1 + v1927 Binop { op=add, lhs=v1918, rhs=v1926 } -> x0 + v1928 Imm(0) -> x1 + v1929 LoadLocal { off=-523, kind=I64 } -> x1 + v1930 LocalAddr(-430) -> x1 + v1931 Load { addr=v1930, disp=0, kind=I64 } -> x1 + v1932 LocalAddr(-430) -> x2 + v1933 BinopI { op=add, lhs=v1932, rhs_imm=8 } -> x6 + v1934 Load { addr=v1932, disp=8, kind=I64 } -> x2 + v1935 Binop { op=add, lhs=v1931, rhs=v1934 } -> x1 + v1936 Binop { op=add, lhs=v1927, rhs=v1935 } -> x0 + v1937 Imm(0) -> x1 + v1938 LoadLocal { off=-523, kind=I64 } -> x1 + v1939 LocalAddr(-432) -> x1 + v1940 Load { addr=v1939, disp=0, kind=I64 } -> x1 + v1941 LocalAddr(-432) -> x2 + v1942 BinopI { op=add, lhs=v1941, rhs_imm=8 } -> x6 + v1943 Load { addr=v1941, disp=8, kind=I64 } -> x2 + v1944 Binop { op=add, lhs=v1940, rhs=v1943 } -> x1 + v1945 Binop { op=add, lhs=v1936, rhs=v1944 } -> x0 + v1946 Imm(0) -> x1 + v1947 LoadLocal { off=-523, kind=I64 } -> x1 + v1948 LocalAddr(-434) -> x1 + v1949 Load { addr=v1948, disp=0, kind=I64 } -> x1 + v1950 LocalAddr(-434) -> x2 + v1951 BinopI { op=add, lhs=v1950, rhs_imm=8 } -> x6 + v1952 Load { addr=v1950, disp=8, kind=I64 } -> x2 + v1953 Binop { op=add, lhs=v1949, rhs=v1952 } -> x1 + v1954 Binop { op=add, lhs=v1945, rhs=v1953 } -> x0 + v1955 Imm(0) -> x1 + v1956 LoadLocal { off=-523, kind=I64 } -> x1 + v1957 LocalAddr(-436) -> x1 + v1958 Load { addr=v1957, disp=0, kind=I64 } -> x1 + v1959 LocalAddr(-436) -> x2 + v1960 BinopI { op=add, lhs=v1959, rhs_imm=8 } -> x6 + v1961 Load { addr=v1959, disp=8, kind=I64 } -> x2 + v1962 Binop { op=add, lhs=v1958, rhs=v1961 } -> x1 + v1963 Binop { op=add, lhs=v1954, rhs=v1962 } -> x0 + v1964 Imm(0) -> x1 + v1965 LoadLocal { off=-523, kind=I64 } -> x1 + v1966 LocalAddr(-438) -> x1 + v1967 Load { addr=v1966, disp=0, kind=I64 } -> x1 + v1968 LocalAddr(-438) -> x2 + v1969 BinopI { op=add, lhs=v1968, rhs_imm=8 } -> x6 + v1970 Load { addr=v1968, disp=8, kind=I64 } -> x2 + v1971 Binop { op=add, lhs=v1967, rhs=v1970 } -> x1 + v1972 Binop { op=add, lhs=v1963, rhs=v1971 } -> x0 + v1973 Imm(0) -> x1 + v1974 LoadLocal { off=-523, kind=I64 } -> x1 + v1975 LocalAddr(-440) -> x1 + v1976 Load { addr=v1975, disp=0, kind=I64 } -> x1 + v1977 LocalAddr(-440) -> x2 + v1978 BinopI { op=add, lhs=v1977, rhs_imm=8 } -> x6 + v1979 Load { addr=v1977, disp=8, kind=I64 } -> x2 + v1980 Binop { op=add, lhs=v1976, rhs=v1979 } -> x1 + v1981 Binop { op=add, lhs=v1972, rhs=v1980 } -> x0 + v1982 Imm(0) -> x1 + v1983 LoadLocal { off=-523, kind=I64 } -> x1 + v1984 LocalAddr(-442) -> x1 + v1985 Load { addr=v1984, disp=0, kind=I64 } -> x1 + v1986 LocalAddr(-442) -> x2 + v1987 BinopI { op=add, lhs=v1986, rhs_imm=8 } -> x6 + v1988 Load { addr=v1986, disp=8, kind=I64 } -> x2 + v1989 Binop { op=add, lhs=v1985, rhs=v1988 } -> x1 + v1990 Binop { op=add, lhs=v1981, rhs=v1989 } -> x0 + v1991 Imm(0) -> x1 + v1992 LoadLocal { off=-523, kind=I64 } -> x1 + v1993 LocalAddr(-444) -> x1 + v1994 Load { addr=v1993, disp=0, kind=I64 } -> x1 + v1995 LocalAddr(-444) -> x2 + v1996 BinopI { op=add, lhs=v1995, rhs_imm=8 } -> x6 + v1997 Load { addr=v1995, disp=8, kind=I64 } -> x2 + v1998 Binop { op=add, lhs=v1994, rhs=v1997 } -> x1 + v1999 Binop { op=add, lhs=v1990, rhs=v1998 } -> x0 + v2000 Imm(0) -> x1 + v2001 LoadLocal { off=-523, kind=I64 } -> x1 + v2002 LocalAddr(-446) -> x1 + v2003 Load { addr=v2002, disp=0, kind=I64 } -> x1 + v2004 LocalAddr(-446) -> x2 + v2005 BinopI { op=add, lhs=v2004, rhs_imm=8 } -> x6 + v2006 Load { addr=v2004, disp=8, kind=I64 } -> x2 + v2007 Binop { op=add, lhs=v2003, rhs=v2006 } -> x1 + v2008 Binop { op=add, lhs=v1999, rhs=v2007 } -> x0 + v2009 Imm(0) -> x1 + v2010 LoadLocal { off=-523, kind=I64 } -> x1 + v2011 LocalAddr(-448) -> x1 + v2012 Load { addr=v2011, disp=0, kind=I64 } -> x1 + v2013 LocalAddr(-448) -> x2 + v2014 BinopI { op=add, lhs=v2013, rhs_imm=8 } -> x6 + v2015 Load { addr=v2013, disp=8, kind=I64 } -> x2 + v2016 Binop { op=add, lhs=v2012, rhs=v2015 } -> x1 + v2017 Binop { op=add, lhs=v2008, rhs=v2016 } -> x0 + v2018 Imm(0) -> x1 + v2019 LoadLocal { off=-523, kind=I64 } -> x1 + v2020 LocalAddr(-450) -> x1 + v2021 Load { addr=v2020, disp=0, kind=I64 } -> x1 + v2022 LocalAddr(-450) -> x2 + v2023 BinopI { op=add, lhs=v2022, rhs_imm=8 } -> x6 + v2024 Load { addr=v2022, disp=8, kind=I64 } -> x2 + v2025 Binop { op=add, lhs=v2021, rhs=v2024 } -> x1 + v2026 Binop { op=add, lhs=v2017, rhs=v2025 } -> x0 + v2027 Imm(0) -> x1 + v2028 LoadLocal { off=-523, kind=I64 } -> x1 + v2029 LocalAddr(-452) -> x1 + v2030 Load { addr=v2029, disp=0, kind=I64 } -> x1 + v2031 LocalAddr(-452) -> x2 + v2032 BinopI { op=add, lhs=v2031, rhs_imm=8 } -> x6 + v2033 Load { addr=v2031, disp=8, kind=I64 } -> x2 + v2034 Binop { op=add, lhs=v2030, rhs=v2033 } -> x1 + v2035 Binop { op=add, lhs=v2026, rhs=v2034 } -> x0 + v2036 Imm(0) -> x1 + v2037 LoadLocal { off=-523, kind=I64 } -> x1 + v2038 LocalAddr(-454) -> x1 + v2039 Load { addr=v2038, disp=0, kind=I64 } -> x1 + v2040 LocalAddr(-454) -> x2 + v2041 BinopI { op=add, lhs=v2040, rhs_imm=8 } -> x6 + v2042 Load { addr=v2040, disp=8, kind=I64 } -> x2 + v2043 Binop { op=add, lhs=v2039, rhs=v2042 } -> x1 + v2044 Binop { op=add, lhs=v2035, rhs=v2043 } -> x0 + v2045 Imm(0) -> x1 + v2046 LoadLocal { off=-523, kind=I64 } -> x1 + v2047 LocalAddr(-456) -> x1 + v2048 Load { addr=v2047, disp=0, kind=I64 } -> x1 + v2049 LocalAddr(-456) -> x2 + v2050 BinopI { op=add, lhs=v2049, rhs_imm=8 } -> x6 + v2051 Load { addr=v2049, disp=8, kind=I64 } -> x2 + v2052 Binop { op=add, lhs=v2048, rhs=v2051 } -> x1 + v2053 Binop { op=add, lhs=v2044, rhs=v2052 } -> x0 + v2054 Imm(0) -> x1 + v2055 LoadLocal { off=-523, kind=I64 } -> x1 + v2056 LocalAddr(-458) -> x1 + v2057 Load { addr=v2056, disp=0, kind=I64 } -> x1 + v2058 LocalAddr(-458) -> x2 + v2059 BinopI { op=add, lhs=v2058, rhs_imm=8 } -> x6 + v2060 Load { addr=v2058, disp=8, kind=I64 } -> x2 + v2061 Binop { op=add, lhs=v2057, rhs=v2060 } -> x1 + v2062 Binop { op=add, lhs=v2053, rhs=v2061 } -> x0 + v2063 Imm(0) -> x1 + v2064 LoadLocal { off=-523, kind=I64 } -> x1 + v2065 LocalAddr(-460) -> x1 + v2066 Load { addr=v2065, disp=0, kind=I64 } -> x1 + v2067 LocalAddr(-460) -> x2 + v2068 BinopI { op=add, lhs=v2067, rhs_imm=8 } -> x6 + v2069 Load { addr=v2067, disp=8, kind=I64 } -> x2 + v2070 Binop { op=add, lhs=v2066, rhs=v2069 } -> x1 + v2071 Binop { op=add, lhs=v2062, rhs=v2070 } -> x0 + v2072 Imm(0) -> x1 + v2073 LoadLocal { off=-523, kind=I64 } -> x1 + v2074 LocalAddr(-462) -> x1 + v2075 Load { addr=v2074, disp=0, kind=I64 } -> x1 + v2076 LocalAddr(-462) -> x2 + v2077 BinopI { op=add, lhs=v2076, rhs_imm=8 } -> x6 + v2078 Load { addr=v2076, disp=8, kind=I64 } -> x2 + v2079 Binop { op=add, lhs=v2075, rhs=v2078 } -> x1 + v2080 Binop { op=add, lhs=v2071, rhs=v2079 } -> x0 + v2081 Imm(0) -> x1 + v2082 LoadLocal { off=-523, kind=I64 } -> x1 + v2083 LocalAddr(-464) -> x1 + v2084 Load { addr=v2083, disp=0, kind=I64 } -> x1 + v2085 LocalAddr(-464) -> x2 + v2086 BinopI { op=add, lhs=v2085, rhs_imm=8 } -> x6 + v2087 Load { addr=v2085, disp=8, kind=I64 } -> x2 + v2088 Binop { op=add, lhs=v2084, rhs=v2087 } -> x1 + v2089 Binop { op=add, lhs=v2080, rhs=v2088 } -> x0 + v2090 Imm(0) -> x1 + v2091 LoadLocal { off=-523, kind=I64 } -> x1 + v2092 LocalAddr(-466) -> x1 + v2093 Load { addr=v2092, disp=0, kind=I64 } -> x1 + v2094 LocalAddr(-466) -> x2 + v2095 BinopI { op=add, lhs=v2094, rhs_imm=8 } -> x6 + v2096 Load { addr=v2094, disp=8, kind=I64 } -> x2 + v2097 Binop { op=add, lhs=v2093, rhs=v2096 } -> x1 + v2098 Binop { op=add, lhs=v2089, rhs=v2097 } -> x0 + v2099 Imm(0) -> x1 + v2100 LoadLocal { off=-523, kind=I64 } -> x1 + v2101 LocalAddr(-468) -> x1 + v2102 Load { addr=v2101, disp=0, kind=I64 } -> x1 + v2103 LocalAddr(-468) -> x2 + v2104 BinopI { op=add, lhs=v2103, rhs_imm=8 } -> x6 + v2105 Load { addr=v2103, disp=8, kind=I64 } -> x2 + v2106 Binop { op=add, lhs=v2102, rhs=v2105 } -> x1 + v2107 Binop { op=add, lhs=v2098, rhs=v2106 } -> x0 + v2108 Imm(0) -> x1 + v2109 LoadLocal { off=-523, kind=I64 } -> x1 + v2110 LocalAddr(-470) -> x1 + v2111 Load { addr=v2110, disp=0, kind=I64 } -> x1 + v2112 LocalAddr(-470) -> x2 + v2113 BinopI { op=add, lhs=v2112, rhs_imm=8 } -> x6 + v2114 Load { addr=v2112, disp=8, kind=I64 } -> x2 + v2115 Binop { op=add, lhs=v2111, rhs=v2114 } -> x1 + v2116 Binop { op=add, lhs=v2107, rhs=v2115 } -> x0 + v2117 Imm(0) -> x1 + v2118 LoadLocal { off=-523, kind=I64 } -> x1 + v2119 LocalAddr(-472) -> x1 + v2120 Load { addr=v2119, disp=0, kind=I64 } -> x1 + v2121 LocalAddr(-472) -> x2 + v2122 BinopI { op=add, lhs=v2121, rhs_imm=8 } -> x6 + v2123 Load { addr=v2121, disp=8, kind=I64 } -> x2 + v2124 Binop { op=add, lhs=v2120, rhs=v2123 } -> x1 + v2125 Binop { op=add, lhs=v2116, rhs=v2124 } -> x0 + v2126 Imm(0) -> x1 + v2127 LoadLocal { off=-523, kind=I64 } -> x1 + v2128 LocalAddr(-474) -> x1 + v2129 Load { addr=v2128, disp=0, kind=I64 } -> x1 + v2130 LocalAddr(-474) -> x2 + v2131 BinopI { op=add, lhs=v2130, rhs_imm=8 } -> x6 + v2132 Load { addr=v2130, disp=8, kind=I64 } -> x2 + v2133 Binop { op=add, lhs=v2129, rhs=v2132 } -> x1 + v2134 Binop { op=add, lhs=v2125, rhs=v2133 } -> x0 + v2135 Imm(0) -> x1 + v2136 LoadLocal { off=-523, kind=I64 } -> x1 + v2137 LocalAddr(-476) -> x1 + v2138 Load { addr=v2137, disp=0, kind=I64 } -> x1 + v2139 LocalAddr(-476) -> x2 + v2140 BinopI { op=add, lhs=v2139, rhs_imm=8 } -> x6 + v2141 Load { addr=v2139, disp=8, kind=I64 } -> x2 + v2142 Binop { op=add, lhs=v2138, rhs=v2141 } -> x1 + v2143 Binop { op=add, lhs=v2134, rhs=v2142 } -> x0 + v2144 Imm(0) -> x1 + v2145 LoadLocal { off=-523, kind=I64 } -> x1 + v2146 LocalAddr(-478) -> x1 + v2147 Load { addr=v2146, disp=0, kind=I64 } -> x1 + v2148 LocalAddr(-478) -> x2 + v2149 BinopI { op=add, lhs=v2148, rhs_imm=8 } -> x6 + v2150 Load { addr=v2148, disp=8, kind=I64 } -> x2 + v2151 Binop { op=add, lhs=v2147, rhs=v2150 } -> x1 + v2152 Binop { op=add, lhs=v2143, rhs=v2151 } -> x0 + v2153 Imm(0) -> x1 + v2154 LoadLocal { off=-523, kind=I64 } -> x1 + v2155 LocalAddr(-480) -> x1 + v2156 Load { addr=v2155, disp=0, kind=I64 } -> x1 + v2157 LocalAddr(-480) -> x2 + v2158 BinopI { op=add, lhs=v2157, rhs_imm=8 } -> x6 + v2159 Load { addr=v2157, disp=8, kind=I64 } -> x2 + v2160 Binop { op=add, lhs=v2156, rhs=v2159 } -> x1 + v2161 Binop { op=add, lhs=v2152, rhs=v2160 } -> x0 + v2162 Imm(0) -> x1 + v2163 LoadLocal { off=-523, kind=I64 } -> x1 + v2164 LocalAddr(-482) -> x1 + v2165 Load { addr=v2164, disp=0, kind=I64 } -> x1 + v2166 LocalAddr(-482) -> x2 + v2167 BinopI { op=add, lhs=v2166, rhs_imm=8 } -> x6 + v2168 Load { addr=v2166, disp=8, kind=I64 } -> x2 + v2169 Binop { op=add, lhs=v2165, rhs=v2168 } -> x1 + v2170 Binop { op=add, lhs=v2161, rhs=v2169 } -> x0 + v2171 Imm(0) -> x1 + v2172 LoadLocal { off=-523, kind=I64 } -> x1 + v2173 LocalAddr(-484) -> x1 + v2174 Load { addr=v2173, disp=0, kind=I64 } -> x1 + v2175 LocalAddr(-484) -> x2 + v2176 BinopI { op=add, lhs=v2175, rhs_imm=8 } -> x6 + v2177 Load { addr=v2175, disp=8, kind=I64 } -> x2 + v2178 Binop { op=add, lhs=v2174, rhs=v2177 } -> x1 + v2179 Binop { op=add, lhs=v2170, rhs=v2178 } -> x0 + v2180 Imm(0) -> x1 + v2181 LoadLocal { off=-523, kind=I64 } -> x1 + v2182 LocalAddr(-486) -> x1 + v2183 Load { addr=v2182, disp=0, kind=I64 } -> x1 + v2184 LocalAddr(-486) -> x2 + v2185 BinopI { op=add, lhs=v2184, rhs_imm=8 } -> x6 + v2186 Load { addr=v2184, disp=8, kind=I64 } -> x2 + v2187 Binop { op=add, lhs=v2183, rhs=v2186 } -> x1 + v2188 Binop { op=add, lhs=v2179, rhs=v2187 } -> x0 + v2189 Imm(0) -> x1 + v2190 LoadLocal { off=-523, kind=I64 } -> x1 + v2191 LocalAddr(-488) -> x1 + v2192 Load { addr=v2191, disp=0, kind=I64 } -> x1 + v2193 LocalAddr(-488) -> x2 + v2194 BinopI { op=add, lhs=v2193, rhs_imm=8 } -> x6 + v2195 Load { addr=v2193, disp=8, kind=I64 } -> x2 + v2196 Binop { op=add, lhs=v2192, rhs=v2195 } -> x1 + v2197 Binop { op=add, lhs=v2188, rhs=v2196 } -> x0 + v2198 Imm(0) -> x1 + v2199 LoadLocal { off=-523, kind=I64 } -> x1 + v2200 LocalAddr(-490) -> x1 + v2201 Load { addr=v2200, disp=0, kind=I64 } -> x1 + v2202 LocalAddr(-490) -> x2 + v2203 BinopI { op=add, lhs=v2202, rhs_imm=8 } -> x6 + v2204 Load { addr=v2202, disp=8, kind=I64 } -> x2 + v2205 Binop { op=add, lhs=v2201, rhs=v2204 } -> x1 + v2206 Binop { op=add, lhs=v2197, rhs=v2205 } -> x0 + v2207 Imm(0) -> x1 + v2208 LoadLocal { off=-523, kind=I64 } -> x1 + v2209 LocalAddr(-492) -> x1 + v2210 Load { addr=v2209, disp=0, kind=I64 } -> x1 + v2211 LocalAddr(-492) -> x2 + v2212 BinopI { op=add, lhs=v2211, rhs_imm=8 } -> x6 + v2213 Load { addr=v2211, disp=8, kind=I64 } -> x2 + v2214 Binop { op=add, lhs=v2210, rhs=v2213 } -> x1 + v2215 Binop { op=add, lhs=v2206, rhs=v2214 } -> x0 + v2216 Imm(0) -> x1 + v2217 LoadLocal { off=-523, kind=I64 } -> x1 + v2218 LocalAddr(-494) -> x1 + v2219 Load { addr=v2218, disp=0, kind=I64 } -> x1 + v2220 LocalAddr(-494) -> x2 + v2221 BinopI { op=add, lhs=v2220, rhs_imm=8 } -> x6 + v2222 Load { addr=v2220, disp=8, kind=I64 } -> x2 + v2223 Binop { op=add, lhs=v2219, rhs=v2222 } -> x1 + v2224 Binop { op=add, lhs=v2215, rhs=v2223 } -> x0 + v2225 Imm(0) -> x1 + v2226 LoadLocal { off=-523, kind=I64 } -> x1 + v2227 LocalAddr(-496) -> x1 + v2228 Load { addr=v2227, disp=0, kind=I64 } -> x1 + v2229 LocalAddr(-496) -> x2 + v2230 BinopI { op=add, lhs=v2229, rhs_imm=8 } -> x6 + v2231 Load { addr=v2229, disp=8, kind=I64 } -> x2 + v2232 Binop { op=add, lhs=v2228, rhs=v2231 } -> x1 + v2233 Binop { op=add, lhs=v2224, rhs=v2232 } -> x0 + v2234 Imm(0) -> x1 + v2235 LoadLocal { off=-523, kind=I64 } -> x1 + v2236 LocalAddr(-498) -> x1 + v2237 Load { addr=v2236, disp=0, kind=I64 } -> x1 + v2238 LocalAddr(-498) -> x2 + v2239 BinopI { op=add, lhs=v2238, rhs_imm=8 } -> x6 + v2240 Load { addr=v2238, disp=8, kind=I64 } -> x2 + v2241 Binop { op=add, lhs=v2237, rhs=v2240 } -> x1 + v2242 Binop { op=add, lhs=v2233, rhs=v2241 } -> x0 + v2243 Imm(0) -> x1 + v2244 LoadLocal { off=-523, kind=I64 } -> x1 + v2245 LocalAddr(-500) -> x1 + v2246 Load { addr=v2245, disp=0, kind=I64 } -> x1 + v2247 LocalAddr(-500) -> x2 + v2248 BinopI { op=add, lhs=v2247, rhs_imm=8 } -> x6 + v2249 Load { addr=v2247, disp=8, kind=I64 } -> x2 + v2250 Binop { op=add, lhs=v2246, rhs=v2249 } -> x1 + v2251 Binop { op=add, lhs=v2242, rhs=v2250 } -> x0 + v2252 Imm(0) -> x1 + v2253 LoadLocal { off=-523, kind=I64 } -> x1 + v2254 LocalAddr(-502) -> x1 + v2255 Load { addr=v2254, disp=0, kind=I64 } -> x1 + v2256 LocalAddr(-502) -> x2 + v2257 BinopI { op=add, lhs=v2256, rhs_imm=8 } -> x6 + v2258 Load { addr=v2256, disp=8, kind=I64 } -> x2 + v2259 Binop { op=add, lhs=v2255, rhs=v2258 } -> x1 + v2260 Binop { op=add, lhs=v2251, rhs=v2259 } -> x0 + v2261 Imm(0) -> x1 + v2262 LoadLocal { off=-523, kind=I64 } -> x1 + v2263 LocalAddr(-504) -> x1 + v2264 Load { addr=v2263, disp=0, kind=I64 } -> x1 + v2265 LocalAddr(-504) -> x2 + v2266 BinopI { op=add, lhs=v2265, rhs_imm=8 } -> x6 + v2267 Load { addr=v2265, disp=8, kind=I64 } -> x2 + v2268 Binop { op=add, lhs=v2264, rhs=v2267 } -> x1 + v2269 Binop { op=add, lhs=v2260, rhs=v2268 } -> x0 + v2270 Imm(0) -> x1 + v2271 LoadLocal { off=-523, kind=I64 } -> x1 + v2272 LocalAddr(-506) -> x1 + v2273 Load { addr=v2272, disp=0, kind=I64 } -> x1 + v2274 LocalAddr(-506) -> x2 + v2275 BinopI { op=add, lhs=v2274, rhs_imm=8 } -> x6 + v2276 Load { addr=v2274, disp=8, kind=I64 } -> x2 + v2277 Binop { op=add, lhs=v2273, rhs=v2276 } -> x1 + v2278 Binop { op=add, lhs=v2269, rhs=v2277 } -> x0 + v2279 Imm(0) -> x1 + v2280 LoadLocal { off=-523, kind=I64 } -> x1 + v2281 LocalAddr(-508) -> x1 + v2282 Load { addr=v2281, disp=0, kind=I64 } -> x1 + v2283 LocalAddr(-508) -> x2 + v2284 BinopI { op=add, lhs=v2283, rhs_imm=8 } -> x6 + v2285 Load { addr=v2283, disp=8, kind=I64 } -> x2 + v2286 Binop { op=add, lhs=v2282, rhs=v2285 } -> x1 + v2287 Binop { op=add, lhs=v2278, rhs=v2286 } -> x0 + v2288 Imm(0) -> x1 + v2289 LoadLocal { off=-523, kind=I64 } -> x1 + v2290 LocalAddr(-510) -> x1 + v2291 Load { addr=v2290, disp=0, kind=I64 } -> x1 + v2292 LocalAddr(-510) -> x2 + v2293 BinopI { op=add, lhs=v2292, rhs_imm=8 } -> x6 + v2294 Load { addr=v2292, disp=8, kind=I64 } -> x2 + v2295 Binop { op=add, lhs=v2291, rhs=v2294 } -> x1 + v2296 Binop { op=add, lhs=v2287, rhs=v2295 } -> x0 + v2297 Imm(0) -> x1 + v2298 LoadLocal { off=-523, kind=I64 } -> x1 + v2299 LocalAddr(-512) -> x1 + v2300 Load { addr=v2299, disp=0, kind=I64 } -> x1 + v2301 LocalAddr(-512) -> x2 + v2302 BinopI { op=add, lhs=v2301, rhs_imm=8 } -> x6 + v2303 Load { addr=v2301, disp=8, kind=I64 } -> x2 + v2304 Binop { op=add, lhs=v2300, rhs=v2303 } -> x1 + v2305 Binop { op=add, lhs=v2296, rhs=v2304 } -> x0 + v2306 Imm(0) -> x1 + v2307 LoadLocal { off=-523, kind=I64 } -> x1 + v2308 LocalAddr(-514) -> x1 + v2309 Load { addr=v2308, disp=0, kind=I64 } -> x1 + v2310 LocalAddr(-514) -> x2 + v2311 BinopI { op=add, lhs=v2310, rhs_imm=8 } -> x6 + v2312 Load { addr=v2310, disp=8, kind=I64 } -> x2 + v2313 Binop { op=add, lhs=v2309, rhs=v2312 } -> x1 + v2314 Binop { op=add, lhs=v2305, rhs=v2313 } -> x0 + v2315 Imm(0) -> x1 + v2316 LoadLocal { off=-523, kind=I64 } -> x1 + v2317 LocalAddr(-516) -> x1 + v2318 Load { addr=v2317, disp=0, kind=I64 } -> x1 + v2319 LocalAddr(-516) -> x2 + v2320 BinopI { op=add, lhs=v2319, rhs_imm=8 } -> x6 + v2321 Load { addr=v2319, disp=8, kind=I64 } -> x2 + v2322 Binop { op=add, lhs=v2318, rhs=v2321 } -> x1 + v2323 Binop { op=add, lhs=v2314, rhs=v2322 } -> x0 + v2324 Imm(0) -> x1 + v2325 LoadLocal { off=-523, kind=I64 } -> x1 + v2326 LocalAddr(-518) -> x1 + v2327 Load { addr=v2326, disp=0, kind=I64 } -> x1 + v2328 LocalAddr(-518) -> x2 + v2329 BinopI { op=add, lhs=v2328, rhs_imm=8 } -> x6 + v2330 Load { addr=v2328, disp=8, kind=I64 } -> x2 + v2331 Binop { op=add, lhs=v2327, rhs=v2330 } -> x1 + v2332 Binop { op=add, lhs=v2323, rhs=v2331 } -> x0 + v2333 Imm(0) -> x1 + v2334 LoadLocal { off=-523, kind=I64 } -> x1 + v2335 LocalAddr(-520) -> x1 + v2336 Load { addr=v2335, disp=0, kind=I64 } -> x1 + v2337 LocalAddr(-520) -> x2 + v2338 BinopI { op=add, lhs=v2337, rhs_imm=8 } -> x6 + v2339 Load { addr=v2337, disp=8, kind=I64 } -> x2 + v2340 Binop { op=add, lhs=v2336, rhs=v2339 } -> x1 + v2341 Binop { op=add, lhs=v2332, rhs=v2340 } -> x0 + v2342 Imm(0) -> x1 + v2343 LoadLocal { off=-523, kind=I64 } -> x1 + v2344 LocalAddr(-522) -> x1 + v2345 Load { addr=v2344, disp=0, kind=I64 } -> x1 + v2346 LocalAddr(-522) -> x2 + v2347 BinopI { op=add, lhs=v2346, rhs_imm=8 } -> x6 + v2348 Load { addr=v2346, disp=8, kind=I64 } -> x2 + v2349 Binop { op=add, lhs=v2345, rhs=v2348 } -> x1 + v2350 Binop { op=add, lhs=v2341, rhs=v2349 } -> x0 + v2351 Imm(0) -> x1 + v2352 LoadLocal { off=-523, kind=I64 } -> x1 + terminator Return(v2350) (exit_acc=v2350) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=sum_longs +fn ent_pc=1 n_params=260 variadic=false locals=1 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 ParamRef(2, kind=I64) -> x2 + v6 Imm(0) -> x0 + v7 ParamRef(3, kind=I64) -> x1 + v8 Imm(0) -> x0 + v9 ParamRef(4, kind=I64) -> x8 + v10 Imm(0) -> x0 + v11 ParamRef(5, kind=I64) -> x9 + v12 Imm(0) -> x0 + v13 Imm(0) -> x0 + v14 Imm(0) -> x3 + v15 LoadLocal { off=-1, kind=I64 } -> x3 + v16 LoadLocal { off=2, kind=I64 } -> x3 + v17 Binop { op=add, lhs=v13, rhs=v1 } -> x0 + v18 Imm(0) -> x7 + v19 LoadLocal { off=-1, kind=I64 } -> x7 + v20 LoadLocal { off=3, kind=I64 } -> x7 + v21 Binop { op=add, lhs=v17, rhs=v3 } -> x0 + v22 Imm(0) -> x6 + v23 LoadLocal { off=-1, kind=I64 } -> x6 + v24 LoadLocal { off=4, kind=I64 } -> x6 + v25 Binop { op=add, lhs=v21, rhs=v5 } -> x0 + v26 Imm(0) -> x2 + v27 LoadLocal { off=-1, kind=I64 } -> x2 + v28 LoadLocal { off=5, kind=I64 } -> x2 + v29 Binop { op=add, lhs=v25, rhs=v7 } -> x0 + v30 Imm(0) -> x1 + v31 LoadLocal { off=-1, kind=I64 } -> x1 + v32 LoadLocal { off=6, kind=I64 } -> x1 + v33 Binop { op=add, lhs=v29, rhs=v9 } -> x0 + v34 Imm(0) -> x1 + v35 LoadLocal { off=-1, kind=I64 } -> x1 + v36 LoadLocal { off=7, kind=I64 } -> x1 + v37 Binop { op=add, lhs=v33, rhs=v11 } -> x0 + v38 Imm(0) -> x1 + v39 LoadLocal { off=-1, kind=I64 } -> x1 + v40 LoadLocal { off=8, kind=I64 } -> x1 + v41 Binop { op=add, lhs=v37, rhs=v40 } -> x0 + v42 Imm(0) -> x1 + v43 LoadLocal { off=-1, kind=I64 } -> x1 + v44 LoadLocal { off=9, kind=I64 } -> x1 + v45 Binop { op=add, lhs=v41, rhs=v44 } -> x0 + v46 Imm(0) -> x1 + v47 LoadLocal { off=-1, kind=I64 } -> x1 + v48 LoadLocal { off=10, kind=I64 } -> x1 + v49 Binop { op=add, lhs=v45, rhs=v48 } -> x0 + v50 Imm(0) -> x1 + v51 LoadLocal { off=-1, kind=I64 } -> x1 + v52 LoadLocal { off=11, kind=I64 } -> x1 + v53 Binop { op=add, lhs=v49, rhs=v52 } -> x0 + v54 Imm(0) -> x1 + v55 LoadLocal { off=-1, kind=I64 } -> x1 + v56 LoadLocal { off=12, kind=I64 } -> x1 + v57 Binop { op=add, lhs=v53, rhs=v56 } -> x0 + v58 Imm(0) -> x1 + v59 LoadLocal { off=-1, kind=I64 } -> x1 + v60 LoadLocal { off=13, kind=I64 } -> x1 + v61 Binop { op=add, lhs=v57, rhs=v60 } -> x0 + v62 Imm(0) -> x1 + v63 LoadLocal { off=-1, kind=I64 } -> x1 + v64 LoadLocal { off=14, kind=I64 } -> x1 + v65 Binop { op=add, lhs=v61, rhs=v64 } -> x0 + v66 Imm(0) -> x1 + v67 LoadLocal { off=-1, kind=I64 } -> x1 + v68 LoadLocal { off=15, kind=I64 } -> x1 + v69 Binop { op=add, lhs=v65, rhs=v68 } -> x0 + v70 Imm(0) -> x1 + v71 LoadLocal { off=-1, kind=I64 } -> x1 + v72 LoadLocal { off=16, kind=I64 } -> x1 + v73 Binop { op=add, lhs=v69, rhs=v72 } -> x0 + v74 Imm(0) -> x1 + v75 LoadLocal { off=-1, kind=I64 } -> x1 + v76 LoadLocal { off=17, kind=I64 } -> x1 + v77 Binop { op=add, lhs=v73, rhs=v76 } -> x0 + v78 Imm(0) -> x1 + v79 LoadLocal { off=-1, kind=I64 } -> x1 + v80 LoadLocal { off=18, kind=I64 } -> x1 + v81 Binop { op=add, lhs=v77, rhs=v80 } -> x0 + v82 Imm(0) -> x1 + v83 LoadLocal { off=-1, kind=I64 } -> x1 + v84 LoadLocal { off=19, kind=I64 } -> x1 + v85 Binop { op=add, lhs=v81, rhs=v84 } -> x0 + v86 Imm(0) -> x1 + v87 LoadLocal { off=-1, kind=I64 } -> x1 + v88 LoadLocal { off=20, kind=I64 } -> x1 + v89 Binop { op=add, lhs=v85, rhs=v88 } -> x0 + v90 Imm(0) -> x1 + v91 LoadLocal { off=-1, kind=I64 } -> x1 + v92 LoadLocal { off=21, kind=I64 } -> x1 + v93 Binop { op=add, lhs=v89, rhs=v92 } -> x0 + v94 Imm(0) -> x1 + v95 LoadLocal { off=-1, kind=I64 } -> x1 + v96 LoadLocal { off=22, kind=I64 } -> x1 + v97 Binop { op=add, lhs=v93, rhs=v96 } -> x0 + v98 Imm(0) -> x1 + v99 LoadLocal { off=-1, kind=I64 } -> x1 + v100 LoadLocal { off=23, kind=I64 } -> x1 + v101 Binop { op=add, lhs=v97, rhs=v100 } -> x0 + v102 Imm(0) -> x1 + v103 LoadLocal { off=-1, kind=I64 } -> x1 + v104 LoadLocal { off=24, kind=I64 } -> x1 + v105 Binop { op=add, lhs=v101, rhs=v104 } -> x0 + v106 Imm(0) -> x1 + v107 LoadLocal { off=-1, kind=I64 } -> x1 + v108 LoadLocal { off=25, kind=I64 } -> x1 + v109 Binop { op=add, lhs=v105, rhs=v108 } -> x0 + v110 Imm(0) -> x1 + v111 LoadLocal { off=-1, kind=I64 } -> x1 + v112 LoadLocal { off=26, kind=I64 } -> x1 + v113 Binop { op=add, lhs=v109, rhs=v112 } -> x0 + v114 Imm(0) -> x1 + v115 LoadLocal { off=-1, kind=I64 } -> x1 + v116 LoadLocal { off=27, kind=I64 } -> x1 + v117 Binop { op=add, lhs=v113, rhs=v116 } -> x0 + v118 Imm(0) -> x1 + v119 LoadLocal { off=-1, kind=I64 } -> x1 + v120 LoadLocal { off=28, kind=I64 } -> x1 + v121 Binop { op=add, lhs=v117, rhs=v120 } -> x0 + v122 Imm(0) -> x1 + v123 LoadLocal { off=-1, kind=I64 } -> x1 + v124 LoadLocal { off=29, kind=I64 } -> x1 + v125 Binop { op=add, lhs=v121, rhs=v124 } -> x0 + v126 Imm(0) -> x1 + v127 LoadLocal { off=-1, kind=I64 } -> x1 + v128 LoadLocal { off=30, kind=I64 } -> x1 + v129 Binop { op=add, lhs=v125, rhs=v128 } -> x0 + v130 Imm(0) -> x1 + v131 LoadLocal { off=-1, kind=I64 } -> x1 + v132 LoadLocal { off=31, kind=I64 } -> x1 + v133 Binop { op=add, lhs=v129, rhs=v132 } -> x0 + v134 Imm(0) -> x1 + v135 LoadLocal { off=-1, kind=I64 } -> x1 + v136 LoadLocal { off=32, kind=I64 } -> x1 + v137 Binop { op=add, lhs=v133, rhs=v136 } -> x0 + v138 Imm(0) -> x1 + v139 LoadLocal { off=-1, kind=I64 } -> x1 + v140 LoadLocal { off=33, kind=I64 } -> x1 + v141 Binop { op=add, lhs=v137, rhs=v140 } -> x0 + v142 Imm(0) -> x1 + v143 LoadLocal { off=-1, kind=I64 } -> x1 + v144 LoadLocal { off=34, kind=I64 } -> x1 + v145 Binop { op=add, lhs=v141, rhs=v144 } -> x0 + v146 Imm(0) -> x1 + v147 LoadLocal { off=-1, kind=I64 } -> x1 + v148 LoadLocal { off=35, kind=I64 } -> x1 + v149 Binop { op=add, lhs=v145, rhs=v148 } -> x0 + v150 Imm(0) -> x1 + v151 LoadLocal { off=-1, kind=I64 } -> x1 + v152 LoadLocal { off=36, kind=I64 } -> x1 + v153 Binop { op=add, lhs=v149, rhs=v152 } -> x0 + v154 Imm(0) -> x1 + v155 LoadLocal { off=-1, kind=I64 } -> x1 + v156 LoadLocal { off=37, kind=I64 } -> x1 + v157 Binop { op=add, lhs=v153, rhs=v156 } -> x0 + v158 Imm(0) -> x1 + v159 LoadLocal { off=-1, kind=I64 } -> x1 + v160 LoadLocal { off=38, kind=I64 } -> x1 + v161 Binop { op=add, lhs=v157, rhs=v160 } -> x0 + v162 Imm(0) -> x1 + v163 LoadLocal { off=-1, kind=I64 } -> x1 + v164 LoadLocal { off=39, kind=I64 } -> x1 + v165 Binop { op=add, lhs=v161, rhs=v164 } -> x0 + v166 Imm(0) -> x1 + v167 LoadLocal { off=-1, kind=I64 } -> x1 + v168 LoadLocal { off=40, kind=I64 } -> x1 + v169 Binop { op=add, lhs=v165, rhs=v168 } -> x0 + v170 Imm(0) -> x1 + v171 LoadLocal { off=-1, kind=I64 } -> x1 + v172 LoadLocal { off=41, kind=I64 } -> x1 + v173 Binop { op=add, lhs=v169, rhs=v172 } -> x0 + v174 Imm(0) -> x1 + v175 LoadLocal { off=-1, kind=I64 } -> x1 + v176 LoadLocal { off=42, kind=I64 } -> x1 + v177 Binop { op=add, lhs=v173, rhs=v176 } -> x0 + v178 Imm(0) -> x1 + v179 LoadLocal { off=-1, kind=I64 } -> x1 + v180 LoadLocal { off=43, kind=I64 } -> x1 + v181 Binop { op=add, lhs=v177, rhs=v180 } -> x0 + v182 Imm(0) -> x1 + v183 LoadLocal { off=-1, kind=I64 } -> x1 + v184 LoadLocal { off=44, kind=I64 } -> x1 + v185 Binop { op=add, lhs=v181, rhs=v184 } -> x0 + v186 Imm(0) -> x1 + v187 LoadLocal { off=-1, kind=I64 } -> x1 + v188 LoadLocal { off=45, kind=I64 } -> x1 + v189 Binop { op=add, lhs=v185, rhs=v188 } -> x0 + v190 Imm(0) -> x1 + v191 LoadLocal { off=-1, kind=I64 } -> x1 + v192 LoadLocal { off=46, kind=I64 } -> x1 + v193 Binop { op=add, lhs=v189, rhs=v192 } -> x0 + v194 Imm(0) -> x1 + v195 LoadLocal { off=-1, kind=I64 } -> x1 + v196 LoadLocal { off=47, kind=I64 } -> x1 + v197 Binop { op=add, lhs=v193, rhs=v196 } -> x0 + v198 Imm(0) -> x1 + v199 LoadLocal { off=-1, kind=I64 } -> x1 + v200 LoadLocal { off=48, kind=I64 } -> x1 + v201 Binop { op=add, lhs=v197, rhs=v200 } -> x0 + v202 Imm(0) -> x1 + v203 LoadLocal { off=-1, kind=I64 } -> x1 + v204 LoadLocal { off=49, kind=I64 } -> x1 + v205 Binop { op=add, lhs=v201, rhs=v204 } -> x0 + v206 Imm(0) -> x1 + v207 LoadLocal { off=-1, kind=I64 } -> x1 + v208 LoadLocal { off=50, kind=I64 } -> x1 + v209 Binop { op=add, lhs=v205, rhs=v208 } -> x0 + v210 Imm(0) -> x1 + v211 LoadLocal { off=-1, kind=I64 } -> x1 + v212 LoadLocal { off=51, kind=I64 } -> x1 + v213 Binop { op=add, lhs=v209, rhs=v212 } -> x0 + v214 Imm(0) -> x1 + v215 LoadLocal { off=-1, kind=I64 } -> x1 + v216 LoadLocal { off=52, kind=I64 } -> x1 + v217 Binop { op=add, lhs=v213, rhs=v216 } -> x0 + v218 Imm(0) -> x1 + v219 LoadLocal { off=-1, kind=I64 } -> x1 + v220 LoadLocal { off=53, kind=I64 } -> x1 + v221 Binop { op=add, lhs=v217, rhs=v220 } -> x0 + v222 Imm(0) -> x1 + v223 LoadLocal { off=-1, kind=I64 } -> x1 + v224 LoadLocal { off=54, kind=I64 } -> x1 + v225 Binop { op=add, lhs=v221, rhs=v224 } -> x0 + v226 Imm(0) -> x1 + v227 LoadLocal { off=-1, kind=I64 } -> x1 + v228 LoadLocal { off=55, kind=I64 } -> x1 + v229 Binop { op=add, lhs=v225, rhs=v228 } -> x0 + v230 Imm(0) -> x1 + v231 LoadLocal { off=-1, kind=I64 } -> x1 + v232 LoadLocal { off=56, kind=I64 } -> x1 + v233 Binop { op=add, lhs=v229, rhs=v232 } -> x0 + v234 Imm(0) -> x1 + v235 LoadLocal { off=-1, kind=I64 } -> x1 + v236 LoadLocal { off=57, kind=I64 } -> x1 + v237 Binop { op=add, lhs=v233, rhs=v236 } -> x0 + v238 Imm(0) -> x1 + v239 LoadLocal { off=-1, kind=I64 } -> x1 + v240 LoadLocal { off=58, kind=I64 } -> x1 + v241 Binop { op=add, lhs=v237, rhs=v240 } -> x0 + v242 Imm(0) -> x1 + v243 LoadLocal { off=-1, kind=I64 } -> x1 + v244 LoadLocal { off=59, kind=I64 } -> x1 + v245 Binop { op=add, lhs=v241, rhs=v244 } -> x0 + v246 Imm(0) -> x1 + v247 LoadLocal { off=-1, kind=I64 } -> x1 + v248 LoadLocal { off=60, kind=I64 } -> x1 + v249 Binop { op=add, lhs=v245, rhs=v248 } -> x0 + v250 Imm(0) -> x1 + v251 LoadLocal { off=-1, kind=I64 } -> x1 + v252 LoadLocal { off=61, kind=I64 } -> x1 + v253 Binop { op=add, lhs=v249, rhs=v252 } -> x0 + v254 Imm(0) -> x1 + v255 LoadLocal { off=-1, kind=I64 } -> x1 + v256 LoadLocal { off=62, kind=I64 } -> x1 + v257 Binop { op=add, lhs=v253, rhs=v256 } -> x0 + v258 Imm(0) -> x1 + v259 LoadLocal { off=-1, kind=I64 } -> x1 + v260 LoadLocal { off=63, kind=I64 } -> x1 + v261 Binop { op=add, lhs=v257, rhs=v260 } -> x0 + v262 Imm(0) -> x1 + v263 LoadLocal { off=-1, kind=I64 } -> x1 + v264 LoadLocal { off=64, kind=I64 } -> x1 + v265 Binop { op=add, lhs=v261, rhs=v264 } -> x0 + v266 Imm(0) -> x1 + v267 LoadLocal { off=-1, kind=I64 } -> x1 + v268 LoadLocal { off=65, kind=I64 } -> x1 + v269 Binop { op=add, lhs=v265, rhs=v268 } -> x0 + v270 Imm(0) -> x1 + v271 LoadLocal { off=-1, kind=I64 } -> x1 + v272 LoadLocal { off=66, kind=I64 } -> x1 + v273 Binop { op=add, lhs=v269, rhs=v272 } -> x0 + v274 Imm(0) -> x1 + v275 LoadLocal { off=-1, kind=I64 } -> x1 + v276 LoadLocal { off=67, kind=I64 } -> x1 + v277 Binop { op=add, lhs=v273, rhs=v276 } -> x0 + v278 Imm(0) -> x1 + v279 LoadLocal { off=-1, kind=I64 } -> x1 + v280 LoadLocal { off=68, kind=I64 } -> x1 + v281 Binop { op=add, lhs=v277, rhs=v280 } -> x0 + v282 Imm(0) -> x1 + v283 LoadLocal { off=-1, kind=I64 } -> x1 + v284 LoadLocal { off=69, kind=I64 } -> x1 + v285 Binop { op=add, lhs=v281, rhs=v284 } -> x0 + v286 Imm(0) -> x1 + v287 LoadLocal { off=-1, kind=I64 } -> x1 + v288 LoadLocal { off=70, kind=I64 } -> x1 + v289 Binop { op=add, lhs=v285, rhs=v288 } -> x0 + v290 Imm(0) -> x1 + v291 LoadLocal { off=-1, kind=I64 } -> x1 + v292 LoadLocal { off=71, kind=I64 } -> x1 + v293 Binop { op=add, lhs=v289, rhs=v292 } -> x0 + v294 Imm(0) -> x1 + v295 LoadLocal { off=-1, kind=I64 } -> x1 + v296 LoadLocal { off=72, kind=I64 } -> x1 + v297 Binop { op=add, lhs=v293, rhs=v296 } -> x0 + v298 Imm(0) -> x1 + v299 LoadLocal { off=-1, kind=I64 } -> x1 + v300 LoadLocal { off=73, kind=I64 } -> x1 + v301 Binop { op=add, lhs=v297, rhs=v300 } -> x0 + v302 Imm(0) -> x1 + v303 LoadLocal { off=-1, kind=I64 } -> x1 + v304 LoadLocal { off=74, kind=I64 } -> x1 + v305 Binop { op=add, lhs=v301, rhs=v304 } -> x0 + v306 Imm(0) -> x1 + v307 LoadLocal { off=-1, kind=I64 } -> x1 + v308 LoadLocal { off=75, kind=I64 } -> x1 + v309 Binop { op=add, lhs=v305, rhs=v308 } -> x0 + v310 Imm(0) -> x1 + v311 LoadLocal { off=-1, kind=I64 } -> x1 + v312 LoadLocal { off=76, kind=I64 } -> x1 + v313 Binop { op=add, lhs=v309, rhs=v312 } -> x0 + v314 Imm(0) -> x1 + v315 LoadLocal { off=-1, kind=I64 } -> x1 + v316 LoadLocal { off=77, kind=I64 } -> x1 + v317 Binop { op=add, lhs=v313, rhs=v316 } -> x0 + v318 Imm(0) -> x1 + v319 LoadLocal { off=-1, kind=I64 } -> x1 + v320 LoadLocal { off=78, kind=I64 } -> x1 + v321 Binop { op=add, lhs=v317, rhs=v320 } -> x0 + v322 Imm(0) -> x1 + v323 LoadLocal { off=-1, kind=I64 } -> x1 + v324 LoadLocal { off=79, kind=I64 } -> x1 + v325 Binop { op=add, lhs=v321, rhs=v324 } -> x0 + v326 Imm(0) -> x1 + v327 LoadLocal { off=-1, kind=I64 } -> x1 + v328 LoadLocal { off=80, kind=I64 } -> x1 + v329 Binop { op=add, lhs=v325, rhs=v328 } -> x0 + v330 Imm(0) -> x1 + v331 LoadLocal { off=-1, kind=I64 } -> x1 + v332 LoadLocal { off=81, kind=I64 } -> x1 + v333 Binop { op=add, lhs=v329, rhs=v332 } -> x0 + v334 Imm(0) -> x1 + v335 LoadLocal { off=-1, kind=I64 } -> x1 + v336 LoadLocal { off=82, kind=I64 } -> x1 + v337 Binop { op=add, lhs=v333, rhs=v336 } -> x0 + v338 Imm(0) -> x1 + v339 LoadLocal { off=-1, kind=I64 } -> x1 + v340 LoadLocal { off=83, kind=I64 } -> x1 + v341 Binop { op=add, lhs=v337, rhs=v340 } -> x0 + v342 Imm(0) -> x1 + v343 LoadLocal { off=-1, kind=I64 } -> x1 + v344 LoadLocal { off=84, kind=I64 } -> x1 + v345 Binop { op=add, lhs=v341, rhs=v344 } -> x0 + v346 Imm(0) -> x1 + v347 LoadLocal { off=-1, kind=I64 } -> x1 + v348 LoadLocal { off=85, kind=I64 } -> x1 + v349 Binop { op=add, lhs=v345, rhs=v348 } -> x0 + v350 Imm(0) -> x1 + v351 LoadLocal { off=-1, kind=I64 } -> x1 + v352 LoadLocal { off=86, kind=I64 } -> x1 + v353 Binop { op=add, lhs=v349, rhs=v352 } -> x0 + v354 Imm(0) -> x1 + v355 LoadLocal { off=-1, kind=I64 } -> x1 + v356 LoadLocal { off=87, kind=I64 } -> x1 + v357 Binop { op=add, lhs=v353, rhs=v356 } -> x0 + v358 Imm(0) -> x1 + v359 LoadLocal { off=-1, kind=I64 } -> x1 + v360 LoadLocal { off=88, kind=I64 } -> x1 + v361 Binop { op=add, lhs=v357, rhs=v360 } -> x0 + v362 Imm(0) -> x1 + v363 LoadLocal { off=-1, kind=I64 } -> x1 + v364 LoadLocal { off=89, kind=I64 } -> x1 + v365 Binop { op=add, lhs=v361, rhs=v364 } -> x0 + v366 Imm(0) -> x1 + v367 LoadLocal { off=-1, kind=I64 } -> x1 + v368 LoadLocal { off=90, kind=I64 } -> x1 + v369 Binop { op=add, lhs=v365, rhs=v368 } -> x0 + v370 Imm(0) -> x1 + v371 LoadLocal { off=-1, kind=I64 } -> x1 + v372 LoadLocal { off=91, kind=I64 } -> x1 + v373 Binop { op=add, lhs=v369, rhs=v372 } -> x0 + v374 Imm(0) -> x1 + v375 LoadLocal { off=-1, kind=I64 } -> x1 + v376 LoadLocal { off=92, kind=I64 } -> x1 + v377 Binop { op=add, lhs=v373, rhs=v376 } -> x0 + v378 Imm(0) -> x1 + v379 LoadLocal { off=-1, kind=I64 } -> x1 + v380 LoadLocal { off=93, kind=I64 } -> x1 + v381 Binop { op=add, lhs=v377, rhs=v380 } -> x0 + v382 Imm(0) -> x1 + v383 LoadLocal { off=-1, kind=I64 } -> x1 + v384 LoadLocal { off=94, kind=I64 } -> x1 + v385 Binop { op=add, lhs=v381, rhs=v384 } -> x0 + v386 Imm(0) -> x1 + v387 LoadLocal { off=-1, kind=I64 } -> x1 + v388 LoadLocal { off=95, kind=I64 } -> x1 + v389 Binop { op=add, lhs=v385, rhs=v388 } -> x0 + v390 Imm(0) -> x1 + v391 LoadLocal { off=-1, kind=I64 } -> x1 + v392 LoadLocal { off=96, kind=I64 } -> x1 + v393 Binop { op=add, lhs=v389, rhs=v392 } -> x0 + v394 Imm(0) -> x1 + v395 LoadLocal { off=-1, kind=I64 } -> x1 + v396 LoadLocal { off=97, kind=I64 } -> x1 + v397 Binop { op=add, lhs=v393, rhs=v396 } -> x0 + v398 Imm(0) -> x1 + v399 LoadLocal { off=-1, kind=I64 } -> x1 + v400 LoadLocal { off=98, kind=I64 } -> x1 + v401 Binop { op=add, lhs=v397, rhs=v400 } -> x0 + v402 Imm(0) -> x1 + v403 LoadLocal { off=-1, kind=I64 } -> x1 + v404 LoadLocal { off=99, kind=I64 } -> x1 + v405 Binop { op=add, lhs=v401, rhs=v404 } -> x0 + v406 Imm(0) -> x1 + v407 LoadLocal { off=-1, kind=I64 } -> x1 + v408 LoadLocal { off=100, kind=I64 } -> x1 + v409 Binop { op=add, lhs=v405, rhs=v408 } -> x0 + v410 Imm(0) -> x1 + v411 LoadLocal { off=-1, kind=I64 } -> x1 + v412 LoadLocal { off=101, kind=I64 } -> x1 + v413 Binop { op=add, lhs=v409, rhs=v412 } -> x0 + v414 Imm(0) -> x1 + v415 LoadLocal { off=-1, kind=I64 } -> x1 + v416 LoadLocal { off=102, kind=I64 } -> x1 + v417 Binop { op=add, lhs=v413, rhs=v416 } -> x0 + v418 Imm(0) -> x1 + v419 LoadLocal { off=-1, kind=I64 } -> x1 + v420 LoadLocal { off=103, kind=I64 } -> x1 + v421 Binop { op=add, lhs=v417, rhs=v420 } -> x0 + v422 Imm(0) -> x1 + v423 LoadLocal { off=-1, kind=I64 } -> x1 + v424 LoadLocal { off=104, kind=I64 } -> x1 + v425 Binop { op=add, lhs=v421, rhs=v424 } -> x0 + v426 Imm(0) -> x1 + v427 LoadLocal { off=-1, kind=I64 } -> x1 + v428 LoadLocal { off=105, kind=I64 } -> x1 + v429 Binop { op=add, lhs=v425, rhs=v428 } -> x0 + v430 Imm(0) -> x1 + v431 LoadLocal { off=-1, kind=I64 } -> x1 + v432 LoadLocal { off=106, kind=I64 } -> x1 + v433 Binop { op=add, lhs=v429, rhs=v432 } -> x0 + v434 Imm(0) -> x1 + v435 LoadLocal { off=-1, kind=I64 } -> x1 + v436 LoadLocal { off=107, kind=I64 } -> x1 + v437 Binop { op=add, lhs=v433, rhs=v436 } -> x0 + v438 Imm(0) -> x1 + v439 LoadLocal { off=-1, kind=I64 } -> x1 + v440 LoadLocal { off=108, kind=I64 } -> x1 + v441 Binop { op=add, lhs=v437, rhs=v440 } -> x0 + v442 Imm(0) -> x1 + v443 LoadLocal { off=-1, kind=I64 } -> x1 + v444 LoadLocal { off=109, kind=I64 } -> x1 + v445 Binop { op=add, lhs=v441, rhs=v444 } -> x0 + v446 Imm(0) -> x1 + v447 LoadLocal { off=-1, kind=I64 } -> x1 + v448 LoadLocal { off=110, kind=I64 } -> x1 + v449 Binop { op=add, lhs=v445, rhs=v448 } -> x0 + v450 Imm(0) -> x1 + v451 LoadLocal { off=-1, kind=I64 } -> x1 + v452 LoadLocal { off=111, kind=I64 } -> x1 + v453 Binop { op=add, lhs=v449, rhs=v452 } -> x0 + v454 Imm(0) -> x1 + v455 LoadLocal { off=-1, kind=I64 } -> x1 + v456 LoadLocal { off=112, kind=I64 } -> x1 + v457 Binop { op=add, lhs=v453, rhs=v456 } -> x0 + v458 Imm(0) -> x1 + v459 LoadLocal { off=-1, kind=I64 } -> x1 + v460 LoadLocal { off=113, kind=I64 } -> x1 + v461 Binop { op=add, lhs=v457, rhs=v460 } -> x0 + v462 Imm(0) -> x1 + v463 LoadLocal { off=-1, kind=I64 } -> x1 + v464 LoadLocal { off=114, kind=I64 } -> x1 + v465 Binop { op=add, lhs=v461, rhs=v464 } -> x0 + v466 Imm(0) -> x1 + v467 LoadLocal { off=-1, kind=I64 } -> x1 + v468 LoadLocal { off=115, kind=I64 } -> x1 + v469 Binop { op=add, lhs=v465, rhs=v468 } -> x0 + v470 Imm(0) -> x1 + v471 LoadLocal { off=-1, kind=I64 } -> x1 + v472 LoadLocal { off=116, kind=I64 } -> x1 + v473 Binop { op=add, lhs=v469, rhs=v472 } -> x0 + v474 Imm(0) -> x1 + v475 LoadLocal { off=-1, kind=I64 } -> x1 + v476 LoadLocal { off=117, kind=I64 } -> x1 + v477 Binop { op=add, lhs=v473, rhs=v476 } -> x0 + v478 Imm(0) -> x1 + v479 LoadLocal { off=-1, kind=I64 } -> x1 + v480 LoadLocal { off=118, kind=I64 } -> x1 + v481 Binop { op=add, lhs=v477, rhs=v480 } -> x0 + v482 Imm(0) -> x1 + v483 LoadLocal { off=-1, kind=I64 } -> x1 + v484 LoadLocal { off=119, kind=I64 } -> x1 + v485 Binop { op=add, lhs=v481, rhs=v484 } -> x0 + v486 Imm(0) -> x1 + v487 LoadLocal { off=-1, kind=I64 } -> x1 + v488 LoadLocal { off=120, kind=I64 } -> x1 + v489 Binop { op=add, lhs=v485, rhs=v488 } -> x0 + v490 Imm(0) -> x1 + v491 LoadLocal { off=-1, kind=I64 } -> x1 + v492 LoadLocal { off=121, kind=I64 } -> x1 + v493 Binop { op=add, lhs=v489, rhs=v492 } -> x0 + v494 Imm(0) -> x1 + v495 LoadLocal { off=-1, kind=I64 } -> x1 + v496 LoadLocal { off=122, kind=I64 } -> x1 + v497 Binop { op=add, lhs=v493, rhs=v496 } -> x0 + v498 Imm(0) -> x1 + v499 LoadLocal { off=-1, kind=I64 } -> x1 + v500 LoadLocal { off=123, kind=I64 } -> x1 + v501 Binop { op=add, lhs=v497, rhs=v500 } -> x0 + v502 Imm(0) -> x1 + v503 LoadLocal { off=-1, kind=I64 } -> x1 + v504 LoadLocal { off=124, kind=I64 } -> x1 + v505 Binop { op=add, lhs=v501, rhs=v504 } -> x0 + v506 Imm(0) -> x1 + v507 LoadLocal { off=-1, kind=I64 } -> x1 + v508 LoadLocal { off=125, kind=I64 } -> x1 + v509 Binop { op=add, lhs=v505, rhs=v508 } -> x0 + v510 Imm(0) -> x1 + v511 LoadLocal { off=-1, kind=I64 } -> x1 + v512 LoadLocal { off=126, kind=I64 } -> x1 + v513 Binop { op=add, lhs=v509, rhs=v512 } -> x0 + v514 Imm(0) -> x1 + v515 LoadLocal { off=-1, kind=I64 } -> x1 + v516 LoadLocal { off=127, kind=I64 } -> x1 + v517 Binop { op=add, lhs=v513, rhs=v516 } -> x0 + v518 Imm(0) -> x1 + v519 LoadLocal { off=-1, kind=I64 } -> x1 + v520 LoadLocal { off=128, kind=I64 } -> x1 + v521 Binop { op=add, lhs=v517, rhs=v520 } -> x0 + v522 Imm(0) -> x1 + v523 LoadLocal { off=-1, kind=I64 } -> x1 + v524 LoadLocal { off=129, kind=I64 } -> x1 + v525 Binop { op=add, lhs=v521, rhs=v524 } -> x0 + v526 Imm(0) -> x1 + v527 LoadLocal { off=-1, kind=I64 } -> x1 + v528 LoadLocal { off=130, kind=I64 } -> x1 + v529 Binop { op=add, lhs=v525, rhs=v528 } -> x0 + v530 Imm(0) -> x1 + v531 LoadLocal { off=-1, kind=I64 } -> x1 + v532 LoadLocal { off=131, kind=I64 } -> x1 + v533 Binop { op=add, lhs=v529, rhs=v532 } -> x0 + v534 Imm(0) -> x1 + v535 LoadLocal { off=-1, kind=I64 } -> x1 + v536 LoadLocal { off=132, kind=I64 } -> x1 + v537 Binop { op=add, lhs=v533, rhs=v536 } -> x0 + v538 Imm(0) -> x1 + v539 LoadLocal { off=-1, kind=I64 } -> x1 + v540 LoadLocal { off=133, kind=I64 } -> x1 + v541 Binop { op=add, lhs=v537, rhs=v540 } -> x0 + v542 Imm(0) -> x1 + v543 LoadLocal { off=-1, kind=I64 } -> x1 + v544 LoadLocal { off=134, kind=I64 } -> x1 + v545 Binop { op=add, lhs=v541, rhs=v544 } -> x0 + v546 Imm(0) -> x1 + v547 LoadLocal { off=-1, kind=I64 } -> x1 + v548 LoadLocal { off=135, kind=I64 } -> x1 + v549 Binop { op=add, lhs=v545, rhs=v548 } -> x0 + v550 Imm(0) -> x1 + v551 LoadLocal { off=-1, kind=I64 } -> x1 + v552 LoadLocal { off=136, kind=I64 } -> x1 + v553 Binop { op=add, lhs=v549, rhs=v552 } -> x0 + v554 Imm(0) -> x1 + v555 LoadLocal { off=-1, kind=I64 } -> x1 + v556 LoadLocal { off=137, kind=I64 } -> x1 + v557 Binop { op=add, lhs=v553, rhs=v556 } -> x0 + v558 Imm(0) -> x1 + v559 LoadLocal { off=-1, kind=I64 } -> x1 + v560 LoadLocal { off=138, kind=I64 } -> x1 + v561 Binop { op=add, lhs=v557, rhs=v560 } -> x0 + v562 Imm(0) -> x1 + v563 LoadLocal { off=-1, kind=I64 } -> x1 + v564 LoadLocal { off=139, kind=I64 } -> x1 + v565 Binop { op=add, lhs=v561, rhs=v564 } -> x0 + v566 Imm(0) -> x1 + v567 LoadLocal { off=-1, kind=I64 } -> x1 + v568 LoadLocal { off=140, kind=I64 } -> x1 + v569 Binop { op=add, lhs=v565, rhs=v568 } -> x0 + v570 Imm(0) -> x1 + v571 LoadLocal { off=-1, kind=I64 } -> x1 + v572 LoadLocal { off=141, kind=I64 } -> x1 + v573 Binop { op=add, lhs=v569, rhs=v572 } -> x0 + v574 Imm(0) -> x1 + v575 LoadLocal { off=-1, kind=I64 } -> x1 + v576 LoadLocal { off=142, kind=I64 } -> x1 + v577 Binop { op=add, lhs=v573, rhs=v576 } -> x0 + v578 Imm(0) -> x1 + v579 LoadLocal { off=-1, kind=I64 } -> x1 + v580 LoadLocal { off=143, kind=I64 } -> x1 + v581 Binop { op=add, lhs=v577, rhs=v580 } -> x0 + v582 Imm(0) -> x1 + v583 LoadLocal { off=-1, kind=I64 } -> x1 + v584 LoadLocal { off=144, kind=I64 } -> x1 + v585 Binop { op=add, lhs=v581, rhs=v584 } -> x0 + v586 Imm(0) -> x1 + v587 LoadLocal { off=-1, kind=I64 } -> x1 + v588 LoadLocal { off=145, kind=I64 } -> x1 + v589 Binop { op=add, lhs=v585, rhs=v588 } -> x0 + v590 Imm(0) -> x1 + v591 LoadLocal { off=-1, kind=I64 } -> x1 + v592 LoadLocal { off=146, kind=I64 } -> x1 + v593 Binop { op=add, lhs=v589, rhs=v592 } -> x0 + v594 Imm(0) -> x1 + v595 LoadLocal { off=-1, kind=I64 } -> x1 + v596 LoadLocal { off=147, kind=I64 } -> x1 + v597 Binop { op=add, lhs=v593, rhs=v596 } -> x0 + v598 Imm(0) -> x1 + v599 LoadLocal { off=-1, kind=I64 } -> x1 + v600 LoadLocal { off=148, kind=I64 } -> x1 + v601 Binop { op=add, lhs=v597, rhs=v600 } -> x0 + v602 Imm(0) -> x1 + v603 LoadLocal { off=-1, kind=I64 } -> x1 + v604 LoadLocal { off=149, kind=I64 } -> x1 + v605 Binop { op=add, lhs=v601, rhs=v604 } -> x0 + v606 Imm(0) -> x1 + v607 LoadLocal { off=-1, kind=I64 } -> x1 + v608 LoadLocal { off=150, kind=I64 } -> x1 + v609 Binop { op=add, lhs=v605, rhs=v608 } -> x0 + v610 Imm(0) -> x1 + v611 LoadLocal { off=-1, kind=I64 } -> x1 + v612 LoadLocal { off=151, kind=I64 } -> x1 + v613 Binop { op=add, lhs=v609, rhs=v612 } -> x0 + v614 Imm(0) -> x1 + v615 LoadLocal { off=-1, kind=I64 } -> x1 + v616 LoadLocal { off=152, kind=I64 } -> x1 + v617 Binop { op=add, lhs=v613, rhs=v616 } -> x0 + v618 Imm(0) -> x1 + v619 LoadLocal { off=-1, kind=I64 } -> x1 + v620 LoadLocal { off=153, kind=I64 } -> x1 + v621 Binop { op=add, lhs=v617, rhs=v620 } -> x0 + v622 Imm(0) -> x1 + v623 LoadLocal { off=-1, kind=I64 } -> x1 + v624 LoadLocal { off=154, kind=I64 } -> x1 + v625 Binop { op=add, lhs=v621, rhs=v624 } -> x0 + v626 Imm(0) -> x1 + v627 LoadLocal { off=-1, kind=I64 } -> x1 + v628 LoadLocal { off=155, kind=I64 } -> x1 + v629 Binop { op=add, lhs=v625, rhs=v628 } -> x0 + v630 Imm(0) -> x1 + v631 LoadLocal { off=-1, kind=I64 } -> x1 + v632 LoadLocal { off=156, kind=I64 } -> x1 + v633 Binop { op=add, lhs=v629, rhs=v632 } -> x0 + v634 Imm(0) -> x1 + v635 LoadLocal { off=-1, kind=I64 } -> x1 + v636 LoadLocal { off=157, kind=I64 } -> x1 + v637 Binop { op=add, lhs=v633, rhs=v636 } -> x0 + v638 Imm(0) -> x1 + v639 LoadLocal { off=-1, kind=I64 } -> x1 + v640 LoadLocal { off=158, kind=I64 } -> x1 + v641 Binop { op=add, lhs=v637, rhs=v640 } -> x0 + v642 Imm(0) -> x1 + v643 LoadLocal { off=-1, kind=I64 } -> x1 + v644 LoadLocal { off=159, kind=I64 } -> x1 + v645 Binop { op=add, lhs=v641, rhs=v644 } -> x0 + v646 Imm(0) -> x1 + v647 LoadLocal { off=-1, kind=I64 } -> x1 + v648 LoadLocal { off=160, kind=I64 } -> x1 + v649 Binop { op=add, lhs=v645, rhs=v648 } -> x0 + v650 Imm(0) -> x1 + v651 LoadLocal { off=-1, kind=I64 } -> x1 + v652 LoadLocal { off=161, kind=I64 } -> x1 + v653 Binop { op=add, lhs=v649, rhs=v652 } -> x0 + v654 Imm(0) -> x1 + v655 LoadLocal { off=-1, kind=I64 } -> x1 + v656 LoadLocal { off=162, kind=I64 } -> x1 + v657 Binop { op=add, lhs=v653, rhs=v656 } -> x0 + v658 Imm(0) -> x1 + v659 LoadLocal { off=-1, kind=I64 } -> x1 + v660 LoadLocal { off=163, kind=I64 } -> x1 + v661 Binop { op=add, lhs=v657, rhs=v660 } -> x0 + v662 Imm(0) -> x1 + v663 LoadLocal { off=-1, kind=I64 } -> x1 + v664 LoadLocal { off=164, kind=I64 } -> x1 + v665 Binop { op=add, lhs=v661, rhs=v664 } -> x0 + v666 Imm(0) -> x1 + v667 LoadLocal { off=-1, kind=I64 } -> x1 + v668 LoadLocal { off=165, kind=I64 } -> x1 + v669 Binop { op=add, lhs=v665, rhs=v668 } -> x0 + v670 Imm(0) -> x1 + v671 LoadLocal { off=-1, kind=I64 } -> x1 + v672 LoadLocal { off=166, kind=I64 } -> x1 + v673 Binop { op=add, lhs=v669, rhs=v672 } -> x0 + v674 Imm(0) -> x1 + v675 LoadLocal { off=-1, kind=I64 } -> x1 + v676 LoadLocal { off=167, kind=I64 } -> x1 + v677 Binop { op=add, lhs=v673, rhs=v676 } -> x0 + v678 Imm(0) -> x1 + v679 LoadLocal { off=-1, kind=I64 } -> x1 + v680 LoadLocal { off=168, kind=I64 } -> x1 + v681 Binop { op=add, lhs=v677, rhs=v680 } -> x0 + v682 Imm(0) -> x1 + v683 LoadLocal { off=-1, kind=I64 } -> x1 + v684 LoadLocal { off=169, kind=I64 } -> x1 + v685 Binop { op=add, lhs=v681, rhs=v684 } -> x0 + v686 Imm(0) -> x1 + v687 LoadLocal { off=-1, kind=I64 } -> x1 + v688 LoadLocal { off=170, kind=I64 } -> x1 + v689 Binop { op=add, lhs=v685, rhs=v688 } -> x0 + v690 Imm(0) -> x1 + v691 LoadLocal { off=-1, kind=I64 } -> x1 + v692 LoadLocal { off=171, kind=I64 } -> x1 + v693 Binop { op=add, lhs=v689, rhs=v692 } -> x0 + v694 Imm(0) -> x1 + v695 LoadLocal { off=-1, kind=I64 } -> x1 + v696 LoadLocal { off=172, kind=I64 } -> x1 + v697 Binop { op=add, lhs=v693, rhs=v696 } -> x0 + v698 Imm(0) -> x1 + v699 LoadLocal { off=-1, kind=I64 } -> x1 + v700 LoadLocal { off=173, kind=I64 } -> x1 + v701 Binop { op=add, lhs=v697, rhs=v700 } -> x0 + v702 Imm(0) -> x1 + v703 LoadLocal { off=-1, kind=I64 } -> x1 + v704 LoadLocal { off=174, kind=I64 } -> x1 + v705 Binop { op=add, lhs=v701, rhs=v704 } -> x0 + v706 Imm(0) -> x1 + v707 LoadLocal { off=-1, kind=I64 } -> x1 + v708 LoadLocal { off=175, kind=I64 } -> x1 + v709 Binop { op=add, lhs=v705, rhs=v708 } -> x0 + v710 Imm(0) -> x1 + v711 LoadLocal { off=-1, kind=I64 } -> x1 + v712 LoadLocal { off=176, kind=I64 } -> x1 + v713 Binop { op=add, lhs=v709, rhs=v712 } -> x0 + v714 Imm(0) -> x1 + v715 LoadLocal { off=-1, kind=I64 } -> x1 + v716 LoadLocal { off=177, kind=I64 } -> x1 + v717 Binop { op=add, lhs=v713, rhs=v716 } -> x0 + v718 Imm(0) -> x1 + v719 LoadLocal { off=-1, kind=I64 } -> x1 + v720 LoadLocal { off=178, kind=I64 } -> x1 + v721 Binop { op=add, lhs=v717, rhs=v720 } -> x0 + v722 Imm(0) -> x1 + v723 LoadLocal { off=-1, kind=I64 } -> x1 + v724 LoadLocal { off=179, kind=I64 } -> x1 + v725 Binop { op=add, lhs=v721, rhs=v724 } -> x0 + v726 Imm(0) -> x1 + v727 LoadLocal { off=-1, kind=I64 } -> x1 + v728 LoadLocal { off=180, kind=I64 } -> x1 + v729 Binop { op=add, lhs=v725, rhs=v728 } -> x0 + v730 Imm(0) -> x1 + v731 LoadLocal { off=-1, kind=I64 } -> x1 + v732 LoadLocal { off=181, kind=I64 } -> x1 + v733 Binop { op=add, lhs=v729, rhs=v732 } -> x0 + v734 Imm(0) -> x1 + v735 LoadLocal { off=-1, kind=I64 } -> x1 + v736 LoadLocal { off=182, kind=I64 } -> x1 + v737 Binop { op=add, lhs=v733, rhs=v736 } -> x0 + v738 Imm(0) -> x1 + v739 LoadLocal { off=-1, kind=I64 } -> x1 + v740 LoadLocal { off=183, kind=I64 } -> x1 + v741 Binop { op=add, lhs=v737, rhs=v740 } -> x0 + v742 Imm(0) -> x1 + v743 LoadLocal { off=-1, kind=I64 } -> x1 + v744 LoadLocal { off=184, kind=I64 } -> x1 + v745 Binop { op=add, lhs=v741, rhs=v744 } -> x0 + v746 Imm(0) -> x1 + v747 LoadLocal { off=-1, kind=I64 } -> x1 + v748 LoadLocal { off=185, kind=I64 } -> x1 + v749 Binop { op=add, lhs=v745, rhs=v748 } -> x0 + v750 Imm(0) -> x1 + v751 LoadLocal { off=-1, kind=I64 } -> x1 + v752 LoadLocal { off=186, kind=I64 } -> x1 + v753 Binop { op=add, lhs=v749, rhs=v752 } -> x0 + v754 Imm(0) -> x1 + v755 LoadLocal { off=-1, kind=I64 } -> x1 + v756 LoadLocal { off=187, kind=I64 } -> x1 + v757 Binop { op=add, lhs=v753, rhs=v756 } -> x0 + v758 Imm(0) -> x1 + v759 LoadLocal { off=-1, kind=I64 } -> x1 + v760 LoadLocal { off=188, kind=I64 } -> x1 + v761 Binop { op=add, lhs=v757, rhs=v760 } -> x0 + v762 Imm(0) -> x1 + v763 LoadLocal { off=-1, kind=I64 } -> x1 + v764 LoadLocal { off=189, kind=I64 } -> x1 + v765 Binop { op=add, lhs=v761, rhs=v764 } -> x0 + v766 Imm(0) -> x1 + v767 LoadLocal { off=-1, kind=I64 } -> x1 + v768 LoadLocal { off=190, kind=I64 } -> x1 + v769 Binop { op=add, lhs=v765, rhs=v768 } -> x0 + v770 Imm(0) -> x1 + v771 LoadLocal { off=-1, kind=I64 } -> x1 + v772 LoadLocal { off=191, kind=I64 } -> x1 + v773 Binop { op=add, lhs=v769, rhs=v772 } -> x0 + v774 Imm(0) -> x1 + v775 LoadLocal { off=-1, kind=I64 } -> x1 + v776 LoadLocal { off=192, kind=I64 } -> x1 + v777 Binop { op=add, lhs=v773, rhs=v776 } -> x0 + v778 Imm(0) -> x1 + v779 LoadLocal { off=-1, kind=I64 } -> x1 + v780 LoadLocal { off=193, kind=I64 } -> x1 + v781 Binop { op=add, lhs=v777, rhs=v780 } -> x0 + v782 Imm(0) -> x1 + v783 LoadLocal { off=-1, kind=I64 } -> x1 + v784 LoadLocal { off=194, kind=I64 } -> x1 + v785 Binop { op=add, lhs=v781, rhs=v784 } -> x0 + v786 Imm(0) -> x1 + v787 LoadLocal { off=-1, kind=I64 } -> x1 + v788 LoadLocal { off=195, kind=I64 } -> x1 + v789 Binop { op=add, lhs=v785, rhs=v788 } -> x0 + v790 Imm(0) -> x1 + v791 LoadLocal { off=-1, kind=I64 } -> x1 + v792 LoadLocal { off=196, kind=I64 } -> x1 + v793 Binop { op=add, lhs=v789, rhs=v792 } -> x0 + v794 Imm(0) -> x1 + v795 LoadLocal { off=-1, kind=I64 } -> x1 + v796 LoadLocal { off=197, kind=I64 } -> x1 + v797 Binop { op=add, lhs=v793, rhs=v796 } -> x0 + v798 Imm(0) -> x1 + v799 LoadLocal { off=-1, kind=I64 } -> x1 + v800 LoadLocal { off=198, kind=I64 } -> x1 + v801 Binop { op=add, lhs=v797, rhs=v800 } -> x0 + v802 Imm(0) -> x1 + v803 LoadLocal { off=-1, kind=I64 } -> x1 + v804 LoadLocal { off=199, kind=I64 } -> x1 + v805 Binop { op=add, lhs=v801, rhs=v804 } -> x0 + v806 Imm(0) -> x1 + v807 LoadLocal { off=-1, kind=I64 } -> x1 + v808 LoadLocal { off=200, kind=I64 } -> x1 + v809 Binop { op=add, lhs=v805, rhs=v808 } -> x0 + v810 Imm(0) -> x1 + v811 LoadLocal { off=-1, kind=I64 } -> x1 + v812 LoadLocal { off=201, kind=I64 } -> x1 + v813 Binop { op=add, lhs=v809, rhs=v812 } -> x0 + v814 Imm(0) -> x1 + v815 LoadLocal { off=-1, kind=I64 } -> x1 + v816 LoadLocal { off=202, kind=I64 } -> x1 + v817 Binop { op=add, lhs=v813, rhs=v816 } -> x0 + v818 Imm(0) -> x1 + v819 LoadLocal { off=-1, kind=I64 } -> x1 + v820 LoadLocal { off=203, kind=I64 } -> x1 + v821 Binop { op=add, lhs=v817, rhs=v820 } -> x0 + v822 Imm(0) -> x1 + v823 LoadLocal { off=-1, kind=I64 } -> x1 + v824 LoadLocal { off=204, kind=I64 } -> x1 + v825 Binop { op=add, lhs=v821, rhs=v824 } -> x0 + v826 Imm(0) -> x1 + v827 LoadLocal { off=-1, kind=I64 } -> x1 + v828 LoadLocal { off=205, kind=I64 } -> x1 + v829 Binop { op=add, lhs=v825, rhs=v828 } -> x0 + v830 Imm(0) -> x1 + v831 LoadLocal { off=-1, kind=I64 } -> x1 + v832 LoadLocal { off=206, kind=I64 } -> x1 + v833 Binop { op=add, lhs=v829, rhs=v832 } -> x0 + v834 Imm(0) -> x1 + v835 LoadLocal { off=-1, kind=I64 } -> x1 + v836 LoadLocal { off=207, kind=I64 } -> x1 + v837 Binop { op=add, lhs=v833, rhs=v836 } -> x0 + v838 Imm(0) -> x1 + v839 LoadLocal { off=-1, kind=I64 } -> x1 + v840 LoadLocal { off=208, kind=I64 } -> x1 + v841 Binop { op=add, lhs=v837, rhs=v840 } -> x0 + v842 Imm(0) -> x1 + v843 LoadLocal { off=-1, kind=I64 } -> x1 + v844 LoadLocal { off=209, kind=I64 } -> x1 + v845 Binop { op=add, lhs=v841, rhs=v844 } -> x0 + v846 Imm(0) -> x1 + v847 LoadLocal { off=-1, kind=I64 } -> x1 + v848 LoadLocal { off=210, kind=I64 } -> x1 + v849 Binop { op=add, lhs=v845, rhs=v848 } -> x0 + v850 Imm(0) -> x1 + v851 LoadLocal { off=-1, kind=I64 } -> x1 + v852 LoadLocal { off=211, kind=I64 } -> x1 + v853 Binop { op=add, lhs=v849, rhs=v852 } -> x0 + v854 Imm(0) -> x1 + v855 LoadLocal { off=-1, kind=I64 } -> x1 + v856 LoadLocal { off=212, kind=I64 } -> x1 + v857 Binop { op=add, lhs=v853, rhs=v856 } -> x0 + v858 Imm(0) -> x1 + v859 LoadLocal { off=-1, kind=I64 } -> x1 + v860 LoadLocal { off=213, kind=I64 } -> x1 + v861 Binop { op=add, lhs=v857, rhs=v860 } -> x0 + v862 Imm(0) -> x1 + v863 LoadLocal { off=-1, kind=I64 } -> x1 + v864 LoadLocal { off=214, kind=I64 } -> x1 + v865 Binop { op=add, lhs=v861, rhs=v864 } -> x0 + v866 Imm(0) -> x1 + v867 LoadLocal { off=-1, kind=I64 } -> x1 + v868 LoadLocal { off=215, kind=I64 } -> x1 + v869 Binop { op=add, lhs=v865, rhs=v868 } -> x0 + v870 Imm(0) -> x1 + v871 LoadLocal { off=-1, kind=I64 } -> x1 + v872 LoadLocal { off=216, kind=I64 } -> x1 + v873 Binop { op=add, lhs=v869, rhs=v872 } -> x0 + v874 Imm(0) -> x1 + v875 LoadLocal { off=-1, kind=I64 } -> x1 + v876 LoadLocal { off=217, kind=I64 } -> x1 + v877 Binop { op=add, lhs=v873, rhs=v876 } -> x0 + v878 Imm(0) -> x1 + v879 LoadLocal { off=-1, kind=I64 } -> x1 + v880 LoadLocal { off=218, kind=I64 } -> x1 + v881 Binop { op=add, lhs=v877, rhs=v880 } -> x0 + v882 Imm(0) -> x1 + v883 LoadLocal { off=-1, kind=I64 } -> x1 + v884 LoadLocal { off=219, kind=I64 } -> x1 + v885 Binop { op=add, lhs=v881, rhs=v884 } -> x0 + v886 Imm(0) -> x1 + v887 LoadLocal { off=-1, kind=I64 } -> x1 + v888 LoadLocal { off=220, kind=I64 } -> x1 + v889 Binop { op=add, lhs=v885, rhs=v888 } -> x0 + v890 Imm(0) -> x1 + v891 LoadLocal { off=-1, kind=I64 } -> x1 + v892 LoadLocal { off=221, kind=I64 } -> x1 + v893 Binop { op=add, lhs=v889, rhs=v892 } -> x0 + v894 Imm(0) -> x1 + v895 LoadLocal { off=-1, kind=I64 } -> x1 + v896 LoadLocal { off=222, kind=I64 } -> x1 + v897 Binop { op=add, lhs=v893, rhs=v896 } -> x0 + v898 Imm(0) -> x1 + v899 LoadLocal { off=-1, kind=I64 } -> x1 + v900 LoadLocal { off=223, kind=I64 } -> x1 + v901 Binop { op=add, lhs=v897, rhs=v900 } -> x0 + v902 Imm(0) -> x1 + v903 LoadLocal { off=-1, kind=I64 } -> x1 + v904 LoadLocal { off=224, kind=I64 } -> x1 + v905 Binop { op=add, lhs=v901, rhs=v904 } -> x0 + v906 Imm(0) -> x1 + v907 LoadLocal { off=-1, kind=I64 } -> x1 + v908 LoadLocal { off=225, kind=I64 } -> x1 + v909 Binop { op=add, lhs=v905, rhs=v908 } -> x0 + v910 Imm(0) -> x1 + v911 LoadLocal { off=-1, kind=I64 } -> x1 + v912 LoadLocal { off=226, kind=I64 } -> x1 + v913 Binop { op=add, lhs=v909, rhs=v912 } -> x0 + v914 Imm(0) -> x1 + v915 LoadLocal { off=-1, kind=I64 } -> x1 + v916 LoadLocal { off=227, kind=I64 } -> x1 + v917 Binop { op=add, lhs=v913, rhs=v916 } -> x0 + v918 Imm(0) -> x1 + v919 LoadLocal { off=-1, kind=I64 } -> x1 + v920 LoadLocal { off=228, kind=I64 } -> x1 + v921 Binop { op=add, lhs=v917, rhs=v920 } -> x0 + v922 Imm(0) -> x1 + v923 LoadLocal { off=-1, kind=I64 } -> x1 + v924 LoadLocal { off=229, kind=I64 } -> x1 + v925 Binop { op=add, lhs=v921, rhs=v924 } -> x0 + v926 Imm(0) -> x1 + v927 LoadLocal { off=-1, kind=I64 } -> x1 + v928 LoadLocal { off=230, kind=I64 } -> x1 + v929 Binop { op=add, lhs=v925, rhs=v928 } -> x0 + v930 Imm(0) -> x1 + v931 LoadLocal { off=-1, kind=I64 } -> x1 + v932 LoadLocal { off=231, kind=I64 } -> x1 + v933 Binop { op=add, lhs=v929, rhs=v932 } -> x0 + v934 Imm(0) -> x1 + v935 LoadLocal { off=-1, kind=I64 } -> x1 + v936 LoadLocal { off=232, kind=I64 } -> x1 + v937 Binop { op=add, lhs=v933, rhs=v936 } -> x0 + v938 Imm(0) -> x1 + v939 LoadLocal { off=-1, kind=I64 } -> x1 + v940 LoadLocal { off=233, kind=I64 } -> x1 + v941 Binop { op=add, lhs=v937, rhs=v940 } -> x0 + v942 Imm(0) -> x1 + v943 LoadLocal { off=-1, kind=I64 } -> x1 + v944 LoadLocal { off=234, kind=I64 } -> x1 + v945 Binop { op=add, lhs=v941, rhs=v944 } -> x0 + v946 Imm(0) -> x1 + v947 LoadLocal { off=-1, kind=I64 } -> x1 + v948 LoadLocal { off=235, kind=I64 } -> x1 + v949 Binop { op=add, lhs=v945, rhs=v948 } -> x0 + v950 Imm(0) -> x1 + v951 LoadLocal { off=-1, kind=I64 } -> x1 + v952 LoadLocal { off=236, kind=I64 } -> x1 + v953 Binop { op=add, lhs=v949, rhs=v952 } -> x0 + v954 Imm(0) -> x1 + v955 LoadLocal { off=-1, kind=I64 } -> x1 + v956 LoadLocal { off=237, kind=I64 } -> x1 + v957 Binop { op=add, lhs=v953, rhs=v956 } -> x0 + v958 Imm(0) -> x1 + v959 LoadLocal { off=-1, kind=I64 } -> x1 + v960 LoadLocal { off=238, kind=I64 } -> x1 + v961 Binop { op=add, lhs=v957, rhs=v960 } -> x0 + v962 Imm(0) -> x1 + v963 LoadLocal { off=-1, kind=I64 } -> x1 + v964 LoadLocal { off=239, kind=I64 } -> x1 + v965 Binop { op=add, lhs=v961, rhs=v964 } -> x0 + v966 Imm(0) -> x1 + v967 LoadLocal { off=-1, kind=I64 } -> x1 + v968 LoadLocal { off=240, kind=I64 } -> x1 + v969 Binop { op=add, lhs=v965, rhs=v968 } -> x0 + v970 Imm(0) -> x1 + v971 LoadLocal { off=-1, kind=I64 } -> x1 + v972 LoadLocal { off=241, kind=I64 } -> x1 + v973 Binop { op=add, lhs=v969, rhs=v972 } -> x0 + v974 Imm(0) -> x1 + v975 LoadLocal { off=-1, kind=I64 } -> x1 + v976 LoadLocal { off=242, kind=I64 } -> x1 + v977 Binop { op=add, lhs=v973, rhs=v976 } -> x0 + v978 Imm(0) -> x1 + v979 LoadLocal { off=-1, kind=I64 } -> x1 + v980 LoadLocal { off=243, kind=I64 } -> x1 + v981 Binop { op=add, lhs=v977, rhs=v980 } -> x0 + v982 Imm(0) -> x1 + v983 LoadLocal { off=-1, kind=I64 } -> x1 + v984 LoadLocal { off=244, kind=I64 } -> x1 + v985 Binop { op=add, lhs=v981, rhs=v984 } -> x0 + v986 Imm(0) -> x1 + v987 LoadLocal { off=-1, kind=I64 } -> x1 + v988 LoadLocal { off=245, kind=I64 } -> x1 + v989 Binop { op=add, lhs=v985, rhs=v988 } -> x0 + v990 Imm(0) -> x1 + v991 LoadLocal { off=-1, kind=I64 } -> x1 + v992 LoadLocal { off=246, kind=I64 } -> x1 + v993 Binop { op=add, lhs=v989, rhs=v992 } -> x0 + v994 Imm(0) -> x1 + v995 LoadLocal { off=-1, kind=I64 } -> x1 + v996 LoadLocal { off=247, kind=I64 } -> x1 + v997 Binop { op=add, lhs=v993, rhs=v996 } -> x0 + v998 Imm(0) -> x1 + v999 LoadLocal { off=-1, kind=I64 } -> x1 + v1000 LoadLocal { off=248, kind=I64 } -> x1 + v1001 Binop { op=add, lhs=v997, rhs=v1000 } -> x0 + v1002 Imm(0) -> x1 + v1003 LoadLocal { off=-1, kind=I64 } -> x1 + v1004 LoadLocal { off=249, kind=I64 } -> x1 + v1005 Binop { op=add, lhs=v1001, rhs=v1004 } -> x0 + v1006 Imm(0) -> x1 + v1007 LoadLocal { off=-1, kind=I64 } -> x1 + v1008 LoadLocal { off=250, kind=I64 } -> x1 + v1009 Binop { op=add, lhs=v1005, rhs=v1008 } -> x0 + v1010 Imm(0) -> x1 + v1011 LoadLocal { off=-1, kind=I64 } -> x1 + v1012 LoadLocal { off=251, kind=I64 } -> x1 + v1013 Binop { op=add, lhs=v1009, rhs=v1012 } -> x0 + v1014 Imm(0) -> x1 + v1015 LoadLocal { off=-1, kind=I64 } -> x1 + v1016 LoadLocal { off=252, kind=I64 } -> x1 + v1017 Binop { op=add, lhs=v1013, rhs=v1016 } -> x0 + v1018 Imm(0) -> x1 + v1019 LoadLocal { off=-1, kind=I64 } -> x1 + v1020 LoadLocal { off=253, kind=I64 } -> x1 + v1021 Binop { op=add, lhs=v1017, rhs=v1020 } -> x0 + v1022 Imm(0) -> x1 + v1023 LoadLocal { off=-1, kind=I64 } -> x1 + v1024 LoadLocal { off=254, kind=I64 } -> x1 + v1025 Binop { op=add, lhs=v1021, rhs=v1024 } -> x0 + v1026 Imm(0) -> x1 + v1027 LoadLocal { off=-1, kind=I64 } -> x1 + v1028 LoadLocal { off=255, kind=I64 } -> x1 + v1029 Binop { op=add, lhs=v1025, rhs=v1028 } -> x0 + v1030 Imm(0) -> x1 + v1031 LoadLocal { off=-1, kind=I64 } -> x1 + v1032 LoadLocal { off=256, kind=I64 } -> x1 + v1033 Binop { op=add, lhs=v1029, rhs=v1032 } -> x0 + v1034 Imm(0) -> x1 + v1035 LoadLocal { off=-1, kind=I64 } -> x1 + v1036 LoadLocal { off=257, kind=I64 } -> x1 + v1037 Binop { op=add, lhs=v1033, rhs=v1036 } -> x0 + v1038 Imm(0) -> x1 + v1039 LoadLocal { off=-1, kind=I64 } -> x1 + v1040 LoadLocal { off=258, kind=I64 } -> x1 + v1041 Binop { op=add, lhs=v1037, rhs=v1040 } -> x0 + v1042 Imm(0) -> x1 + v1043 LoadLocal { off=-1, kind=I64 } -> x1 + v1044 LoadLocal { off=259, kind=I64 } -> x1 + v1045 Binop { op=add, lhs=v1041, rhs=v1044 } -> x0 + v1046 Imm(0) -> x1 + v1047 LoadLocal { off=-1, kind=I64 } -> x1 + v1048 LoadLocal { off=260, kind=I64 } -> x1 + v1049 Binop { op=add, lhs=v1045, rhs=v1048 } -> x0 + v1050 Imm(0) -> x1 + v1051 LoadLocal { off=-1, kind=I64 } -> x1 + v1052 LoadLocal { off=261, kind=I64 } -> x1 + v1053 Binop { op=add, lhs=v1049, rhs=v1052 } -> x0 + v1054 Imm(0) -> x1 + v1055 LoadLocal { off=-1, kind=I64 } -> x1 + terminator Return(v1053) (exit_acc=v1053) +; --- SSA dump (ok=true) ent_pc=2 --- +; name=main +fn ent_pc=2 n_params=0 variadic=false locals=264 + spill_count=251 gpr_used=[3, 12, 13, 14, 15] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ImmCode(ent_pc=1) -> x3 + v2 Imm(0) -> x0 + v3 ImmCode(ent_pc=0) -> x12 + v4 Imm(0) -> x0 + v5 Imm(0) -> x1 + v6 Imm(0) -> x0 + terminator Jmp(b1) (exit_acc=v5) + block 1 start_pc=0 + v7 Phi { incoming=[b0:v5, b2:v11], kind=I64 } -> x1 + v8 LoadLocal { off=-3, kind=I64 } -> x0 + v9 BinopI { op=lt, lhs=v7, rhs_imm=261 } -> x0 + terminator Bz { cond=v9, target=b4, fall=b3 } (exit_acc=v9) + block 2 start_pc=0 + v10 LoadLocal { off=-3, kind=I64 } -> x0 + v11 BinopI { op=add, lhs=v7, rhs_imm=1 } -> x1 + v12 Imm(0) -> x0 + terminator Jmp(b1) (exit_acc=v11) + block 3 start_pc=0 + v13 ImmData(24) -> x0 + v14 LoadLocal { off=-3, kind=I64 } -> x2 + v15 BinopI { op=shl, lhs=v7, rhs_imm=4 } -> x2 + v16 Binop { op=add, lhs=v13, rhs=v15 } -> x2 + v17 Store { addr=v16, disp=0, value=v7, kind=I64 } -> - + v18 LoadLocal { off=-3, kind=I64 } -> x2 + v19 BinopI { op=shl, lhs=v7, rhs_imm=4 } -> x2 + v20 Binop { op=add, lhs=v13, rhs=v19 } -> x0 + v21 BinopI { op=add, lhs=v20, rhs_imm=8 } -> x2 + v22 Imm(2) -> x2 + v23 BinopI { op=shl, lhs=v7, rhs_imm=1 } -> x2 + v24 Store { addr=v20, disp=8, value=v23, kind=I64 } -> - + terminator Jmp(b2) (exit_acc=v24) + block 4 start_pc=0 + v25 ImmData(24) -> x7 + v26 Imm(0) -> x0 + v27 Imm(16) -> x0 + v28 BinopI { op=add, lhs=v25, rhs_imm=16 } -> x6 + v29 Imm(32) -> x0 + v30 BinopI { op=add, lhs=v25, rhs_imm=32 } -> x2 + v31 Imm(48) -> x0 + v32 BinopI { op=add, lhs=v25, rhs_imm=48 } -> x1 + v33 Imm(64) -> x0 + v34 BinopI { op=add, lhs=v25, rhs_imm=64 } -> x8 + v35 Imm(80) -> x0 + v36 BinopI { op=add, lhs=v25, rhs_imm=80 } -> x9 + v37 Imm(96) -> x0 + v38 BinopI { op=add, lhs=v25, rhs_imm=96 } -> x0 + v39 Imm(112) -> x13 + v40 BinopI { op=add, lhs=v25, rhs_imm=112 } -> x13 + v41 Imm(128) -> x14 + v42 BinopI { op=add, lhs=v25, rhs_imm=128 } -> x14 + v43 Imm(144) -> x15 + v44 BinopI { op=add, lhs=v25, rhs_imm=144 } -> x15 + v45 Imm(160) -> [spill 0] + v46 BinopI { op=add, lhs=v25, rhs_imm=160 } -> [spill 0] + v47 Imm(176) -> [spill 1] + v48 BinopI { op=add, lhs=v25, rhs_imm=176 } -> [spill 1] + v49 Imm(192) -> [spill 2] + v50 BinopI { op=add, lhs=v25, rhs_imm=192 } -> [spill 2] + v51 Imm(208) -> [spill 3] + v52 BinopI { op=add, lhs=v25, rhs_imm=208 } -> [spill 3] + v53 Imm(224) -> [spill 4] + v54 BinopI { op=add, lhs=v25, rhs_imm=224 } -> [spill 4] + v55 Imm(240) -> [spill 5] + v56 BinopI { op=add, lhs=v25, rhs_imm=240 } -> [spill 5] + v57 Imm(256) -> [spill 6] + v58 BinopI { op=add, lhs=v25, rhs_imm=256 } -> [spill 6] + v59 Imm(272) -> [spill 7] + v60 BinopI { op=add, lhs=v25, rhs_imm=272 } -> [spill 7] + v61 Imm(288) -> [spill 8] + v62 BinopI { op=add, lhs=v25, rhs_imm=288 } -> [spill 8] + v63 Imm(304) -> [spill 9] + v64 BinopI { op=add, lhs=v25, rhs_imm=304 } -> [spill 9] + v65 Imm(320) -> [spill 10] + v66 BinopI { op=add, lhs=v25, rhs_imm=320 } -> [spill 10] + v67 Imm(336) -> [spill 11] + v68 BinopI { op=add, lhs=v25, rhs_imm=336 } -> [spill 11] + v69 Imm(352) -> [spill 12] + v70 BinopI { op=add, lhs=v25, rhs_imm=352 } -> [spill 12] + v71 Imm(368) -> [spill 13] + v72 BinopI { op=add, lhs=v25, rhs_imm=368 } -> [spill 13] + v73 Imm(384) -> [spill 14] + v74 BinopI { op=add, lhs=v25, rhs_imm=384 } -> [spill 14] + v75 Imm(400) -> [spill 15] + v76 BinopI { op=add, lhs=v25, rhs_imm=400 } -> [spill 15] + v77 Imm(416) -> [spill 16] + v78 BinopI { op=add, lhs=v25, rhs_imm=416 } -> [spill 16] + v79 Imm(432) -> [spill 17] + v80 BinopI { op=add, lhs=v25, rhs_imm=432 } -> [spill 17] + v81 Imm(448) -> [spill 18] + v82 BinopI { op=add, lhs=v25, rhs_imm=448 } -> [spill 18] + v83 Imm(464) -> [spill 19] + v84 BinopI { op=add, lhs=v25, rhs_imm=464 } -> [spill 19] + v85 Imm(480) -> [spill 20] + v86 BinopI { op=add, lhs=v25, rhs_imm=480 } -> [spill 20] + v87 Imm(496) -> [spill 21] + v88 BinopI { op=add, lhs=v25, rhs_imm=496 } -> [spill 21] + v89 Imm(512) -> [spill 22] + v90 BinopI { op=add, lhs=v25, rhs_imm=512 } -> [spill 22] + v91 Imm(528) -> [spill 23] + v92 BinopI { op=add, lhs=v25, rhs_imm=528 } -> [spill 23] + v93 Imm(544) -> [spill 24] + v94 BinopI { op=add, lhs=v25, rhs_imm=544 } -> [spill 24] + v95 Imm(560) -> [spill 25] + v96 BinopI { op=add, lhs=v25, rhs_imm=560 } -> [spill 25] + v97 Imm(576) -> [spill 26] + v98 BinopI { op=add, lhs=v25, rhs_imm=576 } -> [spill 26] + v99 Imm(592) -> [spill 27] + v100 BinopI { op=add, lhs=v25, rhs_imm=592 } -> [spill 27] + v101 Imm(608) -> [spill 28] + v102 BinopI { op=add, lhs=v25, rhs_imm=608 } -> [spill 28] + v103 Imm(624) -> [spill 29] + v104 BinopI { op=add, lhs=v25, rhs_imm=624 } -> [spill 29] + v105 Imm(640) -> [spill 30] + v106 BinopI { op=add, lhs=v25, rhs_imm=640 } -> [spill 30] + v107 Imm(656) -> [spill 31] + v108 BinopI { op=add, lhs=v25, rhs_imm=656 } -> [spill 31] + v109 Imm(672) -> [spill 32] + v110 BinopI { op=add, lhs=v25, rhs_imm=672 } -> [spill 32] + v111 Imm(688) -> [spill 33] + v112 BinopI { op=add, lhs=v25, rhs_imm=688 } -> [spill 33] + v113 Imm(704) -> [spill 34] + v114 BinopI { op=add, lhs=v25, rhs_imm=704 } -> [spill 34] + v115 Imm(720) -> [spill 35] + v116 BinopI { op=add, lhs=v25, rhs_imm=720 } -> [spill 35] + v117 Imm(736) -> [spill 36] + v118 BinopI { op=add, lhs=v25, rhs_imm=736 } -> [spill 36] + v119 Imm(752) -> [spill 37] + v120 BinopI { op=add, lhs=v25, rhs_imm=752 } -> [spill 37] + v121 Imm(768) -> [spill 38] + v122 BinopI { op=add, lhs=v25, rhs_imm=768 } -> [spill 38] + v123 Imm(784) -> [spill 39] + v124 BinopI { op=add, lhs=v25, rhs_imm=784 } -> [spill 39] + v125 Imm(800) -> [spill 40] + v126 BinopI { op=add, lhs=v25, rhs_imm=800 } -> [spill 40] + v127 Imm(816) -> [spill 41] + v128 BinopI { op=add, lhs=v25, rhs_imm=816 } -> [spill 41] + v129 Imm(832) -> [spill 42] + v130 BinopI { op=add, lhs=v25, rhs_imm=832 } -> [spill 42] + v131 Imm(848) -> [spill 43] + v132 BinopI { op=add, lhs=v25, rhs_imm=848 } -> [spill 43] + v133 Imm(864) -> [spill 44] + v134 BinopI { op=add, lhs=v25, rhs_imm=864 } -> [spill 44] + v135 Imm(880) -> [spill 45] + v136 BinopI { op=add, lhs=v25, rhs_imm=880 } -> [spill 45] + v137 Imm(896) -> [spill 46] + v138 BinopI { op=add, lhs=v25, rhs_imm=896 } -> [spill 46] + v139 Imm(912) -> [spill 47] + v140 BinopI { op=add, lhs=v25, rhs_imm=912 } -> [spill 47] + v141 Imm(928) -> [spill 48] + v142 BinopI { op=add, lhs=v25, rhs_imm=928 } -> [spill 48] + v143 Imm(944) -> [spill 49] + v144 BinopI { op=add, lhs=v25, rhs_imm=944 } -> [spill 49] + v145 Imm(960) -> [spill 50] + v146 BinopI { op=add, lhs=v25, rhs_imm=960 } -> [spill 50] + v147 Imm(976) -> [spill 51] + v148 BinopI { op=add, lhs=v25, rhs_imm=976 } -> [spill 51] + v149 Imm(992) -> [spill 52] + v150 BinopI { op=add, lhs=v25, rhs_imm=992 } -> [spill 52] + v151 Imm(1008) -> [spill 53] + v152 BinopI { op=add, lhs=v25, rhs_imm=1008 } -> [spill 53] + v153 Imm(1024) -> [spill 54] + v154 BinopI { op=add, lhs=v25, rhs_imm=1024 } -> [spill 54] + v155 Imm(1040) -> [spill 55] + v156 BinopI { op=add, lhs=v25, rhs_imm=1040 } -> [spill 55] + v157 Imm(1056) -> [spill 56] + v158 BinopI { op=add, lhs=v25, rhs_imm=1056 } -> [spill 56] + v159 Imm(1072) -> [spill 57] + v160 BinopI { op=add, lhs=v25, rhs_imm=1072 } -> [spill 57] + v161 Imm(1088) -> [spill 58] + v162 BinopI { op=add, lhs=v25, rhs_imm=1088 } -> [spill 58] + v163 Imm(1104) -> [spill 59] + v164 BinopI { op=add, lhs=v25, rhs_imm=1104 } -> [spill 59] + v165 Imm(1120) -> [spill 60] + v166 BinopI { op=add, lhs=v25, rhs_imm=1120 } -> [spill 60] + v167 Imm(1136) -> [spill 61] + v168 BinopI { op=add, lhs=v25, rhs_imm=1136 } -> [spill 61] + v169 Imm(1152) -> [spill 62] + v170 BinopI { op=add, lhs=v25, rhs_imm=1152 } -> [spill 62] + v171 Imm(1168) -> [spill 63] + v172 BinopI { op=add, lhs=v25, rhs_imm=1168 } -> [spill 63] + v173 Imm(1184) -> [spill 64] + v174 BinopI { op=add, lhs=v25, rhs_imm=1184 } -> [spill 64] + v175 Imm(1200) -> [spill 65] + v176 BinopI { op=add, lhs=v25, rhs_imm=1200 } -> [spill 65] + v177 Imm(1216) -> [spill 66] + v178 BinopI { op=add, lhs=v25, rhs_imm=1216 } -> [spill 66] + v179 Imm(1232) -> [spill 67] + v180 BinopI { op=add, lhs=v25, rhs_imm=1232 } -> [spill 67] + v181 Imm(1248) -> [spill 68] + v182 BinopI { op=add, lhs=v25, rhs_imm=1248 } -> [spill 68] + v183 Imm(1264) -> [spill 69] + v184 BinopI { op=add, lhs=v25, rhs_imm=1264 } -> [spill 69] + v185 Imm(1280) -> [spill 70] + v186 BinopI { op=add, lhs=v25, rhs_imm=1280 } -> [spill 70] + v187 Imm(1296) -> [spill 71] + v188 BinopI { op=add, lhs=v25, rhs_imm=1296 } -> [spill 71] + v189 Imm(1312) -> [spill 72] + v190 BinopI { op=add, lhs=v25, rhs_imm=1312 } -> [spill 72] + v191 Imm(1328) -> [spill 73] + v192 BinopI { op=add, lhs=v25, rhs_imm=1328 } -> [spill 73] + v193 Imm(1344) -> [spill 74] + v194 BinopI { op=add, lhs=v25, rhs_imm=1344 } -> [spill 74] + v195 Imm(1360) -> [spill 75] + v196 BinopI { op=add, lhs=v25, rhs_imm=1360 } -> [spill 75] + v197 Imm(1376) -> [spill 76] + v198 BinopI { op=add, lhs=v25, rhs_imm=1376 } -> [spill 76] + v199 Imm(1392) -> [spill 77] + v200 BinopI { op=add, lhs=v25, rhs_imm=1392 } -> [spill 77] + v201 Imm(1408) -> [spill 78] + v202 BinopI { op=add, lhs=v25, rhs_imm=1408 } -> [spill 78] + v203 Imm(1424) -> [spill 79] + v204 BinopI { op=add, lhs=v25, rhs_imm=1424 } -> [spill 79] + v205 Imm(1440) -> [spill 80] + v206 BinopI { op=add, lhs=v25, rhs_imm=1440 } -> [spill 80] + v207 Imm(1456) -> [spill 81] + v208 BinopI { op=add, lhs=v25, rhs_imm=1456 } -> [spill 81] + v209 Imm(1472) -> [spill 82] + v210 BinopI { op=add, lhs=v25, rhs_imm=1472 } -> [spill 82] + v211 Imm(1488) -> [spill 83] + v212 BinopI { op=add, lhs=v25, rhs_imm=1488 } -> [spill 83] + v213 Imm(1504) -> [spill 84] + v214 BinopI { op=add, lhs=v25, rhs_imm=1504 } -> [spill 84] + v215 Imm(1520) -> [spill 85] + v216 BinopI { op=add, lhs=v25, rhs_imm=1520 } -> [spill 85] + v217 Imm(1536) -> [spill 86] + v218 BinopI { op=add, lhs=v25, rhs_imm=1536 } -> [spill 86] + v219 Imm(1552) -> [spill 87] + v220 BinopI { op=add, lhs=v25, rhs_imm=1552 } -> [spill 87] + v221 Imm(1568) -> [spill 88] + v222 BinopI { op=add, lhs=v25, rhs_imm=1568 } -> [spill 88] + v223 Imm(1584) -> [spill 89] + v224 BinopI { op=add, lhs=v25, rhs_imm=1584 } -> [spill 89] + v225 Imm(1600) -> [spill 90] + v226 BinopI { op=add, lhs=v25, rhs_imm=1600 } -> [spill 90] + v227 Imm(1616) -> [spill 91] + v228 BinopI { op=add, lhs=v25, rhs_imm=1616 } -> [spill 91] + v229 Imm(1632) -> [spill 92] + v230 BinopI { op=add, lhs=v25, rhs_imm=1632 } -> [spill 92] + v231 Imm(1648) -> [spill 93] + v232 BinopI { op=add, lhs=v25, rhs_imm=1648 } -> [spill 93] + v233 Imm(1664) -> [spill 94] + v234 BinopI { op=add, lhs=v25, rhs_imm=1664 } -> [spill 94] + v235 Imm(1680) -> [spill 95] + v236 BinopI { op=add, lhs=v25, rhs_imm=1680 } -> [spill 95] + v237 Imm(1696) -> [spill 96] + v238 BinopI { op=add, lhs=v25, rhs_imm=1696 } -> [spill 96] + v239 Imm(1712) -> [spill 97] + v240 BinopI { op=add, lhs=v25, rhs_imm=1712 } -> [spill 97] + v241 Imm(1728) -> [spill 98] + v242 BinopI { op=add, lhs=v25, rhs_imm=1728 } -> [spill 98] + v243 Imm(1744) -> [spill 99] + v244 BinopI { op=add, lhs=v25, rhs_imm=1744 } -> [spill 99] + v245 Imm(1760) -> [spill 100] + v246 BinopI { op=add, lhs=v25, rhs_imm=1760 } -> [spill 100] + v247 Imm(1776) -> [spill 101] + v248 BinopI { op=add, lhs=v25, rhs_imm=1776 } -> [spill 101] + v249 Imm(1792) -> [spill 102] + v250 BinopI { op=add, lhs=v25, rhs_imm=1792 } -> [spill 102] + v251 Imm(1808) -> [spill 103] + v252 BinopI { op=add, lhs=v25, rhs_imm=1808 } -> [spill 103] + v253 Imm(1824) -> [spill 104] + v254 BinopI { op=add, lhs=v25, rhs_imm=1824 } -> [spill 104] + v255 Imm(1840) -> [spill 105] + v256 BinopI { op=add, lhs=v25, rhs_imm=1840 } -> [spill 105] + v257 Imm(1856) -> [spill 106] + v258 BinopI { op=add, lhs=v25, rhs_imm=1856 } -> [spill 106] + v259 Imm(1872) -> [spill 107] + v260 BinopI { op=add, lhs=v25, rhs_imm=1872 } -> [spill 107] + v261 Imm(1888) -> [spill 108] + v262 BinopI { op=add, lhs=v25, rhs_imm=1888 } -> [spill 108] + v263 Imm(1904) -> [spill 109] + v264 BinopI { op=add, lhs=v25, rhs_imm=1904 } -> [spill 109] + v265 Imm(1920) -> [spill 110] + v266 BinopI { op=add, lhs=v25, rhs_imm=1920 } -> [spill 110] + v267 Imm(1936) -> [spill 111] + v268 BinopI { op=add, lhs=v25, rhs_imm=1936 } -> [spill 111] + v269 Imm(1952) -> [spill 112] + v270 BinopI { op=add, lhs=v25, rhs_imm=1952 } -> [spill 112] + v271 Imm(1968) -> [spill 113] + v272 BinopI { op=add, lhs=v25, rhs_imm=1968 } -> [spill 113] + v273 Imm(1984) -> [spill 114] + v274 BinopI { op=add, lhs=v25, rhs_imm=1984 } -> [spill 114] + v275 Imm(2000) -> [spill 115] + v276 BinopI { op=add, lhs=v25, rhs_imm=2000 } -> [spill 115] + v277 Imm(2016) -> [spill 116] + v278 BinopI { op=add, lhs=v25, rhs_imm=2016 } -> [spill 116] + v279 Imm(2032) -> [spill 117] + v280 BinopI { op=add, lhs=v25, rhs_imm=2032 } -> [spill 117] + v281 Imm(2048) -> [spill 118] + v282 BinopI { op=add, lhs=v25, rhs_imm=2048 } -> [spill 118] + v283 Imm(2064) -> [spill 119] + v284 BinopI { op=add, lhs=v25, rhs_imm=2064 } -> [spill 119] + v285 Imm(2080) -> [spill 120] + v286 BinopI { op=add, lhs=v25, rhs_imm=2080 } -> [spill 120] + v287 Imm(2096) -> [spill 121] + v288 BinopI { op=add, lhs=v25, rhs_imm=2096 } -> [spill 121] + v289 Imm(2112) -> [spill 122] + v290 BinopI { op=add, lhs=v25, rhs_imm=2112 } -> [spill 122] + v291 Imm(2128) -> [spill 123] + v292 BinopI { op=add, lhs=v25, rhs_imm=2128 } -> [spill 123] + v293 Imm(2144) -> [spill 124] + v294 BinopI { op=add, lhs=v25, rhs_imm=2144 } -> [spill 124] + v295 Imm(2160) -> [spill 125] + v296 BinopI { op=add, lhs=v25, rhs_imm=2160 } -> [spill 125] + v297 Imm(2176) -> [spill 126] + v298 BinopI { op=add, lhs=v25, rhs_imm=2176 } -> [spill 126] + v299 Imm(2192) -> [spill 127] + v300 BinopI { op=add, lhs=v25, rhs_imm=2192 } -> [spill 127] + v301 Imm(2208) -> [spill 128] + v302 BinopI { op=add, lhs=v25, rhs_imm=2208 } -> [spill 128] + v303 Imm(2224) -> [spill 129] + v304 BinopI { op=add, lhs=v25, rhs_imm=2224 } -> [spill 129] + v305 Imm(2240) -> [spill 130] + v306 BinopI { op=add, lhs=v25, rhs_imm=2240 } -> [spill 130] + v307 Imm(2256) -> [spill 131] + v308 BinopI { op=add, lhs=v25, rhs_imm=2256 } -> [spill 131] + v309 Imm(2272) -> [spill 132] + v310 BinopI { op=add, lhs=v25, rhs_imm=2272 } -> [spill 132] + v311 Imm(2288) -> [spill 133] + v312 BinopI { op=add, lhs=v25, rhs_imm=2288 } -> [spill 133] + v313 Imm(2304) -> [spill 134] + v314 BinopI { op=add, lhs=v25, rhs_imm=2304 } -> [spill 134] + v315 Imm(2320) -> [spill 135] + v316 BinopI { op=add, lhs=v25, rhs_imm=2320 } -> [spill 135] + v317 Imm(2336) -> [spill 136] + v318 BinopI { op=add, lhs=v25, rhs_imm=2336 } -> [spill 136] + v319 Imm(2352) -> [spill 137] + v320 BinopI { op=add, lhs=v25, rhs_imm=2352 } -> [spill 137] + v321 Imm(2368) -> [spill 138] + v322 BinopI { op=add, lhs=v25, rhs_imm=2368 } -> [spill 138] + v323 Imm(2384) -> [spill 139] + v324 BinopI { op=add, lhs=v25, rhs_imm=2384 } -> [spill 139] + v325 Imm(2400) -> [spill 140] + v326 BinopI { op=add, lhs=v25, rhs_imm=2400 } -> [spill 140] + v327 Imm(2416) -> [spill 141] + v328 BinopI { op=add, lhs=v25, rhs_imm=2416 } -> [spill 141] + v329 Imm(2432) -> [spill 142] + v330 BinopI { op=add, lhs=v25, rhs_imm=2432 } -> [spill 142] + v331 Imm(2448) -> [spill 143] + v332 BinopI { op=add, lhs=v25, rhs_imm=2448 } -> [spill 143] + v333 Imm(2464) -> [spill 144] + v334 BinopI { op=add, lhs=v25, rhs_imm=2464 } -> [spill 144] + v335 Imm(2480) -> [spill 145] + v336 BinopI { op=add, lhs=v25, rhs_imm=2480 } -> [spill 145] + v337 Imm(2496) -> [spill 146] + v338 BinopI { op=add, lhs=v25, rhs_imm=2496 } -> [spill 146] + v339 Imm(2512) -> [spill 147] + v340 BinopI { op=add, lhs=v25, rhs_imm=2512 } -> [spill 147] + v341 Imm(2528) -> [spill 148] + v342 BinopI { op=add, lhs=v25, rhs_imm=2528 } -> [spill 148] + v343 Imm(2544) -> [spill 149] + v344 BinopI { op=add, lhs=v25, rhs_imm=2544 } -> [spill 149] + v345 Imm(2560) -> [spill 150] + v346 BinopI { op=add, lhs=v25, rhs_imm=2560 } -> [spill 150] + v347 Imm(2576) -> [spill 151] + v348 BinopI { op=add, lhs=v25, rhs_imm=2576 } -> [spill 151] + v349 Imm(2592) -> [spill 152] + v350 BinopI { op=add, lhs=v25, rhs_imm=2592 } -> [spill 152] + v351 Imm(2608) -> [spill 153] + v352 BinopI { op=add, lhs=v25, rhs_imm=2608 } -> [spill 153] + v353 Imm(2624) -> [spill 154] + v354 BinopI { op=add, lhs=v25, rhs_imm=2624 } -> [spill 154] + v355 Imm(2640) -> [spill 155] + v356 BinopI { op=add, lhs=v25, rhs_imm=2640 } -> [spill 155] + v357 Imm(2656) -> [spill 156] + v358 BinopI { op=add, lhs=v25, rhs_imm=2656 } -> [spill 156] + v359 Imm(2672) -> [spill 157] + v360 BinopI { op=add, lhs=v25, rhs_imm=2672 } -> [spill 157] + v361 Imm(2688) -> [spill 158] + v362 BinopI { op=add, lhs=v25, rhs_imm=2688 } -> [spill 158] + v363 Imm(2704) -> [spill 159] + v364 BinopI { op=add, lhs=v25, rhs_imm=2704 } -> [spill 159] + v365 Imm(2720) -> [spill 160] + v366 BinopI { op=add, lhs=v25, rhs_imm=2720 } -> [spill 160] + v367 Imm(2736) -> [spill 161] + v368 BinopI { op=add, lhs=v25, rhs_imm=2736 } -> [spill 161] + v369 Imm(2752) -> [spill 162] + v370 BinopI { op=add, lhs=v25, rhs_imm=2752 } -> [spill 162] + v371 Imm(2768) -> [spill 163] + v372 BinopI { op=add, lhs=v25, rhs_imm=2768 } -> [spill 163] + v373 Imm(2784) -> [spill 164] + v374 BinopI { op=add, lhs=v25, rhs_imm=2784 } -> [spill 164] + v375 Imm(2800) -> [spill 165] + v376 BinopI { op=add, lhs=v25, rhs_imm=2800 } -> [spill 165] + v377 Imm(2816) -> [spill 166] + v378 BinopI { op=add, lhs=v25, rhs_imm=2816 } -> [spill 166] + v379 Imm(2832) -> [spill 167] + v380 BinopI { op=add, lhs=v25, rhs_imm=2832 } -> [spill 167] + v381 Imm(2848) -> [spill 168] + v382 BinopI { op=add, lhs=v25, rhs_imm=2848 } -> [spill 168] + v383 Imm(2864) -> [spill 169] + v384 BinopI { op=add, lhs=v25, rhs_imm=2864 } -> [spill 169] + v385 Imm(2880) -> [spill 170] + v386 BinopI { op=add, lhs=v25, rhs_imm=2880 } -> [spill 170] + v387 Imm(2896) -> [spill 171] + v388 BinopI { op=add, lhs=v25, rhs_imm=2896 } -> [spill 171] + v389 Imm(2912) -> [spill 172] + v390 BinopI { op=add, lhs=v25, rhs_imm=2912 } -> [spill 172] + v391 Imm(2928) -> [spill 173] + v392 BinopI { op=add, lhs=v25, rhs_imm=2928 } -> [spill 173] + v393 Imm(2944) -> [spill 174] + v394 BinopI { op=add, lhs=v25, rhs_imm=2944 } -> [spill 174] + v395 Imm(2960) -> [spill 175] + v396 BinopI { op=add, lhs=v25, rhs_imm=2960 } -> [spill 175] + v397 Imm(2976) -> [spill 176] + v398 BinopI { op=add, lhs=v25, rhs_imm=2976 } -> [spill 176] + v399 Imm(2992) -> [spill 177] + v400 BinopI { op=add, lhs=v25, rhs_imm=2992 } -> [spill 177] + v401 Imm(3008) -> [spill 178] + v402 BinopI { op=add, lhs=v25, rhs_imm=3008 } -> [spill 178] + v403 Imm(3024) -> [spill 179] + v404 BinopI { op=add, lhs=v25, rhs_imm=3024 } -> [spill 179] + v405 Imm(3040) -> [spill 180] + v406 BinopI { op=add, lhs=v25, rhs_imm=3040 } -> [spill 180] + v407 Imm(3056) -> [spill 181] + v408 BinopI { op=add, lhs=v25, rhs_imm=3056 } -> [spill 181] + v409 Imm(3072) -> [spill 182] + v410 BinopI { op=add, lhs=v25, rhs_imm=3072 } -> [spill 182] + v411 Imm(3088) -> [spill 183] + v412 BinopI { op=add, lhs=v25, rhs_imm=3088 } -> [spill 183] + v413 Imm(3104) -> [spill 184] + v414 BinopI { op=add, lhs=v25, rhs_imm=3104 } -> [spill 184] + v415 Imm(3120) -> [spill 185] + v416 BinopI { op=add, lhs=v25, rhs_imm=3120 } -> [spill 185] + v417 Imm(3136) -> [spill 186] + v418 BinopI { op=add, lhs=v25, rhs_imm=3136 } -> [spill 186] + v419 Imm(3152) -> [spill 187] + v420 BinopI { op=add, lhs=v25, rhs_imm=3152 } -> [spill 187] + v421 Imm(3168) -> [spill 188] + v422 BinopI { op=add, lhs=v25, rhs_imm=3168 } -> [spill 188] + v423 Imm(3184) -> [spill 189] + v424 BinopI { op=add, lhs=v25, rhs_imm=3184 } -> [spill 189] + v425 Imm(3200) -> [spill 190] + v426 BinopI { op=add, lhs=v25, rhs_imm=3200 } -> [spill 190] + v427 Imm(3216) -> [spill 191] + v428 BinopI { op=add, lhs=v25, rhs_imm=3216 } -> [spill 191] + v429 Imm(3232) -> [spill 192] + v430 BinopI { op=add, lhs=v25, rhs_imm=3232 } -> [spill 192] + v431 Imm(3248) -> [spill 193] + v432 BinopI { op=add, lhs=v25, rhs_imm=3248 } -> [spill 193] + v433 Imm(3264) -> [spill 194] + v434 BinopI { op=add, lhs=v25, rhs_imm=3264 } -> [spill 194] + v435 Imm(3280) -> [spill 195] + v436 BinopI { op=add, lhs=v25, rhs_imm=3280 } -> [spill 195] + v437 Imm(3296) -> [spill 196] + v438 BinopI { op=add, lhs=v25, rhs_imm=3296 } -> [spill 196] + v439 Imm(3312) -> [spill 197] + v440 BinopI { op=add, lhs=v25, rhs_imm=3312 } -> [spill 197] + v441 Imm(3328) -> [spill 198] + v442 BinopI { op=add, lhs=v25, rhs_imm=3328 } -> [spill 198] + v443 Imm(3344) -> [spill 199] + v444 BinopI { op=add, lhs=v25, rhs_imm=3344 } -> [spill 199] + v445 Imm(3360) -> [spill 200] + v446 BinopI { op=add, lhs=v25, rhs_imm=3360 } -> [spill 200] + v447 Imm(3376) -> [spill 201] + v448 BinopI { op=add, lhs=v25, rhs_imm=3376 } -> [spill 201] + v449 Imm(3392) -> [spill 202] + v450 BinopI { op=add, lhs=v25, rhs_imm=3392 } -> [spill 202] + v451 Imm(3408) -> [spill 203] + v452 BinopI { op=add, lhs=v25, rhs_imm=3408 } -> [spill 203] + v453 Imm(3424) -> [spill 204] + v454 BinopI { op=add, lhs=v25, rhs_imm=3424 } -> [spill 204] + v455 Imm(3440) -> [spill 205] + v456 BinopI { op=add, lhs=v25, rhs_imm=3440 } -> [spill 205] + v457 Imm(3456) -> [spill 206] + v458 BinopI { op=add, lhs=v25, rhs_imm=3456 } -> [spill 206] + v459 Imm(3472) -> [spill 207] + v460 BinopI { op=add, lhs=v25, rhs_imm=3472 } -> [spill 207] + v461 Imm(3488) -> [spill 208] + v462 BinopI { op=add, lhs=v25, rhs_imm=3488 } -> [spill 208] + v463 Imm(3504) -> [spill 209] + v464 BinopI { op=add, lhs=v25, rhs_imm=3504 } -> [spill 209] + v465 Imm(3520) -> [spill 210] + v466 BinopI { op=add, lhs=v25, rhs_imm=3520 } -> [spill 210] + v467 Imm(3536) -> [spill 211] + v468 BinopI { op=add, lhs=v25, rhs_imm=3536 } -> [spill 211] + v469 Imm(3552) -> [spill 212] + v470 BinopI { op=add, lhs=v25, rhs_imm=3552 } -> [spill 212] + v471 Imm(3568) -> [spill 213] + v472 BinopI { op=add, lhs=v25, rhs_imm=3568 } -> [spill 213] + v473 Imm(3584) -> [spill 214] + v474 BinopI { op=add, lhs=v25, rhs_imm=3584 } -> [spill 214] + v475 Imm(3600) -> [spill 215] + v476 BinopI { op=add, lhs=v25, rhs_imm=3600 } -> [spill 215] + v477 Imm(3616) -> [spill 216] + v478 BinopI { op=add, lhs=v25, rhs_imm=3616 } -> [spill 216] + v479 Imm(3632) -> [spill 217] + v480 BinopI { op=add, lhs=v25, rhs_imm=3632 } -> [spill 217] + v481 Imm(3648) -> [spill 218] + v482 BinopI { op=add, lhs=v25, rhs_imm=3648 } -> [spill 218] + v483 Imm(3664) -> [spill 219] + v484 BinopI { op=add, lhs=v25, rhs_imm=3664 } -> [spill 219] + v485 Imm(3680) -> [spill 220] + v486 BinopI { op=add, lhs=v25, rhs_imm=3680 } -> [spill 220] + v487 Imm(3696) -> [spill 221] + v488 BinopI { op=add, lhs=v25, rhs_imm=3696 } -> [spill 221] + v489 Imm(3712) -> [spill 222] + v490 BinopI { op=add, lhs=v25, rhs_imm=3712 } -> [spill 222] + v491 Imm(3728) -> [spill 223] + v492 BinopI { op=add, lhs=v25, rhs_imm=3728 } -> [spill 223] + v493 Imm(3744) -> [spill 224] + v494 BinopI { op=add, lhs=v25, rhs_imm=3744 } -> [spill 224] + v495 Imm(3760) -> [spill 225] + v496 BinopI { op=add, lhs=v25, rhs_imm=3760 } -> [spill 225] + v497 Imm(3776) -> [spill 226] + v498 BinopI { op=add, lhs=v25, rhs_imm=3776 } -> [spill 226] + v499 Imm(3792) -> [spill 227] + v500 BinopI { op=add, lhs=v25, rhs_imm=3792 } -> [spill 227] + v501 Imm(3808) -> [spill 228] + v502 BinopI { op=add, lhs=v25, rhs_imm=3808 } -> [spill 228] + v503 Imm(3824) -> [spill 229] + v504 BinopI { op=add, lhs=v25, rhs_imm=3824 } -> [spill 229] + v505 Imm(3840) -> [spill 230] + v506 BinopI { op=add, lhs=v25, rhs_imm=3840 } -> [spill 230] + v507 Imm(3856) -> [spill 231] + v508 BinopI { op=add, lhs=v25, rhs_imm=3856 } -> [spill 231] + v509 Imm(3872) -> [spill 232] + v510 BinopI { op=add, lhs=v25, rhs_imm=3872 } -> [spill 232] + v511 Imm(3888) -> [spill 233] + v512 BinopI { op=add, lhs=v25, rhs_imm=3888 } -> [spill 233] + v513 Imm(3904) -> [spill 234] + v514 BinopI { op=add, lhs=v25, rhs_imm=3904 } -> [spill 234] + v515 Imm(3920) -> [spill 235] + v516 BinopI { op=add, lhs=v25, rhs_imm=3920 } -> [spill 235] + v517 Imm(3936) -> [spill 236] + v518 BinopI { op=add, lhs=v25, rhs_imm=3936 } -> [spill 236] + v519 Imm(3952) -> [spill 237] + v520 BinopI { op=add, lhs=v25, rhs_imm=3952 } -> [spill 237] + v521 Imm(3968) -> [spill 238] + v522 BinopI { op=add, lhs=v25, rhs_imm=3968 } -> [spill 238] + v523 Imm(3984) -> [spill 239] + v524 BinopI { op=add, lhs=v25, rhs_imm=3984 } -> [spill 239] + v525 Imm(4000) -> [spill 240] + v526 BinopI { op=add, lhs=v25, rhs_imm=4000 } -> [spill 240] + v527 Imm(4016) -> [spill 241] + v528 BinopI { op=add, lhs=v25, rhs_imm=4016 } -> [spill 241] + v529 Imm(4032) -> [spill 242] + v530 BinopI { op=add, lhs=v25, rhs_imm=4032 } -> [spill 242] + v531 Imm(4048) -> [spill 243] + v532 BinopI { op=add, lhs=v25, rhs_imm=4048 } -> [spill 243] + v533 Imm(4064) -> [spill 244] + v534 BinopI { op=add, lhs=v25, rhs_imm=4064 } -> [spill 244] + v535 Imm(4080) -> [spill 245] + v536 BinopI { op=add, lhs=v25, rhs_imm=4080 } -> [spill 245] + v537 Imm(4096) -> [spill 246] + v538 BinopI { op=add, lhs=v25, rhs_imm=4096 } -> [spill 246] + v539 Imm(4112) -> [spill 247] + v540 BinopI { op=add, lhs=v25, rhs_imm=4112 } -> [spill 247] + v541 Imm(4128) -> [spill 248] + v542 BinopI { op=add, lhs=v25, rhs_imm=4128 } -> [spill 248] + v543 Imm(4144) -> [spill 249] + v544 BinopI { op=add, lhs=v25, rhs_imm=4144 } -> [spill 249] + v545 Imm(4160) -> [spill 250] + v546 BinopI { op=add, lhs=v25, rhs_imm=4160 } -> [spill 250] + v547 Call { target_pc=0, args=[v25, v28, v30, v32, v34, v36, v38, v40, v42, v44, v46, v48, v50, v52, v54, v56, v58, v60, v62, v64, v66, v68, v70, v72, v74, v76, v78, v80, v82, v84, v86, v88, v90, v92, v94, v96, v98, v100, v102, v104, v106, v108, v110, v112, v114, v116, v118, v120, v122, v124, v126, v128, v130, v132, v134, v136, v138, v140, v142, v144, v146, v148, v150, v152, v154, v156, v158, v160, v162, v164, v166, v168, v170, v172, v174, v176, v178, v180, v182, v184, v186, v188, v190, v192, v194, v196, v198, v200, v202, v204, v206, v208, v210, v212, v214, v216, v218, v220, v222, v224, v226, v228, v230, v232, v234, v236, v238, v240, v242, v244, v246, v248, v250, v252, v254, v256, v258, v260, v262, v264, v266, v268, v270, v272, v274, v276, v278, v280, v282, v284, v286, v288, v290, v292, v294, v296, v298, v300, v302, v304, v306, v308, v310, v312, v314, v316, v318, v320, v322, v324, v326, v328, v330, v332, v334, v336, v338, v340, v342, v344, v346, v348, v350, v352, v354, v356, v358, v360, v362, v364, v366, v368, v370, v372, v374, v376, v378, v380, v382, v384, v386, v388, v390, v392, v394, v396, v398, v400, v402, v404, v406, v408, v410, v412, v414, v416, v418, v420, v422, v424, v426, v428, v430, v432, v434, v436, v438, v440, v442, v444, v446, v448, v450, v452, v454, v456, v458, v460, v462, v464, v466, v468, v470, v472, v474, v476, v478, v480, v482, v484, v486, v488, v490, v492, v494, v496, v498, v500, v502, v504, v506, v508, v510, v512, v514, v516, v518, v520, v522, v524, v526, v528, v530, v532, v534, v536, v538, v540, v542, v544, v546], fixed_args=261, fp_return=false, fp_arg_mask=0x0 } -> x0 + v548 BinopI { op=ne, lhs=v547, rhs_imm=101790 } -> x0 + terminator Bz { cond=v548, target=b6, fall=b5 } (exit_acc=v548) + block 5 start_pc=0 + v549 Imm(1) -> x0 + terminator Return(v549) (exit_acc=v549) + block 6 start_pc=0 + v550 Imm(1) -> x7 + v551 Imm(2) -> x6 + v552 Imm(3) -> x2 + v553 Imm(4) -> x1 + v554 Imm(5) -> x8 + v555 Imm(6) -> x9 + v556 Imm(7) -> x0 + v557 Imm(8) -> x13 + v558 Imm(9) -> x14 + v559 Imm(10) -> x15 + v560 Imm(11) -> [spill 0] + v561 Imm(12) -> [spill 1] + v562 Imm(13) -> [spill 2] + v563 Imm(14) -> [spill 3] + v564 Imm(15) -> [spill 4] + v565 Imm(16) -> [spill 5] + v566 Imm(17) -> [spill 6] + v567 Imm(18) -> [spill 7] + v568 Imm(19) -> [spill 8] + v569 Imm(20) -> [spill 9] + v570 Imm(21) -> [spill 10] + v571 Imm(22) -> [spill 11] + v572 Imm(23) -> [spill 12] + v573 Imm(24) -> [spill 13] + v574 Imm(25) -> [spill 14] + v575 Imm(26) -> [spill 15] + v576 Imm(27) -> [spill 16] + v577 Imm(28) -> [spill 17] + v578 Imm(29) -> [spill 18] + v579 Imm(30) -> [spill 19] + v580 Imm(31) -> [spill 20] + v581 Imm(32) -> [spill 21] + v582 Imm(33) -> [spill 22] + v583 Imm(34) -> [spill 23] + v584 Imm(35) -> [spill 24] + v585 Imm(36) -> [spill 25] + v586 Imm(37) -> [spill 26] + v587 Imm(38) -> [spill 27] + v588 Imm(39) -> [spill 28] + v589 Imm(40) -> [spill 29] + v590 Imm(41) -> [spill 30] + v591 Imm(42) -> [spill 31] + v592 Imm(43) -> [spill 32] + v593 Imm(44) -> [spill 33] + v594 Imm(45) -> [spill 34] + v595 Imm(46) -> [spill 35] + v596 Imm(47) -> [spill 36] + v597 Imm(48) -> [spill 37] + v598 Imm(49) -> [spill 38] + v599 Imm(50) -> [spill 39] + v600 Imm(51) -> [spill 40] + v601 Imm(52) -> [spill 41] + v602 Imm(53) -> [spill 42] + v603 Imm(54) -> [spill 43] + v604 Imm(55) -> [spill 44] + v605 Imm(56) -> [spill 45] + v606 Imm(57) -> [spill 46] + v607 Imm(58) -> [spill 47] + v608 Imm(59) -> [spill 48] + v609 Imm(60) -> [spill 49] + v610 Imm(61) -> [spill 50] + v611 Imm(62) -> [spill 51] + v612 Imm(63) -> [spill 52] + v613 Imm(64) -> [spill 53] + v614 Imm(65) -> [spill 54] + v615 Imm(66) -> [spill 55] + v616 Imm(67) -> [spill 56] + v617 Imm(68) -> [spill 57] + v618 Imm(69) -> [spill 58] + v619 Imm(70) -> [spill 59] + v620 Imm(71) -> [spill 60] + v621 Imm(72) -> [spill 61] + v622 Imm(73) -> [spill 62] + v623 Imm(74) -> [spill 63] + v624 Imm(75) -> [spill 64] + v625 Imm(76) -> [spill 65] + v626 Imm(77) -> [spill 66] + v627 Imm(78) -> [spill 67] + v628 Imm(79) -> [spill 68] + v629 Imm(80) -> [spill 69] + v630 Imm(81) -> [spill 70] + v631 Imm(82) -> [spill 71] + v632 Imm(83) -> [spill 72] + v633 Imm(84) -> [spill 73] + v634 Imm(85) -> [spill 74] + v635 Imm(86) -> [spill 75] + v636 Imm(87) -> [spill 76] + v637 Imm(88) -> [spill 77] + v638 Imm(89) -> [spill 78] + v639 Imm(90) -> [spill 79] + v640 Imm(91) -> [spill 80] + v641 Imm(92) -> [spill 81] + v642 Imm(93) -> [spill 82] + v643 Imm(94) -> [spill 83] + v644 Imm(95) -> [spill 84] + v645 Imm(96) -> [spill 85] + v646 Imm(97) -> [spill 86] + v647 Imm(98) -> [spill 87] + v648 Imm(99) -> [spill 88] + v649 Imm(100) -> [spill 89] + v650 Imm(101) -> [spill 90] + v651 Imm(102) -> [spill 91] + v652 Imm(103) -> [spill 92] + v653 Imm(104) -> [spill 93] + v654 Imm(105) -> [spill 94] + v655 Imm(106) -> [spill 95] + v656 Imm(107) -> [spill 96] + v657 Imm(108) -> [spill 97] + v658 Imm(109) -> [spill 98] + v659 Imm(110) -> [spill 99] + v660 Imm(111) -> [spill 100] + v661 Imm(112) -> [spill 101] + v662 Imm(113) -> [spill 102] + v663 Imm(114) -> [spill 103] + v664 Imm(115) -> [spill 104] + v665 Imm(116) -> [spill 105] + v666 Imm(117) -> [spill 106] + v667 Imm(118) -> [spill 107] + v668 Imm(119) -> [spill 108] + v669 Imm(120) -> [spill 109] + v670 Imm(121) -> [spill 110] + v671 Imm(122) -> [spill 111] + v672 Imm(123) -> [spill 112] + v673 Imm(124) -> [spill 113] + v674 Imm(125) -> [spill 114] + v675 Imm(126) -> [spill 115] + v676 Imm(127) -> [spill 116] + v677 Imm(128) -> [spill 117] + v678 Imm(129) -> [spill 118] + v679 Imm(130) -> [spill 119] + v680 Imm(131) -> [spill 120] + v681 Imm(132) -> [spill 121] + v682 Imm(133) -> [spill 122] + v683 Imm(134) -> [spill 123] + v684 Imm(135) -> [spill 124] + v685 Imm(136) -> [spill 125] + v686 Imm(137) -> [spill 126] + v687 Imm(138) -> [spill 127] + v688 Imm(139) -> [spill 128] + v689 Imm(140) -> [spill 129] + v690 Imm(141) -> [spill 130] + v691 Imm(142) -> [spill 131] + v692 Imm(143) -> [spill 132] + v693 Imm(144) -> [spill 133] + v694 Imm(145) -> [spill 134] + v695 Imm(146) -> [spill 135] + v696 Imm(147) -> [spill 136] + v697 Imm(148) -> [spill 137] + v698 Imm(149) -> [spill 138] + v699 Imm(150) -> [spill 139] + v700 Imm(151) -> [spill 140] + v701 Imm(152) -> [spill 141] + v702 Imm(153) -> [spill 142] + v703 Imm(154) -> [spill 143] + v704 Imm(155) -> [spill 144] + v705 Imm(156) -> [spill 145] + v706 Imm(157) -> [spill 146] + v707 Imm(158) -> [spill 147] + v708 Imm(159) -> [spill 148] + v709 Imm(160) -> [spill 149] + v710 Imm(161) -> [spill 150] + v711 Imm(162) -> [spill 151] + v712 Imm(163) -> [spill 152] + v713 Imm(164) -> [spill 153] + v714 Imm(165) -> [spill 154] + v715 Imm(166) -> [spill 155] + v716 Imm(167) -> [spill 156] + v717 Imm(168) -> [spill 157] + v718 Imm(169) -> [spill 158] + v719 Imm(170) -> [spill 159] + v720 Imm(171) -> [spill 160] + v721 Imm(172) -> [spill 161] + v722 Imm(173) -> [spill 162] + v723 Imm(174) -> [spill 163] + v724 Imm(175) -> [spill 164] + v725 Imm(176) -> [spill 165] + v726 Imm(177) -> [spill 166] + v727 Imm(178) -> [spill 167] + v728 Imm(179) -> [spill 168] + v729 Imm(180) -> [spill 169] + v730 Imm(181) -> [spill 170] + v731 Imm(182) -> [spill 171] + v732 Imm(183) -> [spill 172] + v733 Imm(184) -> [spill 173] + v734 Imm(185) -> [spill 174] + v735 Imm(186) -> [spill 175] + v736 Imm(187) -> [spill 176] + v737 Imm(188) -> [spill 177] + v738 Imm(189) -> [spill 178] + v739 Imm(190) -> [spill 179] + v740 Imm(191) -> [spill 180] + v741 Imm(192) -> [spill 181] + v742 Imm(193) -> [spill 182] + v743 Imm(194) -> [spill 183] + v744 Imm(195) -> [spill 184] + v745 Imm(196) -> [spill 185] + v746 Imm(197) -> [spill 186] + v747 Imm(198) -> [spill 187] + v748 Imm(199) -> [spill 188] + v749 Imm(200) -> [spill 189] + v750 Imm(201) -> [spill 190] + v751 Imm(202) -> [spill 191] + v752 Imm(203) -> [spill 192] + v753 Imm(204) -> [spill 193] + v754 Imm(205) -> [spill 194] + v755 Imm(206) -> [spill 195] + v756 Imm(207) -> [spill 196] + v757 Imm(208) -> [spill 197] + v758 Imm(209) -> [spill 198] + v759 Imm(210) -> [spill 199] + v760 Imm(211) -> [spill 200] + v761 Imm(212) -> [spill 201] + v762 Imm(213) -> [spill 202] + v763 Imm(214) -> [spill 203] + v764 Imm(215) -> [spill 204] + v765 Imm(216) -> [spill 205] + v766 Imm(217) -> [spill 206] + v767 Imm(218) -> [spill 207] + v768 Imm(219) -> [spill 208] + v769 Imm(220) -> [spill 209] + v770 Imm(221) -> [spill 210] + v771 Imm(222) -> [spill 211] + v772 Imm(223) -> [spill 212] + v773 Imm(224) -> [spill 213] + v774 Imm(225) -> [spill 214] + v775 Imm(226) -> [spill 215] + v776 Imm(227) -> [spill 216] + v777 Imm(228) -> [spill 217] + v778 Imm(229) -> [spill 218] + v779 Imm(230) -> [spill 219] + v780 Imm(231) -> [spill 220] + v781 Imm(232) -> [spill 221] + v782 Imm(233) -> [spill 222] + v783 Imm(234) -> [spill 223] + v784 Imm(235) -> [spill 224] + v785 Imm(236) -> [spill 225] + v786 Imm(237) -> [spill 226] + v787 Imm(238) -> [spill 227] + v788 Imm(239) -> [spill 228] + v789 Imm(240) -> [spill 229] + v790 Imm(241) -> [spill 230] + v791 Imm(242) -> [spill 231] + v792 Imm(243) -> [spill 232] + v793 Imm(244) -> [spill 233] + v794 Imm(245) -> [spill 234] + v795 Imm(246) -> [spill 235] + v796 Imm(247) -> [spill 236] + v797 Imm(248) -> [spill 237] + v798 Imm(249) -> [spill 238] + v799 Imm(250) -> [spill 239] + v800 Imm(251) -> [spill 240] + v801 Imm(252) -> [spill 241] + v802 Imm(253) -> [spill 242] + v803 Imm(254) -> [spill 243] + v804 Imm(255) -> [spill 244] + v805 Imm(256) -> [spill 245] + v806 Imm(257) -> [spill 246] + v807 Imm(258) -> [spill 247] + v808 Imm(259) -> [spill 248] + v809 Imm(260) -> [spill 249] + v810 LoadLocal { off=-1, kind=I64 } -> [spill 250] + v811 CallIndirect { target=v1, args=[v550, v551, v552, v553, v554, v555, v556, v557, v558, v559, v560, v561, v562, v563, v564, v565, v566, v567, v568, v569, v570, v571, v572, v573, v574, v575, v576, v577, v578, v579, v580, v581, v582, v583, v584, v585, v586, v587, v588, v589, v590, v591, v592, v593, v594, v595, v596, v597, v598, v599, v600, v601, v602, v603, v604, v605, v606, v607, v608, v609, v610, v611, v612, v613, v614, v615, v616, v617, v618, v619, v620, v621, v622, v623, v624, v625, v626, v627, v628, v629, v630, v631, v632, v633, v634, v635, v636, v637, v638, v639, v640, v641, v642, v643, v644, v645, v646, v647, v648, v649, v650, v651, v652, v653, v654, v655, v656, v657, v658, v659, v660, v661, v662, v663, v664, v665, v666, v667, v668, v669, v670, v671, v672, v673, v674, v675, v676, v677, v678, v679, v680, v681, v682, v683, v684, v685, v686, v687, v688, v689, v690, v691, v692, v693, v694, v695, v696, v697, v698, v699, v700, v701, v702, v703, v704, v705, v706, v707, v708, v709, v710, v711, v712, v713, v714, v715, v716, v717, v718, v719, v720, v721, v722, v723, v724, v725, v726, v727, v728, v729, v730, v731, v732, v733, v734, v735, v736, v737, v738, v739, v740, v741, v742, v743, v744, v745, v746, v747, v748, v749, v750, v751, v752, v753, v754, v755, v756, v757, v758, v759, v760, v761, v762, v763, v764, v765, v766, v767, v768, v769, v770, v771, v772, v773, v774, v775, v776, v777, v778, v779, v780, v781, v782, v783, v784, v785, v786, v787, v788, v789, v790, v791, v792, v793, v794, v795, v796, v797, v798, v799, v800, v801, v802, v803, v804, v805, v806, v807, v808, v809], callee_variadic=false, fixed_args=260, fp_return=false, fp_arg_mask=0x0 } -> x0 + v812 BinopI { op=ne, lhs=v811, rhs_imm=33930 } -> x0 + terminator Bz { cond=v812, target=b8, fall=b7 } (exit_acc=v812) + block 7 start_pc=0 + v813 Imm(2) -> x0 + terminator Return(v813) (exit_acc=v813) + block 8 start_pc=0 + v814 ImmData(24) -> x7 + v815 Imm(0) -> x0 + v816 Imm(16) -> x0 + v817 BinopI { op=add, lhs=v814, rhs_imm=16 } -> x6 + v818 Imm(32) -> x0 + v819 BinopI { op=add, lhs=v814, rhs_imm=32 } -> x2 + v820 Imm(48) -> x0 + v821 BinopI { op=add, lhs=v814, rhs_imm=48 } -> x1 + v822 Imm(64) -> x0 + v823 BinopI { op=add, lhs=v814, rhs_imm=64 } -> x8 + v824 Imm(80) -> x0 + v825 BinopI { op=add, lhs=v814, rhs_imm=80 } -> x9 + v826 Imm(96) -> x0 + v827 BinopI { op=add, lhs=v814, rhs_imm=96 } -> x0 + v828 Imm(112) -> x3 + v829 BinopI { op=add, lhs=v814, rhs_imm=112 } -> x3 + v830 Imm(128) -> x13 + v831 BinopI { op=add, lhs=v814, rhs_imm=128 } -> x13 + v832 Imm(144) -> x14 + v833 BinopI { op=add, lhs=v814, rhs_imm=144 } -> x14 + v834 Imm(160) -> x15 + v835 BinopI { op=add, lhs=v814, rhs_imm=160 } -> x15 + v836 Imm(176) -> [spill 0] + v837 BinopI { op=add, lhs=v814, rhs_imm=176 } -> [spill 0] + v838 Imm(192) -> [spill 1] + v839 BinopI { op=add, lhs=v814, rhs_imm=192 } -> [spill 1] + v840 Imm(208) -> [spill 2] + v841 BinopI { op=add, lhs=v814, rhs_imm=208 } -> [spill 2] + v842 Imm(224) -> [spill 3] + v843 BinopI { op=add, lhs=v814, rhs_imm=224 } -> [spill 3] + v844 Imm(240) -> [spill 4] + v845 BinopI { op=add, lhs=v814, rhs_imm=240 } -> [spill 4] + v846 Imm(256) -> [spill 5] + v847 BinopI { op=add, lhs=v814, rhs_imm=256 } -> [spill 5] + v848 Imm(272) -> [spill 6] + v849 BinopI { op=add, lhs=v814, rhs_imm=272 } -> [spill 6] + v850 Imm(288) -> [spill 7] + v851 BinopI { op=add, lhs=v814, rhs_imm=288 } -> [spill 7] + v852 Imm(304) -> [spill 8] + v853 BinopI { op=add, lhs=v814, rhs_imm=304 } -> [spill 8] + v854 Imm(320) -> [spill 9] + v855 BinopI { op=add, lhs=v814, rhs_imm=320 } -> [spill 9] + v856 Imm(336) -> [spill 10] + v857 BinopI { op=add, lhs=v814, rhs_imm=336 } -> [spill 10] + v858 Imm(352) -> [spill 11] + v859 BinopI { op=add, lhs=v814, rhs_imm=352 } -> [spill 11] + v860 Imm(368) -> [spill 12] + v861 BinopI { op=add, lhs=v814, rhs_imm=368 } -> [spill 12] + v862 Imm(384) -> [spill 13] + v863 BinopI { op=add, lhs=v814, rhs_imm=384 } -> [spill 13] + v864 Imm(400) -> [spill 14] + v865 BinopI { op=add, lhs=v814, rhs_imm=400 } -> [spill 14] + v866 Imm(416) -> [spill 15] + v867 BinopI { op=add, lhs=v814, rhs_imm=416 } -> [spill 15] + v868 Imm(432) -> [spill 16] + v869 BinopI { op=add, lhs=v814, rhs_imm=432 } -> [spill 16] + v870 Imm(448) -> [spill 17] + v871 BinopI { op=add, lhs=v814, rhs_imm=448 } -> [spill 17] + v872 Imm(464) -> [spill 18] + v873 BinopI { op=add, lhs=v814, rhs_imm=464 } -> [spill 18] + v874 Imm(480) -> [spill 19] + v875 BinopI { op=add, lhs=v814, rhs_imm=480 } -> [spill 19] + v876 Imm(496) -> [spill 20] + v877 BinopI { op=add, lhs=v814, rhs_imm=496 } -> [spill 20] + v878 Imm(512) -> [spill 21] + v879 BinopI { op=add, lhs=v814, rhs_imm=512 } -> [spill 21] + v880 Imm(528) -> [spill 22] + v881 BinopI { op=add, lhs=v814, rhs_imm=528 } -> [spill 22] + v882 Imm(544) -> [spill 23] + v883 BinopI { op=add, lhs=v814, rhs_imm=544 } -> [spill 23] + v884 Imm(560) -> [spill 24] + v885 BinopI { op=add, lhs=v814, rhs_imm=560 } -> [spill 24] + v886 Imm(576) -> [spill 25] + v887 BinopI { op=add, lhs=v814, rhs_imm=576 } -> [spill 25] + v888 Imm(592) -> [spill 26] + v889 BinopI { op=add, lhs=v814, rhs_imm=592 } -> [spill 26] + v890 Imm(608) -> [spill 27] + v891 BinopI { op=add, lhs=v814, rhs_imm=608 } -> [spill 27] + v892 Imm(624) -> [spill 28] + v893 BinopI { op=add, lhs=v814, rhs_imm=624 } -> [spill 28] + v894 Imm(640) -> [spill 29] + v895 BinopI { op=add, lhs=v814, rhs_imm=640 } -> [spill 29] + v896 Imm(656) -> [spill 30] + v897 BinopI { op=add, lhs=v814, rhs_imm=656 } -> [spill 30] + v898 Imm(672) -> [spill 31] + v899 BinopI { op=add, lhs=v814, rhs_imm=672 } -> [spill 31] + v900 Imm(688) -> [spill 32] + v901 BinopI { op=add, lhs=v814, rhs_imm=688 } -> [spill 32] + v902 Imm(704) -> [spill 33] + v903 BinopI { op=add, lhs=v814, rhs_imm=704 } -> [spill 33] + v904 Imm(720) -> [spill 34] + v905 BinopI { op=add, lhs=v814, rhs_imm=720 } -> [spill 34] + v906 Imm(736) -> [spill 35] + v907 BinopI { op=add, lhs=v814, rhs_imm=736 } -> [spill 35] + v908 Imm(752) -> [spill 36] + v909 BinopI { op=add, lhs=v814, rhs_imm=752 } -> [spill 36] + v910 Imm(768) -> [spill 37] + v911 BinopI { op=add, lhs=v814, rhs_imm=768 } -> [spill 37] + v912 Imm(784) -> [spill 38] + v913 BinopI { op=add, lhs=v814, rhs_imm=784 } -> [spill 38] + v914 Imm(800) -> [spill 39] + v915 BinopI { op=add, lhs=v814, rhs_imm=800 } -> [spill 39] + v916 Imm(816) -> [spill 40] + v917 BinopI { op=add, lhs=v814, rhs_imm=816 } -> [spill 40] + v918 Imm(832) -> [spill 41] + v919 BinopI { op=add, lhs=v814, rhs_imm=832 } -> [spill 41] + v920 Imm(848) -> [spill 42] + v921 BinopI { op=add, lhs=v814, rhs_imm=848 } -> [spill 42] + v922 Imm(864) -> [spill 43] + v923 BinopI { op=add, lhs=v814, rhs_imm=864 } -> [spill 43] + v924 Imm(880) -> [spill 44] + v925 BinopI { op=add, lhs=v814, rhs_imm=880 } -> [spill 44] + v926 Imm(896) -> [spill 45] + v927 BinopI { op=add, lhs=v814, rhs_imm=896 } -> [spill 45] + v928 Imm(912) -> [spill 46] + v929 BinopI { op=add, lhs=v814, rhs_imm=912 } -> [spill 46] + v930 Imm(928) -> [spill 47] + v931 BinopI { op=add, lhs=v814, rhs_imm=928 } -> [spill 47] + v932 Imm(944) -> [spill 48] + v933 BinopI { op=add, lhs=v814, rhs_imm=944 } -> [spill 48] + v934 Imm(960) -> [spill 49] + v935 BinopI { op=add, lhs=v814, rhs_imm=960 } -> [spill 49] + v936 Imm(976) -> [spill 50] + v937 BinopI { op=add, lhs=v814, rhs_imm=976 } -> [spill 50] + v938 Imm(992) -> [spill 51] + v939 BinopI { op=add, lhs=v814, rhs_imm=992 } -> [spill 51] + v940 Imm(1008) -> [spill 52] + v941 BinopI { op=add, lhs=v814, rhs_imm=1008 } -> [spill 52] + v942 Imm(1024) -> [spill 53] + v943 BinopI { op=add, lhs=v814, rhs_imm=1024 } -> [spill 53] + v944 Imm(1040) -> [spill 54] + v945 BinopI { op=add, lhs=v814, rhs_imm=1040 } -> [spill 54] + v946 Imm(1056) -> [spill 55] + v947 BinopI { op=add, lhs=v814, rhs_imm=1056 } -> [spill 55] + v948 Imm(1072) -> [spill 56] + v949 BinopI { op=add, lhs=v814, rhs_imm=1072 } -> [spill 56] + v950 Imm(1088) -> [spill 57] + v951 BinopI { op=add, lhs=v814, rhs_imm=1088 } -> [spill 57] + v952 Imm(1104) -> [spill 58] + v953 BinopI { op=add, lhs=v814, rhs_imm=1104 } -> [spill 58] + v954 Imm(1120) -> [spill 59] + v955 BinopI { op=add, lhs=v814, rhs_imm=1120 } -> [spill 59] + v956 Imm(1136) -> [spill 60] + v957 BinopI { op=add, lhs=v814, rhs_imm=1136 } -> [spill 60] + v958 Imm(1152) -> [spill 61] + v959 BinopI { op=add, lhs=v814, rhs_imm=1152 } -> [spill 61] + v960 Imm(1168) -> [spill 62] + v961 BinopI { op=add, lhs=v814, rhs_imm=1168 } -> [spill 62] + v962 Imm(1184) -> [spill 63] + v963 BinopI { op=add, lhs=v814, rhs_imm=1184 } -> [spill 63] + v964 Imm(1200) -> [spill 64] + v965 BinopI { op=add, lhs=v814, rhs_imm=1200 } -> [spill 64] + v966 Imm(1216) -> [spill 65] + v967 BinopI { op=add, lhs=v814, rhs_imm=1216 } -> [spill 65] + v968 Imm(1232) -> [spill 66] + v969 BinopI { op=add, lhs=v814, rhs_imm=1232 } -> [spill 66] + v970 Imm(1248) -> [spill 67] + v971 BinopI { op=add, lhs=v814, rhs_imm=1248 } -> [spill 67] + v972 Imm(1264) -> [spill 68] + v973 BinopI { op=add, lhs=v814, rhs_imm=1264 } -> [spill 68] + v974 Imm(1280) -> [spill 69] + v975 BinopI { op=add, lhs=v814, rhs_imm=1280 } -> [spill 69] + v976 Imm(1296) -> [spill 70] + v977 BinopI { op=add, lhs=v814, rhs_imm=1296 } -> [spill 70] + v978 Imm(1312) -> [spill 71] + v979 BinopI { op=add, lhs=v814, rhs_imm=1312 } -> [spill 71] + v980 Imm(1328) -> [spill 72] + v981 BinopI { op=add, lhs=v814, rhs_imm=1328 } -> [spill 72] + v982 Imm(1344) -> [spill 73] + v983 BinopI { op=add, lhs=v814, rhs_imm=1344 } -> [spill 73] + v984 Imm(1360) -> [spill 74] + v985 BinopI { op=add, lhs=v814, rhs_imm=1360 } -> [spill 74] + v986 Imm(1376) -> [spill 75] + v987 BinopI { op=add, lhs=v814, rhs_imm=1376 } -> [spill 75] + v988 Imm(1392) -> [spill 76] + v989 BinopI { op=add, lhs=v814, rhs_imm=1392 } -> [spill 76] + v990 Imm(1408) -> [spill 77] + v991 BinopI { op=add, lhs=v814, rhs_imm=1408 } -> [spill 77] + v992 Imm(1424) -> [spill 78] + v993 BinopI { op=add, lhs=v814, rhs_imm=1424 } -> [spill 78] + v994 Imm(1440) -> [spill 79] + v995 BinopI { op=add, lhs=v814, rhs_imm=1440 } -> [spill 79] + v996 Imm(1456) -> [spill 80] + v997 BinopI { op=add, lhs=v814, rhs_imm=1456 } -> [spill 80] + v998 Imm(1472) -> [spill 81] + v999 BinopI { op=add, lhs=v814, rhs_imm=1472 } -> [spill 81] + v1000 Imm(1488) -> [spill 82] + v1001 BinopI { op=add, lhs=v814, rhs_imm=1488 } -> [spill 82] + v1002 Imm(1504) -> [spill 83] + v1003 BinopI { op=add, lhs=v814, rhs_imm=1504 } -> [spill 83] + v1004 Imm(1520) -> [spill 84] + v1005 BinopI { op=add, lhs=v814, rhs_imm=1520 } -> [spill 84] + v1006 Imm(1536) -> [spill 85] + v1007 BinopI { op=add, lhs=v814, rhs_imm=1536 } -> [spill 85] + v1008 Imm(1552) -> [spill 86] + v1009 BinopI { op=add, lhs=v814, rhs_imm=1552 } -> [spill 86] + v1010 Imm(1568) -> [spill 87] + v1011 BinopI { op=add, lhs=v814, rhs_imm=1568 } -> [spill 87] + v1012 Imm(1584) -> [spill 88] + v1013 BinopI { op=add, lhs=v814, rhs_imm=1584 } -> [spill 88] + v1014 Imm(1600) -> [spill 89] + v1015 BinopI { op=add, lhs=v814, rhs_imm=1600 } -> [spill 89] + v1016 Imm(1616) -> [spill 90] + v1017 BinopI { op=add, lhs=v814, rhs_imm=1616 } -> [spill 90] + v1018 Imm(1632) -> [spill 91] + v1019 BinopI { op=add, lhs=v814, rhs_imm=1632 } -> [spill 91] + v1020 Imm(1648) -> [spill 92] + v1021 BinopI { op=add, lhs=v814, rhs_imm=1648 } -> [spill 92] + v1022 Imm(1664) -> [spill 93] + v1023 BinopI { op=add, lhs=v814, rhs_imm=1664 } -> [spill 93] + v1024 Imm(1680) -> [spill 94] + v1025 BinopI { op=add, lhs=v814, rhs_imm=1680 } -> [spill 94] + v1026 Imm(1696) -> [spill 95] + v1027 BinopI { op=add, lhs=v814, rhs_imm=1696 } -> [spill 95] + v1028 Imm(1712) -> [spill 96] + v1029 BinopI { op=add, lhs=v814, rhs_imm=1712 } -> [spill 96] + v1030 Imm(1728) -> [spill 97] + v1031 BinopI { op=add, lhs=v814, rhs_imm=1728 } -> [spill 97] + v1032 Imm(1744) -> [spill 98] + v1033 BinopI { op=add, lhs=v814, rhs_imm=1744 } -> [spill 98] + v1034 Imm(1760) -> [spill 99] + v1035 BinopI { op=add, lhs=v814, rhs_imm=1760 } -> [spill 99] + v1036 Imm(1776) -> [spill 100] + v1037 BinopI { op=add, lhs=v814, rhs_imm=1776 } -> [spill 100] + v1038 Imm(1792) -> [spill 101] + v1039 BinopI { op=add, lhs=v814, rhs_imm=1792 } -> [spill 101] + v1040 Imm(1808) -> [spill 102] + v1041 BinopI { op=add, lhs=v814, rhs_imm=1808 } -> [spill 102] + v1042 Imm(1824) -> [spill 103] + v1043 BinopI { op=add, lhs=v814, rhs_imm=1824 } -> [spill 103] + v1044 Imm(1840) -> [spill 104] + v1045 BinopI { op=add, lhs=v814, rhs_imm=1840 } -> [spill 104] + v1046 Imm(1856) -> [spill 105] + v1047 BinopI { op=add, lhs=v814, rhs_imm=1856 } -> [spill 105] + v1048 Imm(1872) -> [spill 106] + v1049 BinopI { op=add, lhs=v814, rhs_imm=1872 } -> [spill 106] + v1050 Imm(1888) -> [spill 107] + v1051 BinopI { op=add, lhs=v814, rhs_imm=1888 } -> [spill 107] + v1052 Imm(1904) -> [spill 108] + v1053 BinopI { op=add, lhs=v814, rhs_imm=1904 } -> [spill 108] + v1054 Imm(1920) -> [spill 109] + v1055 BinopI { op=add, lhs=v814, rhs_imm=1920 } -> [spill 109] + v1056 Imm(1936) -> [spill 110] + v1057 BinopI { op=add, lhs=v814, rhs_imm=1936 } -> [spill 110] + v1058 Imm(1952) -> [spill 111] + v1059 BinopI { op=add, lhs=v814, rhs_imm=1952 } -> [spill 111] + v1060 Imm(1968) -> [spill 112] + v1061 BinopI { op=add, lhs=v814, rhs_imm=1968 } -> [spill 112] + v1062 Imm(1984) -> [spill 113] + v1063 BinopI { op=add, lhs=v814, rhs_imm=1984 } -> [spill 113] + v1064 Imm(2000) -> [spill 114] + v1065 BinopI { op=add, lhs=v814, rhs_imm=2000 } -> [spill 114] + v1066 Imm(2016) -> [spill 115] + v1067 BinopI { op=add, lhs=v814, rhs_imm=2016 } -> [spill 115] + v1068 Imm(2032) -> [spill 116] + v1069 BinopI { op=add, lhs=v814, rhs_imm=2032 } -> [spill 116] + v1070 Imm(2048) -> [spill 117] + v1071 BinopI { op=add, lhs=v814, rhs_imm=2048 } -> [spill 117] + v1072 Imm(2064) -> [spill 118] + v1073 BinopI { op=add, lhs=v814, rhs_imm=2064 } -> [spill 118] + v1074 Imm(2080) -> [spill 119] + v1075 BinopI { op=add, lhs=v814, rhs_imm=2080 } -> [spill 119] + v1076 Imm(2096) -> [spill 120] + v1077 BinopI { op=add, lhs=v814, rhs_imm=2096 } -> [spill 120] + v1078 Imm(2112) -> [spill 121] + v1079 BinopI { op=add, lhs=v814, rhs_imm=2112 } -> [spill 121] + v1080 Imm(2128) -> [spill 122] + v1081 BinopI { op=add, lhs=v814, rhs_imm=2128 } -> [spill 122] + v1082 Imm(2144) -> [spill 123] + v1083 BinopI { op=add, lhs=v814, rhs_imm=2144 } -> [spill 123] + v1084 Imm(2160) -> [spill 124] + v1085 BinopI { op=add, lhs=v814, rhs_imm=2160 } -> [spill 124] + v1086 Imm(2176) -> [spill 125] + v1087 BinopI { op=add, lhs=v814, rhs_imm=2176 } -> [spill 125] + v1088 Imm(2192) -> [spill 126] + v1089 BinopI { op=add, lhs=v814, rhs_imm=2192 } -> [spill 126] + v1090 Imm(2208) -> [spill 127] + v1091 BinopI { op=add, lhs=v814, rhs_imm=2208 } -> [spill 127] + v1092 Imm(2224) -> [spill 128] + v1093 BinopI { op=add, lhs=v814, rhs_imm=2224 } -> [spill 128] + v1094 Imm(2240) -> [spill 129] + v1095 BinopI { op=add, lhs=v814, rhs_imm=2240 } -> [spill 129] + v1096 Imm(2256) -> [spill 130] + v1097 BinopI { op=add, lhs=v814, rhs_imm=2256 } -> [spill 130] + v1098 Imm(2272) -> [spill 131] + v1099 BinopI { op=add, lhs=v814, rhs_imm=2272 } -> [spill 131] + v1100 Imm(2288) -> [spill 132] + v1101 BinopI { op=add, lhs=v814, rhs_imm=2288 } -> [spill 132] + v1102 Imm(2304) -> [spill 133] + v1103 BinopI { op=add, lhs=v814, rhs_imm=2304 } -> [spill 133] + v1104 Imm(2320) -> [spill 134] + v1105 BinopI { op=add, lhs=v814, rhs_imm=2320 } -> [spill 134] + v1106 Imm(2336) -> [spill 135] + v1107 BinopI { op=add, lhs=v814, rhs_imm=2336 } -> [spill 135] + v1108 Imm(2352) -> [spill 136] + v1109 BinopI { op=add, lhs=v814, rhs_imm=2352 } -> [spill 136] + v1110 Imm(2368) -> [spill 137] + v1111 BinopI { op=add, lhs=v814, rhs_imm=2368 } -> [spill 137] + v1112 Imm(2384) -> [spill 138] + v1113 BinopI { op=add, lhs=v814, rhs_imm=2384 } -> [spill 138] + v1114 Imm(2400) -> [spill 139] + v1115 BinopI { op=add, lhs=v814, rhs_imm=2400 } -> [spill 139] + v1116 Imm(2416) -> [spill 140] + v1117 BinopI { op=add, lhs=v814, rhs_imm=2416 } -> [spill 140] + v1118 Imm(2432) -> [spill 141] + v1119 BinopI { op=add, lhs=v814, rhs_imm=2432 } -> [spill 141] + v1120 Imm(2448) -> [spill 142] + v1121 BinopI { op=add, lhs=v814, rhs_imm=2448 } -> [spill 142] + v1122 Imm(2464) -> [spill 143] + v1123 BinopI { op=add, lhs=v814, rhs_imm=2464 } -> [spill 143] + v1124 Imm(2480) -> [spill 144] + v1125 BinopI { op=add, lhs=v814, rhs_imm=2480 } -> [spill 144] + v1126 Imm(2496) -> [spill 145] + v1127 BinopI { op=add, lhs=v814, rhs_imm=2496 } -> [spill 145] + v1128 Imm(2512) -> [spill 146] + v1129 BinopI { op=add, lhs=v814, rhs_imm=2512 } -> [spill 146] + v1130 Imm(2528) -> [spill 147] + v1131 BinopI { op=add, lhs=v814, rhs_imm=2528 } -> [spill 147] + v1132 Imm(2544) -> [spill 148] + v1133 BinopI { op=add, lhs=v814, rhs_imm=2544 } -> [spill 148] + v1134 Imm(2560) -> [spill 149] + v1135 BinopI { op=add, lhs=v814, rhs_imm=2560 } -> [spill 149] + v1136 Imm(2576) -> [spill 150] + v1137 BinopI { op=add, lhs=v814, rhs_imm=2576 } -> [spill 150] + v1138 Imm(2592) -> [spill 151] + v1139 BinopI { op=add, lhs=v814, rhs_imm=2592 } -> [spill 151] + v1140 Imm(2608) -> [spill 152] + v1141 BinopI { op=add, lhs=v814, rhs_imm=2608 } -> [spill 152] + v1142 Imm(2624) -> [spill 153] + v1143 BinopI { op=add, lhs=v814, rhs_imm=2624 } -> [spill 153] + v1144 Imm(2640) -> [spill 154] + v1145 BinopI { op=add, lhs=v814, rhs_imm=2640 } -> [spill 154] + v1146 Imm(2656) -> [spill 155] + v1147 BinopI { op=add, lhs=v814, rhs_imm=2656 } -> [spill 155] + v1148 Imm(2672) -> [spill 156] + v1149 BinopI { op=add, lhs=v814, rhs_imm=2672 } -> [spill 156] + v1150 Imm(2688) -> [spill 157] + v1151 BinopI { op=add, lhs=v814, rhs_imm=2688 } -> [spill 157] + v1152 Imm(2704) -> [spill 158] + v1153 BinopI { op=add, lhs=v814, rhs_imm=2704 } -> [spill 158] + v1154 Imm(2720) -> [spill 159] + v1155 BinopI { op=add, lhs=v814, rhs_imm=2720 } -> [spill 159] + v1156 Imm(2736) -> [spill 160] + v1157 BinopI { op=add, lhs=v814, rhs_imm=2736 } -> [spill 160] + v1158 Imm(2752) -> [spill 161] + v1159 BinopI { op=add, lhs=v814, rhs_imm=2752 } -> [spill 161] + v1160 Imm(2768) -> [spill 162] + v1161 BinopI { op=add, lhs=v814, rhs_imm=2768 } -> [spill 162] + v1162 Imm(2784) -> [spill 163] + v1163 BinopI { op=add, lhs=v814, rhs_imm=2784 } -> [spill 163] + v1164 Imm(2800) -> [spill 164] + v1165 BinopI { op=add, lhs=v814, rhs_imm=2800 } -> [spill 164] + v1166 Imm(2816) -> [spill 165] + v1167 BinopI { op=add, lhs=v814, rhs_imm=2816 } -> [spill 165] + v1168 Imm(2832) -> [spill 166] + v1169 BinopI { op=add, lhs=v814, rhs_imm=2832 } -> [spill 166] + v1170 Imm(2848) -> [spill 167] + v1171 BinopI { op=add, lhs=v814, rhs_imm=2848 } -> [spill 167] + v1172 Imm(2864) -> [spill 168] + v1173 BinopI { op=add, lhs=v814, rhs_imm=2864 } -> [spill 168] + v1174 Imm(2880) -> [spill 169] + v1175 BinopI { op=add, lhs=v814, rhs_imm=2880 } -> [spill 169] + v1176 Imm(2896) -> [spill 170] + v1177 BinopI { op=add, lhs=v814, rhs_imm=2896 } -> [spill 170] + v1178 Imm(2912) -> [spill 171] + v1179 BinopI { op=add, lhs=v814, rhs_imm=2912 } -> [spill 171] + v1180 Imm(2928) -> [spill 172] + v1181 BinopI { op=add, lhs=v814, rhs_imm=2928 } -> [spill 172] + v1182 Imm(2944) -> [spill 173] + v1183 BinopI { op=add, lhs=v814, rhs_imm=2944 } -> [spill 173] + v1184 Imm(2960) -> [spill 174] + v1185 BinopI { op=add, lhs=v814, rhs_imm=2960 } -> [spill 174] + v1186 Imm(2976) -> [spill 175] + v1187 BinopI { op=add, lhs=v814, rhs_imm=2976 } -> [spill 175] + v1188 Imm(2992) -> [spill 176] + v1189 BinopI { op=add, lhs=v814, rhs_imm=2992 } -> [spill 176] + v1190 Imm(3008) -> [spill 177] + v1191 BinopI { op=add, lhs=v814, rhs_imm=3008 } -> [spill 177] + v1192 Imm(3024) -> [spill 178] + v1193 BinopI { op=add, lhs=v814, rhs_imm=3024 } -> [spill 178] + v1194 Imm(3040) -> [spill 179] + v1195 BinopI { op=add, lhs=v814, rhs_imm=3040 } -> [spill 179] + v1196 Imm(3056) -> [spill 180] + v1197 BinopI { op=add, lhs=v814, rhs_imm=3056 } -> [spill 180] + v1198 Imm(3072) -> [spill 181] + v1199 BinopI { op=add, lhs=v814, rhs_imm=3072 } -> [spill 181] + v1200 Imm(3088) -> [spill 182] + v1201 BinopI { op=add, lhs=v814, rhs_imm=3088 } -> [spill 182] + v1202 Imm(3104) -> [spill 183] + v1203 BinopI { op=add, lhs=v814, rhs_imm=3104 } -> [spill 183] + v1204 Imm(3120) -> [spill 184] + v1205 BinopI { op=add, lhs=v814, rhs_imm=3120 } -> [spill 184] + v1206 Imm(3136) -> [spill 185] + v1207 BinopI { op=add, lhs=v814, rhs_imm=3136 } -> [spill 185] + v1208 Imm(3152) -> [spill 186] + v1209 BinopI { op=add, lhs=v814, rhs_imm=3152 } -> [spill 186] + v1210 Imm(3168) -> [spill 187] + v1211 BinopI { op=add, lhs=v814, rhs_imm=3168 } -> [spill 187] + v1212 Imm(3184) -> [spill 188] + v1213 BinopI { op=add, lhs=v814, rhs_imm=3184 } -> [spill 188] + v1214 Imm(3200) -> [spill 189] + v1215 BinopI { op=add, lhs=v814, rhs_imm=3200 } -> [spill 189] + v1216 Imm(3216) -> [spill 190] + v1217 BinopI { op=add, lhs=v814, rhs_imm=3216 } -> [spill 190] + v1218 Imm(3232) -> [spill 191] + v1219 BinopI { op=add, lhs=v814, rhs_imm=3232 } -> [spill 191] + v1220 Imm(3248) -> [spill 192] + v1221 BinopI { op=add, lhs=v814, rhs_imm=3248 } -> [spill 192] + v1222 Imm(3264) -> [spill 193] + v1223 BinopI { op=add, lhs=v814, rhs_imm=3264 } -> [spill 193] + v1224 Imm(3280) -> [spill 194] + v1225 BinopI { op=add, lhs=v814, rhs_imm=3280 } -> [spill 194] + v1226 Imm(3296) -> [spill 195] + v1227 BinopI { op=add, lhs=v814, rhs_imm=3296 } -> [spill 195] + v1228 Imm(3312) -> [spill 196] + v1229 BinopI { op=add, lhs=v814, rhs_imm=3312 } -> [spill 196] + v1230 Imm(3328) -> [spill 197] + v1231 BinopI { op=add, lhs=v814, rhs_imm=3328 } -> [spill 197] + v1232 Imm(3344) -> [spill 198] + v1233 BinopI { op=add, lhs=v814, rhs_imm=3344 } -> [spill 198] + v1234 Imm(3360) -> [spill 199] + v1235 BinopI { op=add, lhs=v814, rhs_imm=3360 } -> [spill 199] + v1236 Imm(3376) -> [spill 200] + v1237 BinopI { op=add, lhs=v814, rhs_imm=3376 } -> [spill 200] + v1238 Imm(3392) -> [spill 201] + v1239 BinopI { op=add, lhs=v814, rhs_imm=3392 } -> [spill 201] + v1240 Imm(3408) -> [spill 202] + v1241 BinopI { op=add, lhs=v814, rhs_imm=3408 } -> [spill 202] + v1242 Imm(3424) -> [spill 203] + v1243 BinopI { op=add, lhs=v814, rhs_imm=3424 } -> [spill 203] + v1244 Imm(3440) -> [spill 204] + v1245 BinopI { op=add, lhs=v814, rhs_imm=3440 } -> [spill 204] + v1246 Imm(3456) -> [spill 205] + v1247 BinopI { op=add, lhs=v814, rhs_imm=3456 } -> [spill 205] + v1248 Imm(3472) -> [spill 206] + v1249 BinopI { op=add, lhs=v814, rhs_imm=3472 } -> [spill 206] + v1250 Imm(3488) -> [spill 207] + v1251 BinopI { op=add, lhs=v814, rhs_imm=3488 } -> [spill 207] + v1252 Imm(3504) -> [spill 208] + v1253 BinopI { op=add, lhs=v814, rhs_imm=3504 } -> [spill 208] + v1254 Imm(3520) -> [spill 209] + v1255 BinopI { op=add, lhs=v814, rhs_imm=3520 } -> [spill 209] + v1256 Imm(3536) -> [spill 210] + v1257 BinopI { op=add, lhs=v814, rhs_imm=3536 } -> [spill 210] + v1258 Imm(3552) -> [spill 211] + v1259 BinopI { op=add, lhs=v814, rhs_imm=3552 } -> [spill 211] + v1260 Imm(3568) -> [spill 212] + v1261 BinopI { op=add, lhs=v814, rhs_imm=3568 } -> [spill 212] + v1262 Imm(3584) -> [spill 213] + v1263 BinopI { op=add, lhs=v814, rhs_imm=3584 } -> [spill 213] + v1264 Imm(3600) -> [spill 214] + v1265 BinopI { op=add, lhs=v814, rhs_imm=3600 } -> [spill 214] + v1266 Imm(3616) -> [spill 215] + v1267 BinopI { op=add, lhs=v814, rhs_imm=3616 } -> [spill 215] + v1268 Imm(3632) -> [spill 216] + v1269 BinopI { op=add, lhs=v814, rhs_imm=3632 } -> [spill 216] + v1270 Imm(3648) -> [spill 217] + v1271 BinopI { op=add, lhs=v814, rhs_imm=3648 } -> [spill 217] + v1272 Imm(3664) -> [spill 218] + v1273 BinopI { op=add, lhs=v814, rhs_imm=3664 } -> [spill 218] + v1274 Imm(3680) -> [spill 219] + v1275 BinopI { op=add, lhs=v814, rhs_imm=3680 } -> [spill 219] + v1276 Imm(3696) -> [spill 220] + v1277 BinopI { op=add, lhs=v814, rhs_imm=3696 } -> [spill 220] + v1278 Imm(3712) -> [spill 221] + v1279 BinopI { op=add, lhs=v814, rhs_imm=3712 } -> [spill 221] + v1280 Imm(3728) -> [spill 222] + v1281 BinopI { op=add, lhs=v814, rhs_imm=3728 } -> [spill 222] + v1282 Imm(3744) -> [spill 223] + v1283 BinopI { op=add, lhs=v814, rhs_imm=3744 } -> [spill 223] + v1284 Imm(3760) -> [spill 224] + v1285 BinopI { op=add, lhs=v814, rhs_imm=3760 } -> [spill 224] + v1286 Imm(3776) -> [spill 225] + v1287 BinopI { op=add, lhs=v814, rhs_imm=3776 } -> [spill 225] + v1288 Imm(3792) -> [spill 226] + v1289 BinopI { op=add, lhs=v814, rhs_imm=3792 } -> [spill 226] + v1290 Imm(3808) -> [spill 227] + v1291 BinopI { op=add, lhs=v814, rhs_imm=3808 } -> [spill 227] + v1292 Imm(3824) -> [spill 228] + v1293 BinopI { op=add, lhs=v814, rhs_imm=3824 } -> [spill 228] + v1294 Imm(3840) -> [spill 229] + v1295 BinopI { op=add, lhs=v814, rhs_imm=3840 } -> [spill 229] + v1296 Imm(3856) -> [spill 230] + v1297 BinopI { op=add, lhs=v814, rhs_imm=3856 } -> [spill 230] + v1298 Imm(3872) -> [spill 231] + v1299 BinopI { op=add, lhs=v814, rhs_imm=3872 } -> [spill 231] + v1300 Imm(3888) -> [spill 232] + v1301 BinopI { op=add, lhs=v814, rhs_imm=3888 } -> [spill 232] + v1302 Imm(3904) -> [spill 233] + v1303 BinopI { op=add, lhs=v814, rhs_imm=3904 } -> [spill 233] + v1304 Imm(3920) -> [spill 234] + v1305 BinopI { op=add, lhs=v814, rhs_imm=3920 } -> [spill 234] + v1306 Imm(3936) -> [spill 235] + v1307 BinopI { op=add, lhs=v814, rhs_imm=3936 } -> [spill 235] + v1308 Imm(3952) -> [spill 236] + v1309 BinopI { op=add, lhs=v814, rhs_imm=3952 } -> [spill 236] + v1310 Imm(3968) -> [spill 237] + v1311 BinopI { op=add, lhs=v814, rhs_imm=3968 } -> [spill 237] + v1312 Imm(3984) -> [spill 238] + v1313 BinopI { op=add, lhs=v814, rhs_imm=3984 } -> [spill 238] + v1314 Imm(4000) -> [spill 239] + v1315 BinopI { op=add, lhs=v814, rhs_imm=4000 } -> [spill 239] + v1316 Imm(4016) -> [spill 240] + v1317 BinopI { op=add, lhs=v814, rhs_imm=4016 } -> [spill 240] + v1318 Imm(4032) -> [spill 241] + v1319 BinopI { op=add, lhs=v814, rhs_imm=4032 } -> [spill 241] + v1320 Imm(4048) -> [spill 242] + v1321 BinopI { op=add, lhs=v814, rhs_imm=4048 } -> [spill 242] + v1322 Imm(4064) -> [spill 243] + v1323 BinopI { op=add, lhs=v814, rhs_imm=4064 } -> [spill 243] + v1324 Imm(4080) -> [spill 244] + v1325 BinopI { op=add, lhs=v814, rhs_imm=4080 } -> [spill 244] + v1326 Imm(4096) -> [spill 245] + v1327 BinopI { op=add, lhs=v814, rhs_imm=4096 } -> [spill 245] + v1328 Imm(4112) -> [spill 246] + v1329 BinopI { op=add, lhs=v814, rhs_imm=4112 } -> [spill 246] + v1330 Imm(4128) -> [spill 247] + v1331 BinopI { op=add, lhs=v814, rhs_imm=4128 } -> [spill 247] + v1332 Imm(4144) -> [spill 248] + v1333 BinopI { op=add, lhs=v814, rhs_imm=4144 } -> [spill 248] + v1334 Imm(4160) -> [spill 249] + v1335 BinopI { op=add, lhs=v814, rhs_imm=4160 } -> [spill 249] + v1336 LoadLocal { off=-2, kind=I64 } -> [spill 250] + v1337 CallIndirect { target=v3, args=[v814, v817, v819, v821, v823, v825, v827, v829, v831, v833, v835, v837, v839, v841, v843, v845, v847, v849, v851, v853, v855, v857, v859, v861, v863, v865, v867, v869, v871, v873, v875, v877, v879, v881, v883, v885, v887, v889, v891, v893, v895, v897, v899, v901, v903, v905, v907, v909, v911, v913, v915, v917, v919, v921, v923, v925, v927, v929, v931, v933, v935, v937, v939, v941, v943, v945, v947, v949, v951, v953, v955, v957, v959, v961, v963, v965, v967, v969, v971, v973, v975, v977, v979, v981, v983, v985, v987, v989, v991, v993, v995, v997, v999, v1001, v1003, v1005, v1007, v1009, v1011, v1013, v1015, v1017, v1019, v1021, v1023, v1025, v1027, v1029, v1031, v1033, v1035, v1037, v1039, v1041, v1043, v1045, v1047, v1049, v1051, v1053, v1055, v1057, v1059, v1061, v1063, v1065, v1067, v1069, v1071, v1073, v1075, v1077, v1079, v1081, v1083, v1085, v1087, v1089, v1091, v1093, v1095, v1097, v1099, v1101, v1103, v1105, v1107, v1109, v1111, v1113, v1115, v1117, v1119, v1121, v1123, v1125, v1127, v1129, v1131, v1133, v1135, v1137, v1139, v1141, v1143, v1145, v1147, v1149, v1151, v1153, v1155, v1157, v1159, v1161, v1163, v1165, v1167, v1169, v1171, v1173, v1175, v1177, v1179, v1181, v1183, v1185, v1187, v1189, v1191, v1193, v1195, v1197, v1199, v1201, v1203, v1205, v1207, v1209, v1211, v1213, v1215, v1217, v1219, v1221, v1223, v1225, v1227, v1229, v1231, v1233, v1235, v1237, v1239, v1241, v1243, v1245, v1247, v1249, v1251, v1253, v1255, v1257, v1259, v1261, v1263, v1265, v1267, v1269, v1271, v1273, v1275, v1277, v1279, v1281, v1283, v1285, v1287, v1289, v1291, v1293, v1295, v1297, v1299, v1301, v1303, v1305, v1307, v1309, v1311, v1313, v1315, v1317, v1319, v1321, v1323, v1325, v1327, v1329, v1331, v1333, v1335], callee_variadic=false, fixed_args=261, fp_return=false, fp_arg_mask=0x0 } -> x0 + v1338 BinopI { op=ne, lhs=v1337, rhs_imm=101790 } -> x0 + terminator Bz { cond=v1338, target=b10, fall=b9 } (exit_acc=v1338) + block 9 start_pc=0 + v1339 Imm(3) -> x0 + terminator Return(v1339) (exit_acc=v1339) + block 10 start_pc=0 + v1340 Imm(0) -> x0 + terminator Return(v1340) (exit_acc=v1340) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/float_arith_in_static_init.ssa b/tests/snapshots/ssa/float_arith_in_static_init.ssa index 473ec8a4b..02f921fd9 100644 --- a/tests/snapshots/ssa/float_arith_in_static_init.ssa +++ b/tests/snapshots/ssa/float_arith_in_static_init.ssa @@ -18,7 +18,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=1 v8 ImmData(40) -> x1 v9 Imm(4) -> x1 v10 BinopI { op=add, lhs=v1, rhs_imm=4 } -> x1 - v11 Load { addr=v10, disp=0, kind=F32 } -> d0 [f32] + v11 Load { addr=v1, disp=4, kind=F32 } -> d0 [f32] v12 Imm(4612811918334230528) -> x1 v13 Fneg(v12) -> d1 v14 FpCast { kind=F32ToF64, value=v11 } -> d0 @@ -30,8 +30,8 @@ fn ent_pc=1 n_params=0 variadic=false locals=1 block 4 start_pc=0 v17 ImmData(40) -> x1 v18 Imm(8) -> x1 - v19 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x0 - v20 Load { addr=v19, disp=0, kind=F32 } -> d0 [f32] + v19 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x1 + v20 Load { addr=v1, disp=8, kind=F32 } -> d0 [f32] v21 Imm(4622945017495814144) -> x0 v22 FpCast { kind=F32ToF64, value=v20 } -> d0 v23 Binop { op=fne, lhs=v22, rhs=v21 } -> x0 @@ -65,8 +65,8 @@ fn ent_pc=1 n_params=0 variadic=false locals=1 block 10 start_pc=0 v40 ImmData(56) -> x0 v41 Imm(8) -> x1 - v42 BinopI { op=add, lhs=v40, rhs_imm=8 } -> x0 - v43 Load { addr=v42, disp=0, kind=F64 } -> d0 + v42 BinopI { op=add, lhs=v40, rhs_imm=8 } -> x1 + v43 Load { addr=v40, disp=8, kind=F64 } -> d0 v44 Imm(4604930618986332160) -> x0 v45 Fneg(v44) -> d1 v46 Binop { op=fne, lhs=v43, rhs=v45 } -> x0 diff --git a/tests/snapshots/ssa/float_increment_decrement.ssa b/tests/snapshots/ssa/float_increment_decrement.ssa index 85ad72086..971b50493 100644 --- a/tests/snapshots/ssa/float_increment_decrement.ssa +++ b/tests/snapshots/ssa/float_increment_decrement.ssa @@ -155,11 +155,11 @@ fn ent_pc=0 n_params=0 variadic=false locals=22 v113 FpCast { kind=F64ToF32, value=v112 } -> d0 [f32] v114 Store { addr=v108, disp=0, value=v113, kind=F32 } -> - v115 LocalAddr(-12) -> x0 - v116 BinopI { op=add, lhs=v115, rhs_imm=8 } -> x0 - v117 Load { addr=v116, disp=0, kind=F64 } -> d0 + v116 BinopI { op=add, lhs=v115, rhs_imm=8 } -> x1 + v117 Load { addr=v115, disp=8, kind=F64 } -> d0 v118 Imm(-4616189618054758400) -> x1 v119 Binop { op=fadd, lhs=v117, rhs=v118 } -> d0 - v120 Store { addr=v116, disp=0, value=v119, kind=F64 } -> - + v120 Store { addr=v115, disp=8, value=v119, kind=F64 } -> - v121 LocalAddr(-12) -> x0 v122 Load { addr=v121, disp=0, kind=F32 } -> d0 [f32] v123 Imm(4612811918334230528) -> x0 @@ -169,8 +169,8 @@ fn ent_pc=0 n_params=0 variadic=false locals=22 terminator Bnz { cond=v125, target=b35, fall=b19 } (exit_acc=v125) block 19 start_pc=0 v127 LocalAddr(-12) -> x0 - v128 BinopI { op=add, lhs=v127, rhs_imm=8 } -> x0 - v129 Load { addr=v128, disp=0, kind=F64 } -> d0 + v128 BinopI { op=add, lhs=v127, rhs_imm=8 } -> x1 + v129 Load { addr=v127, disp=8, kind=F64 } -> d0 v130 Imm(4609434218613702656) -> x0 v131 Binop { op=fne, lhs=v129, rhs=v130 } -> x1 v132 Imm(0) -> x0 @@ -204,21 +204,21 @@ fn ent_pc=0 n_params=0 variadic=false locals=22 v150 Mcpy { dst=v148, src=v149, size=24 } -> x0 v151 LocalAddr(-15) -> x0 v152 Imm(8) -> x1 - v153 BinopI { op=add, lhs=v151, rhs_imm=8 } -> x0 - v154 Load { addr=v153, disp=0, kind=F64 } -> d0 + v153 BinopI { op=add, lhs=v151, rhs_imm=8 } -> x1 + v154 Load { addr=v151, disp=8, kind=F64 } -> d0 v155 Imm(4607182418800017408) -> x1 v156 Binop { op=fadd, lhs=v154, rhs=v155 } -> d0 - v157 Store { addr=v153, disp=0, value=v156, kind=F64 } -> - + v157 Store { addr=v151, disp=8, value=v156, kind=F64 } -> - v158 LocalAddr(-15) -> x0 v159 Imm(16) -> x1 - v160 BinopI { op=add, lhs=v158, rhs_imm=16 } -> x0 - v161 Load { addr=v160, disp=0, kind=F64 } -> d0 + v160 BinopI { op=add, lhs=v158, rhs_imm=16 } -> x1 + v161 Load { addr=v158, disp=16, kind=F64 } -> d0 v162 Imm(-4616189618054758400) -> x1 v163 Binop { op=fadd, lhs=v161, rhs=v162 } -> d0 - v164 Store { addr=v160, disp=0, value=v163, kind=F64 } -> - + v164 Store { addr=v158, disp=16, value=v163, kind=F64 } -> - v165 LocalAddr(-15) -> x0 - v166 BinopI { op=add, lhs=v165, rhs_imm=8 } -> x0 - v167 Load { addr=v166, disp=0, kind=F64 } -> d0 + v166 BinopI { op=add, lhs=v165, rhs_imm=8 } -> x1 + v167 Load { addr=v165, disp=8, kind=F64 } -> d0 v168 Imm(4611686018427387904) -> x0 v169 Binop { op=fne, lhs=v167, rhs=v168 } -> x1 v170 Imm(0) -> x0 @@ -226,8 +226,8 @@ fn ent_pc=0 n_params=0 variadic=false locals=22 block 25 start_pc=0 v171 LocalAddr(-15) -> x0 v172 Imm(16) -> x1 - v173 BinopI { op=add, lhs=v171, rhs_imm=16 } -> x0 - v174 Load { addr=v173, disp=0, kind=F64 } -> d0 + v173 BinopI { op=add, lhs=v171, rhs_imm=16 } -> x1 + v174 Load { addr=v171, disp=16, kind=F64 } -> d0 v175 Imm(4607182418800017408) -> x0 v176 Binop { op=fne, lhs=v174, rhs=v175 } -> x1 v177 Imm(0) -> x0 diff --git a/tests/snapshots/ssa/float_is_four_bytes.ssa b/tests/snapshots/ssa/float_is_four_bytes.ssa index fcbb40210..7eb9e802f 100644 --- a/tests/snapshots/ssa/float_is_four_bytes.ssa +++ b/tests/snapshots/ssa/float_is_four_bytes.ssa @@ -152,8 +152,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=13 v89 Phi { incoming=[b36:v74, b13:v87], kind=I64 } -> x3 v90 ImmData(40) -> x0 v91 Imm(4) -> x1 - v92 BinopI { op=add, lhs=v90, rhs_imm=4 } -> x0 - v93 Load { addr=v92, disp=0, kind=F32 } -> d0 [f32] + v92 BinopI { op=add, lhs=v90, rhs_imm=4 } -> x1 + v93 Load { addr=v90, disp=4, kind=F32 } -> d0 [f32] v94 Imm(4612811918334230528) -> x0 v95 FpCast { kind=F32ToF64, value=v93 } -> d0 v96 Binop { op=fne, lhs=v95, rhs=v94 } -> x0 @@ -162,8 +162,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=13 v97 ImmData(232) -> x7 v98 ImmData(40) -> x0 v99 Imm(4) -> x1 - v100 BinopI { op=add, lhs=v98, rhs_imm=4 } -> x0 - v101 Load { addr=v100, disp=0, kind=F32 } -> d0 [f32] + v100 BinopI { op=add, lhs=v98, rhs_imm=4 } -> x1 + v101 Load { addr=v98, disp=4, kind=F32 } -> d0 [f32] v102 FpCast { kind=F32ToF64, value=v101 } -> d0 v103 CallExt { binding_idx=0, args=[v97, v102], fp_arg_mask=0x2 } -> x0 v104 Imm(8) -> x3 @@ -173,8 +173,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=13 v106 Phi { incoming=[b37:v89, b15:v104], kind=I64 } -> x3 v107 ImmData(40) -> x0 v108 Imm(8) -> x1 - v109 BinopI { op=add, lhs=v107, rhs_imm=8 } -> x0 - v110 Load { addr=v109, disp=0, kind=F32 } -> d0 [f32] + v109 BinopI { op=add, lhs=v107, rhs_imm=8 } -> x1 + v110 Load { addr=v107, disp=8, kind=F32 } -> d0 [f32] v111 Imm(4615063718147915776) -> x0 v112 FpCast { kind=F32ToF64, value=v110 } -> d0 v113 Binop { op=fne, lhs=v112, rhs=v111 } -> x0 @@ -183,8 +183,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=13 v114 ImmData(252) -> x7 v115 ImmData(40) -> x0 v116 Imm(8) -> x1 - v117 BinopI { op=add, lhs=v115, rhs_imm=8 } -> x0 - v118 Load { addr=v117, disp=0, kind=F32 } -> d0 [f32] + v117 BinopI { op=add, lhs=v115, rhs_imm=8 } -> x1 + v118 Load { addr=v115, disp=8, kind=F32 } -> d0 [f32] v119 FpCast { kind=F32ToF64, value=v118 } -> d0 v120 CallExt { binding_idx=0, args=[v114, v119], fp_arg_mask=0x2 } -> x0 v121 Imm(9) -> x3 @@ -194,8 +194,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=13 v123 Phi { incoming=[b38:v106, b17:v121], kind=I64 } -> x3 v124 ImmData(40) -> x0 v125 Imm(12) -> x1 - v126 BinopI { op=add, lhs=v124, rhs_imm=12 } -> x0 - v127 Load { addr=v126, disp=0, kind=F32 } -> d0 [f32] + v126 BinopI { op=add, lhs=v124, rhs_imm=12 } -> x1 + v127 Load { addr=v124, disp=12, kind=F32 } -> d0 [f32] v128 Imm(4616752568008179712) -> x0 v129 FpCast { kind=F32ToF64, value=v127 } -> d0 v130 Binop { op=fne, lhs=v129, rhs=v128 } -> x0 @@ -204,8 +204,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=13 v131 ImmData(272) -> x7 v132 ImmData(40) -> x0 v133 Imm(12) -> x1 - v134 BinopI { op=add, lhs=v132, rhs_imm=12 } -> x0 - v135 Load { addr=v134, disp=0, kind=F32 } -> d0 [f32] + v134 BinopI { op=add, lhs=v132, rhs_imm=12 } -> x1 + v135 Load { addr=v132, disp=12, kind=F32 } -> d0 [f32] v136 FpCast { kind=F32ToF64, value=v135 } -> d0 v137 CallExt { binding_idx=0, args=[v131, v136], fp_arg_mask=0x2 } -> x0 v138 Imm(10) -> x3 diff --git a/tests/snapshots/ssa/fma_numeric_kernels.ssa b/tests/snapshots/ssa/fma_numeric_kernels.ssa index a75b1d2c0..7ae3d438f 100644 --- a/tests/snapshots/ssa/fma_numeric_kernels.ssa +++ b/tests/snapshots/ssa/fma_numeric_kernels.ssa @@ -184,24 +184,24 @@ fn ent_pc=4 n_params=0 variadic=false locals=31 v4 Store { addr=v1, disp=0, value=v3, kind=F64 } -> - v5 LocalAddr(-5) -> x0 v6 Imm(8) -> x1 - v7 BinopI { op=add, lhs=v5, rhs_imm=8 } -> x0 + v7 BinopI { op=add, lhs=v5, rhs_imm=8 } -> x1 v8 Imm(4611686018427387904) -> x2 - v9 Store { addr=v7, disp=0, value=v8, kind=F64 } -> - + v9 Store { addr=v5, disp=8, value=v8, kind=F64 } -> - v10 LocalAddr(-5) -> x0 v11 Imm(16) -> x1 - v12 BinopI { op=add, lhs=v10, rhs_imm=16 } -> x0 + v12 BinopI { op=add, lhs=v10, rhs_imm=16 } -> x1 v13 Imm(4613937818241073152) -> x1 - v14 Store { addr=v12, disp=0, value=v13, kind=F64 } -> - + v14 Store { addr=v10, disp=16, value=v13, kind=F64 } -> - v15 LocalAddr(-5) -> x0 v16 Imm(24) -> x1 - v17 BinopI { op=add, lhs=v15, rhs_imm=24 } -> x0 + v17 BinopI { op=add, lhs=v15, rhs_imm=24 } -> x1 v18 Imm(4616189618054758400) -> x1 - v19 Store { addr=v17, disp=0, value=v18, kind=F64 } -> - + v19 Store { addr=v15, disp=24, value=v18, kind=F64 } -> - v20 LocalAddr(-5) -> x0 v21 Imm(32) -> x1 - v22 BinopI { op=add, lhs=v20, rhs_imm=32 } -> x0 + v22 BinopI { op=add, lhs=v20, rhs_imm=32 } -> x1 v23 Imm(4617315517961601024) -> x1 - v24 Store { addr=v22, disp=0, value=v23, kind=F64 } -> - + v24 Store { addr=v20, disp=32, value=v23, kind=F64 } -> - v25 LocalAddr(-5) -> x7 v26 Imm(5) -> x6 v27 Call { target_pc=1, args=[v25, v26, v8], fixed_args=3, fp_return=true, fp_arg_mask=0x4 } -> d0 diff --git a/tests/snapshots/ssa/fp_load_folded_disp.ssa b/tests/snapshots/ssa/fp_load_folded_disp.ssa new file mode 100644 index 000000000..6a6ed4450 --- /dev/null +++ b/tests/snapshots/ssa/fp_load_folded_disp.ssa @@ -0,0 +1,186 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=read_f +fn ent_pc=0 n_params=1 variadic=false locals=0 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I64 } -> x0 + v4 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x0 + v5 Load { addr=v1, disp=8, kind=F32 } -> d0 [f32] + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=read_d +fn ent_pc=1 n_params=1 variadic=false locals=0 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I64 } -> x0 + v4 BinopI { op=add, lhs=v1, rhs_imm=16 } -> x0 + v5 Load { addr=v1, disp=16, kind=F64 } -> d0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=2 --- +; name=read_g2 +fn ent_pc=2 n_params=1 variadic=false locals=0 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I64 } -> x0 + v4 BinopI { op=add, lhs=v1, rhs_imm=24 } -> x0 + v5 Imm(8) -> x0 + v6 BinopI { op=add, lhs=v1, rhs_imm=32 } -> x0 + v7 Load { addr=v1, disp=32, kind=F32 } -> d0 [f32] + terminator Return(v7) (exit_acc=v7) +; --- SSA dump (ok=true) ent_pc=3 --- +; name=bump_d +fn ent_pc=3 n_params=1 variadic=false locals=0 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I64 } -> x0 + v4 BinopI { op=add, lhs=v1, rhs_imm=16 } -> x0 + v5 Load { addr=v1, disp=16, kind=F64 } -> d0 + v6 Imm(4602678819172646912) -> x0 + v7 Binop { op=fadd, lhs=v5, rhs=v6 } -> d0 + v8 Store { addr=v1, disp=16, value=v7, kind=F64 } -> - + v9 Imm(0) -> x0 + terminator Return(v9) (exit_acc=v9) +; --- SSA dump (ok=true) ent_pc=4 --- +; name=main +fn ent_pc=4 n_params=0 variadic=false locals=6 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-5) -> x0 + v2 Imm(-1) -> x1 + v3 Store { addr=v1, disp=0, value=v2, kind=I64 } -> - + v4 LocalAddr(-5) -> x0 + v5 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x1 + v6 Imm(4608308318706860032) -> x1 + v7 FpCast { kind=F64ToF32, value=v6 } -> d0 [f32] + v8 Store { addr=v4, disp=8, value=v7, kind=F32 } -> - + v9 LocalAddr(-5) -> x0 + v10 BinopI { op=add, lhs=v9, rhs_imm=16 } -> x2 + v11 Imm(4612811918334230528) -> x2 + v12 Store { addr=v9, disp=16, value=v11, kind=F64 } -> - + v13 LocalAddr(-5) -> x0 + v14 BinopI { op=add, lhs=v13, rhs_imm=24 } -> x2 + v15 Imm(0) -> x2 + v16 FpCast { kind=F64ToF32, value=v15 } -> d0 [f32] + v17 Store { addr=v13, disp=24, value=v16, kind=F32 } -> - + v18 LocalAddr(-5) -> x0 + v19 BinopI { op=add, lhs=v18, rhs_imm=24 } -> x2 + v20 Imm(4) -> x2 + v21 BinopI { op=add, lhs=v18, rhs_imm=28 } -> x2 + v22 Store { addr=v18, disp=28, value=v16, kind=F32 } -> - + v23 LocalAddr(-5) -> x0 + v24 BinopI { op=add, lhs=v23, rhs_imm=24 } -> x2 + v25 Imm(8) -> x2 + v26 BinopI { op=add, lhs=v23, rhs_imm=32 } -> x2 + v27 Imm(4617034042984890368) -> x2 + v28 FpCast { kind=F64ToF32, value=v27 } -> d0 [f32] + v29 Store { addr=v23, disp=32, value=v28, kind=F32 } -> - + v30 LocalAddr(-5) -> x0 + v31 Imm(0) -> x2 + v32 BinopI { op=add, lhs=v30, rhs_imm=8 } -> x2 + v33 Load { addr=v30, disp=8, kind=F32 } -> d0 [f32] + v34 FpCast { kind=F32ToF64, value=v33 } -> d0 + v35 Binop { op=fne, lhs=v34, rhs=v6 } -> x0 + terminator Bz { cond=v35, target=b2, fall=b1 } (exit_acc=v35) + block 1 start_pc=0 + v36 Imm(1) -> x0 + terminator Return(v36) (exit_acc=v36) + block 2 start_pc=0 + v37 LocalAddr(-5) -> x0 + v38 Imm(0) -> x1 + v39 BinopI { op=add, lhs=v37, rhs_imm=16 } -> x1 + v40 Load { addr=v37, disp=16, kind=F64 } -> d0 + v41 Imm(4612811918334230528) -> x0 + v42 Binop { op=fne, lhs=v40, rhs=v41 } -> x0 + terminator Bz { cond=v42, target=b4, fall=b3 } (exit_acc=v42) + block 3 start_pc=0 + v43 Imm(2) -> x0 + terminator Return(v43) (exit_acc=v43) + block 4 start_pc=0 + v44 LocalAddr(-5) -> x0 + v45 Imm(0) -> x1 + v46 BinopI { op=add, lhs=v44, rhs_imm=24 } -> x1 + v47 Imm(8) -> x1 + v48 BinopI { op=add, lhs=v44, rhs_imm=32 } -> x1 + v49 Load { addr=v44, disp=32, kind=F32 } -> d0 [f32] + v50 Imm(4617034042984890368) -> x0 + v51 FpCast { kind=F32ToF64, value=v49 } -> d0 + v52 Binop { op=fne, lhs=v51, rhs=v50 } -> x0 + terminator Bz { cond=v52, target=b6, fall=b5 } (exit_acc=v52) + block 5 start_pc=0 + v53 Imm(3) -> x0 + terminator Return(v53) (exit_acc=v53) + block 6 start_pc=0 + v54 LocalAddr(-5) -> x7 + v55 Call { target_pc=3, args=[v54], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + v56 LocalAddr(-5) -> x0 + v57 BinopI { op=add, lhs=v56, rhs_imm=16 } -> x1 + v58 Load { addr=v56, disp=16, kind=F64 } -> d0 + v59 Imm(4613937818241073152) -> x0 + v60 Binop { op=fne, lhs=v58, rhs=v59 } -> x0 + terminator Bz { cond=v60, target=b8, fall=b7 } (exit_acc=v60) + block 7 start_pc=0 + v61 Imm(4) -> x0 + terminator Return(v61) (exit_acc=v61) + block 8 start_pc=0 + v62 Imm(0) -> x0 + terminator Return(v62) (exit_acc=v62) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/hfa_param_interleave.ssa b/tests/snapshots/ssa/hfa_param_interleave.ssa index 77bf6e746..9df4cfbe4 100644 --- a/tests/snapshots/ssa/hfa_param_interleave.ssa +++ b/tests/snapshots/ssa/hfa_param_interleave.ssa @@ -9,29 +9,29 @@ fn ent_pc=0 n_params=6 variadic=false locals=6 v3 LocalAddr(-1) -> x0 v4 Load { addr=v3, disp=0, kind=F32 } -> d1 [f32] v5 LocalAddr(-1) -> x0 - v6 BinopI { op=add, lhs=v5, rhs_imm=4 } -> x0 - v7 Load { addr=v6, disp=0, kind=F32 } -> d2 [f32] + v6 BinopI { op=add, lhs=v5, rhs_imm=4 } -> x1 + v7 Load { addr=v5, disp=4, kind=F32 } -> d2 [f32] v8 Binop { op=fadd, lhs=v4, rhs=v7 } -> d1 [f32] v9 LocalAddr(-2) -> x0 v10 Load { addr=v9, disp=0, kind=F32 } -> d2 [f32] v11 Binop { op=fadd, lhs=v8, rhs=v10 } -> d1 [f32] v12 LocalAddr(-2) -> x0 - v13 BinopI { op=add, lhs=v12, rhs_imm=4 } -> x0 - v14 Load { addr=v13, disp=0, kind=F32 } -> d2 [f32] + v13 BinopI { op=add, lhs=v12, rhs_imm=4 } -> x1 + v14 Load { addr=v12, disp=4, kind=F32 } -> d2 [f32] v15 Binop { op=fadd, lhs=v11, rhs=v14 } -> d1 [f32] v16 LocalAddr(-3) -> x0 v17 Load { addr=v16, disp=0, kind=F32 } -> d2 [f32] v18 Binop { op=fadd, lhs=v15, rhs=v17 } -> d1 [f32] v19 LocalAddr(-3) -> x0 - v20 BinopI { op=add, lhs=v19, rhs_imm=4 } -> x0 - v21 Load { addr=v20, disp=0, kind=F32 } -> d2 [f32] + v20 BinopI { op=add, lhs=v19, rhs_imm=4 } -> x1 + v21 Load { addr=v19, disp=4, kind=F32 } -> d2 [f32] v22 Binop { op=fadd, lhs=v18, rhs=v21 } -> d1 [f32] v23 LocalAddr(-4) -> x0 v24 Load { addr=v23, disp=0, kind=F32 } -> d2 [f32] v25 Binop { op=fadd, lhs=v22, rhs=v24 } -> d1 [f32] v26 LocalAddr(-4) -> x0 - v27 BinopI { op=add, lhs=v26, rhs_imm=4 } -> x0 - v28 Load { addr=v27, disp=0, kind=F32 } -> d2 [f32] + v27 BinopI { op=add, lhs=v26, rhs_imm=4 } -> x1 + v28 Load { addr=v26, disp=4, kind=F32 } -> d2 [f32] v29 Binop { op=fadd, lhs=v25, rhs=v28 } -> d1 [f32] v30 LoadLocal { off=-6, kind=F32 } -> d2 [f32] v31 Binop { op=fadd, lhs=v29, rhs=v1 } -> d0 [f32] diff --git a/tests/snapshots/ssa/hfa_struct_return.ssa b/tests/snapshots/ssa/hfa_struct_return.ssa index d7f7f8a9d..8c8399831 100644 --- a/tests/snapshots/ssa/hfa_struct_return.ssa +++ b/tests/snapshots/ssa/hfa_struct_return.ssa @@ -25,9 +25,9 @@ fn ent_pc=1 n_params=2 variadic=false locals=2 v6 LoadLocal { off=2, kind=F64 } -> d2 v7 Store { addr=v5, disp=0, value=v1, kind=F64 } -> - v8 LocalAddr(-2) -> x0 - v9 BinopI { op=add, lhs=v8, rhs_imm=8 } -> x0 + v9 BinopI { op=add, lhs=v8, rhs_imm=8 } -> x1 v10 LoadLocal { off=3, kind=F64 } -> d0 - v11 Store { addr=v9, disp=0, value=v3, kind=F64 } -> - + v11 Store { addr=v8, disp=8, value=v3, kind=F64 } -> - v12 LocalAddr(-2) -> x0 terminator Return(v12) (exit_acc=v12) ; --- SSA dump (ok=true) ent_pc=2 --- @@ -40,13 +40,13 @@ fn ent_pc=2 n_params=4 variadic=false locals=3 v2 LoadLocal { off=3, kind=F64 } -> d0 v3 Store { addr=v1, disp=0, value=v2, kind=F64 } -> - v4 LocalAddr(-3) -> x0 - v5 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x0 + v5 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x1 v6 LoadLocal { off=4, kind=F64 } -> d0 - v7 Store { addr=v5, disp=0, value=v6, kind=F64 } -> - + v7 Store { addr=v4, disp=8, value=v6, kind=F64 } -> - v8 LocalAddr(-3) -> x0 - v9 BinopI { op=add, lhs=v8, rhs_imm=16 } -> x0 + v9 BinopI { op=add, lhs=v8, rhs_imm=16 } -> x1 v10 LoadLocal { off=5, kind=F64 } -> d0 - v11 Store { addr=v9, disp=0, value=v10, kind=F64 } -> - + v11 Store { addr=v8, disp=16, value=v10, kind=F64 } -> - v12 LoadLocal { off=2, kind=I64 } -> x0 v13 LocalAddr(-3) -> x1 v14 Mcpy { dst=v12, src=v13, size=24 } -> x1 @@ -61,17 +61,17 @@ fn ent_pc=3 n_params=5 variadic=false locals=4 v2 LoadLocal { off=3, kind=F64 } -> d0 v3 Store { addr=v1, disp=0, value=v2, kind=F64 } -> - v4 LocalAddr(-4) -> x0 - v5 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x0 + v5 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x1 v6 LoadLocal { off=4, kind=F64 } -> d0 - v7 Store { addr=v5, disp=0, value=v6, kind=F64 } -> - + v7 Store { addr=v4, disp=8, value=v6, kind=F64 } -> - v8 LocalAddr(-4) -> x0 - v9 BinopI { op=add, lhs=v8, rhs_imm=16 } -> x0 + v9 BinopI { op=add, lhs=v8, rhs_imm=16 } -> x1 v10 LoadLocal { off=5, kind=F64 } -> d0 - v11 Store { addr=v9, disp=0, value=v10, kind=F64 } -> - + v11 Store { addr=v8, disp=16, value=v10, kind=F64 } -> - v12 LocalAddr(-4) -> x0 - v13 BinopI { op=add, lhs=v12, rhs_imm=24 } -> x0 + v13 BinopI { op=add, lhs=v12, rhs_imm=24 } -> x1 v14 LoadLocal { off=6, kind=F64 } -> d0 - v15 Store { addr=v13, disp=0, value=v14, kind=F64 } -> - + v15 Store { addr=v12, disp=24, value=v14, kind=F64 } -> - v16 LoadLocal { off=2, kind=I64 } -> x0 v17 LocalAddr(-4) -> x1 v18 Mcpy { dst=v16, src=v17, size=32 } -> x1 @@ -90,9 +90,9 @@ fn ent_pc=4 n_params=2 variadic=false locals=3 v6 LoadLocal { off=-1, kind=F32 } -> d2 [f32] v7 Store { addr=v5, disp=0, value=v1, kind=F32 } -> - v8 LocalAddr(-3) -> x0 - v9 BinopI { op=add, lhs=v8, rhs_imm=4 } -> x0 + v9 BinopI { op=add, lhs=v8, rhs_imm=4 } -> x1 v10 LoadLocal { off=-2, kind=F32 } -> d0 [f32] - v11 Store { addr=v9, disp=0, value=v3, kind=F32 } -> - + v11 Store { addr=v8, disp=4, value=v3, kind=F32 } -> - v12 LocalAddr(-3) -> x0 terminator Return(v12) (exit_acc=v12) ; --- SSA dump (ok=true) ent_pc=5 --- @@ -104,8 +104,8 @@ fn ent_pc=5 n_params=1 variadic=false locals=2 v1 LocalAddr(-2) -> x0 v2 Load { addr=v1, disp=0, kind=F64 } -> d0 v3 LocalAddr(-2) -> x0 - v4 BinopI { op=add, lhs=v3, rhs_imm=8 } -> x0 - v5 Load { addr=v4, disp=0, kind=F64 } -> d1 + v4 BinopI { op=add, lhs=v3, rhs_imm=8 } -> x1 + v5 Load { addr=v3, disp=8, kind=F64 } -> d1 v6 Binop { op=fadd, lhs=v2, rhs=v5 } -> d0 terminator Return(v6) (exit_acc=v6) ; --- SSA dump (ok=true) ent_pc=6 --- @@ -117,16 +117,16 @@ fn ent_pc=6 n_params=1 variadic=false locals=4 v1 LocalAddr(-4) -> x0 v2 Load { addr=v1, disp=0, kind=F64 } -> d0 v3 LocalAddr(-4) -> x0 - v4 BinopI { op=add, lhs=v3, rhs_imm=8 } -> x0 - v5 Load { addr=v4, disp=0, kind=F64 } -> d1 + v4 BinopI { op=add, lhs=v3, rhs_imm=8 } -> x1 + v5 Load { addr=v3, disp=8, kind=F64 } -> d1 v6 Binop { op=fadd, lhs=v2, rhs=v5 } -> d0 v7 LocalAddr(-4) -> x0 - v8 BinopI { op=add, lhs=v7, rhs_imm=16 } -> x0 - v9 Load { addr=v8, disp=0, kind=F64 } -> d1 + v8 BinopI { op=add, lhs=v7, rhs_imm=16 } -> x1 + v9 Load { addr=v7, disp=16, kind=F64 } -> d1 v10 Binop { op=fadd, lhs=v6, rhs=v9 } -> d0 v11 LocalAddr(-4) -> x0 - v12 BinopI { op=add, lhs=v11, rhs_imm=24 } -> x0 - v13 Load { addr=v12, disp=0, kind=F64 } -> d1 + v12 BinopI { op=add, lhs=v11, rhs_imm=24 } -> x1 + v13 Load { addr=v11, disp=24, kind=F64 } -> d1 v14 Binop { op=fadd, lhs=v10, rhs=v13 } -> d0 terminator Return(v14) (exit_acc=v14) ; --- SSA dump (ok=true) ent_pc=7 --- @@ -138,16 +138,16 @@ fn ent_pc=7 n_params=1 variadic=false locals=2 v1 LocalAddr(-2) -> x0 v2 Load { addr=v1, disp=0, kind=F32 } -> d0 [f32] v3 LocalAddr(-2) -> x0 - v4 BinopI { op=add, lhs=v3, rhs_imm=4 } -> x0 - v5 Load { addr=v4, disp=0, kind=F32 } -> d1 [f32] + v4 BinopI { op=add, lhs=v3, rhs_imm=4 } -> x1 + v5 Load { addr=v3, disp=4, kind=F32 } -> d1 [f32] v6 Binop { op=fadd, lhs=v2, rhs=v5 } -> d0 [f32] v7 LocalAddr(-2) -> x0 - v8 BinopI { op=add, lhs=v7, rhs_imm=8 } -> x0 - v9 Load { addr=v8, disp=0, kind=F32 } -> d1 [f32] + v8 BinopI { op=add, lhs=v7, rhs_imm=8 } -> x1 + v9 Load { addr=v7, disp=8, kind=F32 } -> d1 [f32] v10 Binop { op=fadd, lhs=v6, rhs=v9 } -> d0 [f32] v11 LocalAddr(-2) -> x0 - v12 BinopI { op=add, lhs=v11, rhs_imm=12 } -> x0 - v13 Load { addr=v12, disp=0, kind=F32 } -> d1 [f32] + v12 BinopI { op=add, lhs=v11, rhs_imm=12 } -> x1 + v13 Load { addr=v11, disp=12, kind=F32 } -> d1 [f32] v14 Binop { op=fadd, lhs=v10, rhs=v13 } -> d0 [f32] terminator Return(v14) (exit_acc=v14) ; --- SSA dump (ok=true) ent_pc=8 --- @@ -182,8 +182,8 @@ fn ent_pc=8 n_params=0 variadic=false locals=45 terminator Bnz { cond=v18, target=b31, fall=b3 } (exit_acc=v18) block 3 start_pc=0 v20 LocalAddr(-4) -> x0 - v21 BinopI { op=add, lhs=v20, rhs_imm=8 } -> x0 - v22 Load { addr=v21, disp=0, kind=F64 } -> d0 + v21 BinopI { op=add, lhs=v20, rhs_imm=8 } -> x1 + v22 Load { addr=v20, disp=8, kind=F64 } -> d0 v23 Imm(4602678819172646912) -> x0 v24 Binop { op=fne, lhs=v22, rhs=v23 } -> x3 v25 Imm(0) -> x0 @@ -214,8 +214,8 @@ fn ent_pc=8 n_params=0 variadic=false locals=45 terminator Bnz { cond=v41, target=b32, fall=b7 } (exit_acc=v41) block 7 start_pc=0 v44 LocalAddr(-9) -> x0 - v45 BinopI { op=add, lhs=v44, rhs_imm=8 } -> x0 - v46 Load { addr=v45, disp=0, kind=F64 } -> d0 + v45 BinopI { op=add, lhs=v44, rhs_imm=8 } -> x1 + v46 Load { addr=v44, disp=8, kind=F64 } -> d0 v47 Imm(4611686018427387904) -> x0 v48 Binop { op=fne, lhs=v46, rhs=v47 } -> x0 v49 BinopI { op=ne, lhs=v48, rhs_imm=0 } -> x3 @@ -228,8 +228,8 @@ fn ent_pc=8 n_params=0 variadic=false locals=45 terminator Bnz { cond=v51, target=b33, fall=b9 } (exit_acc=v51) block 9 start_pc=0 v54 LocalAddr(-9) -> x0 - v55 BinopI { op=add, lhs=v54, rhs_imm=16 } -> x0 - v56 Load { addr=v55, disp=0, kind=F64 } -> d0 + v55 BinopI { op=add, lhs=v54, rhs_imm=16 } -> x1 + v56 Load { addr=v54, disp=16, kind=F64 } -> d0 v57 Imm(4613937818241073152) -> x0 v58 Binop { op=fne, lhs=v56, rhs=v57 } -> x3 v59 Imm(0) -> x0 @@ -261,8 +261,8 @@ fn ent_pc=8 n_params=0 variadic=false locals=45 terminator Bnz { cond=v76, target=b34, fall=b13 } (exit_acc=v76) block 13 start_pc=0 v79 LocalAddr(-16) -> x0 - v80 BinopI { op=add, lhs=v79, rhs_imm=8 } -> x0 - v81 Load { addr=v80, disp=0, kind=F64 } -> d0 + v80 BinopI { op=add, lhs=v79, rhs_imm=8 } -> x1 + v81 Load { addr=v79, disp=8, kind=F64 } -> d0 v82 Imm(4626322717216342016) -> x0 v83 Binop { op=fne, lhs=v81, rhs=v82 } -> x0 v84 BinopI { op=ne, lhs=v83, rhs_imm=0 } -> x3 @@ -276,8 +276,8 @@ fn ent_pc=8 n_params=0 variadic=false locals=45 terminator Bnz { cond=v86, target=b35, fall=b15 } (exit_acc=v86) block 15 start_pc=0 v90 LocalAddr(-16) -> x0 - v91 BinopI { op=add, lhs=v90, rhs_imm=16 } -> x0 - v92 Load { addr=v91, disp=0, kind=F64 } -> d0 + v91 BinopI { op=add, lhs=v90, rhs_imm=16 } -> x1 + v92 Load { addr=v90, disp=16, kind=F64 } -> d0 v93 Imm(4629137466983448576) -> x0 v94 Binop { op=fne, lhs=v92, rhs=v93 } -> x0 v95 BinopI { op=ne, lhs=v94, rhs_imm=0 } -> x12 @@ -290,8 +290,8 @@ fn ent_pc=8 n_params=0 variadic=false locals=45 terminator Bnz { cond=v97, target=b36, fall=b17 } (exit_acc=v97) block 17 start_pc=0 v100 LocalAddr(-16) -> x0 - v101 BinopI { op=add, lhs=v100, rhs_imm=24 } -> x0 - v102 Load { addr=v101, disp=0, kind=F64 } -> d0 + v101 BinopI { op=add, lhs=v100, rhs_imm=24 } -> x1 + v102 Load { addr=v100, disp=24, kind=F64 } -> d0 v103 Imm(4630826316843712512) -> x0 v104 Binop { op=fne, lhs=v102, rhs=v103 } -> x12 v105 Imm(0) -> x0 @@ -320,8 +320,8 @@ fn ent_pc=8 n_params=0 variadic=false locals=45 terminator Bnz { cond=v120, target=b37, fall=b21 } (exit_acc=v120) block 21 start_pc=0 v122 LocalAddr(-21) -> x0 - v123 BinopI { op=add, lhs=v122, rhs_imm=4 } -> x0 - v124 Load { addr=v123, disp=0, kind=F32 } -> d0 [f32] + v123 BinopI { op=add, lhs=v122, rhs_imm=4 } -> x1 + v124 Load { addr=v122, disp=4, kind=F32 } -> d0 [f32] v125 Imm(4612811918334230528) -> x0 v126 FpCast { kind=F32ToF64, value=v124 } -> d0 v127 Binop { op=fne, lhs=v126, rhs=v125 } -> x3 diff --git a/tests/snapshots/ssa/indirect_call_target_scratch_exhausted.ssa b/tests/snapshots/ssa/indirect_call_target_scratch_exhausted.ssa new file mode 100644 index 000000000..33163816c --- /dev/null +++ b/tests/snapshots/ssa/indirect_call_target_scratch_exhausted.ssa @@ -0,0 +1,322 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=sum17 +fn ent_pc=0 n_params=17 variadic=false locals=0 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 ParamRef(2, kind=I64) -> x2 + v6 Imm(0) -> x0 + v7 ParamRef(3, kind=I64) -> x1 + v8 Imm(0) -> x0 + v9 ParamRef(4, kind=I64) -> x8 + v10 Imm(0) -> x0 + v11 ParamRef(5, kind=I64) -> x9 + v12 Imm(0) -> x0 + v13 LoadLocal { off=2, kind=I64 } -> x0 + v14 LoadLocal { off=3, kind=I64 } -> x0 + v15 Binop { op=add, lhs=v1, rhs=v3 } -> x0 + v16 LoadLocal { off=4, kind=I64 } -> x6 + v17 Binop { op=add, lhs=v15, rhs=v5 } -> x0 + v18 LoadLocal { off=5, kind=I64 } -> x2 + v19 Binop { op=add, lhs=v17, rhs=v7 } -> x0 + v20 LoadLocal { off=6, kind=I64 } -> x1 + v21 Binop { op=add, lhs=v19, rhs=v9 } -> x0 + v22 LoadLocal { off=7, kind=I64 } -> x1 + v23 Binop { op=add, lhs=v21, rhs=v11 } -> x0 + v24 LoadLocal { off=8, kind=I64 } -> x1 + v25 Binop { op=add, lhs=v23, rhs=v24 } -> x0 + v26 LoadLocal { off=9, kind=I64 } -> x1 + v27 Binop { op=add, lhs=v25, rhs=v26 } -> x0 + v28 LoadLocal { off=10, kind=I64 } -> x1 + v29 Binop { op=add, lhs=v27, rhs=v28 } -> x0 + v30 LoadLocal { off=11, kind=I64 } -> x1 + v31 Binop { op=add, lhs=v29, rhs=v30 } -> x0 + v32 LoadLocal { off=12, kind=I64 } -> x1 + v33 Binop { op=add, lhs=v31, rhs=v32 } -> x0 + v34 LoadLocal { off=13, kind=I64 } -> x1 + v35 Binop { op=add, lhs=v33, rhs=v34 } -> x0 + v36 LoadLocal { off=14, kind=I64 } -> x1 + v37 Binop { op=add, lhs=v35, rhs=v36 } -> x0 + v38 LoadLocal { off=15, kind=I64 } -> x1 + v39 Binop { op=add, lhs=v37, rhs=v38 } -> x0 + v40 LoadLocal { off=16, kind=I64 } -> x1 + v41 Binop { op=add, lhs=v39, rhs=v40 } -> x0 + v42 LoadLocal { off=17, kind=I64 } -> x1 + v43 Binop { op=add, lhs=v41, rhs=v42 } -> x0 + v44 LoadLocal { off=18, kind=I64 } -> x1 + v45 Binop { op=add, lhs=v43, rhs=v44 } -> x0 + terminator Return(v45) (exit_acc=v45) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=sum16p +fn ent_pc=1 n_params=16 variadic=false locals=32 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-2) -> x0 + v2 Load { addr=v1, disp=0, kind=I64 } -> x0 + v3 LocalAddr(-2) -> x1 + v4 BinopI { op=add, lhs=v3, rhs_imm=8 } -> x2 + v5 Load { addr=v3, disp=8, kind=I64 } -> x1 + v6 Binop { op=add, lhs=v2, rhs=v5 } -> x0 + v7 LocalAddr(-4) -> x1 + v8 Load { addr=v7, disp=0, kind=I64 } -> x1 + v9 Binop { op=add, lhs=v6, rhs=v8 } -> x0 + v10 LocalAddr(-4) -> x1 + v11 BinopI { op=add, lhs=v10, rhs_imm=8 } -> x2 + v12 Load { addr=v10, disp=8, kind=I64 } -> x1 + v13 Binop { op=add, lhs=v9, rhs=v12 } -> x0 + v14 LocalAddr(-6) -> x1 + v15 Load { addr=v14, disp=0, kind=I64 } -> x1 + v16 Binop { op=add, lhs=v13, rhs=v15 } -> x0 + v17 LocalAddr(-6) -> x1 + v18 BinopI { op=add, lhs=v17, rhs_imm=8 } -> x2 + v19 Load { addr=v17, disp=8, kind=I64 } -> x1 + v20 Binop { op=add, lhs=v16, rhs=v19 } -> x0 + v21 LocalAddr(-8) -> x1 + v22 Load { addr=v21, disp=0, kind=I64 } -> x1 + v23 Binop { op=add, lhs=v20, rhs=v22 } -> x0 + v24 LocalAddr(-8) -> x1 + v25 BinopI { op=add, lhs=v24, rhs_imm=8 } -> x2 + v26 Load { addr=v24, disp=8, kind=I64 } -> x1 + v27 Binop { op=add, lhs=v23, rhs=v26 } -> x0 + v28 LocalAddr(-10) -> x1 + v29 Load { addr=v28, disp=0, kind=I64 } -> x1 + v30 Binop { op=add, lhs=v27, rhs=v29 } -> x0 + v31 LocalAddr(-10) -> x1 + v32 BinopI { op=add, lhs=v31, rhs_imm=8 } -> x2 + v33 Load { addr=v31, disp=8, kind=I64 } -> x1 + v34 Binop { op=add, lhs=v30, rhs=v33 } -> x0 + v35 LocalAddr(-12) -> x1 + v36 Load { addr=v35, disp=0, kind=I64 } -> x1 + v37 Binop { op=add, lhs=v34, rhs=v36 } -> x0 + v38 LocalAddr(-12) -> x1 + v39 BinopI { op=add, lhs=v38, rhs_imm=8 } -> x2 + v40 Load { addr=v38, disp=8, kind=I64 } -> x1 + v41 Binop { op=add, lhs=v37, rhs=v40 } -> x0 + v42 LocalAddr(-14) -> x1 + v43 Load { addr=v42, disp=0, kind=I64 } -> x1 + v44 Binop { op=add, lhs=v41, rhs=v43 } -> x0 + v45 LocalAddr(-14) -> x1 + v46 BinopI { op=add, lhs=v45, rhs_imm=8 } -> x2 + v47 Load { addr=v45, disp=8, kind=I64 } -> x1 + v48 Binop { op=add, lhs=v44, rhs=v47 } -> x0 + v49 LocalAddr(-16) -> x1 + v50 Load { addr=v49, disp=0, kind=I64 } -> x1 + v51 Binop { op=add, lhs=v48, rhs=v50 } -> x0 + v52 LocalAddr(-16) -> x1 + v53 BinopI { op=add, lhs=v52, rhs_imm=8 } -> x2 + v54 Load { addr=v52, disp=8, kind=I64 } -> x1 + v55 Binop { op=add, lhs=v51, rhs=v54 } -> x0 + v56 LocalAddr(-18) -> x1 + v57 Load { addr=v56, disp=0, kind=I64 } -> x1 + v58 Binop { op=add, lhs=v55, rhs=v57 } -> x0 + v59 LocalAddr(-18) -> x1 + v60 BinopI { op=add, lhs=v59, rhs_imm=8 } -> x2 + v61 Load { addr=v59, disp=8, kind=I64 } -> x1 + v62 Binop { op=add, lhs=v58, rhs=v61 } -> x0 + v63 LocalAddr(-20) -> x1 + v64 Load { addr=v63, disp=0, kind=I64 } -> x1 + v65 Binop { op=add, lhs=v62, rhs=v64 } -> x0 + v66 LocalAddr(-20) -> x1 + v67 BinopI { op=add, lhs=v66, rhs_imm=8 } -> x2 + v68 Load { addr=v66, disp=8, kind=I64 } -> x1 + v69 Binop { op=add, lhs=v65, rhs=v68 } -> x0 + v70 LocalAddr(-22) -> x1 + v71 Load { addr=v70, disp=0, kind=I64 } -> x1 + v72 Binop { op=add, lhs=v69, rhs=v71 } -> x0 + v73 LocalAddr(-22) -> x1 + v74 BinopI { op=add, lhs=v73, rhs_imm=8 } -> x2 + v75 Load { addr=v73, disp=8, kind=I64 } -> x1 + v76 Binop { op=add, lhs=v72, rhs=v75 } -> x0 + v77 LocalAddr(-24) -> x1 + v78 Load { addr=v77, disp=0, kind=I64 } -> x1 + v79 Binop { op=add, lhs=v76, rhs=v78 } -> x0 + v80 LocalAddr(-24) -> x1 + v81 BinopI { op=add, lhs=v80, rhs_imm=8 } -> x2 + v82 Load { addr=v80, disp=8, kind=I64 } -> x1 + v83 Binop { op=add, lhs=v79, rhs=v82 } -> x0 + v84 LocalAddr(-26) -> x1 + v85 Load { addr=v84, disp=0, kind=I64 } -> x1 + v86 Binop { op=add, lhs=v83, rhs=v85 } -> x0 + v87 LocalAddr(-26) -> x1 + v88 BinopI { op=add, lhs=v87, rhs_imm=8 } -> x2 + v89 Load { addr=v87, disp=8, kind=I64 } -> x1 + v90 Binop { op=add, lhs=v86, rhs=v89 } -> x0 + v91 LocalAddr(-28) -> x1 + v92 Load { addr=v91, disp=0, kind=I64 } -> x1 + v93 Binop { op=add, lhs=v90, rhs=v92 } -> x0 + v94 LocalAddr(-28) -> x1 + v95 BinopI { op=add, lhs=v94, rhs_imm=8 } -> x2 + v96 Load { addr=v94, disp=8, kind=I64 } -> x1 + v97 Binop { op=add, lhs=v93, rhs=v96 } -> x0 + v98 LocalAddr(-30) -> x1 + v99 Load { addr=v98, disp=0, kind=I64 } -> x1 + v100 Binop { op=add, lhs=v97, rhs=v99 } -> x0 + v101 LocalAddr(-30) -> x1 + v102 BinopI { op=add, lhs=v101, rhs_imm=8 } -> x2 + v103 Load { addr=v101, disp=8, kind=I64 } -> x1 + v104 Binop { op=add, lhs=v100, rhs=v103 } -> x0 + v105 LocalAddr(-32) -> x1 + v106 Load { addr=v105, disp=0, kind=I64 } -> x1 + v107 Binop { op=add, lhs=v104, rhs=v106 } -> x0 + v108 LocalAddr(-32) -> x1 + v109 BinopI { op=add, lhs=v108, rhs_imm=8 } -> x2 + v110 Load { addr=v108, disp=8, kind=I64 } -> x1 + v111 Binop { op=add, lhs=v107, rhs=v110 } -> x0 + terminator Return(v111) (exit_acc=v111) +; --- SSA dump (ok=true) ent_pc=2 --- +; name=main +fn ent_pc=2 n_params=0 variadic=false locals=20 + spill_count=8 gpr_used=[3, 12, 13, 14, 15] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ImmCode(ent_pc=0) -> x0 + v2 Imm(0) -> x1 + v3 ImmCode(ent_pc=1) -> x3 + v4 Imm(0) -> x1 + v5 Imm(0) -> x2 + v6 Imm(0) -> x1 + terminator Jmp(b1) (exit_acc=v5) + block 1 start_pc=0 + v7 Phi { incoming=[b0:v5, b2:v11], kind=I64 } -> x2 + v8 LoadLocal { off=-3, kind=I64 } -> x1 + v9 BinopI { op=lt, lhs=v7, rhs_imm=16 } -> x1 + terminator Bz { cond=v9, target=b4, fall=b3 } (exit_acc=v9) + block 2 start_pc=0 + v10 LoadLocal { off=-3, kind=I64 } -> x1 + v11 BinopI { op=add, lhs=v7, rhs_imm=1 } -> x2 + v12 Imm(0) -> x1 + terminator Jmp(b1) (exit_acc=v11) + block 3 start_pc=0 + v13 ImmData(24) -> x1 + v14 LoadLocal { off=-3, kind=I64 } -> x6 + v15 BinopI { op=shl, lhs=v7, rhs_imm=4 } -> x6 + v16 Binop { op=add, lhs=v13, rhs=v15 } -> x6 + v17 Store { addr=v16, disp=0, value=v7, kind=I64 } -> - + v18 LoadLocal { off=-3, kind=I64 } -> x6 + v19 BinopI { op=shl, lhs=v7, rhs_imm=4 } -> x6 + v20 Binop { op=add, lhs=v13, rhs=v19 } -> x1 + v21 BinopI { op=add, lhs=v20, rhs_imm=8 } -> x6 + v22 Imm(2) -> x6 + v23 BinopI { op=shl, lhs=v7, rhs_imm=1 } -> x6 + v24 Store { addr=v20, disp=8, value=v23, kind=I64 } -> - + terminator Jmp(b2) (exit_acc=v24) + block 4 start_pc=0 + v25 Imm(1) -> x7 + v26 Imm(2) -> x6 + v27 Imm(3) -> x2 + v28 Imm(4) -> x1 + v29 Imm(5) -> x8 + v30 Imm(6) -> x9 + v31 Imm(7) -> x12 + v32 Imm(8) -> x13 + v33 Imm(9) -> x14 + v34 Imm(10) -> x15 + v35 Imm(11) -> [spill 0] + v36 Imm(12) -> [spill 1] + v37 Imm(13) -> [spill 2] + v38 Imm(14) -> [spill 3] + v39 Imm(15) -> [spill 4] + v40 Imm(16) -> [spill 5] + v41 Imm(17) -> [spill 6] + v42 LoadLocal { off=-1, kind=I64 } -> [spill 7] + v43 CallIndirect { target=v1, args=[v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41], callee_variadic=false, fixed_args=17, fp_return=false, fp_arg_mask=0x0 } -> x0 + v44 BinopI { op=ne, lhs=v43, rhs_imm=153 } -> x0 + terminator Bz { cond=v44, target=b6, fall=b5 } (exit_acc=v44) + block 5 start_pc=0 + v45 Imm(1) -> x0 + terminator Return(v45) (exit_acc=v45) + block 6 start_pc=0 + v46 ImmData(24) -> x7 + v47 Imm(0) -> x0 + v48 Imm(16) -> x0 + v49 BinopI { op=add, lhs=v46, rhs_imm=16 } -> x6 + v50 Imm(32) -> x0 + v51 BinopI { op=add, lhs=v46, rhs_imm=32 } -> x2 + v52 Imm(48) -> x0 + v53 BinopI { op=add, lhs=v46, rhs_imm=48 } -> x1 + v54 Imm(64) -> x0 + v55 BinopI { op=add, lhs=v46, rhs_imm=64 } -> x8 + v56 Imm(80) -> x0 + v57 BinopI { op=add, lhs=v46, rhs_imm=80 } -> x9 + v58 Imm(96) -> x0 + v59 BinopI { op=add, lhs=v46, rhs_imm=96 } -> x0 + v60 Imm(112) -> x12 + v61 BinopI { op=add, lhs=v46, rhs_imm=112 } -> x12 + v62 Imm(128) -> x13 + v63 BinopI { op=add, lhs=v46, rhs_imm=128 } -> x13 + v64 Imm(144) -> x14 + v65 BinopI { op=add, lhs=v46, rhs_imm=144 } -> x14 + v66 Imm(160) -> x15 + v67 BinopI { op=add, lhs=v46, rhs_imm=160 } -> x15 + v68 Imm(176) -> [spill 0] + v69 BinopI { op=add, lhs=v46, rhs_imm=176 } -> [spill 0] + v70 Imm(192) -> [spill 1] + v71 BinopI { op=add, lhs=v46, rhs_imm=192 } -> [spill 1] + v72 Imm(208) -> [spill 2] + v73 BinopI { op=add, lhs=v46, rhs_imm=208 } -> [spill 2] + v74 Imm(224) -> [spill 3] + v75 BinopI { op=add, lhs=v46, rhs_imm=224 } -> [spill 3] + v76 Imm(240) -> [spill 4] + v77 BinopI { op=add, lhs=v46, rhs_imm=240 } -> [spill 4] + v78 LoadLocal { off=-2, kind=I64 } -> [spill 5] + v79 CallIndirect { target=v3, args=[v46, v49, v51, v53, v55, v57, v59, v61, v63, v65, v67, v69, v71, v73, v75, v77], callee_variadic=false, fixed_args=16, fp_return=false, fp_arg_mask=0x0 } -> x0 + v80 BinopI { op=ne, lhs=v79, rhs_imm=360 } -> x0 + terminator Bz { cond=v80, target=b8, fall=b7 } (exit_acc=v80) + block 7 start_pc=0 + v81 Imm(2) -> x0 + terminator Return(v81) (exit_acc=v81) + block 8 start_pc=0 + v82 Imm(0) -> x0 + terminator Return(v82) (exit_acc=v82) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/init_float_to_int.ssa b/tests/snapshots/ssa/init_float_to_int.ssa index 1b8c29617..3adc41c1a 100644 --- a/tests/snapshots/ssa/init_float_to_int.ssa +++ b/tests/snapshots/ssa/init_float_to_int.ssa @@ -84,8 +84,8 @@ fn ent_pc=0 n_params=0 variadic=false locals=4 block 13 start_pc=0 v53 ImmData(48) -> x0 v54 Imm(8) -> x1 - v55 BinopI { op=add, lhs=v53, rhs_imm=8 } -> x0 - v56 Load { addr=v55, disp=0, kind=F64 } -> d0 + v55 BinopI { op=add, lhs=v53, rhs_imm=8 } -> x1 + v56 Load { addr=v53, disp=8, kind=F64 } -> d0 v57 Imm(4611686018427387904) -> x0 v58 Binop { op=fne, lhs=v56, rhs=v57 } -> x1 v59 Imm(0) -> x0 diff --git a/tests/snapshots/ssa/init_scalar_conversion.ssa b/tests/snapshots/ssa/init_scalar_conversion.ssa index 30a7a63aa..ddf079a52 100644 --- a/tests/snapshots/ssa/init_scalar_conversion.ssa +++ b/tests/snapshots/ssa/init_scalar_conversion.ssa @@ -12,8 +12,8 @@ fn ent_pc=0 n_params=1 variadic=false locals=7 terminator Bz { cond=v4, target=b7, fall=b1 } (exit_acc=v4) block 1 start_pc=0 v6 LocalAddr(-4) -> x0 - v7 BinopI { op=add, lhs=v6, rhs_imm=8 } -> x0 - v8 Load { addr=v7, disp=0, kind=F64 } -> d0 + v7 BinopI { op=add, lhs=v6, rhs_imm=8 } -> x1 + v8 Load { addr=v6, disp=8, kind=F64 } -> d0 v9 Imm(0) -> x0 v10 Binop { op=feq, lhs=v8, rhs=v9 } -> x0 v11 BinopI { op=ne, lhs=v10, rhs_imm=0 } -> x2 @@ -27,8 +27,8 @@ fn ent_pc=0 n_params=1 variadic=false locals=7 terminator Bz { cond=v13, target=b8, fall=b3 } (exit_acc=v13) block 3 start_pc=0 v17 LocalAddr(-4) -> x0 - v18 BinopI { op=add, lhs=v17, rhs_imm=16 } -> x0 - v19 Load { addr=v18, disp=0, kind=F64 } -> d0 + v18 BinopI { op=add, lhs=v17, rhs_imm=16 } -> x1 + v19 Load { addr=v17, disp=16, kind=F64 } -> d0 v20 Imm(4650599933957636096) -> x0 v21 Binop { op=feq, lhs=v19, rhs=v20 } -> x0 v22 BinopI { op=ne, lhs=v21, rhs_imm=0 } -> x1 @@ -43,8 +43,8 @@ fn ent_pc=0 n_params=1 variadic=false locals=7 block 5 start_pc=0 v28 LocalAddr(-4) -> x0 v29 BinopI { op=add, lhs=v28, rhs_imm=16 } -> x1 - v30 BinopI { op=add, lhs=v28, rhs_imm=24 } -> x0 - v31 Load { addr=v30, disp=0, kind=F64 } -> d0 + v30 BinopI { op=add, lhs=v28, rhs_imm=24 } -> x1 + v31 Load { addr=v28, disp=24, kind=F64 } -> d0 v32 Imm(4647961106050973696) -> x0 v33 Binop { op=feq, lhs=v31, rhs=v32 } -> x0 v34 BinopI { op=ne, lhs=v33, rhs_imm=0 } -> x2 @@ -80,8 +80,8 @@ fn ent_pc=1 n_params=0 variadic=false locals=24 v12 LoadLocal { off=-2, kind=I32 } -> x0 v13 FpCast { kind=IntToFp, value=v3 } -> d0 v14 LocalAddr(-4) -> x0 - v15 BinopI { op=add, lhs=v14, rhs_imm=8 } -> x0 - v16 Store { addr=v15, disp=0, value=v13, kind=F64 } -> - + v15 BinopI { op=add, lhs=v14, rhs_imm=8 } -> x1 + v16 Store { addr=v14, disp=8, value=v13, kind=F64 } -> - v17 LocalAddr(-4) -> x0 v18 Load { addr=v17, disp=0, kind=F64 } -> d0 v19 Imm(4650599933957636096) -> x0 @@ -90,8 +90,8 @@ fn ent_pc=1 n_params=0 variadic=false locals=24 terminator Bnz { cond=v20, target=b25, fall=b1 } (exit_acc=v20) block 1 start_pc=0 v22 LocalAddr(-4) -> x0 - v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x0 - v24 Load { addr=v23, disp=0, kind=F64 } -> d0 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x1 + v24 Load { addr=v22, disp=8, kind=F64 } -> d0 v25 Imm(4647961106050973696) -> x0 v26 Binop { op=fne, lhs=v24, rhs=v25 } -> x13 v27 Imm(0) -> x0 @@ -112,21 +112,21 @@ fn ent_pc=1 n_params=0 variadic=false locals=24 v36 LocalAddr(-8) -> x0 v37 Store { addr=v36, disp=0, value=v35, kind=F64 } -> - v38 LocalAddr(-8) -> x0 - v39 BinopI { op=add, lhs=v38, rhs_imm=8 } -> x0 - v40 Store { addr=v39, disp=0, value=v35, kind=F64 } -> - + v39 BinopI { op=add, lhs=v38, rhs_imm=8 } -> x1 + v40 Store { addr=v38, disp=8, value=v35, kind=F64 } -> - v41 LoadLocal { off=-1, kind=I32 } -> x0 v42 FpCast { kind=IntToFp, value=v1 } -> d0 v43 LocalAddr(-8) -> x0 - v44 BinopI { op=add, lhs=v43, rhs_imm=16 } -> x0 - v45 Store { addr=v44, disp=0, value=v42, kind=F64 } -> - + v44 BinopI { op=add, lhs=v43, rhs_imm=16 } -> x1 + v45 Store { addr=v43, disp=16, value=v42, kind=F64 } -> - v46 LoadLocal { off=-2, kind=I32 } -> x0 v47 FpCast { kind=IntToFp, value=v3 } -> d0 v48 LocalAddr(-8) -> x0 - v49 BinopI { op=add, lhs=v48, rhs_imm=24 } -> x0 - v50 Store { addr=v49, disp=0, value=v47, kind=F64 } -> - + v49 BinopI { op=add, lhs=v48, rhs_imm=24 } -> x1 + v50 Store { addr=v48, disp=24, value=v47, kind=F64 } -> - v51 LocalAddr(-8) -> x0 - v52 BinopI { op=add, lhs=v51, rhs_imm=16 } -> x0 - v53 Load { addr=v52, disp=0, kind=F64 } -> d0 + v52 BinopI { op=add, lhs=v51, rhs_imm=16 } -> x1 + v53 Load { addr=v51, disp=16, kind=F64 } -> d0 v54 Imm(4650599933957636096) -> x0 v55 Binop { op=fne, lhs=v53, rhs=v54 } -> x13 v56 Imm(0) -> x0 @@ -134,8 +134,8 @@ fn ent_pc=1 n_params=0 variadic=false locals=24 block 5 start_pc=0 v57 LocalAddr(-8) -> x0 v58 BinopI { op=add, lhs=v57, rhs_imm=16 } -> x1 - v59 BinopI { op=add, lhs=v57, rhs_imm=24 } -> x0 - v60 Load { addr=v59, disp=0, kind=F64 } -> d0 + v59 BinopI { op=add, lhs=v57, rhs_imm=24 } -> x1 + v60 Load { addr=v57, disp=24, kind=F64 } -> d0 v61 Imm(4647961106050973696) -> x0 v62 Binop { op=fne, lhs=v60, rhs=v61 } -> x13 v63 Imm(0) -> x0 @@ -158,8 +158,8 @@ fn ent_pc=1 n_params=0 variadic=false locals=24 v74 LoadLocal { off=-2, kind=I32 } -> x0 v75 FpCast { kind=IntToFp, value=v3 } -> d0 v76 LocalAddr(-10) -> x0 - v77 BinopI { op=add, lhs=v76, rhs_imm=8 } -> x0 - v78 Store { addr=v77, disp=0, value=v75, kind=F64 } -> - + v77 BinopI { op=add, lhs=v76, rhs_imm=8 } -> x1 + v78 Store { addr=v76, disp=8, value=v75, kind=F64 } -> - v79 LocalAddr(-10) -> x0 v80 Imm(0) -> x1 v81 Load { addr=v79, disp=0, kind=F64 } -> d0 @@ -170,8 +170,8 @@ fn ent_pc=1 n_params=0 variadic=false locals=24 block 9 start_pc=0 v85 LocalAddr(-10) -> x0 v86 Imm(8) -> x1 - v87 BinopI { op=add, lhs=v85, rhs_imm=8 } -> x0 - v88 Load { addr=v87, disp=0, kind=F64 } -> d0 + v87 BinopI { op=add, lhs=v85, rhs_imm=8 } -> x1 + v88 Load { addr=v85, disp=8, kind=F64 } -> d0 v89 Imm(4647961106050973696) -> x0 v90 Binop { op=fne, lhs=v88, rhs=v89 } -> x13 v91 Imm(0) -> x0 @@ -268,18 +268,18 @@ fn ent_pc=1 n_params=0 variadic=false locals=24 v156 LocalAddr(-19) -> x0 v157 Store { addr=v156, disp=0, value=v155, kind=F64 } -> - v158 LocalAddr(-19) -> x0 - v159 BinopI { op=add, lhs=v158, rhs_imm=8 } -> x0 - v160 Store { addr=v159, disp=0, value=v155, kind=F64 } -> - + v159 BinopI { op=add, lhs=v158, rhs_imm=8 } -> x1 + v160 Store { addr=v158, disp=8, value=v155, kind=F64 } -> - v161 LoadLocal { off=-1, kind=I32 } -> x0 v162 FpCast { kind=IntToFp, value=v1 } -> d0 v163 LocalAddr(-19) -> x0 - v164 BinopI { op=add, lhs=v163, rhs_imm=16 } -> x0 - v165 Store { addr=v164, disp=0, value=v162, kind=F64 } -> - + v164 BinopI { op=add, lhs=v163, rhs_imm=16 } -> x1 + v165 Store { addr=v163, disp=16, value=v162, kind=F64 } -> - v166 LoadLocal { off=-2, kind=I32 } -> x0 v167 FpCast { kind=IntToFp, value=v3 } -> d0 v168 LocalAddr(-19) -> x0 - v169 BinopI { op=add, lhs=v168, rhs_imm=24 } -> x0 - v170 Store { addr=v169, disp=0, value=v167, kind=F64 } -> - + v169 BinopI { op=add, lhs=v168, rhs_imm=24 } -> x1 + v170 Store { addr=v168, disp=24, value=v167, kind=F64 } -> - v171 LocalAddr(-19) -> x7 v172 Call { target_pc=0, args=[v171], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 v173 BinopI { op=eq, lhs=v172, rhs_imm=0 } -> x0 diff --git a/tests/snapshots/ssa/mixed_sse_int_aggregate_args.ssa b/tests/snapshots/ssa/mixed_sse_int_aggregate_args.ssa index 04d4ed255..14b3bc870 100644 --- a/tests/snapshots/ssa/mixed_sse_int_aggregate_args.ssa +++ b/tests/snapshots/ssa/mixed_sse_int_aggregate_args.ssa @@ -43,8 +43,8 @@ fn ent_pc=0 n_params=5 variadic=false locals=9 terminator Bnz { cond=v23, target=b18, fall=b7 } (exit_acc=v23) block 7 start_pc=0 v25 LocalAddr(-4) -> x0 - v26 BinopI { op=add, lhs=v25, rhs_imm=8 } -> x0 - v27 Load { addr=v26, disp=0, kind=F64 } -> d1 + v26 BinopI { op=add, lhs=v25, rhs_imm=8 } -> x1 + v27 Load { addr=v25, disp=8, kind=F64 } -> d1 v28 Imm(4602678819172646912) -> x0 v29 Binop { op=fne, lhs=v27, rhs=v28 } -> x1 v30 Imm(0) -> x0 @@ -73,8 +73,8 @@ fn ent_pc=0 n_params=5 variadic=false locals=9 terminator Bnz { cond=v41, target=b19, fall=b13 } (exit_acc=v41) block 13 start_pc=0 v43 LocalAddr(-6) -> x0 - v44 BinopI { op=add, lhs=v43, rhs_imm=8 } -> x0 - v45 Load { addr=v44, disp=0, kind=F64 } -> d0 + v44 BinopI { op=add, lhs=v43, rhs_imm=8 } -> x1 + v45 Load { addr=v43, disp=8, kind=F64 } -> d0 v46 Imm(4616752568008179712) -> x0 v47 Binop { op=fne, lhs=v45, rhs=v46 } -> x1 v48 Imm(0) -> x0 @@ -135,16 +135,16 @@ fn ent_pc=2 n_params=0 variadic=false locals=11 v9 Imm(11) -> x1 v10 Store { addr=v8, disp=0, value=v9, kind=I64 } -> - v11 LocalAddr(-4) -> x0 - v12 BinopI { op=add, lhs=v11, rhs_imm=8 } -> x0 + v12 BinopI { op=add, lhs=v11, rhs_imm=8 } -> x1 v13 Imm(4602678819172646912) -> x1 - v14 Store { addr=v12, disp=0, value=v13, kind=F64 } -> - + v14 Store { addr=v11, disp=8, value=v13, kind=F64 } -> - v15 LocalAddr(-6) -> x0 v16 Imm(4615063718147915776) -> x1 v17 Store { addr=v15, disp=0, value=v16, kind=F64 } -> - v18 LocalAddr(-6) -> x0 - v19 BinopI { op=add, lhs=v18, rhs_imm=8 } -> x0 + v19 BinopI { op=add, lhs=v18, rhs_imm=8 } -> x1 v20 Imm(4616752568008179712) -> x1 - v21 Store { addr=v19, disp=0, value=v20, kind=F64 } -> - + v21 Store { addr=v18, disp=8, value=v20, kind=F64 } -> - v22 Imm(4) -> x7 v23 LocalAddr(-2) -> x6 v24 LocalAddr(-4) -> x2 diff --git a/tests/snapshots/ssa/mixed_struct_gpr_abi.ssa b/tests/snapshots/ssa/mixed_struct_gpr_abi.ssa index 5867a73e9..8008bfb61 100644 --- a/tests/snapshots/ssa/mixed_struct_gpr_abi.ssa +++ b/tests/snapshots/ssa/mixed_struct_gpr_abi.ssa @@ -10,8 +10,8 @@ fn ent_pc=0 n_params=2 variadic=false locals=2 v4 Load { addr=v3, disp=0, kind=I64 } -> x0 v5 FpCast { kind=IntToFp, value=v4 } -> d0 v6 LocalAddr(-2) -> x0 - v7 BinopI { op=add, lhs=v6, rhs_imm=8 } -> x0 - v8 Load { addr=v7, disp=0, kind=F64 } -> d1 + v7 BinopI { op=add, lhs=v6, rhs_imm=8 } -> x1 + v8 Load { addr=v6, disp=8, kind=F64 } -> d1 v9 Imm(4611686018427387904) -> x0 v10 Binop { op=fmul, lhs=v8, rhs=v9 } -> d2 v11 Fma { a=v8, b=v9, c=v5, neg_product=false, neg_addend=false } -> d0 @@ -62,8 +62,8 @@ fn ent_pc=1 n_params=7 variadic=false locals=2 v35 Load { addr=v34, disp=0, kind=I64 } -> x1 v36 Binop { op=add, lhs=v33, rhs=v35 } -> x0 v37 LocalAddr(-2) -> x1 - v38 BinopI { op=add, lhs=v37, rhs_imm=8 } -> x1 - v39 Load { addr=v38, disp=0, kind=F64 } -> d0 + v38 BinopI { op=add, lhs=v37, rhs_imm=8 } -> x2 + v39 Load { addr=v37, disp=8, kind=F64 } -> d0 v40 FpCast { kind=FpToInt, value=v39 } -> x1 v41 Binop { op=add, lhs=v36, rhs=v40 } -> x0 terminator Return(v41) (exit_acc=v41) diff --git a/tests/snapshots/ssa/negative_float_in_array_init.ssa b/tests/snapshots/ssa/negative_float_in_array_init.ssa index 63adac9c8..f5670eb3a 100644 --- a/tests/snapshots/ssa/negative_float_in_array_init.ssa +++ b/tests/snapshots/ssa/negative_float_in_array_init.ssa @@ -17,7 +17,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=2 v7 ImmData(40) -> x1 v8 Imm(8) -> x1 v9 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x1 - v10 Load { addr=v9, disp=0, kind=F64 } -> d0 + v10 Load { addr=v1, disp=8, kind=F64 } -> d0 v11 Imm(4612811918334230528) -> x1 v12 Fneg(v11) -> d1 v13 Binop { op=fne, lhs=v10, rhs=v12 } -> x1 @@ -29,7 +29,7 @@ fn ent_pc=1 n_params=0 variadic=false locals=2 v15 ImmData(40) -> x1 v16 Imm(16) -> x1 v17 BinopI { op=add, lhs=v1, rhs_imm=16 } -> x1 - v18 Load { addr=v17, disp=0, kind=F64 } -> d0 + v18 Load { addr=v1, disp=16, kind=F64 } -> d0 v19 Imm(4764320886503243776) -> x1 v20 Fneg(v19) -> d1 v21 Binop { op=fne, lhs=v18, rhs=v20 } -> x1 @@ -43,11 +43,11 @@ fn ent_pc=1 n_params=0 variadic=false locals=2 v25 Load { addr=v1, disp=0, kind=F64 } -> d0 v26 Imm(8) -> x1 v27 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x1 - v28 Load { addr=v27, disp=0, kind=F64 } -> d1 + v28 Load { addr=v1, disp=8, kind=F64 } -> d1 v29 Binop { op=fadd, lhs=v25, rhs=v28 } -> d0 v30 Imm(16) -> x1 - v31 BinopI { op=add, lhs=v1, rhs_imm=16 } -> x0 - v32 Load { addr=v31, disp=0, kind=F64 } -> d1 + v31 BinopI { op=add, lhs=v1, rhs_imm=16 } -> x1 + v32 Load { addr=v1, disp=16, kind=F64 } -> d1 v33 Binop { op=fadd, lhs=v29, rhs=v32 } -> d0 v34 Imm(0) -> x0 v35 LoadLocal { off=-1, kind=F64 } -> d1 diff --git a/tests/snapshots/ssa/out_pointer_return_float_args.ssa b/tests/snapshots/ssa/out_pointer_return_float_args.ssa index d18973dd7..4ddff7ed4 100644 --- a/tests/snapshots/ssa/out_pointer_return_float_args.ssa +++ b/tests/snapshots/ssa/out_pointer_return_float_args.ssa @@ -16,17 +16,17 @@ fn ent_pc=0 n_params=4 variadic=false locals=6 v10 LoadLocal { off=-1, kind=F32 } -> d4 [f32] v11 Store { addr=v9, disp=0, value=v1, kind=F32 } -> - v12 LocalAddr(-6) -> x0 - v13 BinopI { op=add, lhs=v12, rhs_imm=4 } -> x0 + v13 BinopI { op=add, lhs=v12, rhs_imm=4 } -> x1 v14 LoadLocal { off=-2, kind=F32 } -> d0 [f32] - v15 Store { addr=v13, disp=0, value=v3, kind=F32 } -> - + v15 Store { addr=v12, disp=4, value=v3, kind=F32 } -> - v16 LocalAddr(-6) -> x0 - v17 BinopI { op=add, lhs=v16, rhs_imm=8 } -> x0 + v17 BinopI { op=add, lhs=v16, rhs_imm=8 } -> x1 v18 LoadLocal { off=-3, kind=F32 } -> d0 [f32] - v19 Store { addr=v17, disp=0, value=v5, kind=F32 } -> - + v19 Store { addr=v16, disp=8, value=v5, kind=F32 } -> - v20 LocalAddr(-6) -> x0 - v21 BinopI { op=add, lhs=v20, rhs_imm=12 } -> x0 + v21 BinopI { op=add, lhs=v20, rhs_imm=12 } -> x1 v22 LoadLocal { off=-4, kind=F32 } -> d0 [f32] - v23 Store { addr=v21, disp=0, value=v7, kind=F32 } -> - + v23 Store { addr=v20, disp=12, value=v7, kind=F32 } -> - v24 LocalAddr(-6) -> x0 terminator Return(v24) (exit_acc=v24) ; --- SSA dump (ok=true) ent_pc=1 --- @@ -49,21 +49,21 @@ fn ent_pc=1 n_params=6 variadic=false locals=8 v12 LoadLocal { off=-1, kind=F32 } -> d0 [f32] v13 Store { addr=v11, disp=0, value=v12, kind=F32 } -> - v14 LocalAddr(-8) -> x0 - v15 BinopI { op=add, lhs=v14, rhs_imm=4 } -> x0 + v15 BinopI { op=add, lhs=v14, rhs_imm=4 } -> x1 v16 LoadLocal { off=-2, kind=F32 } -> d0 [f32] - v17 Store { addr=v15, disp=0, value=v16, kind=F32 } -> - + v17 Store { addr=v14, disp=4, value=v16, kind=F32 } -> - v18 LocalAddr(-8) -> x0 - v19 BinopI { op=add, lhs=v18, rhs_imm=8 } -> x0 + v19 BinopI { op=add, lhs=v18, rhs_imm=8 } -> x1 v20 LoadLocal { off=-3, kind=F32 } -> d0 [f32] - v21 Store { addr=v19, disp=0, value=v20, kind=F32 } -> - + v21 Store { addr=v18, disp=8, value=v20, kind=F32 } -> - v22 LocalAddr(-8) -> x0 - v23 BinopI { op=add, lhs=v22, rhs_imm=12 } -> x0 + v23 BinopI { op=add, lhs=v22, rhs_imm=12 } -> x1 v24 LoadLocal { off=-4, kind=F32 } -> d0 [f32] - v25 Store { addr=v23, disp=0, value=v24, kind=F32 } -> - + v25 Store { addr=v22, disp=12, value=v24, kind=F32 } -> - v26 LocalAddr(-8) -> x0 - v27 BinopI { op=add, lhs=v26, rhs_imm=16 } -> x0 + v27 BinopI { op=add, lhs=v26, rhs_imm=16 } -> x1 v28 LoadLocal { off=-5, kind=F32 } -> d0 [f32] - v29 Store { addr=v27, disp=0, value=v28, kind=F32 } -> - + v29 Store { addr=v26, disp=16, value=v28, kind=F32 } -> - v30 LoadLocal { off=2, kind=I64 } -> x0 v31 LocalAddr(-8) -> x1 v32 Mcpy { dst=v30, src=v31, size=20 } -> x1 @@ -78,13 +78,13 @@ fn ent_pc=2 n_params=4 variadic=false locals=3 v2 LoadLocal { off=3, kind=F64 } -> d0 v3 Store { addr=v1, disp=0, value=v2, kind=F64 } -> - v4 LocalAddr(-3) -> x0 - v5 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x0 + v5 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x1 v6 LoadLocal { off=4, kind=F64 } -> d0 - v7 Store { addr=v5, disp=0, value=v6, kind=F64 } -> - + v7 Store { addr=v4, disp=8, value=v6, kind=F64 } -> - v8 LocalAddr(-3) -> x0 - v9 BinopI { op=add, lhs=v8, rhs_imm=16 } -> x0 + v9 BinopI { op=add, lhs=v8, rhs_imm=16 } -> x1 v10 LoadLocal { off=5, kind=F64 } -> d0 - v11 Store { addr=v9, disp=0, value=v10, kind=F64 } -> - + v11 Store { addr=v8, disp=16, value=v10, kind=F64 } -> - v12 LoadLocal { off=2, kind=I64 } -> x0 v13 LocalAddr(-3) -> x1 v14 Mcpy { dst=v12, src=v13, size=24 } -> x1 @@ -116,8 +116,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=43 terminator Bnz { cond=v16, target=b25, fall=b1 } (exit_acc=v16) block 1 start_pc=0 v19 LocalAddr(-2) -> x0 - v20 BinopI { op=add, lhs=v19, rhs_imm=4 } -> x0 - v21 Load { addr=v20, disp=0, kind=F32 } -> d0 [f32] + v20 BinopI { op=add, lhs=v19, rhs_imm=4 } -> x1 + v21 Load { addr=v19, disp=4, kind=F32 } -> d0 [f32] v22 Imm(4611686018427387904) -> x0 v23 FpCast { kind=F32ToF64, value=v21 } -> d0 v24 Binop { op=fne, lhs=v23, rhs=v22 } -> x0 @@ -132,8 +132,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=43 terminator Bnz { cond=v27, target=b26, fall=b3 } (exit_acc=v27) block 3 start_pc=0 v31 LocalAddr(-2) -> x0 - v32 BinopI { op=add, lhs=v31, rhs_imm=8 } -> x0 - v33 Load { addr=v32, disp=0, kind=F32 } -> d0 [f32] + v32 BinopI { op=add, lhs=v31, rhs_imm=8 } -> x1 + v33 Load { addr=v31, disp=8, kind=F32 } -> d0 [f32] v34 Imm(4613937818241073152) -> x0 v35 FpCast { kind=F32ToF64, value=v33 } -> d0 v36 Binop { op=fne, lhs=v35, rhs=v34 } -> x0 @@ -147,8 +147,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=43 terminator Bnz { cond=v39, target=b27, fall=b5 } (exit_acc=v39) block 5 start_pc=0 v42 LocalAddr(-2) -> x0 - v43 BinopI { op=add, lhs=v42, rhs_imm=12 } -> x0 - v44 Load { addr=v43, disp=0, kind=F32 } -> d0 [f32] + v43 BinopI { op=add, lhs=v42, rhs_imm=12 } -> x1 + v44 Load { addr=v42, disp=12, kind=F32 } -> d0 [f32] v45 Imm(4616189618054758400) -> x0 v46 FpCast { kind=F32ToF64, value=v44 } -> d0 v47 Binop { op=fne, lhs=v46, rhs=v45 } -> x12 @@ -203,8 +203,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=43 terminator Bnz { cond=v87, target=b28, fall=b9 } (exit_acc=v87) block 9 start_pc=0 v90 LocalAddr(-7) -> x0 - v91 BinopI { op=add, lhs=v90, rhs_imm=4 } -> x0 - v92 Load { addr=v91, disp=0, kind=F32 } -> d0 [f32] + v91 BinopI { op=add, lhs=v90, rhs_imm=4 } -> x1 + v92 Load { addr=v90, disp=4, kind=F32 } -> d0 [f32] v93 Imm(4612811918334230528) -> x0 v94 FpCast { kind=F32ToF64, value=v92 } -> d0 v95 Binop { op=fne, lhs=v94, rhs=v93 } -> x0 @@ -219,8 +219,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=43 terminator Bnz { cond=v98, target=b29, fall=b11 } (exit_acc=v98) block 11 start_pc=0 v102 LocalAddr(-7) -> x0 - v103 BinopI { op=add, lhs=v102, rhs_imm=8 } -> x0 - v104 Load { addr=v103, disp=0, kind=F32 } -> d0 [f32] + v103 BinopI { op=add, lhs=v102, rhs_imm=8 } -> x1 + v104 Load { addr=v102, disp=8, kind=F32 } -> d0 [f32] v105 Imm(4615063718147915776) -> x0 v106 FpCast { kind=F32ToF64, value=v104 } -> d0 v107 Binop { op=fne, lhs=v106, rhs=v105 } -> x0 @@ -235,8 +235,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=43 terminator Bnz { cond=v110, target=b30, fall=b13 } (exit_acc=v110) block 13 start_pc=0 v114 LocalAddr(-7) -> x0 - v115 BinopI { op=add, lhs=v114, rhs_imm=12 } -> x0 - v116 Load { addr=v115, disp=0, kind=F32 } -> d0 [f32] + v115 BinopI { op=add, lhs=v114, rhs_imm=12 } -> x1 + v116 Load { addr=v114, disp=12, kind=F32 } -> d0 [f32] v117 Imm(4616752568008179712) -> x0 v118 FpCast { kind=F32ToF64, value=v116 } -> d0 v119 Binop { op=fne, lhs=v118, rhs=v117 } -> x0 @@ -250,8 +250,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=43 terminator Bnz { cond=v122, target=b31, fall=b15 } (exit_acc=v122) block 15 start_pc=0 v125 LocalAddr(-7) -> x0 - v126 BinopI { op=add, lhs=v125, rhs_imm=16 } -> x0 - v127 Load { addr=v126, disp=0, kind=F32 } -> d0 [f32] + v126 BinopI { op=add, lhs=v125, rhs_imm=16 } -> x1 + v127 Load { addr=v125, disp=16, kind=F32 } -> d0 [f32] v128 Imm(4617878467915022336) -> x0 v129 FpCast { kind=F32ToF64, value=v127 } -> d0 v130 Binop { op=fne, lhs=v129, rhs=v128 } -> x3 @@ -283,8 +283,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=43 terminator Bnz { cond=v147, target=b32, fall=b19 } (exit_acc=v147) block 19 start_pc=0 v150 LocalAddr(-13) -> x0 - v151 BinopI { op=add, lhs=v150, rhs_imm=8 } -> x0 - v152 Load { addr=v151, disp=0, kind=F64 } -> d0 + v151 BinopI { op=add, lhs=v150, rhs_imm=8 } -> x1 + v152 Load { addr=v150, disp=8, kind=F64 } -> d0 v153 Imm(4626322717216342016) -> x0 v154 Binop { op=fne, lhs=v152, rhs=v153 } -> x0 v155 BinopI { op=ne, lhs=v154, rhs_imm=0 } -> x2 @@ -297,8 +297,8 @@ fn ent_pc=3 n_params=0 variadic=false locals=43 terminator Bnz { cond=v157, target=b33, fall=b21 } (exit_acc=v157) block 21 start_pc=0 v160 LocalAddr(-13) -> x0 - v161 BinopI { op=add, lhs=v160, rhs_imm=16 } -> x0 - v162 Load { addr=v161, disp=0, kind=F64 } -> d0 + v161 BinopI { op=add, lhs=v160, rhs_imm=16 } -> x1 + v162 Load { addr=v160, disp=16, kind=F64 } -> d0 v163 Imm(4629137466983448576) -> x0 v164 Binop { op=fne, lhs=v162, rhs=v163 } -> x2 v165 Imm(0) -> x0 diff --git a/tests/snapshots/ssa/static_neg_infinity_init.ssa b/tests/snapshots/ssa/static_neg_infinity_init.ssa index 38b0540eb..ce2d4a0a9 100644 --- a/tests/snapshots/ssa/static_neg_infinity_init.ssa +++ b/tests/snapshots/ssa/static_neg_infinity_init.ssa @@ -42,8 +42,8 @@ fn ent_pc=14 n_params=0 variadic=false locals=1 terminator Return(v5) (exit_acc=v5) block 2 start_pc=0 v6 ImmData(16) -> x0 - v7 BinopI { op=add, lhs=v6, rhs_imm=8 } -> x0 - v8 Load { addr=v7, disp=0, kind=F64 } -> d0 + v7 BinopI { op=add, lhs=v6, rhs_imm=8 } -> x1 + v8 Load { addr=v6, disp=8, kind=F64 } -> d0 v9 Call { target_pc=13, args=[v8], fixed_args=1, fp_return=false, fp_arg_mask=0x1 } -> x0 v10 BinopI { op=eq, lhs=v9, rhs_imm=0 } -> x0 terminator Bz { cond=v10, target=b4, fall=b3 } (exit_acc=v10) diff --git a/tests/snapshots/ssa/struct_arg_indirect_subscript.ssa b/tests/snapshots/ssa/struct_arg_indirect_subscript.ssa index 04af1e852..bb5e9c2a3 100644 --- a/tests/snapshots/ssa/struct_arg_indirect_subscript.ssa +++ b/tests/snapshots/ssa/struct_arg_indirect_subscript.ssa @@ -62,8 +62,8 @@ fn ent_pc=1 n_params=2 variadic=false locals=2 v5 Imm(4616189618054758400) -> x0 v6 Binop { op=fmul, lhs=v4, rhs=v5 } -> d1 v7 LocalAddr(-2) -> x1 - v8 BinopI { op=add, lhs=v7, rhs_imm=8 } -> x1 - v9 Load { addr=v8, disp=0, kind=F64 } -> d1 + v8 BinopI { op=add, lhs=v7, rhs_imm=8 } -> x2 + v9 Load { addr=v7, disp=8, kind=F64 } -> d1 v10 Imm(4611686018427387904) -> x1 v11 Binop { op=fmul, lhs=v9, rhs=v10 } -> d1 v12 Fma { a=v4, b=v5, c=v11, neg_product=false, neg_addend=false } -> d0 diff --git a/tests/snapshots/ssa/two_d_float_array_partial_init.ssa b/tests/snapshots/ssa/two_d_float_array_partial_init.ssa index a74340323..0f3ca366b 100644 --- a/tests/snapshots/ssa/two_d_float_array_partial_init.ssa +++ b/tests/snapshots/ssa/two_d_float_array_partial_init.ssa @@ -159,11 +159,11 @@ fn ent_pc=1 n_params=0 variadic=false locals=8 v66 Load { addr=v64, disp=0, kind=F32 } -> d1 [f32] v67 Imm(4) -> x6 v68 BinopI { op=add, lhs=v64, rhs_imm=4 } -> x6 - v69 Load { addr=v68, disp=0, kind=F32 } -> d2 [f32] + v69 Load { addr=v64, disp=4, kind=F32 } -> d2 [f32] v70 Binop { op=fadd, lhs=v66, rhs=v69 } -> d1 [f32] v71 Imm(8) -> x6 - v72 BinopI { op=add, lhs=v64, rhs_imm=8 } -> x2 - v73 Load { addr=v72, disp=0, kind=F32 } -> d2 [f32] + v72 BinopI { op=add, lhs=v64, rhs_imm=8 } -> x6 + v73 Load { addr=v64, disp=8, kind=F32 } -> d2 [f32] v74 Binop { op=fadd, lhs=v70, rhs=v73 } -> d1 [f32] v75 Binop { op=fadd, lhs=v60, rhs=v74 } -> d0 [f32] v76 Store { addr=v59, disp=0, value=v75, kind=F32 } -> - diff --git a/tests/snapshots/ssa/two_d_stride_no_leak_across_exprs.ssa b/tests/snapshots/ssa/two_d_stride_no_leak_across_exprs.ssa index 58c2487c1..cee3c4bbe 100644 --- a/tests/snapshots/ssa/two_d_stride_no_leak_across_exprs.ssa +++ b/tests/snapshots/ssa/two_d_stride_no_leak_across_exprs.ssa @@ -66,8 +66,8 @@ fn ent_pc=2 n_params=0 variadic=false locals=163 block 6 start_pc=0 v37 LocalAddr(-161) -> x0 v38 Imm(32) -> x1 - v39 BinopI { op=add, lhs=v37, rhs_imm=32 } -> x0 - v40 Load { addr=v39, disp=0, kind=F32 } -> d0 [f32] + v39 BinopI { op=add, lhs=v37, rhs_imm=32 } -> x1 + v40 Load { addr=v37, disp=32, kind=F32 } -> d0 [f32] v41 Imm(4611686018427387904) -> x0 v42 FpCast { kind=F32ToF64, value=v40 } -> d0 v43 Binop { op=fne, lhs=v42, rhs=v41 } -> x0 diff --git a/tests/snapshots/ssa/unary_plus_init_and_param_shadow.ssa b/tests/snapshots/ssa/unary_plus_init_and_param_shadow.ssa index a0ad44dfe..2e5cba929 100644 --- a/tests/snapshots/ssa/unary_plus_init_and_param_shadow.ssa +++ b/tests/snapshots/ssa/unary_plus_init_and_param_shadow.ssa @@ -63,7 +63,7 @@ fn ent_pc=2 n_params=0 variadic=false locals=5 v9 ImmData(8) -> x0 v10 Imm(8) -> x0 v11 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x0 - v12 Load { addr=v11, disp=0, kind=F64 } -> d0 + v12 Load { addr=v1, disp=8, kind=F64 } -> d0 v13 Imm(4604480259023595110) -> x7 v14 Call { target_pc=0, args=[v12, v13], fixed_args=2, fp_return=false, fp_arg_mask=0x3 } -> x0 v15 BinopI { op=eq, lhs=v14, rhs_imm=0 } -> x0 @@ -75,7 +75,7 @@ fn ent_pc=2 n_params=0 variadic=false locals=5 v17 ImmData(8) -> x0 v18 Imm(16) -> x0 v19 BinopI { op=add, lhs=v1, rhs_imm=16 } -> x0 - v20 Load { addr=v19, disp=0, kind=F64 } -> d0 + v20 Load { addr=v1, disp=16, kind=F64 } -> d0 v21 Imm(4607182418800017408) -> x7 v22 Call { target_pc=0, args=[v20, v21], fixed_args=2, fp_return=false, fp_arg_mask=0x3 } -> x0 v23 BinopI { op=eq, lhs=v22, rhs_imm=0 } -> x0 @@ -87,7 +87,7 @@ fn ent_pc=2 n_params=0 variadic=false locals=5 v25 ImmData(8) -> x0 v26 Imm(24) -> x0 v27 BinopI { op=add, lhs=v1, rhs_imm=24 } -> x0 - v28 Load { addr=v27, disp=0, kind=F64 } -> d0 + v28 Load { addr=v1, disp=24, kind=F64 } -> d0 v29 Imm(4611686018427387904) -> x0 v30 Fneg(v29) -> d1 v31 Call { target_pc=0, args=[v28, v30], fixed_args=2, fp_return=false, fp_arg_mask=0x3 } -> x0 diff --git a/tests/snapshots/ssa/union_member_unbraced_init.ssa b/tests/snapshots/ssa/union_member_unbraced_init.ssa index efe072450..c22c61c12 100644 --- a/tests/snapshots/ssa/union_member_unbraced_init.ssa +++ b/tests/snapshots/ssa/union_member_unbraced_init.ssa @@ -131,8 +131,8 @@ fn ent_pc=0 n_params=0 variadic=false locals=15 block 24 start_pc=0 v78 ImmData(64) -> x0 v79 Imm(24) -> x1 - v80 BinopI { op=add, lhs=v78, rhs_imm=24 } -> x0 - v81 Load { addr=v80, disp=0, kind=F64 } -> d0 + v80 BinopI { op=add, lhs=v78, rhs_imm=24 } -> x1 + v81 Load { addr=v78, disp=24, kind=F64 } -> d0 v82 Imm(4616189618054758400) -> x0 v83 Binop { op=fne, lhs=v81, rhs=v82 } -> x1 v84 Imm(0) -> x0 diff --git a/tests/snapshots/ssa/variadic_agg_return_classes.ssa b/tests/snapshots/ssa/variadic_agg_return_classes.ssa index 71b34a066..28c1088ec 100644 --- a/tests/snapshots/ssa/variadic_agg_return_classes.ssa +++ b/tests/snapshots/ssa/variadic_agg_return_classes.ssa @@ -11,9 +11,9 @@ fn ent_pc=0 n_params=1 variadic=true locals=2 v5 Binop { op=fmul, lhs=v2, rhs=v4 } -> d0 v6 Store { addr=v1, disp=0, value=v5, kind=F64 } -> - v7 LocalAddr(-2) -> x0 - v8 BinopI { op=add, lhs=v7, rhs_imm=8 } -> x0 + v8 BinopI { op=add, lhs=v7, rhs_imm=8 } -> x1 v9 Imm(4612248968380809216) -> x1 - v10 Store { addr=v8, disp=0, value=v9, kind=F64 } -> - + v10 Store { addr=v7, disp=8, value=v9, kind=F64 } -> - v11 LocalAddr(-2) -> x0 terminator Return(v11) (exit_acc=v11) ; --- SSA dump (ok=true) ent_pc=1 --- @@ -53,8 +53,8 @@ fn ent_pc=2 n_params=0 variadic=false locals=15 terminator Bnz { cond=v9, target=b9, fall=b1 } (exit_acc=v9) block 1 start_pc=0 v11 LocalAddr(-2) -> x0 - v12 BinopI { op=add, lhs=v11, rhs_imm=8 } -> x0 - v13 Load { addr=v12, disp=0, kind=F64 } -> d0 + v12 BinopI { op=add, lhs=v11, rhs_imm=8 } -> x1 + v13 Load { addr=v11, disp=8, kind=F64 } -> d0 v14 Imm(4612248968380809216) -> x0 v15 Binop { op=fne, lhs=v13, rhs=v14 } -> x3 v16 Imm(0) -> x0 diff --git a/tests/snapshots/ssa/variadic_hfa_struct_arg.ssa b/tests/snapshots/ssa/variadic_hfa_struct_arg.ssa index 3bd2b0cf7..af2581bf9 100644 --- a/tests/snapshots/ssa/variadic_hfa_struct_arg.ssa +++ b/tests/snapshots/ssa/variadic_hfa_struct_arg.ssa @@ -17,8 +17,8 @@ fn ent_pc=0 n_params=1 variadic=true locals=5 v11 LocalAddr(-5) -> x0 v12 Load { addr=v11, disp=0, kind=F64 } -> d0 v13 LocalAddr(-5) -> x0 - v14 BinopI { op=add, lhs=v13, rhs_imm=8 } -> x0 - v15 Load { addr=v14, disp=0, kind=F64 } -> d1 + v14 BinopI { op=add, lhs=v13, rhs_imm=8 } -> x1 + v15 Load { addr=v13, disp=8, kind=F64 } -> d1 v16 Binop { op=fadd, lhs=v12, rhs=v15 } -> d0 terminator Return(v16) (exit_acc=v16) ; --- SSA dump (ok=true) ent_pc=1 --- @@ -31,9 +31,9 @@ fn ent_pc=1 n_params=0 variadic=false locals=5 v2 Imm(4609434218613702656) -> x1 v3 Store { addr=v1, disp=0, value=v2, kind=F64 } -> - v4 LocalAddr(-2) -> x0 - v5 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x0 + v5 BinopI { op=add, lhs=v4, rhs_imm=8 } -> x1 v6 Imm(4612248968380809216) -> x1 - v7 Store { addr=v5, disp=0, value=v6, kind=F64 } -> - + v7 Store { addr=v4, disp=8, value=v6, kind=F64 } -> - v8 Imm(1) -> x7 v9 LocalAddr(-2) -> x6 v10 Call { target_pc=0, args=[v8, v9], fixed_args=1, fp_return=true, fp_arg_mask=0x0 } -> d0 From 60f728631e22386c4c28e945ad353784ce3e643b Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 01:33:22 -0700 Subject: [PATCH 61/67] tests: normalize CRLF in the auto-include printf assertion The Windows CRT emits \r\n for \n on stdout, so the exact-bytes comparison failed on the Windows lanes; strip CR before comparing. Co-Authored-By: Claude Fable 5 --- tests/cli_linker_smoke.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/cli_linker_smoke.rs b/tests/cli_linker_smoke.rs index c8a7277b7..c86cf297a 100644 --- a/tests/cli_linker_smoke.rs +++ b/tests/cli_linker_smoke.rs @@ -2972,5 +2972,10 @@ fn link_defined_symbol_wins_over_auto_included_binding() { ); let out = Command::new(&exe2).output().expect("run prog2"); assert_eq!(out.status.code(), Some(0), "auto-included printf runs"); - assert_eq!(String::from_utf8_lossy(&out.stdout), "hi\n"); + // The Windows CRT translates `\n` to `\r\n` on stdout; strip CR so + // the comparison holds on every host. + assert_eq!( + String::from_utf8_lossy(&out.stdout).replace('\r', ""), + "hi\n" + ); } From 6a001847c7d3244eb6aa7005828e958873acb047 Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 01:33:45 -0700 Subject: [PATCH 62/67] object/linker: honor PE executable exports, drop bogus Mach-O data-import symbol, harden silent fallbacks #340: --export-all/--export-data now reach PE executables. `.edata` is emitted whenever the image exports anything (pragma set or an executable's dynamic exports), and the export directory resolves each name to its runtime RVA (text or data). Previously the flags no-op'd for PE executables so GetProcAddress returned NULL for every host symbol. #341: a Mach-O data import (bound through the GOT, no PLT trampoline) no longer gets a local text symbol at code offset 0 (the first function's address), which mislabeled backtraces and breakpoints. `Build`'s per-import trampoline offsets become `Vec>` so the writers key each local symbol by import index, not by an ordering contract the synth path does not uphold; a `None` slot emits no text symbol. #333: convert five silent fallbacks to diagnostics. * pe.rs pad_to overshoot -> hard error (layout-drift guard, replacing a release-compiled-out debug_assert). * elf.rs export whose ent_pc misses pc_to_native -> error, matching the Mach-O/PE writers instead of dropping it from .dynsym. * mach_o.rs __tlv_bootstrap ordinal via one shared helper for the bind stream and the nlist entry; error when no linked dylib is libSystem rather than guessing ordinal 1. * synth_build.rs import->dylib routing miss defaults to 0 only for a flat-lookup import or a single-dylib image; a miss with several dylibs is an error, not a silent misroute. * link.rs merged import->dylib map rejects a cross-unit routing conflict and a per-unit dylib index out of range instead of first-writer-wins + unwrap_or(0). Regression tests: macho_data_import_gets_no_bogus_local_text_symbol (tests/linker.rs), plus writer/unit tests for each guard. Co-Authored-By: Claude Opus 4.8 --- src/c5/codegen/aarch64/encode.rs | 4 +- src/c5/codegen/mod.rs | 6 +- src/c5/codegen/x86_64/encode.rs | 4 +- src/c5/linker/link.rs | 92 ++++++++-- src/c5/linker/synth_build.rs | 155 ++++++++++++----- src/c5/object/dwarf.rs | 37 ++-- src/c5/object/elf.rs | 71 ++++++-- src/c5/object/mach_o.rs | 115 ++++++------ src/c5/object/pe.rs | 289 ++++++++++++++++++++++++------- src/c5/tests/linker.rs | 90 ++++++++++ 10 files changed, 667 insertions(+), 196 deletions(-) diff --git a/src/c5/codegen/aarch64/encode.rs b/src/c5/codegen/aarch64/encode.rs index 7bcb1c3fc..89e478f14 100644 --- a/src/c5/codegen/aarch64/encode.rs +++ b/src/c5/codegen/aarch64/encode.rs @@ -1900,7 +1900,9 @@ pub(crate) fn lower( // Overwritten by `lower_for` from `NativeOptions::debug_info`. debug_info: true, merged_dwarf: None, - plt_trampoline_offsets, + // Every import on this single-TU path gets a trampoline (data + // imports ride `ResolvedImports::data_bindings`, not `imports`). + plt_trampoline_offsets: plt_trampoline_offsets.into_iter().map(Some).collect(), }) } diff --git a/src/c5/codegen/mod.rs b/src/c5/codegen/mod.rs index 3b3fb6600..5f65ebbcc 100644 --- a/src/c5/codegen/mod.rs +++ b/src/c5/codegen/mod.rs @@ -1441,7 +1441,9 @@ pub(crate) struct Build { /// trampoline. Indexed by `ResolvedImports::imports` slot -- /// `plt_trampoline_offsets[i]` is the local code address the /// per-format writer should expose as `imports[i].local_name` - /// in the static symbol table. + /// in the static symbol table. `None` for an import with no + /// trampoline (a data import bound through the GOT/IAT); the + /// writers must not synthesize a text symbol for those. /// /// Each trampoline is a tiny GOT/IAT-load + tail-jump (3 /// instructions on aarch64 / 1 instruction on x86_64) that @@ -1451,7 +1453,7 @@ pub(crate) struct Build { /// the GOT load -- so a debugger's `b malloc` resolves /// against this in-image local symbol rather than getting /// lost in the dynamic linker's macro-expansion sites. - pub plt_trampoline_offsets: Vec, + pub plt_trampoline_offsets: Vec>, /// Post-prologue native byte offset of each function, keyed by /// `ent_pc`. The SSA emit records `code.len()` right after the /// prologue; the DWARF CFI pass turns the value into the FDE's diff --git a/src/c5/codegen/x86_64/encode.rs b/src/c5/codegen/x86_64/encode.rs index 30c21dbde..70f8ca8de 100644 --- a/src/c5/codegen/x86_64/encode.rs +++ b/src/c5/codegen/x86_64/encode.rs @@ -2342,7 +2342,9 @@ pub(crate) fn lower( // Overwritten by `lower_for` from `NativeOptions::debug_info`. debug_info: true, merged_dwarf: None, - plt_trampoline_offsets, + // Every import on this single-TU path gets a trampoline (data + // imports ride `ResolvedImports::data_bindings`, not `imports`). + plt_trampoline_offsets: plt_trampoline_offsets.into_iter().map(Some).collect(), }) } diff --git a/src/c5/linker/link.rs b/src/c5/linker/link.rs index 315c883b2..b512f1d0e 100644 --- a/src/c5/linker/link.rs +++ b/src/c5/linker/link.rs @@ -1052,23 +1052,43 @@ pub fn link_native_objects_with_options( } // Build the merged import->dylib map. Each unit's per-import // dylib_index is local to that unit's `dylibs` list; translate - // through `merged_idx_for[unit_idx][per_unit_idx]` so the value - // refers to the merged `dylibs` order. First entry per import - // name wins -- a sibling unit redeclaring the same name picks - // up the same dylib through cross-TU resolution anyway. + // through `local_to_merged` so the value refers to the merged + // `dylibs` order. Two units routing the same import to different + // dylibs is a conflict: whichever entry won, the loser's calls + // would bind against the wrong library, so reject it. let mut import_dylib_map: BTreeMap = BTreeMap::new(); - for obj in objs { + for (i, obj) in objs.iter().enumerate() { let mut local_to_merged: Vec = Vec::with_capacity(obj.dylibs.len()); for d in &obj.dylibs { - let merged_idx = dylibs.iter().position(|m| m == d).unwrap_or(0) as u32; + // The merged list was built from these same entries above, + // so the position lookup cannot miss. + let merged_idx = dylibs + .iter() + .position(|m| m == d) + .expect("merged dylib list contains every per-unit path") + as u32; local_to_merged.push(merged_idx); } for (name, idx) in &obj.import_dylib_map { - if import_dylib_map.contains_key(name) { - continue; + let merged_idx = local_to_merged.get(*idx as usize).copied().ok_or_else(|| { + link_err(&format!( + "object {i}: import `{name}` routes to dylib index {idx} \ + out of range ({} dylibs declared)", + obj.dylibs.len(), + )) + })?; + match import_dylib_map.get(name) { + None => { + import_dylib_map.insert(name.clone(), merged_idx); + } + Some(&prev) if prev == merged_idx => {} + Some(&prev) => { + return Err(link_err(&format!( + "import `{name}` routed to `{}` by one object and `{}` by another", + dylibs[prev as usize], dylibs[merged_idx as usize], + ))); + } } - let merged_idx = local_to_merged.get(*idx as usize).copied().unwrap_or(0); - import_dylib_map.insert(name.clone(), merged_idx); } } @@ -2603,6 +2623,58 @@ mod tests { ); } + /// Two objects routing the same import name to different dylibs is a + /// conflict; first-writer-wins previously bound the loser's calls + /// against the wrong library with no diagnostic. + #[test] + fn conflicting_import_dylib_routing_errors() { + let mk = |dylib: &str| NativeObject { + machine: NativeMachine::X86_64, + text: alloc::vec::Vec::new(), + data: alloc::vec::Vec::new(), + data_align: 1, + bss_size: 0, + tls_data: alloc::vec::Vec::new(), + tls_bss_size: 0, + symbols: alloc::vec::Vec::new(), + text_relocs: alloc::vec::Vec::new(), + data_relocs: alloc::vec::Vec::new(), + dylibs: alloc::vec![dylib.to_string()], + import_dylib_map: alloc::vec![("f".to_string(), 0u32)], + exports: alloc::vec::Vec::new(), + tls_index_fixups: alloc::vec::Vec::new(), + macho_tlv_descriptors: alloc::vec::Vec::new(), + macho_tlv_fixups: alloc::vec::Vec::new(), + tls_symbols: alloc::vec::Vec::new(), + macho_tlv_descriptor_syms: alloc::vec::Vec::new(), + elf_tpoff_fixups: alloc::vec::Vec::new(), + copy_relocs: alloc::vec::Vec::new(), + debug_info: alloc::vec::Vec::new(), + debug_abbrev: alloc::vec::Vec::new(), + debug_line: alloc::vec::Vec::new(), + debug_str: alloc::vec::Vec::new(), + debug_info_relocs: alloc::vec::Vec::new(), + debug_line_relocs: alloc::vec::Vec::new(), + }; + // Same routing across units links fine. + let merged = link_native_objects(&[mk("libA.so"), mk("libA.so")]).expect("consistent"); + assert_eq!(merged.import_dylib_map.get("f"), Some(&0)); + // Divergent routing errors and names both libraries. + let err = link_native_objects(&[mk("libA.so"), mk("libB.so")]).unwrap_err(); + assert!( + err.to_string().contains("libA.so") && err.to_string().contains("libB.so"), + "error must name both dylibs: {err}" + ); + // A per-unit dylib index past the unit's dylib list errors. + let mut bad = mk("libA.so"); + bad.import_dylib_map = alloc::vec![("f".to_string(), 5u32)]; + let err = link_native_objects(&[bad]).unwrap_err(); + assert!( + err.to_string().contains("out of range"), + "expected an index diagnostic, got: {err}" + ); + } + fn compile_native(src: &str, target: Target, opts: NativeOptions) -> NativeObject { let program = Compiler::new(src.to_string()).compile().expect("compile"); let bytes = emit_native_with_options(&program, target, opts).expect("emit"); diff --git a/src/c5/linker/synth_build.rs b/src/c5/linker/synth_build.rs index af7491755..06935bc1f 100644 --- a/src/c5/linker/synth_build.rs +++ b/src/c5/linker/synth_build.rs @@ -124,14 +124,14 @@ fn synth_program_and_build( } else { resolve_entry_offset(merged, entry_name)? }; - let imports = synth_imports(merged, target); + let imports = synth_imports(merged, target)?; let SynthFixups { got: got_fixups, data: data_fixups, func: func_fixups, } = synth_fixups(merged, plt)?; let (data_relocs, code_relocs) = synth_relocs(merged); - let plt_trampoline_offsets = synth_plt_offsets(merged, plt); + let plt_trampoline_offsets = synth_plt_offsets(merged, plt)?; let exports = synth_exports(merged, export_all, output_kind); let pc_to_native = synth_pc_to_native(&merged.text, &code_relocs, &exports); @@ -295,17 +295,20 @@ fn synth_program_and_build( // dynamically loaded module resolves them (a Python C extension // binding `PyFloat_Type` and the rest of the C-API against the // interpreter executable). macOS publishes every global of every - // executable through the Mach-O symtab. ELF splits the same coverage - // across two flags matching the system toolchain's `-rdynamic`: - // `--export-all` adds functions (STT_FUNC), `--export-data` adds data - // globals (STT_OBJECT). Both gate the export because it widens the - // global symbol scope. Resolved from `merged.defined` at link time; - // shared libraries use `exports`, and the PE writer ignores the field. + // executable through the Mach-O symtab. ELF and PE split the same + // coverage across two flags matching the toolchain's `-rdynamic`: + // `--export-all` adds functions (STT_FUNC / .edata name), + // `--export-data` adds data globals (STT_OBJECT / .edata name). Both + // gate the export because it widens the global symbol scope. Resolved + // from `merged.defined` at link time; shared libraries use `exports`. let is_exec = output_kind == OutputKind::Executable; let macos_exec = target == Target::MacOSAarch64 && is_exec; - let elf_exec = matches!(target, Target::LinuxX64 | Target::LinuxAarch64) && is_exec; - let export_funcs = macos_exec || (elf_exec && export_all); - let export_data_globals = macos_exec || (elf_exec && export_data); + let flagged_exec = matches!( + target, + Target::LinuxX64 | Target::LinuxAarch64 | Target::WindowsX64 | Target::WindowsAarch64 + ) && is_exec; + let export_funcs = macos_exec || (flagged_exec && export_all); + let export_data_globals = macos_exec || (flagged_exec && export_data); let dynamic_exports: Vec = if export_funcs || export_data_globals { merged .defined @@ -476,7 +479,7 @@ fn resolve_entry_offset(merged: &MergedNative, entry_name: &str) -> Result ResolvedImports { +fn synth_imports(merged: &MergedNative, target: Target) -> Result { // `merged.dylibs` holds each `#pragma dylib` path the input // units recorded (in declaration order, deduped). When a // unit was produced before the `.badc.dylibs` section landed @@ -506,11 +509,27 @@ fn synth_imports(merged: &MergedNative, target: Target) -> ResolvedImports { .iter() .map(|(local, host)| (local.as_str(), host.as_str())) .collect(); - let imports: Vec = merged - .imports - .iter() - .enumerate() - .map(|(i, name)| ResolvedImport { + let mut imports: Vec = Vec::with_capacity(merged.imports.len()); + for (i, name) in merged.imports.iter().enumerate() { + let flat_lookup = merged.flat_imports.contains(name); + // `import_dylib_map` carries the per-import dylib assignment the + // .o writer recorded. A miss is defaulted to dylib 0 only when + // nothing hangs on the choice: a flat-lookup import binds through + // the loader's global scope (the ordinal is unread), and a + // single-dylib image (including the legacy-`.o` default fallback + // above) leaves one library to route to. With several dylibs a + // miss would silently bind the call to the wrong library, so fail. + let dylib_index = match merged.import_dylib_map.get(name) { + Some(&idx) => idx as usize, + None if flat_lookup || dylibs.len() <= 1 => 0, + None => { + return Err(synth_err(&alloc::format!( + "import `{name}` carries no dylib routing ({} dylibs in the image)", + dylibs.len(), + ))); + } + }; + imports.push(ResolvedImport { binding_idx: i as i64, // The .o writer stores each libc import under its // per-target `real_symbol` (the name the dynamic @@ -527,33 +546,27 @@ fn synth_imports(merged: &MergedNative, target: Target) -> ResolvedImports { // the host's exported `_name`; ELF uses the name verbatim. real_symbol: if let Some(host) = data_binding_hosts.get(name.as_str()) { (*host).to_string() - } else if merged.flat_imports.contains(name) && target == Target::MacOSAarch64 { + } else if flat_lookup && target == Target::MacOSAarch64 { alloc::format!("_{name}") } else { name.clone() }, - // `import_dylib_map` carries the per-import dylib - // assignment the .o writer recorded. An import - // missing from the map falls back to dylib 0 (the - // first dylib in the merge) so legacy `.o` files - // produced before NT_BADC_BINDING_MAP landed still - // round-trip. - dylib_index: merged.import_dylib_map.get(name).copied().unwrap_or(0) as usize, - flat_lookup: merged.flat_imports.contains(name), + dylib_index, + flat_lookup, is_variadic: false, fixed_args: 0, return_type_tag: 0, returns_long_double: false, param_types: Vec::new(), - }) - .collect(); + }); + } // Data bindings are surfaced separately, from the merged // `.note.badc` copy-reloc records (see `synth_data_copy_relocs`). - ResolvedImports { + Ok(ResolvedImports { imports, dylibs, data_bindings: Vec::new(), - } + }) } fn default_dylib(target: Target) -> ResolvedDylib { @@ -925,14 +938,26 @@ fn synth_exports( exports } -fn synth_plt_offsets(merged: &MergedNative, plt: &[PltTrampoline]) -> Vec { - let mut offsets = alloc::vec![0usize; merged.imports.len()]; +/// Per-import trampoline offsets aligned with `merged.imports`. +/// `None` for an import no trampoline was emitted for (a data import +/// bound through the GOT/IAT), so a writer never fabricates a text +/// symbol at the slot's default offset for it. +fn synth_plt_offsets( + merged: &MergedNative, + plt: &[PltTrampoline], +) -> Result>, C5Error> { + let mut offsets = alloc::vec![None; merged.imports.len()]; for t in plt { - if t.import_index < offsets.len() { - offsets[t.import_index] = t.text_offset; + if t.import_index >= offsets.len() { + return Err(synth_err(&alloc::format!( + "PLT trampoline references import index {} out of range ({} imports)", + t.import_index, + offsets.len(), + ))); } + offsets[t.import_index] = Some(t.text_offset); } - offsets + Ok(offsets) } fn synth_err(msg: &str) -> C5Error { @@ -1027,7 +1052,7 @@ mod tests { // target's `real_symbol` from `#pragma binding`; the // synthesizer passes the name through verbatim. merged.imports = alloc::vec!["_malloc".to_string()]; - let imports = synth_imports(&merged, Target::MacOSAarch64); + let imports = synth_imports(&merged, Target::MacOSAarch64).expect("synth"); assert_eq!(imports.dylibs.len(), 1); assert!( imports.dylibs[0].path.contains("libSystem"), @@ -1042,7 +1067,7 @@ mod tests { fn synth_imports_no_underscore_for_linux() { let mut merged = tiny_aarch64_main(); merged.imports = alloc::vec!["malloc".to_string()]; - let imports = synth_imports(&merged, Target::LinuxAarch64); + let imports = synth_imports(&merged, Target::LinuxAarch64).expect("synth"); assert_eq!(imports.imports[0].real_symbol, "malloc"); } @@ -1055,14 +1080,66 @@ mod tests { let mut merged = tiny_aarch64_main(); merged.imports = alloc::vec!["JS_ToIndex".to_string()]; merged.flat_imports.insert("JS_ToIndex".to_string()); - let mac = synth_imports(&merged, Target::MacOSAarch64); + let mac = synth_imports(&merged, Target::MacOSAarch64).expect("synth"); assert!(mac.imports[0].flat_lookup, "must be flat-lookup on macOS"); assert_eq!(mac.imports[0].real_symbol, "_JS_ToIndex"); - let elf = synth_imports(&merged, Target::LinuxAarch64); + let elf = synth_imports(&merged, Target::LinuxAarch64).expect("synth"); assert!(elf.imports[0].flat_lookup, "must be flat-lookup on ELF"); assert_eq!(elf.imports[0].real_symbol, "JS_ToIndex"); } + /// A non-flat import missing from the routing map is defaulted to + /// dylib 0 only when a single dylib leaves no choice; with several + /// dylibs the old `unwrap_or(0)` silently misrouted the binding. + #[test] + fn synth_imports_unmapped_routing() { + let mut merged = tiny_aarch64_main(); + merged.imports = alloc::vec!["puts".to_string()]; + merged.dylibs = alloc::vec!["/usr/lib/libSystem.B.dylib".to_string()]; + let single = synth_imports(&merged, Target::MacOSAarch64).expect("single dylib routes"); + assert_eq!(single.imports[0].dylib_index, 0); + + merged.dylibs.push("/usr/lib/libother.dylib".to_string()); + let err = synth_imports(&merged, Target::MacOSAarch64).expect_err("ambiguous miss"); + assert!( + alloc::format!("{err}").contains("puts"), + "error must name the import: {err}" + ); + + // A flat-lookup import binds through the loader's global scope; + // the ordinal is unread, so the miss is fine. + merged.flat_imports.insert("puts".to_string()); + let flat = synth_imports(&merged, Target::MacOSAarch64).expect("flat import routes"); + assert!(flat.imports[0].flat_lookup); + + // A mapped import routes as recorded. + merged.flat_imports.clear(); + merged.import_dylib_map.insert("puts".to_string(), 1); + let mapped = synth_imports(&merged, Target::MacOSAarch64).expect("mapped"); + assert_eq!(mapped.imports[0].dylib_index, 1); + } + + /// `synth_plt_offsets` keeps a `None` slot for an import without a + /// trampoline (a data import) so no writer fabricates a text symbol + /// at the slot's default offset for it. + #[test] + fn synth_plt_offsets_leaves_untrampolined_imports_none() { + let mut merged = tiny_aarch64_main(); + merged.imports = alloc::vec!["environ".to_string(), "malloc".to_string()]; + let plt = alloc::vec![PltTrampoline { + text_offset: 0x40, + import_index: 1, + }]; + let offsets = synth_plt_offsets(&merged, &plt).expect("offsets"); + assert_eq!(offsets, alloc::vec![None, Some(0x40)]); + + let bad = alloc::vec![PltTrampoline { + text_offset: 0x40, + import_index: 7, + }]; + assert!(synth_plt_offsets(&merged, &bad).is_err()); + } + #[test] fn synth_exports_resolves_pragma_export_names_only() { // synth_exports promotes the `#pragma export` union diff --git a/src/c5/object/dwarf.rs b/src/c5/object/dwarf.rs index b24cb18dc..9b23d024d 100644 --- a/src/c5/object/dwarf.rs +++ b/src/c5/object/dwarf.rs @@ -534,8 +534,10 @@ fn prologue_size_for(ent_pc: usize, low_pc: usize, build: &Build) -> u32 { fn end_of_user_text(build: &Build) -> usize { build .plt_trampoline_offsets - .first() + .iter() .copied() + .flatten() + .min() .unwrap_or(build.text.len()) } @@ -564,7 +566,13 @@ fn collect_plt_subprograms( build.plt_trampoline_offsets.len(), "trampoline-offset count must match import count" ); - let n = imports.len(); + // A data import (bound through the GOT) has no trampoline + // (`None` slot) and gets no stub DIE. + let stubbed: Vec<(&super::ResolvedImport, usize)> = imports + .iter() + .zip(build.plt_trampoline_offsets.iter()) + .filter_map(|(imp, off)| off.map(|o| (imp, o))) + .collect(); // Per-stub size. Trampolines are emitted contiguously and // are uniform-sized per arch, so the delta between two // consecutive offsets is exact. The last-stub-to-text-end @@ -574,10 +582,10 @@ fn collect_plt_subprograms( // `build.text.len() - offsets.last()` overshoots by the // marker bytes (the overshoot was visible as DW_AT_high_pc // = 0x1f instead of 0xc on the linked_list fixture). - let stub_size = if n >= 2 { - (build.plt_trampoline_offsets[1] - build.plt_trampoline_offsets[0]) as u64 + let stub_size = if stubbed.len() >= 2 { + (stubbed[1].1 - stubbed[0].1) as u64 } else { - // Single import: fall back to the per-arch constant. Has + // Single stub: fall back to the per-arch constant. Has // to match `super::aarch64::emit_plt_trampolines` // (3 instructions = 12 bytes) / // `super::x86_64::emit_plt_trampolines` (1 jmp = 6 @@ -588,11 +596,9 @@ fn collect_plt_subprograms( } }; - imports + stubbed .iter() - .enumerate() - .map(|(i, imp)| { - let off = build.plt_trampoline_offsets[i]; + .map(|&(imp, off)| { // Synthetic per-param names: `arg0`, `arg1`, ... The // c5 binding doesn't track parameter names, but // gdb's `info args` and `bt` skip name-less entries @@ -2229,7 +2235,12 @@ impl DebugFrameFdeHeader { /// `build.text` by `emit_plt_trampolines`, so the range is /// `[code_vmaddr + offsets[0], code_vmaddr + build.text.len())`. fn plt_pool_range(build: &Build, code_vmaddr: u64) -> Option<(u64, u64)> { - let first = build.plt_trampoline_offsets.first().copied()?; + let first = build + .plt_trampoline_offsets + .iter() + .copied() + .flatten() + .min()?; let start = code_vmaddr + first as u64; let end = code_vmaddr + build.text.len() as u64; if end > start { @@ -2921,7 +2932,7 @@ mod tests { assert_eq!(plt_pool_range(&build, 0x1000), None); // Once a trampoline is recorded, the range covers from the // first stub byte to the end of `build.text`. - build.plt_trampoline_offsets = alloc::vec![0xc0, 0xcc]; + build.plt_trampoline_offsets = alloc::vec![Some(0xc0), Some(0xcc)]; build.text.extend(alloc::vec![0u8; 0x40]); // pretend trampolines are appended assert_eq!(plt_pool_range(&build, 0x1000), Some((0x10c0, 0x1140))); } @@ -3003,7 +3014,7 @@ mod tests { let build = Build { copy_relocs: Default::default(), text, - plt_trampoline_offsets: alloc::vec![0xc0, 0xcc], + plt_trampoline_offsets: alloc::vec![Some(0xc0), Some(0xcc)], imports, ..Build::default() }; @@ -3090,7 +3101,7 @@ mod tests { let mut build = Build { copy_relocs: Default::default(), text: alloc::vec![0u8; 0x200], - plt_trampoline_offsets: alloc::vec![0x180, 0x18c, 0x198], + plt_trampoline_offsets: alloc::vec![Some(0x180), Some(0x18c), Some(0x198)], ..Build::default() }; assert_eq!(end_of_user_text(&build), 0x180); diff --git a/src/c5/object/elf.rs b/src/c5/object/elf.rs index 747d833fe..f9c8c35c2 100644 --- a/src/c5/object/elf.rs +++ b/src/c5/object/elf.rs @@ -656,14 +656,22 @@ fn build_plt_symtab( build.plt_trampoline_offsets.len(), "trampoline-offset count must match import count" ); + // A data import (bound through the GOT) has no trampoline + // (`None` slot); a text symbol for it would mislabel whatever + // code sits at the fabricated address. + let plt_locals: Vec<(&str, usize)> = imports + .iter() + .zip(build.plt_trampoline_offsets.iter()) + .filter_map(|(imp, off)| off.map(|o| (imp.local_name.as_str(), o))) + .collect(); // .strtab: leading NUL (st_name=0 -> empty string sentinel) // followed by NUL-separated import names. let mut strtab = alloc::vec![0u8]; - let mut name_offsets: Vec = Vec::with_capacity(imports.len()); - for imp in imports { + let mut name_offsets: Vec = Vec::with_capacity(plt_locals.len()); + for &(name, _) in &plt_locals { name_offsets.push(strtab.len() as u32); - strtab.extend_from_slice(imp.local_name.as_bytes()); + strtab.extend_from_slice(name.as_bytes()); strtab.push(0); } @@ -671,7 +679,7 @@ fn build_plt_symtab( // STT_FUNC per trampoline. Local symbols come first by spec // (the .symtab section header's `sh_info` field points one // past the last local entry). - let mut symtab: Vec = Vec::with_capacity((1 + imports.len()) * ELF64_SYM_SIZE as usize); + let mut symtab: Vec = Vec::with_capacity((1 + plt_locals.len()) * ELF64_SYM_SIZE as usize); write_struct( &mut symtab, &Elf64Sym { @@ -683,9 +691,8 @@ fn build_plt_symtab( st_size: 0, }, ); - for (i, imp) in imports.iter().enumerate() { - let _ = imp; - let st_value = text_vmaddr + build.plt_trampoline_offsets[i] as u64; + for (i, &(_, tramp_offset)) in plt_locals.iter().enumerate() { + let st_value = text_vmaddr + tramp_offset as u64; write_struct( &mut symtab, &Elf64Sym { @@ -719,7 +726,13 @@ fn build_plt_symtab( .iter() .map(|&pc| build.pc_to_native[pc] as u64) .collect(); - boundaries.extend(build.plt_trampoline_offsets.iter().map(|&o| o as u64)); + boundaries.extend( + build + .plt_trampoline_offsets + .iter() + .flatten() + .map(|&o| o as u64), + ); boundaries.push(text_len); boundaries.sort_unstable(); for (i, name) in build.func_names.iter().enumerate() { @@ -1361,13 +1374,25 @@ pub(super) fn write( // executable has no exports, so the tables are unchanged. let mut elf_exports: Vec = Vec::new(); for exp in &build.exports { - if let Some(&native_off) = build.pc_to_native.get(exp.ent_pc) { - elf_exports.push(ElfExport { - name: exp.name.clone(), - section: super::DynamicExportSection::Text, - offset: native_off as u64, - }); + let native_off = build + .pc_to_native + .get(exp.ent_pc) + .copied() + .unwrap_or(usize::MAX); + if native_off == usize::MAX { + return Err(C5Error::Compile(crate::c5::error::fmt_internal_err( + &format!( + "ELF: exported function `{}` (bc PC {}) doesn't \ + align with any native instruction", + exp.name, exp.ent_pc + ), + ))); } + elf_exports.push(ElfExport { + name: exp.name.clone(), + section: super::DynamicExportSection::Text, + offset: native_off as u64, + }); } for d in &build.dynamic_exports { if !elf_exports.iter().any(|e| e.name == d.name) { @@ -3017,6 +3042,24 @@ mod tests { assert_eq!(e_machine, EM_AARCH64); } + /// An export whose ent_pc misses `pc_to_native` must fail the write + /// with a diagnostic; it was previously dropped from `.dynsym` + /// silently, shipping a shared library without the symbol. + #[test] + fn export_with_unmapped_ent_pc_errors() { + let mut build = tiny_build(); + build.output_kind = super::super::OutputKind::SharedLibrary; + build.exports = vec![crate::c5::program::ExportedFunction { + name: "ghost".into(), + ent_pc: 999, + }]; + let err = write(&tiny_program(), &build, Machine::Aarch64).unwrap_err(); + assert!( + err.to_string().contains("ghost"), + "error must name the export: {err}" + ); + } + #[test] fn program_header_table_self_describes() { let bytes = write(&tiny_program(), &tiny_build(), Machine::Aarch64).unwrap(); diff --git a/src/c5/object/mach_o.rs b/src/c5/object/mach_o.rs index bb918cb79..f76017d53 100644 --- a/src/c5/object/mach_o.rs +++ b/src/c5/object/mach_o.rs @@ -1607,6 +1607,27 @@ struct TlvBindContext { segment_offset: u64, /// Number of TLV descriptors that need binding. tlv_count: usize, + /// 1-based LC_LOAD_DYLIB ordinal of libSystem, which defines + /// `__tlv_bootstrap` (see [`tlv_bootstrap_ordinal`]). + bootstrap_ordinal: u64, +} + +/// 1-based LC_LOAD_DYLIB ordinal of libSystem, the dylib that defines +/// `__tlv_bootstrap`. The bind stream and the matching nlist entry both +/// resolve the ordinal through here so they cannot diverge. An image +/// using TLV without linking libSystem cannot bind the descriptors, so +/// that is an error rather than a guessed ordinal. +fn tlv_bootstrap_ordinal(dylibs: &[crate::c5::codegen::ResolvedDylib]) -> Result { + dylibs + .iter() + .position(|d| d.path.contains("libSystem")) + .map(|i| (i + 1) as u64) + .ok_or_else(|| { + C5Error::Compile(crate::c5::error::fmt_internal_err( + "Mach-O: `_Thread_local` requires libSystem for `__tlv_bootstrap`, \ + but no linked dylib matches libSystem", + )) + }) } /// Bind opcode stream that resolves the program's imports plus, @@ -1719,20 +1740,7 @@ fn build_bind_opcodes( out.push(BIND_OPCODE_DO_BIND); } if let Some(ctx) = tlv_ctx { - // `__tlv_bootstrap` always lives in libSystem; its - // dylib ordinal is the position of libSystem in the - // per-image dylib list, +1. We reuse the first dylib - // (libSystem is always present on macOS targets) for - // simplicity; if the order ever changes, the - // matching nlist entry's ordinal is computed the same - // way. - let bootstrap_ordinal = imports - .dylibs - .iter() - .position(|d| d.path.contains("libSystem")) - .map(|i| (i + 1) as u64) - .unwrap_or(1); - let bootstrap_source = BindSource::Dylib(bootstrap_ordinal); + let bootstrap_source = BindSource::Dylib(ctx.bootstrap_ordinal); if current_source != Some(bootstrap_source) { push_bind_source(&mut out, bootstrap_source); } @@ -2091,6 +2099,7 @@ pub(super) fn write(program: &Program, build: &Build) -> Result, C5Error Some(TlvBindContext { segment_offset: thread_vars_offset_in_segment, tlv_count: n_tlv, + bootstrap_ordinal: tlv_bootstrap_ordinal(&build.imports.dylibs)?, }) } else { None @@ -2130,25 +2139,20 @@ pub(super) fn write(program: &Program, build: &Build) -> Result, C5Error // `real_symbol` ("_malloc") so `nm`/`lldb` show the name // the C source uses. // - // Test fixtures sometimes hand us a `Build` with imports but - // no trampoline offsets (no per-arch lower() ran); in that - // case we skip the local section. - let emit_plt_locals = !build.plt_trampoline_offsets.is_empty(); - // One local symbol per PLT trampoline. Function imports carry a - // trampoline; data imports (bound through the GOT) do not, and the - // routing appends them after the function imports, so the first - // `plt_trampoline_offsets.len()` imports are exactly the trampolined - // ones. The remaining imports still get an undefined symtab entry + - // bind below. - let n_trampolines = build.plt_trampoline_offsets.len(); - let mut symbol_names: Vec<&str> = if emit_plt_locals { - build.imports.imports[..n_trampolines] - .iter() - .map(|imp| imp.local_name.as_str()) - .collect() - } else { - Vec::new() - }; + // One local symbol per PLT trampoline. A data import (bound through + // the GOT) carries no trampoline (`None` slot) and gets only the + // undefined symtab entry + bind below -- a local text symbol for it + // would sit at the slot's default address (the first function's + // bytes) and mislabel backtraces and breakpoints. Keyed by import + // index, not by ordering, so the two never diverge. + let plt_locals: Vec<(&str, usize)> = build + .imports + .imports + .iter() + .zip(build.plt_trampoline_offsets.iter()) + .filter_map(|(imp, off)| off.map(|o| (imp.local_name.as_str(), o))) + .collect(); + let mut symbol_names: Vec<&str> = plt_locals.iter().map(|&(name, _)| name).collect(); // Executable dynamic exports: every defined global symbol, so a // dlopen'd module binds the program's symbols. `#pragma export` // populates `build.exports` for shared libraries instead, so the @@ -2186,16 +2190,10 @@ pub(super) fn write(program: &Program, build: &Build) -> Result, C5Error // [Locals] one entry per PLT trampoline. Data imports have no // trampoline; they appear only as undefined import symbols below. - if emit_plt_locals { - debug_assert!( - n_trampolines <= build.imports.imports.len(), - "more trampolines than imports" - ); - for (i, &tramp_offset) in build.plt_trampoline_offsets.iter().enumerate() { - let n_strx = str_indices[i]; - let n_value = code_vmaddr_base + tramp_offset as u64; - symtab.extend_from_slice(&nlist_local(n_strx, n_value, SECT_INDEX_TEXT)); - } + for (i, &(_, tramp_offset)) in plt_locals.iter().enumerate() { + let n_strx = str_indices[i]; + let n_value = code_vmaddr_base + tramp_offset as u64; + symtab.extend_from_slice(&nlist_local(n_strx, n_value, SECT_INDEX_TEXT)); } // [Defined exports] (N_EXT | N_SECT). Each one's `n_value` @@ -2259,16 +2257,7 @@ pub(super) fn write(program: &Program, build: &Build) -> Result, C5Error symtab.extend_from_slice(&nlist_undef(n_strx, ordinal)); } if tls_present { - // `__tlv_bootstrap` comes from libSystem.B.dylib (which is - // already in the dylib list because every macOS Mach-O - // we emit links libSystem). Find its ordinal. - let bootstrap_dylib_ordinal = build - .imports - .dylibs - .iter() - .position(|d| d.path.contains("libSystem")) - .map(|i| (i + 1) as u8) - .unwrap_or(1); + let bootstrap_dylib_ordinal = tlv_bootstrap_ordinal(&build.imports.dylibs)? as u8; let bootstrap_strx = str_indices[symbol_names.len() - 1]; symtab.extend_from_slice(&nlist_undef(bootstrap_strx, bootstrap_dylib_ordinal)); } @@ -2985,6 +2974,26 @@ mod tests { ); } + /// `__tlv_bootstrap` binds against libSystem's real ordinal; an + /// image whose dylib list lacks libSystem cannot bind the TLV + /// descriptors and must fail rather than guess ordinal 1. + #[test] + fn tlv_bootstrap_ordinal_requires_libsystem() { + use crate::c5::codegen::ResolvedDylib; + let dylibs = vec![ + ResolvedDylib { + name: "libfoo".into(), + path: "/usr/lib/libfoo.dylib".into(), + }, + ResolvedDylib { + name: "libSystem".into(), + path: "/usr/lib/libSystem.B.dylib".into(), + }, + ]; + assert_eq!(tlv_bootstrap_ordinal(&dylibs).unwrap(), 2); + assert!(tlv_bootstrap_ordinal(&dylibs[..1]).is_err()); + } + #[test] fn uleb128_round_trips() { // Spot-check the encoder against a few known values from diff --git a/src/c5/object/pe.rs b/src/c5/object/pe.rs index a819ecc37..c1725c3f8 100644 --- a/src/c5/object/pe.rs +++ b/src/c5/object/pe.rs @@ -392,7 +392,13 @@ pub(super) fn write( let reloc_section_present = !build.tls_data.is_empty() || !build.data_relocs.is_empty() || !build.code_relocs.is_empty(); - let edata_section_present = is_dll && !build.exports.is_empty(); + // `.edata` is present whenever the image exports anything: a + // `#pragma export` set (shared library or executable, matching the + // ELF `.dynsym` behaviour) or an executable's `--export-all` / + // `--export-data` dynamic exports. A PE executable may legally carry + // an export directory; GetProcAddress resolves against it, which is + // what a plugin host loading modules relies on. + let edata_section_present = !build.exports.is_empty() || !build.dynamic_exports.is_empty(); // Emit DWARF debug sections in PE images so lldb / // gdb can resolve user-function names + types in PE // backtraces. Suppressed when the user passed `--no-debug` / @@ -603,11 +609,10 @@ pub(super) fn write( // `.edata` holds the IMAGE_EXPORT_DIRECTORY plus the // arrays it references -- function RVAs, name RVAs, - // ordinals, plus the DLL name and each export name. - // Only present in shared-library output with at least one - // `#pragma export` symbol. (`edata_section_present` was - // already computed above so the headers-size pass knew - // about it.) + // ordinals, plus the image name and each export name. + // Present when the image exports anything (see + // `edata_section_present` above, computed early so the + // headers-size pass knew about it). let edata_rva: u32 = if edata_section_present { round_up( if reloc_section_present { @@ -634,13 +639,51 @@ pub(super) fn write( 0 }; let edata_bytes: Vec = if edata_section_present { - build_export_directory( - edata_rva, - text_rva + text_prologue_len, - &build.exports, - &build.pc_to_native, - build.shared_lib_name.as_deref(), - )? + // Resolve every export to its runtime RVA. `#pragma export` + // entries carry a bc PC that maps through `pc_to_native`; + // dynamic exports already carry a byte offset within + // `build.text` / `build.data`. Names may overlap when + // `--export-all` re-covers a `#pragma export` symbol; the + // pragma entry wins (both resolve to the same address). + let mut entries: Vec<(String, u32)> = Vec::new(); + for exp in &build.exports { + let native_off = build + .pc_to_native + .get(exp.ent_pc) + .copied() + .unwrap_or(usize::MAX); + if native_off == usize::MAX { + return Err(C5Error::Compile(crate::c5::error::fmt_internal_err( + &format!( + "PE: exported function `{}` (bc PC {}) doesn't \ + align with any native instruction", + exp.name, exp.ent_pc + ), + ))); + } + entries.push(( + exp.name.clone(), + text_rva + text_prologue_len + native_off as u32, + )); + } + for d in &build.dynamic_exports { + if entries.iter().any(|(n, _)| n == &d.name) { + continue; + } + let rva = match d.section { + super::DynamicExportSection::Text => text_rva + text_prologue_len + d.offset as u32, + super::DynamicExportSection::Data => { + if !data_section_present { + return Err(C5Error::Compile(crate::c5::error::fmt_internal_err( + &format!("PE: data export `{}` without a .data section", d.name), + ))); + } + data_rva + d.offset as u32 + } + }; + entries.push((d.name.clone(), rva)); + } + build_export_directory(edata_rva, entries, build.shared_lib_name.as_deref())? } else { Vec::new() }; @@ -780,9 +823,19 @@ pub(super) fn write( // of `b malloc` resolution by some tool versions. let mut coff_symbols: Vec = Vec::new(); if emit_plt_coff_symbols { - for (i, imp) in build.imports.imports.iter().enumerate() { - let trampoline_rva = - text_rva + text_prologue_len + build.plt_trampoline_offsets[i] as u32; + for (imp, off) in build + .imports + .imports + .iter() + .zip(build.plt_trampoline_offsets.iter()) + { + // A data import (bound through the IAT) has no trampoline; + // a text symbol for it would mislabel the code at the + // fabricated RVA. + let Some(tramp_offset) = *off else { + continue; + }; + let trampoline_rva = text_rva + text_prologue_len + tramp_offset as u32; let mut name_field = [0u8; 8]; let name_bytes = imp.local_name.as_bytes(); if name_bytes.len() <= 8 { @@ -1091,13 +1144,13 @@ pub(super) fn write( }); } write_section_headers(&mut out, §ions); - pad_to(&mut out, text_file_off as usize); + pad_to(&mut out, text_file_off as usize)?; out.extend_from_slice(&text_bytes); - pad_to(&mut out, (text_file_off + text_raw_size) as usize); + pad_to(&mut out, (text_file_off + text_raw_size) as usize)?; out.extend_from_slice(&pdata_bytes); - pad_to(&mut out, (pdata_file_off + pdata_raw_size) as usize); + pad_to(&mut out, (pdata_file_off + pdata_raw_size) as usize)?; out.extend_from_slice(&idata_bytes); - pad_to(&mut out, (idata_file_off + idata_raw_size) as usize); + pad_to(&mut out, (idata_file_off + idata_raw_size) as usize)?; if data_section_present { // Apply pointer-to-global initializers in `.data`: // each `int *p = &x;` slot holds the preferred VA @@ -1157,7 +1210,7 @@ pub(super) fn write( pad_to( &mut out, (data_file_off + tls_layout.tls_index_offset_in_data) as usize, - ); + )?; // `_tls_index` -- 4-byte slot, zero-initialised; the // Windows loader writes the chosen slot index here at // module-init time. @@ -1167,7 +1220,7 @@ pub(super) fn write( pad_to( &mut out, (data_file_off + tls_layout.directory_offset_in_data) as usize, - ); + )?; // IMAGE_TLS_DIRECTORY64. Layout: // StartAddressOfRawData : u64 -- VA of init data start // EndAddressOfRawData : u64 -- VA of init data end @@ -1215,32 +1268,39 @@ pub(super) fn write( } } if reloc_section_present { - pad_to(&mut out, reloc_file_off as usize); + pad_to(&mut out, reloc_file_off as usize)?; out.extend_from_slice(&reloc_bytes); } if edata_section_present { - pad_to(&mut out, edata_file_off as usize); + pad_to(&mut out, edata_file_off as usize)?; out.extend_from_slice(&edata_bytes); } // DWARF debug sections come last in the file image // (before the COFF string table that names them). for slot in &dwarf_pe_sections { - pad_to(&mut out, slot.file_off as usize); + pad_to(&mut out, slot.file_off as usize)?; out.extend_from_slice(&slot.bytes); } // COFF symbol table immediately before its string // table. Both live at the file tail (post-DWARF). Emitted // when there are PLT trampolines; absent otherwise. if !coff_symbols.is_empty() { - pad_to(&mut out, coff_symtab_file_off as usize); + pad_to(&mut out, coff_symtab_file_off as usize)?; out.extend_from_slice(&coff_symbols); } if !coff_strtab.is_empty() { - pad_to(&mut out, coff_strtab_file_off as usize); + pad_to(&mut out, coff_strtab_file_off as usize)?; out.extend_from_slice(&coff_strtab); } - pad_to(&mut out, total_file_size); - debug_assert_eq!(out.len(), total_file_size, "file size mismatch"); + pad_to(&mut out, total_file_size)?; + if out.len() != total_file_size { + return Err(C5Error::Compile(crate::c5::error::fmt_internal_err( + &format!( + "PE layout drift: emitted {:#x} bytes, layout computed {total_file_size:#x}", + out.len(), + ), + ))); + } Ok(out) } @@ -1303,21 +1363,20 @@ struct ImageExportDirectory { const IMAGE_EXPORT_DIRECTORY_SIZE: usize = 40; const _: () = assert!(core::mem::size_of::() == IMAGE_EXPORT_DIRECTORY_SIZE); -/// Build the `.edata` section bytes for a DLL with exports. +/// Build the `.edata` section bytes for an image with exports. /// Layout: `IMAGE_EXPORT_DIRECTORY` followed by /// AddressOfFunctions / AddressOfNames / -/// AddressOfNameOrdinals arrays, then the DLL-name and +/// AddressOfNameOrdinals arrays, then the image-name and /// per-export-name strings (NUL-terminated). /// -/// All RVAs in the directory are image-relative; the -/// `text_prologue_rva` is `text_rva + stub_len`, the byte -/// where `build.text` starts. Each export's runtime RVA is -/// `text_prologue_rva + pc_to_native[ent_pc]`. +/// `exports` pairs each export name with its resolved image-relative +/// RVA (functions and data alike). The name pointer table is lexically +/// ordered, as the loader and GetProcAddress binary-search it; the +/// parallel ordinal table maps each name back to its +/// AddressOfFunctions slot. fn build_export_directory( edata_rva: u32, - text_prologue_rva: u32, - exports: &[crate::c5::program::ExportedFunction], - pc_to_native: &[usize], + exports: Vec<(String, u32)>, image_name: Option<&str>, ) -> Result, C5Error> { let n = exports.len() as u32; @@ -1328,7 +1387,7 @@ fn build_export_directory( let ordinals_off = names_off + 4 * n; let strings_off = ordinals_off + 2 * n; - // The DLL-name string heads the string blob; per-export + // The image-name string heads the string blob; per-export // names follow, each NUL-terminated. We compute their // RVAs as we go so the AddressOfNames entries match. let dll_name = image_name.unwrap_or("c5-output.dll"); @@ -1355,34 +1414,21 @@ fn build_export_directory( }, ); - // AddressOfFunctions -- RVA of each function. - for exp in exports { - let native_off = pc_to_native.get(exp.ent_pc).copied().unwrap_or(usize::MAX); - if native_off == usize::MAX { - return Err(C5Error::Compile(crate::c5::error::fmt_internal_err( - &format!( - "PE: exported function `{}` (bc PC {}) doesn't \ - align with any native instruction", - exp.name, exp.ent_pc - ), - ))); - } - let rva = text_prologue_rva + native_off as u32; + // AddressOfFunctions -- resolved RVA of each export. + for (_, rva) in &exports { out.extend_from_slice(&rva.to_le_bytes()); } - // The name pointer table must be lexically ordered (the loader - // and GetProcAddress binary-search it); the parallel ordinal - // table maps each name back to its declaration-order - // AddressOfFunctions slot. + // The name pointer table must be lexically ordered; the parallel + // ordinal table maps each name back to its AddressOfFunctions slot. let mut by_name: Vec = (0..exports.len()).collect(); - by_name.sort_by(|&a, &b| exports[a].name.as_bytes().cmp(exports[b].name.as_bytes())); + by_name.sort_by(|&a, &b| exports[a].0.as_bytes().cmp(exports[b].0.as_bytes())); // AddressOfNames -- RVA of each export's name string. let mut cur = strings_rva + dll_name.len() as u32 + 1; for &i in &by_name { out.extend_from_slice(&cur.to_le_bytes()); - cur += exports[i].name.len() as u32 + 1; + cur += exports[i].0.len() as u32 + 1; } // AddressOfNameOrdinals -- u16 unbiased ordinal per name. @@ -1390,12 +1436,12 @@ fn build_export_directory( out.extend_from_slice(&(i as u16).to_le_bytes()); } - // String blob: DLL name first, then each export name in + // String blob: image name first, then each export name in // name-pointer-table order. out.extend_from_slice(dll_name.as_bytes()); out.push(0); for &i in &by_name { - out.extend_from_slice(exports[i].name.as_bytes()); + out.extend_from_slice(exports[i].0.as_bytes()); out.push(0); } @@ -2907,10 +2953,21 @@ fn round_up_usize(value: usize, align: usize) -> usize { (value + align - 1) & !(align - 1) } -fn pad_to(out: &mut Vec, target_len: usize) { - if out.len() < target_len { - out.resize(target_len, 0); +/// Zero-pad `out` to the precomputed file offset of the next section. +/// A write cursor already past the target means the layout pass and +/// the emission pass disagree; every later `pointer_to_raw_data` would +/// then be wrong, so that is a hard error rather than a silent overlap. +fn pad_to(out: &mut Vec, target_len: usize) -> Result<(), C5Error> { + if out.len() > target_len { + return Err(C5Error::Compile(crate::c5::error::fmt_internal_err( + &format!( + "PE layout drift: write cursor {:#x} past computed file offset {target_len:#x}", + out.len(), + ), + ))); } + out.resize(target_len, 0); + Ok(()) } #[cfg(test)] @@ -2951,6 +3008,56 @@ mod tests { assert_eq!(round_up(0x201, 0x200), 0x400); } + /// `pad_to` rejects a write cursor already past the layout's + /// computed file offset instead of silently overlapping sections. + #[test] + fn pad_to_rejects_cursor_past_target() { + let mut out = alloc::vec![0u8; 16]; + assert!(pad_to(&mut out, 8).is_err()); + assert!(pad_to(&mut out, 16).is_ok()); + pad_to(&mut out, 32).expect("grow"); + assert_eq!(out.len(), 32); + } + + /// The export name pointer table is binary-searched by + /// GetProcAddress, so `build_export_directory` orders the entries + /// lexically with the ordinal table pointing back at each name's + /// AddressOfFunctions slot. + #[test] + fn export_directory_sorts_names_lexically() { + let bytes = build_export_directory( + 0x5000, + alloc::vec![ + ("zeta".to_string(), 0x1000u32), + ("alpha".to_string(), 0x2000u32), + ], + Some("t.dll"), + ) + .expect("build export directory"); + let name_pos = |needle: &[u8]| { + bytes + .windows(needle.len()) + .position(|w| w == needle) + .expect("name present") + }; + assert!(name_pos(b"alpha\0") < name_pos(b"zeta\0")); + // AddressOfFunctions stays in declaration order. + let funcs_off = IMAGE_EXPORT_DIRECTORY_SIZE; + let rva0 = u32::from_le_bytes(bytes[funcs_off..funcs_off + 4].try_into().unwrap()); + let rva1 = u32::from_le_bytes(bytes[funcs_off + 4..funcs_off + 8].try_into().unwrap()); + assert_eq!((rva0, rva1), (0x1000, 0x2000)); + // Ordinal table (after funcs + names arrays) maps sorted names + // back to their slots: alpha -> slot 1, zeta -> slot 0. + let ordinals_off = funcs_off + 4 * 2 + 4 * 2; + let ord0 = u16::from_le_bytes(bytes[ordinals_off..ordinals_off + 2].try_into().unwrap()); + let ord1 = u16::from_le_bytes( + bytes[ordinals_off + 2..ordinals_off + 4] + .try_into() + .unwrap(), + ); + assert_eq!((ord0, ord1), (1, 0)); + } + /// The packed AArch64 RUNTIME_FUNCTION encodes `FunctionLength` /// in 11 bits (units = 4-byte instructions). The maximum /// representable value is `0x7FF == 2047` instructions; a @@ -3051,6 +3158,62 @@ mod tests { assert_eq!(size, 0, "TLS size must be 0 when no TLS present"); } + /// A PE executable may legally carry an export directory (a plugin + /// host publishing its API for GetProcAddress). `--export-all` / + /// `--export-data` reach PE executables through `dynamic_exports`; + /// the flags previously no-op'd for PE, leaving the directory empty. + #[test] + fn executable_dynamic_exports_emit_export_directory() { + use crate::Compiler; + let program = Compiler::new("int main() { return 0; }".to_string()) + .compile() + .expect("compile"); + let mut build = lower_for( + &program, + super::super::Target::WindowsX64, + super::super::NativeOptions::default(), + ) + .expect("lower"); + build.dynamic_exports = alloc::vec![crate::c5::codegen::DynamicExport { + name: "bump".to_string(), + section: super::super::DynamicExportSection::Text, + offset: 0, + }]; + let bytes = write( + &program, + &build, + Machine::X86_64, + super::super::Target::WindowsX64, + ) + .expect("write PE"); + let (rva, size) = read_data_directory(&bytes, DATA_DIRECTORY_EXPORT); + assert_ne!(rva, 0, "export directory RVA must be set"); + assert_ne!(size, 0, "export directory size must be set"); + assert!( + bytes.windows(5).any(|w| w == b"bump\0"), + "the export name must appear in the image" + ); + + // Without dynamic exports the executable carries no directory. + let plain = write( + &program, + &lower_for( + &program, + super::super::Target::WindowsX64, + super::super::NativeOptions::default(), + ) + .expect("lower"), + Machine::X86_64, + super::super::Target::WindowsX64, + ) + .expect("write PE"); + assert_eq!( + read_data_directory(&plain, DATA_DIRECTORY_EXPORT), + (0, 0), + "a plain executable must carry no export directory" + ); + } + /// PE with `_Thread_local`: TLS directory entry must point /// at a non-empty IMAGE_TLS_DIRECTORY64 of size 40, and the /// directory's contents must reference plausible RVAs (well diff --git a/src/c5/tests/linker.rs b/src/c5/tests/linker.rs index 965a1ecf9..eefdeb93f 100644 --- a/src/c5/tests/linker.rs +++ b/src/c5/tests/linker.rs @@ -2233,3 +2233,93 @@ fn dead_libc_bindings_fail_at_build_not_at_load() { link_one(src).expect("bound libc call must link"); } } + +#[test] +fn macho_data_import_gets_no_bogus_local_text_symbol() { + // A Mach-O data import (`environ`, bound through the GOT) carries no + // PLT trampoline. The symtab previously fabricated a local text + // symbol for it at code offset 0 -- the first function's address -- + // mislabeling backtraces and breakpoints. Only imports that actually + // have a trampoline get a local text symbol; a data import keeps just + // its undefined entry. + use crate::c5::linker::{ + emit_aarch64_plt, link_native_objects, parse_native_elf, write_native_image_from_merged, + }; + use crate::c5::{CompileOptions, NativeOptions, OutputKind, Target, emit_native_with_options}; + let program = Compiler::with_options( + "#include \n\ + #include \n\ + int main(void) { return environ != 0 ? (int)strlen(\"x\") : 0; }\n" + .to_string(), + Target::MacOSAarch64, + CompileOptions::default(), + ) + .compile() + .expect("compile"); + let opts = NativeOptions { + output_kind: OutputKind::Relocatable, + ..Default::default() + }; + let bytes = emit_native_with_options(&program, Target::MacOSAarch64, opts).expect("emit"); + let obj = parse_native_elf(&bytes).expect("parse ET_REL"); + let mut merged = link_native_objects(&[obj]).expect("link"); + let plt = emit_aarch64_plt(&mut merged).expect("plt"); + let exe = write_native_image_from_merged( + &merged, + &plt, + "main", + None, + OutputKind::Executable, + Target::MacOSAarch64, + None, + ) + .expect("write executable"); + + // Walk LC_SYMTAB collecting (name, n_type). N_STAB=0xe0, N_TYPE=0x0e, + // N_SECT=0x0e, N_EXT=0x01. + const LC_SYMTAB: u32 = 2; + let ncmds = u32::from_le_bytes(exe[16..20].try_into().unwrap()); + let mut p = 32usize; + let mut names: alloc::vec::Vec<(String, u8)> = alloc::vec::Vec::new(); + for _ in 0..ncmds { + let cmd = u32::from_le_bytes(exe[p..p + 4].try_into().unwrap()); + let cmdsize = u32::from_le_bytes(exe[p + 4..p + 8].try_into().unwrap()) as usize; + if cmd == LC_SYMTAB { + let symoff = u32::from_le_bytes(exe[p + 8..p + 12].try_into().unwrap()) as usize; + let nsyms = u32::from_le_bytes(exe[p + 12..p + 16].try_into().unwrap()) as usize; + let stroff = u32::from_le_bytes(exe[p + 16..p + 20].try_into().unwrap()) as usize; + for k in 0..nsyms { + let e = symoff + k * 16; + let n_strx = u32::from_le_bytes(exe[e..e + 4].try_into().unwrap()) as usize; + let n_type = exe[e + 4]; + let s = stroff + n_strx; + let len = exe[s..].iter().position(|&b| b == 0).unwrap(); + names.push(( + String::from_utf8_lossy(&exe[s..s + len]).into_owned(), + n_type, + )); + } + break; + } + p += cmdsize; + } + // No local (N_SECT set, N_EXT clear) symbol named `environ`. + assert!( + !names + .iter() + .any(|(n, t)| n == "environ" && t & 0x0e == 0x0e && t & 0x01 == 0), + "data import `environ` must not get a bogus local text symbol: {names:?}" + ); + // Its undefined import entry (`_environ`, N_SECT clear) survives. + assert!( + names.iter().any(|(n, t)| n == "_environ" && t & 0x0e == 0), + "data import must keep its undefined `_environ` entry: {names:?}" + ); + // A real function import (`_strlen`) still gets its local text symbol. + assert!( + names + .iter() + .any(|(n, t)| n == "_strlen" && t & 0x0e == 0x0e && t & 0x01 == 0), + "a trampolined import must keep its local text symbol: {names:?}" + ); +} From f156029eba96b110edad47043e684f85ebf05713 Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 02:00:50 -0700 Subject: [PATCH 63/67] headers: bundle os/lock.h and crt_externs.h for the macOS demos tcl's macOS notifier includes (os_unfair_lock) and quickjs-libc includes (_NSGetEnviron); both bind to libSystem under the underscore-prefixed Mach-O names. Co-Authored-By: Claude Fable 5 --- headers/include/crt_externs.h | 19 +++++++++++++++++++ headers/include/os/lock.h | 23 +++++++++++++++++++++++ src/c5/headers.rs | 5 +++++ 3 files changed, 47 insertions(+) create mode 100644 headers/include/crt_externs.h create mode 100644 headers/include/os/lock.h diff --git a/headers/include/crt_externs.h b/headers/include/crt_externs.h new file mode 100644 index 000000000..9b50aca62 --- /dev/null +++ b/headers/include/crt_externs.h @@ -0,0 +1,19 @@ +/* Apple : accessors for the process argument and +** environment vectors, which a Mach-O image reaches through +** libSystem rather than as data symbols. */ +#pragma once + +#ifdef __APPLE__ + +#pragma dylib(libc, "/usr/lib/libSystem.B.dylib") +#pragma binding(libc::_NSGetEnviron, "__NSGetEnviron") +#pragma binding(libc::_NSGetArgc, "__NSGetArgc") +#pragma binding(libc::_NSGetArgv, "__NSGetArgv") +#pragma binding(libc::_NSGetProgname, "__NSGetProgname") + +char ***_NSGetEnviron(void); +int *_NSGetArgc(void); +char ***_NSGetArgv(void); +char **_NSGetProgname(void); + +#endif diff --git a/headers/include/os/lock.h b/headers/include/os/lock.h new file mode 100644 index 000000000..cc85e7b80 --- /dev/null +++ b/headers/include/os/lock.h @@ -0,0 +1,23 @@ +/* Apple : the os_unfair_lock primitive. Opaque one-word +** lock; libSystem provides the operations. */ +#pragma once + +#ifdef __APPLE__ + +typedef struct os_unfair_lock_s { + unsigned int _os_unfair_lock_opaque; +} os_unfair_lock, *os_unfair_lock_t; + +#define OS_UNFAIR_LOCK_INIT \ + ((os_unfair_lock){0}) + +#pragma dylib(libc, "/usr/lib/libSystem.B.dylib") +#pragma binding(libc::os_unfair_lock_lock, "_os_unfair_lock_lock") +#pragma binding(libc::os_unfair_lock_unlock, "_os_unfair_lock_unlock") +#pragma binding(libc::os_unfair_lock_trylock, "_os_unfair_lock_trylock") + +void os_unfair_lock_lock(os_unfair_lock_t lock); +void os_unfair_lock_unlock(os_unfair_lock_t lock); +int os_unfair_lock_trylock(os_unfair_lock_t lock); + +#endif diff --git a/src/c5/headers.rs b/src/c5/headers.rs index a39a4da05..85b113b7f 100644 --- a/src/c5/headers.rs +++ b/src/c5/headers.rs @@ -354,6 +354,11 @@ pub(super) const EMBEDDED_HEADERS: &[(&str, &str)] = &[ include_str!("../../headers/include/AvailabilityMacros.h"), ), ("os/log.h", include_str!("../../headers/include/os/log.h")), + ("os/lock.h", include_str!("../../headers/include/os/lock.h")), + ( + "crt_externs.h", + include_str!("../../headers/include/crt_externs.h"), + ), ("windows.h", include_str!("../../headers/include/windows.h")), ("winbase.h", include_str!("../../headers/include/winbase.h")), ( From fd2cfac4dbf468b82cc87df5c79dbb652746a153 Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 01:05:52 -0700 Subject: [PATCH 64/67] c5: implement C99 variable-length arrays Add C99 6.7.6.2 variable-length arrays (block-scope, single dimension), closing the conformance gap where any non-constant array dimension was rejected at parse time. Frame mechanism: reuse the existing per-frame alloca arena. A VLA declaration evaluates its runtime element count, multiplies by the element size, and allocates from the arena via Intrinsic::Alloca; the base pointer and byte count are stored in two hidden frame slots. A function that declares a VLA sets the alloca-top slot, which already disables mem2reg promotion for the whole function (the runtime-sized, address-taken array is never promoted) and blocks inlining. Reclamation: two new intrinsics, AllocaSave and AllocaRestore, read and write the arena top. parse_block_stmt brackets a VLA-declaring block with VlaScopeEnter / VlaScopeExit so the storage is reclaimed on block exit and, for a loop body, on every iteration -- the fixed arena does not grow unboundedly. Type representation: Symbol gains is_vla + the two hidden-slot indices. A VLA identifier decays through Expr::VlaBase (a load of the base pointer); sizeof of a VLA lowers to Expr::VlaSizeof (a load of the byte count) per 6.5.3.4p2. Indexing, deref, pointer arithmetic, and address-of then reuse the existing pointer paths. IN scope: single-dimension block-scope VLA; runtime sizeof; a dimension from a function argument; per-iteration scope reclamation; a VLA parameter (adjusted to a pointer, 6.7.6.3p7). __STDC_NO_VLA__ is no longer predefined. Rejected cleanly (no miscompile): multidimensional VLAs (runtime element stride); file-scope / variably-modified file objects; a VLA with an initializer (6.7.8p3). Regressions: vla_basic_sum, vla_runtime_sizeof, vla_size_from_arg, vla_scope_reclaim_loop, vla_param_decay (native + native_elf + native_elf_x64 + PE fixture tables and a JIT lane in tests/vla.rs); vla_multidim_rejected, vla_file_scope_rejected, vla_initializer_rejected assert the diagnostics. Co-Authored-By: Claude Fable 5 --- src/c5/ast/mod.rs | 42 ++++++++-- src/c5/ast/walk.rs | 72 ++++++++++++++-- src/c5/codegen/aarch64/emit.rs | 60 ++++++++++++++ src/c5/codegen/x86_64/emit.rs | 44 ++++++++++ src/c5/compiler/const_expr.rs | 49 +++++++++++ src/c5/compiler/declarator.rs | 62 +++++++++++--- src/c5/compiler/emit.rs | 62 ++++++++++++++ src/c5/compiler/expr.rs | 25 ++++-- src/c5/compiler/locals.rs | 45 ++++++++++ src/c5/compiler/mod.rs | 40 ++++++++- src/c5/compiler/run_compile.rs | 1 + src/c5/compiler/sizeof_expr.rs | 9 ++ src/c5/compiler/stmt.rs | 30 +++++++ src/c5/op.rs | 12 +++ src/c5/preprocessor.rs | 3 +- src/c5/symbol.rs | 18 ++++ src/c5/tests/mod.rs | 1 + src/c5/tests/native.rs | 5 ++ src/c5/tests/native_elf.rs | 5 ++ src/c5/tests/native_elf_x64.rs | 5 ++ src/c5/tests/native_pe_arm64.rs | 5 ++ src/c5/tests/native_pe_x64.rs | 5 ++ src/c5/tests/vla.rs | 92 +++++++++++++++++++++ src/c5/vm/ssa.rs | 17 ++++ tests/fixtures/c/predefined_macros.c | 7 +- tests/fixtures/c/vla_basic_sum.c | 24 ++++++ tests/fixtures/c/vla_file_scope_rejected.c | 5 ++ tests/fixtures/c/vla_initializer_rejected.c | 5 ++ tests/fixtures/c/vla_multidim_rejected.c | 7 ++ tests/fixtures/c/vla_param_decay.c | 17 ++++ tests/fixtures/c/vla_runtime_sizeof.c | 20 +++++ tests/fixtures/c/vla_scope_reclaim_loop.c | 20 +++++ tests/fixtures/c/vla_size_from_arg.c | 22 +++++ 33 files changed, 803 insertions(+), 33 deletions(-) create mode 100644 src/c5/tests/vla.rs create mode 100644 tests/fixtures/c/vla_basic_sum.c create mode 100644 tests/fixtures/c/vla_file_scope_rejected.c create mode 100644 tests/fixtures/c/vla_initializer_rejected.c create mode 100644 tests/fixtures/c/vla_multidim_rejected.c create mode 100644 tests/fixtures/c/vla_param_decay.c create mode 100644 tests/fixtures/c/vla_runtime_sizeof.c create mode 100644 tests/fixtures/c/vla_scope_reclaim_loop.c create mode 100644 tests/fixtures/c/vla_size_from_arg.c diff --git a/src/c5/ast/mod.rs b/src/c5/ast/mod.rs index 82275bb7e..d8dc35cbc 100644 --- a/src/c5/ast/mod.rs +++ b/src/c5/ast/mod.rs @@ -340,6 +340,15 @@ pub(crate) enum Expr { array_size: i64, init: LocalInit, }, + /// A variable-length array identifier in a value context (C99 + /// 6.3.2.1p3 decay). The array's storage is at a runtime address + /// held in `ptr_slot`; the walker loads that pointer. `ty` is the + /// decayed element-pointer type. + VlaBase { ptr_slot: i64, ty: i64 }, + /// `sizeof ` -- the runtime byte count the matching + /// `Decl::Vla` stored into `size_slot` (C99 6.5.3.4p2: for a VLA + /// the operand is evaluated and the result is a runtime value). + VlaSizeof { size_slot: i64 }, } /// One item inside a compound statement. C99 6.8.2's @@ -412,6 +421,13 @@ pub(crate) enum Stmt { /// `parse_block_stmt` can capture decls alongside stmts via a /// single stmt-id sequence. Decl(DeclId), + /// Snapshot the per-frame alloca-arena top into `save_slot` on + /// entry to a block that declares a variable-length array. Paired + /// with `VlaScopeExit` so the VLA storage is reclaimed on block + /// exit and, for a loop body, on every iteration (C99 6.2.4p2). + VlaScopeEnter { save_slot: i64 }, + /// Restore the alloca-arena top from `save_slot` on block exit. + VlaScopeExit { save_slot: i64 }, } /// One stored element in a runtime aggregate initializer. @@ -476,10 +492,21 @@ pub(crate) enum Decl { slot_off: i64, init: LocalInit, }, - /// Variable-length array declaration. `dim` is the runtime - /// dimension expression; the walker emits `Inst::AllocaInit` - /// to reserve the matching stack region. C99 6.7.6.2p4. - Vla { sym: u32, dim: ExprId }, + /// Variable-length array declaration (C99 6.7.6.2). `dim` is the + /// runtime element-count expression; `elem_size` is the element's + /// byte size. The walker evaluates `dim * elem_size`, allocates + /// that many bytes from the per-frame alloca arena, stores the + /// base pointer into `ptr_slot`, and the byte count into + /// `size_slot` (read back by `sizeof`). `elem_ty` carries the + /// element type for struct-size remapping. + Vla { + sym: u32, + elem_ty: i64, + elem_size: i64, + ptr_slot: i64, + size_slot: i64, + dim: ExprId, + }, /// Block-scope `static T name [= init];` declaration. C99 /// 6.2.4p3 (lifetime is whole program) + 6.7.8p4 (init must /// be constant). The parser promotes the symbol to the `Glo` @@ -876,7 +903,9 @@ fn visit_expr_ty(expr: &mut Expr, f: &mut impl FnMut(&mut i64)) { | Expr::Comma { ty, .. } | Expr::ShortCircuit { ty, .. } | Expr::Intrinsic { ty, .. } - | Expr::Atomic { ty, .. } => f(ty), + | Expr::Atomic { ty, .. } + | Expr::VlaBase { ty, .. } => f(ty), + Expr::VlaSizeof { .. } => {} Expr::Cast { to_ty, .. } => f(to_ty), Expr::CompoundLiteral { ty, init, .. } => { f(ty); @@ -902,7 +931,8 @@ fn visit_decl_ty(decl: &mut Decl, f: &mut impl FnMut(&mut i64)) { } } } - Decl::Vla { .. } | Decl::StaticLocal { .. } => {} + Decl::Vla { elem_ty, .. } => f(elem_ty), + Decl::StaticLocal { .. } => {} } } diff --git a/src/c5/ast/walk.rs b/src/c5/ast/walk.rs index fb7d10590..9e470cd89 100644 --- a/src/c5/ast/walk.rs +++ b/src/c5/ast/walk.rs @@ -1150,6 +1150,26 @@ impl<'a> Walker<'a> { self.walk_decl(b, decl_id)?; Ok(false) } + // C99 6.2.4p2: snapshot the alloca-arena top on entry to a + // VLA-declaring block, restore it on exit so the storage is + // reclaimed (per loop iteration for a loop body). + Stmt::VlaScopeEnter { save_slot } => { + let slot = *save_slot; + let top = b.intrinsic( + super::super::op::Intrinsic::AllocaSave as i64, + alloc::vec::Vec::new(), + ); + b.store_local(slot, top, super::super::ir::StoreKind::I64); + Ok(false) + } + Stmt::VlaScopeExit { save_slot } => { + let saved = b.load_local(*save_slot, super::super::ir::LoadKind::I64); + b.intrinsic( + super::super::op::Intrinsic::AllocaRestore as i64, + alloc::vec![saved], + ); + Ok(false) + } } } @@ -1178,10 +1198,34 @@ impl<'a> Walker<'a> { let init_clone = init.clone(); self.emit_local_init(b, slot, ty, &init_clone) } - super::super::ast::Decl::Vla { .. } => Err(WalkError::UnsupportedStmt { - id: 0, - kind: "Decl::Vla", - }), + super::super::ast::Decl::Vla { + elem_size, + ptr_slot, + size_slot, + dim, + .. + } => { + // C99 6.7.6.2: allocate `count * sizeof(elem)` bytes + // from the per-frame alloca arena, store the base + // pointer for decay and the byte count for `sizeof`. + let elem_size = *elem_size; + let ptr_slot = *ptr_slot; + let size_slot = *size_slot; + let dim = *dim; + let n = self.walk_expr_rvalue(b, dim)?; + let bytes = if elem_size == 1 { + n + } else { + b.binop_imm(BinOp::Mul, n, elem_size) + }; + b.store_local(size_slot, bytes, super::super::ir::StoreKind::I64); + let ptr = b.intrinsic( + super::super::op::Intrinsic::Alloca as i64, + alloc::vec![bytes], + ); + b.store_local(ptr_slot, ptr, super::super::ir::StoreKind::I64); + Ok(()) + } super::super::ast::Decl::StaticLocal { .. } => { // C99 6.2.4p3 + 6.7.8p4: storage + initializer // live in the data segment; nothing to emit in @@ -2860,6 +2904,8 @@ impl<'a> Walker<'a> { Expr::StrLit { ty, .. } => *ty, Expr::Intrinsic { ty, .. } => *ty, Expr::Atomic { ty, .. } => *ty, + Expr::VlaBase { ty, .. } => *ty, + Expr::VlaSizeof { .. } => Ty::Int as i64, // `&&label` is a `void *` (char-pointer encoding). Expr::LabelAddr(_) => { crate::c5::token::Ty::Char as i64 + crate::c5::token::Ty::Ptr as i64 @@ -3102,6 +3148,17 @@ impl<'a> Walker<'a> { Ok(old) } Expr::Sizeof(s) => Ok(b.imm(s.size_bytes)), + // C99 6.3.2.1p3: a VLA lvalue decays to a pointer to its + // first element -- the runtime base pointer the matching + // `Decl::Vla` stored into `ptr_slot`. + Expr::VlaBase { ptr_slot, .. } => { + Ok(b.load_local(*ptr_slot, super::super::ir::LoadKind::I64)) + } + // C99 6.5.3.4p2: `sizeof ` is the runtime byte count + // the matching `Decl::Vla` stored into `size_slot`. + Expr::VlaSizeof { size_slot } => { + Ok(b.load_local(*size_slot, super::super::ir::LoadKind::I64)) + } Expr::CompoundLiteral { slot_off, ty, @@ -4269,9 +4326,12 @@ fn expr_ty(e: &Expr) -> Option { | Expr::Comma { ty, .. } | Expr::ShortCircuit { ty, .. } | Expr::Intrinsic { ty, .. } - | Expr::Atomic { ty, .. } => Some(*ty), + | Expr::Atomic { ty, .. } + | Expr::VlaBase { ty, .. } => Some(*ty), Expr::Cast { to_ty, .. } => Some(*to_ty), Expr::Sizeof(s) => Some(s.result_ty), + // `sizeof ` is a runtime `size_t`; c5 types it as `int`. + Expr::VlaSizeof { .. } => Some(crate::c5::token::Ty::Int as i64), Expr::CompoundLiteral { ty, .. } => Some(*ty), // `&&label` is a `void *` (char-pointer encoding). Expr::LabelAddr(_) => { @@ -4398,6 +4458,8 @@ fn lvalue_shape_label(expr: &Expr) -> &'static str { Expr::ShortCircuit { .. } => "ShortCircuit", Expr::Atomic { .. } => "Atomic", Expr::LabelAddr(_) => "LabelAddr", + Expr::VlaBase { .. } => "VlaBase", + Expr::VlaSizeof { .. } => "VlaSizeof", } } diff --git a/src/c5/codegen/aarch64/emit.rs b/src/c5/codegen/aarch64/emit.rs index 301c504d1..e2398e072 100644 --- a/src/c5/codegen/aarch64/emit.rs +++ b/src/c5/codegen/aarch64/emit.rs @@ -3142,6 +3142,47 @@ fn emit_intrinsic( emit(code, enc_str_imm(rd, scratch.primary, 0)); true } + I::AllocaSave => { + // Read the arena top for a VLA block snapshot (C99 6.7.6.2). + if current_alloca_top == 0 { + bail_msg("AllocaSave: AllocaInit didn't run for this function"); + return false; + } + let Some(rd) = int_or_spill_scratch(dst, scratch) else { + bail_msg("AllocaSave: dst not int reg / spill"); + return false; + }; + emit_arena_top_addr(code, scratch.secondary, current_alloca_top); + emit(code, enc_ldr_imm(rd, scratch.secondary, 0)); + spill_local_addr_to_dst(code, dst, rd, frame); + true + } + I::AllocaRestore => { + // Restore the arena top on VLA block exit. + if current_alloca_top == 0 { + bail_msg("AllocaRestore: AllocaInit didn't run for this function"); + return false; + } + if args.len() != 1 { + bail_msg("AllocaRestore: expected 1 arg"); + return false; + } + let v_place = alloc + .places + .get(args[0] as usize) + .copied() + .unwrap_or(Place::None); + let v = match materialize_int(code, v_place, scratch.primary, frame) { + Some(r) => r, + None => { + bail_msg("AllocaRestore: arg not int reg / spill / fp"); + return false; + } + }; + emit_arena_top_addr(code, scratch.secondary, current_alloca_top); + emit(code, enc_str_imm(v, scratch.secondary, 0)); + true + } I::SetjmpAArch64 => { // c5 binds 's setjmp() to this intrinsic on // Windows aarch64 because msvcrt's longjmp routes @@ -4515,6 +4556,25 @@ fn spill_local_addr_to_dst(code: &mut Vec, dst: Place, src: Reg, frame: Fram } } +/// Materialize the per-frame alloca-arena bookkeeping slot address +/// (`fp - top_offset`) into `reg`. Mirrors the `AllocaInit` / +/// `Alloca` address computation for the VLA save / restore ops. +fn emit_arena_top_addr(code: &mut Vec, reg: Reg, top_offset: u32) { + if top_offset < 4096 { + emit(code, enc_sub_imm(reg, Reg(29), top_offset)); + } else { + let high = top_offset & !0xfff; + let low = top_offset & 0xfff; + emit( + code, + super::encode::enc_sub_imm_lsl12(reg, Reg(29), high >> 12), + ); + if low != 0 { + emit(code, enc_sub_imm(reg, reg, low)); + } + } +} + /// `Inst::Extend { value, kind }` -- sign-extend the low bytes of a /// GPR value to 64 bits via the `SXTB` / `SXTH` / `SXTW` aliases. fn emit_extend( diff --git a/src/c5/codegen/x86_64/emit.rs b/src/c5/codegen/x86_64/emit.rs index 4219be84f..6061c54ae 100644 --- a/src/c5/codegen/x86_64/emit.rs +++ b/src/c5/codegen/x86_64/emit.rs @@ -6633,6 +6633,50 @@ fn emit_intrinsic( spill_dst_to_slot(code, dst, rd_phys, frame); true } + I::AllocaSave => { + // Read the arena top for a VLA block snapshot (C99 6.7.6.2). + if current_alloca_top == 0 { + bail_msg("AllocaSave: AllocaInit didn't run for this function"); + return false; + } + let Some(rd) = int_or_spill_dst(dst) else { + bail_msg("AllocaSave: dst not int reg / spill"); + return false; + }; + let rd_phys = if matches!(dst, Place::Spill(_)) { + SCRATCH_R10 + } else { + rd + }; + emit_mov_r_mem(code, rd_phys, Reg::RBP, -(current_alloca_top as i32)); + spill_dst_to_slot(code, dst, rd_phys, frame); + true + } + I::AllocaRestore => { + // Restore the arena top on VLA block exit. + if current_alloca_top == 0 { + bail_msg("AllocaRestore: AllocaInit didn't run for this function"); + return false; + } + if args.len() != 1 { + bail_msg("AllocaRestore: expected 1 arg"); + return false; + } + let v_place = alloc + .places + .get(args[0] as usize) + .copied() + .unwrap_or(Place::None); + let v = match materialize_int(code, v_place, SCRATCH_R10, frame) { + Some(r) => r, + None => { + bail_msg("AllocaRestore: arg not int reg / spill / fp"); + return false; + } + }; + emit_mov_mem_r(code, Reg::RBP, -(current_alloca_top as i32), v); + true + } I::SetjmpAArch64 | I::LongjmpAArch64 => { bail_msg("intrinsic: AArch64 setjmp / longjmp on non-AArch64 target"); false diff --git a/src/c5/compiler/const_expr.rs b/src/c5/compiler/const_expr.rs index ca6a2f99d..29881569b 100644 --- a/src/c5/compiler/const_expr.rs +++ b/src/c5/compiler/const_expr.rs @@ -252,6 +252,51 @@ impl Compiler { Ok(self.parse_const_expr_cond_val()?.as_int()) } + /// Try to fold an array-declarator dimension to an integer + /// constant. Returns `Some(value)` for a constant dimension, or + /// `None` when the dimension is a non-constant expression (a C99 + /// 6.7.6.2 variable-length array) -- in which case the lexer is + /// restored so the caller can re-parse the dimension as a runtime + /// expression. + pub(super) fn try_parse_constant_dim(&mut self) -> Result, C5Error> { + let snap = self.lex.snapshot(); + self.pending.const_expr_nonconst = false; + match self.parse_const_expr_cond_val() { + // Folded to a constant; the caller validates the trailing `]`. + Ok(v) => Ok(Some(v.as_int())), + // Non-constant operand -> a VLA dimension: rewind for the + // caller's runtime-expression parse. + Err(_) if self.pending.const_expr_nonconst => { + self.lex.restore(snap); + Ok(None) + } + // A genuine constant-expression error (division by zero, an + // overflowing shift, ...) is diagnosed, not treated as a VLA. + Err(e) => Err(e), + } + } + + /// Consume an array-declarator dimension up to (not including) the + /// matching `]`. Used for a variable-length array parameter, whose + /// size is discarded when the array is adjusted to a pointer (C99 + /// 6.7.6.3p7); also absorbs the `[*]` unspecified-size form. + pub(super) fn skip_array_dimension_expr(&mut self) -> Result<(), C5Error> { + let mut depth: i64 = 0; + loop { + if self.lex.tk == Token::Brak { + depth += 1; + } else if self.lex.tk == ']' { + if depth == 0 { + return Ok(()); + } + depth -= 1; + } else if self.lex.tk == 0 { + return Err(self.compile_err("close bracket expected in array declarator")); + } + self.next()?; + } + } + /// Parse a C11 6.7.10 `_Static_assert(, /// "");` (or its C23 `static_assert` alias). /// On entry the current token is `Token::StaticAssert`. The @@ -945,6 +990,10 @@ impl Compiler { } else { alloc::string::String::new() }; + // Reached a non-constant operand rather than a malformed + // constant: the array-declarator reads this to tell a C99 + // 6.7.6.2 VLA dimension apart from a constant-expression error. + self.pending.const_expr_nonconst = true; Err(self.compile_err(format!( "constant integer expected (got {}{id_suffix})", super::super::token::describe(self.lex.tk), diff --git a/src/c5/compiler/declarator.rs b/src/c5/compiler/declarator.rs index c1324b08c..423be2f6a 100644 --- a/src/c5/compiler/declarator.rs +++ b/src/c5/compiler/declarator.rs @@ -509,15 +509,13 @@ impl Compiler { // decide how to interpret it. self.next()?; array_size = -1; - } else { - // `int xs[N]` -- N must fold to a positive integer - // constant. The constant-expression evaluator - // accepts integer literals (with optional unary - // minus) and identifiers bound to compile-time - // integer constants (Token::Num via enum or via - // `#define`s the preprocessor folded into the - // source token stream). - let n = self.parse_constant_int()?; + } else if let Some(n) = self.try_parse_constant_dim()? { + // `int xs[N]` -- N folded to an integer constant. The + // constant-expression evaluator accepts integer literals + // (with optional unary minus) and identifiers bound to + // compile-time integer constants (Token::Num via enum or + // via `#define`s the preprocessor folded into the source + // token stream). if n < 0 { return Err( self.compile_err(format!("array dimension must be positive (got {n})")) @@ -533,6 +531,39 @@ impl Compiler { // allocated past the fixed part. Route it through the same // `array_size = -1` sentinel. array_size = if n == 0 { -1 } else { n }; + } else { + // Non-constant dimension (C99 6.7.6.2). In a parameter it + // is adjusted to a pointer, so the size is parsed and + // discarded (6.7.6.3p7). At block scope it declares a + // variable-length array. Everywhere else it is a + // constraint violation. + if param_ctx { + self.skip_array_dimension_expr()?; + // `skip_array_dimension_expr` stops at the `]`; consume + // it so the declarator resumes past the dimension. + self.next()?; + array_size = -1; + } else if self.pending.vla_allowed { + self.expr(Token::Assign as i64)?; + self.pending.vla_dim_expr = self.ast_acc.take(); + if self.lex.tk != ']' { + return Err(self.compile_err("close bracket expected in array declarator")); + } + self.next()?; + if self.lex.tk == Token::Brak { + return Err(self.compile_err( + "multidimensional variable-length arrays are not supported", + )); + } + array_size = super::VLA_ARRAY_SIZE; + if idx != usize::MAX { + return Ok((idx, ty, array_size)); + } + } else { + return Err( + self.compile_err("variable-length array is only allowed at block scope") + ); + } } // Trailing dimensions for N-dim arrays. c5 stores // `array_size = product(dims)` (total element count), @@ -556,7 +587,18 @@ impl Compiler { self.next()?; continue; } - let m = self.parse_constant_int()?; + let Some(m) = self.try_parse_constant_dim()? else { + // A non-constant inner dimension makes the whole + // object a variably-modified type (C99 6.7.6.2); c5's + // stride model is compile-time only, so reject it + // cleanly rather than miscompile the row stride. + if self.pending.vla_allowed || param_ctx { + return Err(self.compile_err( + "multidimensional variable-length arrays are not supported", + )); + } + return Err(self.compile_err("constant integer expected in array declarator")); + }; if m <= 0 { return Err( self.compile_err(format!("array dimension must be positive (got {m})")) diff --git a/src/c5/compiler/emit.rs b/src/c5/compiler/emit.rs index 21eca4518..f79c8b314 100644 --- a/src/c5/compiler/emit.rs +++ b/src/c5/compiler/emit.rs @@ -561,6 +561,9 @@ impl Compiler { // `array_dims` for the duration of its scope. Restore // copies the shadow back on scope exit. s.h_array_dims = s.array_dims.clone(); + s.h_is_vla = s.is_vla; + s.h_vla_ptr_slot = s.vla_ptr_slot; + s.h_vla_size_slot = s.vla_size_slot; } /// Inverse of [`Self::shadow_symbol`]: restore the saved outer @@ -576,6 +579,9 @@ impl Compiler { sym.array_size = sym.h_array_size; sym.inner_array_size = sym.h_inner_array_size; sym.array_dims = core::mem::take(&mut sym.h_array_dims); + sym.is_vla = sym.h_is_vla; + sym.vla_ptr_slot = sym.h_vla_ptr_slot; + sym.vla_size_slot = sym.h_vla_size_slot; sym.is_scope_static = false; sym.is_scope_typedef = false; } @@ -948,6 +954,62 @@ impl Compiler { .push_stmt(super::super::ast::Stmt::Decl(decl_id), pos) } + /// Push a `Decl::Vla` (C99 6.7.6.2) wrapped in a `Stmt::Decl` so + /// the block's item collection picks it up in source order. The + /// walker allocates the runtime-sized storage at this point. + pub(super) fn ast_emit_vla_decl( + &mut self, + sym: u32, + elem_ty: i64, + elem_size: i64, + ptr_slot: i64, + size_slot: i64, + dim: super::super::ast::ExprId, + ) -> super::super::ast::StmtId { + let pos = self.ast_src_pos(); + let decl_id = self.ast.push_decl( + super::super::ast::Decl::Vla { + sym, + elem_ty, + elem_size, + ptr_slot, + size_slot, + dim, + }, + pos, + ); + self.ast + .push_stmt(super::super::ast::Stmt::Decl(decl_id), pos) + } + + /// Push an `Expr::VlaBase` (a VLA identifier decayed to its + /// runtime base pointer, C99 6.3.2.1p3) and set it as the new + /// accumulator so the wrapping index / call-arg / assignment site + /// finds the pointer on `ast_acc`. + pub(super) fn ast_emit_vla_base( + &mut self, + ptr_slot: i64, + ty: i64, + ) -> super::super::ast::ExprId { + let pos = self.ast_src_pos(); + let id = self + .ast + .push_expr(super::super::ast::Expr::VlaBase { ptr_slot, ty }, pos); + self.ast_acc = Some(id); + id + } + + /// Push an `Expr::VlaSizeof` (the runtime byte count of a VLA, + /// C99 6.5.3.4p2) and set it as the new accumulator. + pub(super) fn ast_emit_vla_sizeof(&mut self, size_slot: i64) -> super::super::ast::ExprId { + let pos = self.ast_src_pos(); + let id = self + .ast + .push_expr(super::super::ast::Expr::VlaSizeof { size_slot }, pos); + self.ast_acc = Some(id); + id + } + /// Push an `Expr::Call` and set it as the new accumulator. /// Called by the function-call parser site after the per-arg /// temp store + reverse push + call dispatch lands. `callee` diff --git a/src/c5/compiler/expr.rs b/src/c5/compiler/expr.rs index 21a128c8b..dc32bba42 100644 --- a/src/c5/compiler/expr.rs +++ b/src/c5/compiler/expr.rs @@ -506,12 +506,15 @@ impl Compiler { let total_bytes = self.sizeof_operand_bytes()?; self.emit_imm(total_bytes); self.ty = Ty::Int as i64; - // Dual-emit: sizeof is a compile-time constant per - // 6.5.3.4p2. Seed the accumulator with the matching - // IntLit so a wrapping expression (call argument, - // binary op, assignment) finds the value on - // `ast_acc`. - self.ast_emit_int_lit(total_bytes, self.ty); + // C99 6.5.3.4p2: `sizeof` of a variable-length array is a + // runtime value -- emit a load of the VLA's byte-count + // slot. Every other operand folds to a compile-time + // constant; seed the accumulator with the matching IntLit. + if let Some(size_slot) = self.pending.sizeof_vla_size_slot.take() { + self.ast_emit_vla_sizeof(size_slot); + } else { + self.ast_emit_int_lit(total_bytes, self.ty); + } } else if self.lex.tk == Token::Alignof { // C11 6.5.3.4: `_Alignof ( type-name )`, a compile-time // constant. Emit the alignment as a runtime immediate and @@ -1317,6 +1320,7 @@ impl Compiler { self.ty = self.symbols[id_idx].type_; let is_struct_value = is_struct_ty(self.ty) && struct_ptr_depth(self.ty) == 0; let is_array_var = self.symbols[id_idx].array_size != 0; + let is_vla_var = self.symbols[id_idx].is_vla; // A function-pointer variable carries its callee parameter // types so the dereferenced-call shape `(*fp)(args)` (which // reaches the postfix path rather than the direct-identifier @@ -1335,7 +1339,14 @@ impl Compiler { // "address-as-value" rule but keep their type // because the `.field` operator needs the struct's // value type to look up offsets. - if is_array_var { + if is_vla_var { + // C99 6.3.2.1p3: a VLA decays to a pointer to its + // first element -- the runtime base pointer, loaded + // from the hidden slot, not a fixed frame address. + let ptr_slot = self.symbols[id_idx].vla_ptr_slot; + self.ty += Ty::Ptr as i64; + self.ast_emit_vla_base(ptr_slot, self.ty); + } else if is_array_var { if identifier_is_local { // Array decay produces the array's // address rather than a scalar value, so diff --git a/src/c5/compiler/locals.rs b/src/c5/compiler/locals.rs index 82c33a6a3..4d775f630 100644 --- a/src/c5/compiler/locals.rs +++ b/src/c5/compiler/locals.rs @@ -65,6 +65,10 @@ impl Compiler { /// emit its local declaration. A non-`Loc` binding (a redeclaration /// that resolved elsewhere) discards the carriers without emitting. pub(super) fn finalize_local_init(&mut self, loc_idx: usize) { + // A VLA already emitted its `Decl::Vla` in `allocate_vla_local`. + if self.symbols[loc_idx].is_vla { + return; + } if self.symbols[loc_idx].class == Token::Loc as i64 { let slot_off = self.symbols[loc_idx].val; let init = self.drain_pending_local_init(); @@ -132,7 +136,11 @@ impl Compiler { self.pending.base_is_function_type = base_is_function_type; self.pending.typedef_fn_proto = base_typedef_fn_proto; self.pending.fn_ptr_param_types = base_fn_ptr_param_types.clone(); + // C99 6.7.6.2: a non-constant array dimension at block scope + // is a variable-length array. + self.pending.vla_allowed = true; let (loc_idx, ty, mut array_size) = self.parse_declarator(lbt)?; + self.pending.vla_allowed = false; // C23 6.7.13.5 `[[maybe_unused]]` / GNU // `__attribute__((unused))` on the declaration suppresses // the unused-variable diagnostic for the names it declares. @@ -612,12 +620,49 @@ impl Compiler { /// * deferred-size array (`int xs[] = {...};`): the /// initializer determines the dimension first, then storage /// is reserved. + /// C99 6.7.6.2 variable-length array local. Reserves two hidden + /// frame slots -- the runtime base pointer and the runtime byte + /// count -- and records a `Decl::Vla`; the walker allocates the + /// storage from the per-frame alloca arena. The array is not + /// promotable and its storage is reclaimed on block exit by the + /// scope bracket `parse_block_stmt` emits. + fn allocate_vla_local(&mut self, loc_idx: usize, elem_ty: i64) -> Result<(), C5Error> { + // C99 6.7.8p3: a VLA declaration may not carry an initializer. + if self.lex.tk == Token::Assign { + return Err(self.compile_err("a variable-length array may not have an initializer")); + } + let dim = match self.pending.vla_dim_expr.take() { + Some(d) => d, + None => return Err(self.compile_err("variable-length array has no dimension")), + }; + let ptr_slot = self.reserve_slots(1); + let size_slot = self.reserve_slots(1); + let elem_size = self.size_of_type(elem_ty) as i64; + let s = &mut self.symbols[loc_idx]; + s.is_vla = true; + s.type_ = elem_ty; + s.array_size = 0; + s.vla_ptr_slot = ptr_slot; + s.vla_size_slot = size_slot; + s.was_written = true; + s.address_escaped = true; + self.func_vla_decls += 1; + // The VLA storage comes from the per-frame alloca arena, so the + // function reserves the arena and its bookkeeping slot. + self.uses_alloca_in_current_fn = true; + self.ast_emit_vla_decl(loc_idx as u32, elem_ty, elem_size, ptr_slot, size_slot, dim); + Ok(()) + } + pub(super) fn allocate_local_with_init( &mut self, loc_idx: usize, ty: i64, declared_array_size: i64, ) -> Result<(), C5Error> { + if declared_array_size == super::VLA_ARRAY_SIZE { + return self.allocate_vla_local(loc_idx, ty); + } // C99 6.7.9: an initializer at the declaration site counts // as a store from the perspective of the dead-store // analysis. Mark before parsing the initializer so diff --git a/src/c5/compiler/mod.rs b/src/c5/compiler/mod.rs index e15984660..df0952b57 100644 --- a/src/c5/compiler/mod.rs +++ b/src/c5/compiler/mod.rs @@ -295,6 +295,12 @@ impl CompileOptions { /// function-pointer chain-depth tracker into one carrier so the /// `Compiler` field list reads as "lexer + symbols + codegen /// output + transient state" instead of eleven loose fields. +/// Sentinel `array_size` for a C99 6.7.6.2 variable-length array +/// declarator: distinct from `0` (scalar), `> 0` (constant array), +/// and `-1` (deferred / flexible `T x[]`). The dimension expression +/// rides on `Pending::vla_dim_expr`. +pub(in crate::c5::compiler) const VLA_ARRAY_SIZE: i64 = -2; + #[derive(Debug)] pub(in crate::c5::compiler) struct Pending { /// Side channel from the base-type parsers @@ -428,6 +434,26 @@ pub(in crate::c5::compiler) struct Pending { /// the array length. Cleared by every base-type parse /// (`0` means "not from an array typedef"). pub typedef_base_array_size: i64, + /// Set true while parsing a block-scope object declarator, where + /// a non-constant array dimension is a C99 6.7.6.2 variable-length + /// array. Elsewhere (file scope, struct member, typedef, cast, + /// sizeof) a non-constant dimension is a constraint violation. + pub vla_allowed: bool, + /// The declarator's parsed VLA dimension expression, set when the + /// leading `[expr]` was non-constant and `vla_allowed`. `None` for + /// a constant-dimension array. Consumed by the local-decl site. + pub vla_dim_expr: Option, + /// Set by `sizeof_operand_bytes` to the VLA's runtime-byte-count + /// slot when the operand is a variable-length array (C99 + /// 6.5.3.4p2); the `sizeof` site then emits a runtime load instead + /// of a constant. `None` for a constant-size operand. + pub sizeof_vla_size_slot: Option, + /// Set by the constant-expression evaluator when it fails because it + /// reached a non-constant operand (a runtime identifier, call, ...), + /// as opposed to a malformed constant (division by zero, ...). Lets + /// the array-declarator distinguish a C99 6.7.6.2 VLA dimension from + /// a genuine constant-expression error that must be diagnosed. + pub const_expr_nonconst: bool, /// Binding-site carrier for a function-pointer typedef's /// prototype: `Some((fixed_param_count, is_variadic))` when the /// base type was a typedef whose alias is a function-pointer @@ -623,6 +649,10 @@ impl Default for Pending { init_inner_dims: alloc::vec::Vec::new(), init_target_array_size: 0, typedef_base_array_size: 0, + vla_allowed: false, + vla_dim_expr: None, + sizeof_vla_size_slot: None, + const_expr_nonconst: false, typedef_fn_proto: None, fn_ptr_param_types: None, indirect_callee_params: None, @@ -701,6 +731,13 @@ pub struct Compiler { /// definition. uses_alloca_in_current_fn: bool, + /// Count of C99 6.7.6.2 variable-length arrays declared so far in + /// the current function. Snapshotted around a block's declarations + /// so `parse_block_stmt` knows whether to bracket the block with + /// the alloca-arena save / restore that reclaims VLA storage on + /// exit. Reset on each new function definition. + func_vla_decls: usize, + /// True when the most recent decl-spec parse consumed an /// `inline` / `__inline` / `__inline__` keyword. Captured at /// function-symbol commit time onto `FinishedFunction::is_inline` @@ -1194,7 +1231,7 @@ impl Compiler { /// Reserve `n_slots` eight-byte frame cells and return the /// negative base offset, bumping the high-water mark. Callers /// own any `multi_cell_temps` push and any `loc_offs` recycle. - fn reserve_slots(&mut self, n_slots: i64) -> i64 { + pub(super) fn reserve_slots(&mut self, n_slots: i64) -> i64 { self.loc_offs += n_slots; if self.loc_offs > self.max_loc_offs { self.max_loc_offs = self.loc_offs; @@ -1312,6 +1349,7 @@ impl Compiler { max_loc_offs: 0, multi_cell_temps: alloc::vec::Vec::new(), uses_alloca_in_current_fn: false, + func_vla_decls: 0, pending_is_inline: false, pending_noreturn: false, const_unevaluated: 0, diff --git a/src/c5/compiler/run_compile.rs b/src/c5/compiler/run_compile.rs index 650c48026..ab2a98408 100644 --- a/src/c5/compiler/run_compile.rs +++ b/src/c5/compiler/run_compile.rs @@ -878,6 +878,7 @@ impl Compiler { self.labels.clear(); self.unresolved_gotos.clear(); self.uses_alloca_in_current_fn = false; + self.func_vla_decls = 0; self.ast_reset(); let ent_pc = self.next_ent_pc; diff --git a/src/c5/compiler/sizeof_expr.rs b/src/c5/compiler/sizeof_expr.rs index 6c824d7dd..5698e5b10 100644 --- a/src/c5/compiler/sizeof_expr.rs +++ b/src/c5/compiler/sizeof_expr.rs @@ -50,6 +50,9 @@ impl Compiler { } pub(super) fn sizeof_operand_bytes(&mut self) -> Result { + // Cleared each call; set only when the operand is a VLA whose + // size the `sizeof` site must read at runtime (C99 6.5.3.4p2). + self.pending.sizeof_vla_size_slot = None; // Snapshot the lex state before any speculative paren // consumption so the operand-shape dispatch below can // restore when `sizeof (expr)->m` turns out to wrap the @@ -155,6 +158,12 @@ impl Compiler { let idx = self.lex.curr_id_idx; let var_ty = self.symbols[idx].type_; let arr = self.symbols[idx].array_size; + // C99 6.5.3.4p2: `sizeof` of a VLA is the runtime byte + // count. Signal the caller to load it from the VLA's + // size slot; the returned constant is unused in that case. + if self.symbols[idx].is_vla { + self.pending.sizeof_vla_size_slot = Some(self.symbols[idx].vla_size_slot); + } self.next()?; if arr > 0 { arr * self.size_of_type(var_ty) as i64 diff --git a/src/c5/compiler/stmt.rs b/src/c5/compiler/stmt.rs index e6312f8e1..3096ca935 100644 --- a/src/c5/compiler/stmt.rs +++ b/src/c5/compiler/stmt.rs @@ -346,7 +346,11 @@ impl Compiler { self.pending.base_is_function_type = base_is_function_type; self.pending.typedef_fn_proto = base_typedef_fn_proto; self.pending.fn_ptr_param_types = base_fn_ptr_param_types.clone(); + // C99 6.7.6.2: a non-constant array dimension at block scope + // is a variable-length array. + self.pending.vla_allowed = true; let (loc_idx, ty, mut array_size) = self.parse_declarator(lbt)?; + self.pending.vla_allowed = false; // C99 6.3.2.1p4: a function-pointer rvalue auto-decays // through any unary `*` chain. The `Symbol::fn_ptr_indirection` // side-channel records how many indirection levels sit between @@ -490,6 +494,10 @@ impl Compiler { let mut block_symbols = Vec::new(); let mut top_level_ids: alloc::vec::Vec = alloc::vec::Vec::new(); + // C99 6.2.4p2: a VLA declared directly in this block has its + // storage reclaimed on block exit. Track whether any appears so + // the block is bracketed with the alloca-arena save / restore. + let mut block_has_vla = false; while self.lex.tk != '}' { // C23 6.7.13 / 6.8: an attribute-specifier-sequence may // lead either a declaration or a statement at block scope. @@ -514,7 +522,11 @@ impl Compiler { } else if self.lex_is_type_start() { let item_before = self.ast_stmts_snapshot(); let sym_before = block_symbols.len(); + let vla_before = self.func_vla_decls; self.parse_block_local_decl(&mut block_symbols)?; + if self.func_vla_decls > vla_before { + block_has_vla = true; + } if leading_maybe_unused { // C23 6.7.13.5: `[[maybe_unused]]` on a declaration // suppresses the unused diagnostics for the names it @@ -547,6 +559,24 @@ impl Compiler { top_level_ids.push(item_id); } } + // C99 6.2.4p2: bracket a VLA-declaring block so the arena top + // is snapshotted on entry and restored on exit, reclaiming the + // VLA storage (per iteration when the block is a loop body). + if block_has_vla { + let save_slot = self.reserve_slots(1); + let pos = self.ast_src_pos(); + let enter = self + .ast + .push_stmt(super::super::ast::Stmt::VlaScopeEnter { save_slot }, pos); + let exit = self + .ast + .push_stmt(super::super::ast::Stmt::VlaScopeExit { save_slot }, pos); + let mut bracketed = alloc::vec::Vec::with_capacity(top_level_ids.len() + 2); + bracketed.push(enter); + bracketed.extend_from_slice(&top_level_ids); + bracketed.push(exit); + top_level_ids = bracketed; + } // Wrap the collected top-level stmt ids into a // `Stmt::Compound`. Only this Compound references the // top-level stmts -- inner wrappers are dead AST entries diff --git a/src/c5/op.rs b/src/c5/op.rs index afe7dcfc4..3a32ffd24 100644 --- a/src/c5/op.rs +++ b/src/c5/op.rs @@ -186,6 +186,16 @@ pub enum Intrinsic { /// (eax/edx destinations) then the input value (ecx = register index). /// x86_64 only. The interpreter zeroes the outputs. Xgetbv = 45, + /// Read the current per-frame alloca-arena top pointer (the + /// bookkeeping slot the matching `AllocaInit` set up). Takes no + /// argument, returns the top. Used to snapshot the arena on entry + /// to a block that declares a variable-length array (C99 6.7.6.2) + /// so the storage is reclaimed on block exit. + AllocaSave = 46, + /// Write the per-frame alloca-arena top pointer back to a value a + /// prior `AllocaSave` captured. One argument (the saved top); + /// returns nothing. Reclaims a VLA block's storage on exit. + AllocaRestore = 47, } impl Intrinsic { @@ -236,6 +246,8 @@ impl Intrinsic { 43 => Some(Intrinsic::AtomicThreadFence), 44 => Some(Intrinsic::Cpuid), 45 => Some(Intrinsic::Xgetbv), + 46 => Some(Intrinsic::AllocaSave), + 47 => Some(Intrinsic::AllocaRestore), _ => None, } } diff --git a/src/c5/preprocessor.rs b/src/c5/preprocessor.rs index 304bdcbfe..9c800b5eb 100644 --- a/src/c5/preprocessor.rs +++ b/src/c5/preprocessor.rs @@ -490,7 +490,8 @@ impl Preprocessor { // thread-local storage. GCC and clang made the same choice while // they lacked ``. `` is provided, so // `__STDC_NO_ATOMICS__` also stays undefined. - macros.insert("__STDC_NO_VLA__".to_string(), "1".to_string()); + // `__STDC_NO_VLA__` stays undefined: c5 supports C99 6.7.6.2 + // variable-length arrays (single dimension, block scope). macros.insert("__STDC_NO_COMPLEX__".to_string(), "1".to_string()); macros.insert( "__DATE__".to_string(), diff --git a/src/c5/symbol.rs b/src/c5/symbol.rs index f41ef5c0b..a77548f21 100644 --- a/src/c5/symbol.rs +++ b/src/c5/symbol.rs @@ -94,6 +94,24 @@ pub(crate) struct Symbol { /// Shadow slot for `array_dims`. See `h_array_size`. pub h_array_dims: Vec, + /// True for a C99 6.7.6.2 variable-length array local: the + /// element count is a runtime expression, so the storage is + /// allocated from the per-frame alloca arena rather than a fixed + /// frame slot. `type_` holds the element type; `array_size` stays + /// 0 (it is not a constant array). `vla_ptr_slot` is the hidden + /// frame slot holding the runtime base pointer; `vla_size_slot` + /// holds the runtime byte count so `sizeof` reports `n * + /// sizeof(elem)` per 6.5.3.4p2. + pub is_vla: bool, + pub vla_ptr_slot: i64, + pub vla_size_slot: i64, + /// Shadow slots for the VLA fields, saved / restored alongside + /// `array_size` so an inner binding that reuses the name does not + /// corrupt an outer VLA (C99 6.2.1p4). + pub h_is_vla: bool, + pub h_vla_ptr_slot: i64, + pub h_vla_size_slot: i64, + /// True once a `Token::Glo` symbol has been seen with an /// explicit initializer (`= ...`). Tentative-definition /// merges (C11 6.9.2): a forward `static T x;` (or the same diff --git a/src/c5/tests/mod.rs b/src/c5/tests/mod.rs index cac735b5f..93f609543 100644 --- a/src/c5/tests/mod.rs +++ b/src/c5/tests/mod.rs @@ -46,6 +46,7 @@ mod programs; #[cfg(feature = "full")] mod reloc_golden; mod types; +mod vla; /// Absolute path of `tests/fixtures/c/` relative to the crate root. fn fixture_path(name: &str) -> PathBuf { diff --git a/src/c5/tests/native.rs b/src/c5/tests/native.rs index 7d4283a29..decd95767 100644 --- a/src/c5/tests/native.rs +++ b/src/c5/tests/native.rs @@ -365,6 +365,11 @@ fn build_and_run_fixture_with_options(name: &str, opts: NativeOptions, suffix: & /// pointers resolve to native offsets via `FuncFixup`, so fixtures /// that exercise those paths run end-to-end. const NATIVE_FIXTURES: &[(&str, i32)] = &[ + ("vla_basic_sum.c", 0), + ("vla_runtime_sizeof.c", 0), + ("vla_size_from_arg.c", 0), + ("vla_scope_reclaim_loop.c", 0), + ("vla_param_decay.c", 0), ("mem2reg_param_promoted.c", 0), ("phi_class_for_loop_sum.c", 45), ("phi_class_nested_loops.c", 49), diff --git a/src/c5/tests/native_elf.rs b/src/c5/tests/native_elf.rs index 29fd3fba5..fee4718aa 100644 --- a/src/c5/tests/native_elf.rs +++ b/src/c5/tests/native_elf.rs @@ -315,6 +315,11 @@ fn build_and_run_fixture_with_options(name: &str, opts: NativeOptions, suffix: & /// stay in sync because both backends should faithfully execute the /// same fixtures; if they drift, one of them has a bug. const NATIVE_ELF_FIXTURES: &[(&str, i32)] = &[ + ("vla_basic_sum.c", 0), + ("vla_runtime_sizeof.c", 0), + ("vla_size_from_arg.c", 0), + ("vla_scope_reclaim_loop.c", 0), + ("vla_param_decay.c", 0), ("arithmetic.c", 60), ("goto.c", 5), ("switch_statement.c", 25), diff --git a/src/c5/tests/native_elf_x64.rs b/src/c5/tests/native_elf_x64.rs index 8b4ebd042..15407c8aa 100644 --- a/src/c5/tests/native_elf_x64.rs +++ b/src/c5/tests/native_elf_x64.rs @@ -275,6 +275,11 @@ fn build_and_run_fixture_with_options(name: &str, opts: NativeOptions, suffix: & } const NATIVE_ELF_X64_FIXTURES: &[(&str, i32)] = &[ + ("vla_basic_sum.c", 0), + ("vla_runtime_sizeof.c", 0), + ("vla_size_from_arg.c", 0), + ("vla_scope_reclaim_loop.c", 0), + ("vla_param_decay.c", 0), ("arithmetic.c", 60), ("goto.c", 5), ("switch_statement.c", 25), diff --git a/src/c5/tests/native_pe_arm64.rs b/src/c5/tests/native_pe_arm64.rs index 84ffaf3f3..e003473ba 100644 --- a/src/c5/tests/native_pe_arm64.rs +++ b/src/c5/tests/native_pe_arm64.rs @@ -619,6 +619,11 @@ fn build_and_run_fixture_with_options(name: &str, opts: NativeOptions, suffix: & /// limitations (POSIX-only setenv shape, dlopen-against-libc-soname) /// are arch-independent. const NATIVE_PE_ARM64_FIXTURES: &[(&str, i32)] = &[ + ("vla_basic_sum.c", 0), + ("vla_runtime_sizeof.c", 0), + ("vla_size_from_arg.c", 0), + ("vla_scope_reclaim_loop.c", 0), + ("vla_param_decay.c", 0), ("arithmetic.c", 60), ("strtof_parses_float.c", 0), ("snprintf_truncation_c99.c", 0), diff --git a/src/c5/tests/native_pe_x64.rs b/src/c5/tests/native_pe_x64.rs index 82a2b967d..eb83de562 100644 --- a/src/c5/tests/native_pe_x64.rs +++ b/src/c5/tests/native_pe_x64.rs @@ -632,6 +632,11 @@ fn build_and_run_fixture_with_options(name: &str, opts: NativeOptions, suffix: & /// Subset of the cross-arch fixture corpus that doesn't lean on /// POSIX-only semantics. const NATIVE_PE_X64_FIXTURES: &[(&str, i32)] = &[ + ("vla_basic_sum.c", 0), + ("vla_runtime_sizeof.c", 0), + ("vla_size_from_arg.c", 0), + ("vla_scope_reclaim_loop.c", 0), + ("vla_param_decay.c", 0), ("arithmetic.c", 60), ("strtof_parses_float.c", 0), ("snprintf_truncation_c99.c", 0), diff --git a/src/c5/tests/vla.rs b/src/c5/tests/vla.rs new file mode 100644 index 000000000..721ed3b67 --- /dev/null +++ b/src/c5/tests/vla.rs @@ -0,0 +1,92 @@ +//! C99 6.7.6.2 variable-length array regression tests. +//! +//! The runnable fixtures go through the JIT, whose lowering is the same +//! as the AOT Mach-O / ELF backends; those backends also run the same +//! fixtures through their `fixture_parity` tables (see +//! `super::native::NATIVE_FIXTURES`, `super::native_elf`, +//! `super::native_elf_x64`). The constraint-violation fixtures assert a +//! clean compile-time diagnostic rather than a miscompile. + +use crate::Compiler; + +/// Compile a fixture and return the diagnostic message, panicking if it +/// compiled. Used for the C99 constraint violations that must be +/// rejected, not silently accepted. +fn compile_error(name: &str) -> String { + let src = super::load_fixture(name); + match Compiler::new(super::with_prelude(&src)).compile() { + Ok(_) => panic!("{name}: expected a compile error, but it compiled"), + Err(e) => alloc::format!("{e}"), + } +} + +#[test] +fn multidim_vla_rejected() { + assert!( + compile_error("vla_multidim_rejected.c").contains("multidimensional variable-length"), + "wrong diagnostic for a multidimensional VLA" + ); +} + +#[test] +fn file_scope_vla_rejected() { + assert!( + compile_error("vla_file_scope_rejected.c").contains("variable-length array"), + "wrong diagnostic for a file-scope VLA" + ); +} + +#[test] +fn vla_initializer_rejected() { + assert!( + compile_error("vla_initializer_rejected.c").contains("may not have an initializer"), + "wrong diagnostic for an initialized VLA" + ); +} + +/// The runnable fixtures execute through the JIT on the hosts where the +/// loader is implemented (Linux aarch64 / x86_64, macOS arm64). Each +/// fixture self-checks and returns 0 on success. +#[cfg(any( + all( + target_os = "linux", + any(target_arch = "aarch64", target_arch = "x86_64") + ), + all(target_os = "macos", target_arch = "aarch64"), +))] +mod jit_lane { + use crate::{Compiler, jit_run}; + + fn jit_fixture_exit(name: &str) -> i32 { + let src = super::super::load_fixture(name); + let program = Compiler::new(super::super::with_prelude(&src)) + .compile() + .expect("compile failed"); + jit_run(&program, &[name.to_string()]).expect("jit_run failed") + } + + #[test] + fn basic_sum() { + assert_eq!(jit_fixture_exit("vla_basic_sum.c"), 0); + } + + #[test] + fn runtime_sizeof() { + assert_eq!(jit_fixture_exit("vla_runtime_sizeof.c"), 0); + } + + #[test] + fn size_from_arg() { + assert_eq!(jit_fixture_exit("vla_size_from_arg.c"), 0); + } + + #[test] + fn scope_reclaim_loop() { + assert_eq!(jit_fixture_exit("vla_scope_reclaim_loop.c"), 0); + } + + #[test] + fn param_decay() { + assert_eq!(jit_fixture_exit("vla_param_decay.c"), 0); + } +} diff --git a/src/c5/vm/ssa.rs b/src/c5/vm/ssa.rs index bd0fc27fc..ae21313be 100644 --- a/src/c5/vm/ssa.rs +++ b/src/c5/vm/ssa.rs @@ -1956,6 +1956,23 @@ fn run_intrinsic( frame.regs[v as usize] = base as i64; Ok(()) } + // VLA block reclamation (C99 6.7.6.2): snapshot / restore the + // frame's bump-allocation cursor so a VLA declared in a block + // (or a loop body, once per iteration) frees on exit. + Intrinsic::AllocaSave => { + frame.regs[v as usize] = mem.stack_top as i64; + Ok(()) + } + Intrinsic::AllocaRestore => { + let saved = args + .first() + .map(|&a| frame.regs[a as usize]) + .ok_or_else(|| { + C5Error::Runtime("vm_ssa: AllocaRestore expects 1 argument".to_string()) + })?; + mem.release_frame(saved as usize); + Ok(()) + } Intrinsic::VaStart => { let ap_addr = frame.regs[args[0] as usize] as usize; let last_addr = frame.regs[args[1] as usize]; diff --git a/tests/fixtures/c/predefined_macros.c b/tests/fixtures/c/predefined_macros.c index f9f2ea3cd..5d5c8416a 100644 --- a/tests/fixtures/c/predefined_macros.c +++ b/tests/fixtures/c/predefined_macros.c @@ -42,12 +42,13 @@ int main() { if (file_str[0] == 0) return 9; // C11 6.10.8.3 conditional-feature macros. badc reports - // __STDC_VERSION__ == 201112L and provides neither variable length - // arrays nor _Complex, so it predefines those two to 1. + // __STDC_VERSION__ == 201112L. It supports C99 6.7.6.2 variable + // length arrays, so __STDC_NO_VLA__ stays undefined; it does not + // provide _Complex, so __STDC_NO_COMPLEX__ is predefined to 1. // __STDC_NO_THREADS__ stays undefined (badc supports the // _Thread_local storage classifier that code gates on this macro), // and __STDC_NO_ATOMICS__ stays undefined ( is provided). -#if !defined(__STDC_NO_VLA__) || (__STDC_NO_VLA__ != 1) +#ifdef __STDC_NO_VLA__ return 10; #endif #if !defined(__STDC_NO_COMPLEX__) || (__STDC_NO_COMPLEX__ != 1) diff --git a/tests/fixtures/c/vla_basic_sum.c b/tests/fixtures/c/vla_basic_sum.c new file mode 100644 index 000000000..ac09daa8b --- /dev/null +++ b/tests/fixtures/c/vla_basic_sum.c @@ -0,0 +1,24 @@ +/* C99 6.7.6.2 variable-length array: a runtime-sized local array, read + and written elementwise. Returns 0 on success. */ +static int compute(int n) { + int a[n]; + for (int i = 0; i < n; i++) { + a[i] = i * 2; + } + int s = 0; + for (int i = 0; i < n; i++) { + s += a[i]; + } + return s; +} + +int main(void) { + /* 0 + 2 + 4 + 6 + 8 = 20 */ + if (compute(5) != 20) { + return 1; + } + if (compute(1) != 0) { + return 2; + } + return 0; +} diff --git a/tests/fixtures/c/vla_file_scope_rejected.c b/tests/fixtures/c/vla_file_scope_rejected.c new file mode 100644 index 000000000..7deb05926 --- /dev/null +++ b/tests/fixtures/c/vla_file_scope_rejected.c @@ -0,0 +1,5 @@ +/* C99 6.7.6.2p2: a variably-modified type at file scope is a + constraint violation. */ +extern int n; +int g[n]; +int main(void) { return 0; } diff --git a/tests/fixtures/c/vla_initializer_rejected.c b/tests/fixtures/c/vla_initializer_rejected.c new file mode 100644 index 000000000..db7553888 --- /dev/null +++ b/tests/fixtures/c/vla_initializer_rejected.c @@ -0,0 +1,5 @@ +/* C99 6.7.8p3: a variable-length array may not have an initializer. */ +int f(int n) { + int a[n] = {1, 2, 3}; + return a[0]; +} diff --git a/tests/fixtures/c/vla_multidim_rejected.c b/tests/fixtures/c/vla_multidim_rejected.c new file mode 100644 index 000000000..f608ba584 --- /dev/null +++ b/tests/fixtures/c/vla_multidim_rejected.c @@ -0,0 +1,7 @@ +/* Multidimensional VLAs need runtime element strides, which c5's + compile-time stride model cannot represent; rejected cleanly rather + than miscompiled (C99 6.7.6.2). */ +int f(int n, int m) { + int a[n][m]; + return a[0][0]; +} diff --git a/tests/fixtures/c/vla_param_decay.c b/tests/fixtures/c/vla_param_decay.c new file mode 100644 index 000000000..389a3f7e3 --- /dev/null +++ b/tests/fixtures/c/vla_param_decay.c @@ -0,0 +1,17 @@ +/* C99 6.7.6.3p7: a variable-length array parameter is adjusted to a + pointer to the element type; the dimension expression documents the + intent but the parameter is passed as a plain pointer. */ +static int dot(int n, int a[n], int b[n]) { + int s = 0; + for (int i = 0; i < n; i++) { + s += a[i] * b[i]; + } + return s; +} + +int main(void) { + int x[4] = {1, 2, 3, 4}; + int y[4] = {5, 6, 7, 8}; + /* 5 + 12 + 21 + 32 = 70 */ + return dot(4, x, y) == 70 ? 0 : 1; +} diff --git a/tests/fixtures/c/vla_runtime_sizeof.c b/tests/fixtures/c/vla_runtime_sizeof.c new file mode 100644 index 000000000..3cc222bcb --- /dev/null +++ b/tests/fixtures/c/vla_runtime_sizeof.c @@ -0,0 +1,20 @@ +/* C99 6.5.3.4p2: sizeof applied to a variable-length array is a + runtime value, n * sizeof(element). The size is fixed at the + declaration (6.7.6.2p4), so a later change to n does not affect it. */ +int main(void) { + int n = 7; + long a[n]; + unsigned long sz = sizeof(a); + if (sz != (unsigned long)n * sizeof(long)) { + return 1; + } + /* sizeof(a) / sizeof(a[0]) recovers the element count. */ + if (sz / sizeof(a[0]) != (unsigned long)n) { + return 2; + } + n = 100; + if (sizeof(a) != 7 * sizeof(long)) { + return 3; + } + return 0; +} diff --git a/tests/fixtures/c/vla_scope_reclaim_loop.c b/tests/fixtures/c/vla_scope_reclaim_loop.c new file mode 100644 index 000000000..d0990fb8e --- /dev/null +++ b/tests/fixtures/c/vla_scope_reclaim_loop.c @@ -0,0 +1,20 @@ +/* C99 6.2.4p2: a VLA declared in a loop body is reclaimed on each + iteration. The per-frame arena is fixed-size, so without the arena + top being restored per iteration this would exhaust it and trap long + before the loop ends. Self-checks the accumulated value. */ +int main(void) { + long total = 0; + for (int iter = 0; iter < 100000; iter++) { + int n = 64; + int a[n]; + for (int i = 0; i < n; i++) { + a[i] = i; + } + total += a[iter & 63]; + } + long expect = 0; + for (int iter = 0; iter < 100000; iter++) { + expect += (iter & 63); + } + return total == expect ? 0 : 1; +} diff --git a/tests/fixtures/c/vla_size_from_arg.c b/tests/fixtures/c/vla_size_from_arg.c new file mode 100644 index 000000000..33d7359ef --- /dev/null +++ b/tests/fixtures/c/vla_size_from_arg.c @@ -0,0 +1,22 @@ +/* A variable-length array whose dimension is a function argument. */ +static int fill_and_sum(int n) { + char buf[n]; + for (int i = 0; i < n; i++) { + buf[i] = (char)(i + 1); + } + int s = 0; + for (int i = 0; i < n; i++) { + s += buf[i]; + } + return s; +} + +int main(void) { + if (fill_and_sum(10) != 55) { + return 1; + } + if (fill_and_sum(4) != 10) { + return 2; + } + return 0; +} From 4b194dd4c0a51f7420ede6620097262f60fc8975 Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 02:07:57 -0700 Subject: [PATCH 65/67] tests: snapshots for the VLA fixtures Co-Authored-By: Claude Fable 5 --- tests/snapshots/asm/vla_basic_sum.aarch64.asm | 98 ++++++++++++ tests/snapshots/asm/vla_basic_sum.x64.asm | 103 ++++++++++++ .../snapshots/asm/vla_param_decay.aarch64.asm | 69 +++++++++ tests/snapshots/asm/vla_param_decay.x64.asm | 77 +++++++++ .../asm/vla_runtime_sizeof.aarch64.asm | 76 +++++++++ .../snapshots/asm/vla_runtime_sizeof.x64.asm | 69 +++++++++ .../asm/vla_scope_reclaim_loop.aarch64.asm | 121 +++++++++++++++ .../asm/vla_scope_reclaim_loop.x64.asm | 106 +++++++++++++ .../asm/vla_size_from_arg.aarch64.asm | 101 ++++++++++++ tests/snapshots/asm/vla_size_from_arg.x64.asm | 104 +++++++++++++ tests/snapshots/ssa/vla_basic_sum.ssa | 136 ++++++++++++++++ tests/snapshots/ssa/vla_param_decay.ssa | 125 +++++++++++++++ tests/snapshots/ssa/vla_runtime_sizeof.ssa | 94 +++++++++++ .../snapshots/ssa/vla_scope_reclaim_loop.ssa | 146 ++++++++++++++++++ tests/snapshots/ssa/vla_size_from_arg.ssa | 135 ++++++++++++++++ 15 files changed, 1560 insertions(+) create mode 100644 tests/snapshots/asm/vla_basic_sum.aarch64.asm create mode 100644 tests/snapshots/asm/vla_basic_sum.x64.asm create mode 100644 tests/snapshots/asm/vla_param_decay.aarch64.asm create mode 100644 tests/snapshots/asm/vla_param_decay.x64.asm create mode 100644 tests/snapshots/asm/vla_runtime_sizeof.aarch64.asm create mode 100644 tests/snapshots/asm/vla_runtime_sizeof.x64.asm create mode 100644 tests/snapshots/asm/vla_scope_reclaim_loop.aarch64.asm create mode 100644 tests/snapshots/asm/vla_scope_reclaim_loop.x64.asm create mode 100644 tests/snapshots/asm/vla_size_from_arg.aarch64.asm create mode 100644 tests/snapshots/asm/vla_size_from_arg.x64.asm create mode 100644 tests/snapshots/ssa/vla_basic_sum.ssa create mode 100644 tests/snapshots/ssa/vla_param_decay.ssa create mode 100644 tests/snapshots/ssa/vla_runtime_sizeof.ssa create mode 100644 tests/snapshots/ssa/vla_scope_reclaim_loop.ssa create mode 100644 tests/snapshots/ssa/vla_size_from_arg.ssa diff --git a/tests/snapshots/asm/vla_basic_sum.aarch64.asm b/tests/snapshots/asm/vla_basic_sum.aarch64.asm new file mode 100644 index 000000000..03acfe6fb --- /dev/null +++ b/tests/snapshots/asm/vla_basic_sum.aarch64.asm @@ -0,0 +1,98 @@ + +vla_basic_sum.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + str x0, [sp, #-0x10]! + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x2, lsl #12 // =0x2000 + sub sp, sp, #0x40 + str x19, [sp] + sub x16, x29, #0x30 + str x16, [x16] + stur w0, [x29, #0x10] + ldursw x0, [x29, #0x10] + lsl x0, x0, #2 + stur x0, [x29, #-0x10] + add x17, x0, #0xf + and x17, x17, #0xfffffffffffffff0 + sub x16, x29, #0x30 + ldr x0, [x16] + sub x0, x0, x17 + sub x17, x16, #0x2, lsl #12 // =0x2000 + cmp x0, x17 + b.hs + brk #0x1 + str x0, [x16] + stur x0, [x29, #-0x8] + mov x0, #0x0 // =0 + stur w0, [x29, #-0x18] + ldursw x0, [x29, #-0x18] + ldursw x1, [x29, #0x10] + cmp x0, x1 + b.ge + b + ldursw x0, [x29, #-0x18] + add x0, x0, #0x1 + stur w0, [x29, #-0x18] + b + ldur x0, [x29, #-0x8] + ldursw x1, [x29, #-0x18] + lsl x2, x1, #1 + str w2, [x0, x1, lsl #2] + b + mov x0, #0x0 // =0 + stur w0, [x29, #-0x20] + stur w0, [x29, #-0x28] + ldursw x0, [x29, #-0x28] + ldursw x1, [x29, #0x10] + cmp x0, x1 + b.ge + b + ldursw x0, [x29, #-0x28] + add x0, x0, #0x1 + stur w0, [x29, #-0x28] + b + ldursw x0, [x29, #-0x20] + ldur x1, [x29, #-0x8] + ldursw x2, [x29, #-0x28] + ldrsw x1, [x1, x2, lsl #2] + add x0, x0, x1 + stur w0, [x29, #-0x20] + b + ldursw x0, [x29, #-0x20] + ldr x19, [sp] + add sp, sp, #0x2, lsl #12 // =0x2000 + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0x10 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + mov x0, #0x5 // =5 + bl + cmp x0, #0x14 + b.eq + mov x0, #0x1 // =1 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x1 // =1 + bl + cmp x0, #0x0 + b.eq + mov x0, #0x2 // =2 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/vla_basic_sum.x64.asm b/tests/snapshots/asm/vla_basic_sum.x64.asm new file mode 100644 index 000000000..50e084120 --- /dev/null +++ b/tests/snapshots/asm/vla_basic_sum.x64.asm @@ -0,0 +1,103 @@ + +vla_basic_sum.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + popq %r10 + subq $0x10, %rsp + movq %rdi, (%rsp) + pushq %r10 + pushq %rbp + movq %rsp, %rbp + subq $0x2030, %rsp # imm = 0x2030 + leaq -0x30(%rbp), %r10 + movq %r10, (%r10) + movl %edi, 0x10(%rbp) + movslq 0x10(%rbp), %rax + shlq $0x2, %rax + movq %rax, -0x10(%rbp) + movq %rax, %r10 + addq $0xf, %r10 + andq $-0x10, %r10 + leaq -0x30(%rbp), %r11 + movq (%r11), %rax + subq %r10, %rax + leaq -0x2000(%r11), %r10 + cmpq %r10, %rax + jae + ud2 + movq %rax, (%r11) + movq %rax, -0x8(%rbp) + xorq %rax, %rax + movl %eax, -0x18(%rbp) + movslq -0x18(%rbp), %rax + movslq 0x10(%rbp), %rcx + cmpq %rcx, %rax + jge + jmp + movslq -0x18(%rbp), %rax + incq %rax + movl %eax, -0x18(%rbp) + jmp + movq -0x8(%rbp), %rax + movslq -0x18(%rbp), %rcx + movq %rcx, %rdx + shlq $0x1, %rdx + movl %edx, (%rax,%rcx,4) + jmp + xorq %rax, %rax + movl %eax, -0x20(%rbp) + movl %eax, -0x28(%rbp) + movslq -0x28(%rbp), %rax + movslq 0x10(%rbp), %rcx + cmpq %rcx, %rax + jge + jmp + movslq -0x28(%rbp), %rax + incq %rax + movl %eax, -0x28(%rbp) + jmp + movslq -0x20(%rbp), %rax + movq -0x8(%rbp), %rcx + movslq -0x28(%rbp), %rdx + movslq (%rcx,%rdx,4), %rcx + addq %rcx, %rax + movl %eax, -0x20(%rbp) + jmp + movslq -0x20(%rbp), %rax + addq $0x2030, %rsp # imm = 0x2030 + popq %rbp + popq %r11 + addq $0x10, %rsp + pushq %r11 + retq + +
: + pushq %rbp + movq %rsp, %rbp + movl $0x5, %edi + callq + cmpq $0x14, %rax + je + movl $0x1, %eax + popq %rbp + retq + movl $0x1, %edi + callq + testq %rax, %rax + je + movl $0x2, %eax + popq %rbp + retq + xorq %rax, %rax + popq %rbp + retq + addb %al, (%rax) diff --git a/tests/snapshots/asm/vla_param_decay.aarch64.asm b/tests/snapshots/asm/vla_param_decay.aarch64.asm new file mode 100644 index 000000000..ead0a86c0 --- /dev/null +++ b/tests/snapshots/asm/vla_param_decay.aarch64.asm @@ -0,0 +1,69 @@ + +vla_param_decay.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + sxtw x0, w0 + mov x4, #0x0 // =0 + mov x3, x4 + sxtw x5, w4 + cmp x5, x0 + b.ge + b + sxtw x4, w4 + add x4, x4, #0x1 + b + sxtw x5, w4 + lsl x5, x5, #2 + add x6, x1, x5 + ldrsw x6, [x6] + add x5, x2, x5 + ldrsw x5, [x5] + mul x5, x6, x5 + add x3, x3, x5 + b + sxtw x0, w3 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x40 + sub x0, x29, #0x10 + adrp x1, + add x1, x1, + str x10, [sp, #-0x10]! + ldr x10, [x1] + str x10, [x0] + ldr x10, [x1, #0x8] + str x10, [x0, #0x8] + ldr x10, [sp], #0x10 + sub x0, x29, #0x20 + adrp x1, + add x1, x1, + str x10, [sp, #-0x10]! + ldr x10, [x1] + str x10, [x0] + ldr x10, [x1, #0x8] + str x10, [x0, #0x8] + ldr x10, [sp], #0x10 + mov x0, #0x4 // =4 + sub x1, x29, #0x10 + sub x2, x29, #0x20 + bl + cmp x0, #0x46 + b.ne + mov x1, #0x0 // =0 + b + mov x1, #0x1 // =1 + mov x0, x1 + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/vla_param_decay.x64.asm b/tests/snapshots/asm/vla_param_decay.x64.asm new file mode 100644 index 000000000..c722865c1 --- /dev/null +++ b/tests/snapshots/asm/vla_param_decay.x64.asm @@ -0,0 +1,77 @@ + +vla_param_decay.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + pushq %rbp + movq %rsp, %rbp + subq $0x10, %rsp + movq %rbx, (%rsp) + movslq %edi, %rdi + xorq %rcx, %rcx + movq %rcx, %rax + movslq %ecx, %r8 + cmpq %rdi, %r8 + jge + jmp + movslq %ecx, %rcx + incq %rcx + jmp + movslq %ecx, %r8 + shlq $0x2, %r8 + leaq (%rsi,%r8), %r9 + movslq (%r9), %r9 + addq %rdx, %r8 + movslq (%r8), %r8 + imulq %r9, %r8 + addq %r8, %rax + jmp + movslq %eax, %rax + movq (%rsp), %rbx + addq $0x10, %rsp + popq %rbp + retq + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x40, %rsp + leaq -0x10(%rbp), %rax + leaq , %rcx + pushq %rdx + movq (%rcx), %rdx + movq %rdx, (%rax) + movq 0x8(%rcx), %rdx + movq %rdx, 0x8(%rax) + popq %rdx + leaq -0x20(%rbp), %rax + leaq , %rcx + pushq %rdx + movq (%rcx), %rdx + movq %rdx, (%rax) + movq 0x8(%rcx), %rdx + movq %rdx, 0x8(%rax) + popq %rdx + movl $0x4, %edi + leaq -0x10(%rbp), %rsi + leaq -0x20(%rbp), %rdx + callq + cmpq $0x46, %rax + jne + xorq %rcx, %rcx + jmp + movl $0x1, %ecx + movq %rcx, %rax + addq $0x40, %rsp + popq %rbp + retq + addb %al, (%rax) + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/vla_runtime_sizeof.aarch64.asm b/tests/snapshots/asm/vla_runtime_sizeof.aarch64.asm new file mode 100644 index 000000000..f194719ac --- /dev/null +++ b/tests/snapshots/asm/vla_runtime_sizeof.aarch64.asm @@ -0,0 +1,76 @@ + +vla_runtime_sizeof.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x2, lsl #12 // =0x2000 + sub sp, sp, #0x40 + str x19, [sp] + sub x16, x29, #0x28 + str x16, [x16] + mov x0, #0x7 // =7 + stur w0, [x29, #-0x8] + ldursw x0, [x29, #-0x8] + lsl x0, x0, #3 + stur x0, [x29, #-0x18] + add x17, x0, #0xf + and x17, x17, #0xfffffffffffffff0 + sub x16, x29, #0x28 + ldr x0, [x16] + sub x0, x0, x17 + sub x17, x16, #0x2, lsl #12 // =0x2000 + cmp x0, x17 + b.hs + brk #0x1 + str x0, [x16] + stur x0, [x29, #-0x10] + ldur x0, [x29, #-0x18] + stur x0, [x29, #-0x20] + ldur x0, [x29, #-0x20] + ldursw x1, [x29, #-0x8] + lsl x1, x1, #3 + cmp x0, x1 + b.eq + mov x0, #0x1 // =1 + ldr x19, [sp] + add sp, sp, #0x2, lsl #12 // =0x2000 + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret + ldur x0, [x29, #-0x20] + lsr x0, x0, #3 + ldursw x1, [x29, #-0x8] + cmp x0, x1 + b.eq + mov x0, #0x2 // =2 + ldr x19, [sp] + add sp, sp, #0x2, lsl #12 // =0x2000 + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x64 // =100 + stur w0, [x29, #-0x8] + ldur x0, [x29, #-0x18] + cmp x0, #0x38 + b.eq + mov x0, #0x3 // =3 + ldr x19, [sp] + add sp, sp, #0x2, lsl #12 // =0x2000 + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldr x19, [sp] + add sp, sp, #0x2, lsl #12 // =0x2000 + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/vla_runtime_sizeof.x64.asm b/tests/snapshots/asm/vla_runtime_sizeof.x64.asm new file mode 100644 index 000000000..a3fb62f1b --- /dev/null +++ b/tests/snapshots/asm/vla_runtime_sizeof.x64.asm @@ -0,0 +1,69 @@ + +vla_runtime_sizeof.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x2030, %rsp # imm = 0x2030 + leaq -0x28(%rbp), %r10 + movq %r10, (%r10) + movl $0x7, %eax + movl %eax, -0x8(%rbp) + movslq -0x8(%rbp), %rax + shlq $0x3, %rax + movq %rax, -0x18(%rbp) + movq %rax, %r10 + addq $0xf, %r10 + andq $-0x10, %r10 + leaq -0x28(%rbp), %r11 + movq (%r11), %rax + subq %r10, %rax + leaq -0x2000(%r11), %r10 + cmpq %r10, %rax + jae + ud2 + movq %rax, (%r11) + movq %rax, -0x10(%rbp) + movq -0x18(%rbp), %rax + movq %rax, -0x20(%rbp) + movq -0x20(%rbp), %rax + movslq -0x8(%rbp), %rcx + shlq $0x3, %rcx + cmpq %rcx, %rax + je + movl $0x1, %eax + addq $0x2030, %rsp # imm = 0x2030 + popq %rbp + retq + movq -0x20(%rbp), %rax + shrq $0x3, %rax + movslq -0x8(%rbp), %rcx + cmpq %rcx, %rax + je + movl $0x2, %eax + addq $0x2030, %rsp # imm = 0x2030 + popq %rbp + retq + movl $0x64, %eax + movl %eax, -0x8(%rbp) + movq -0x18(%rbp), %rax + cmpq $0x38, %rax + je + movl $0x3, %eax + addq $0x2030, %rsp # imm = 0x2030 + popq %rbp + retq + xorq %rax, %rax + addq $0x2030, %rsp # imm = 0x2030 + popq %rbp + retq + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/asm/vla_scope_reclaim_loop.aarch64.asm b/tests/snapshots/asm/vla_scope_reclaim_loop.aarch64.asm new file mode 100644 index 000000000..98eb3131f --- /dev/null +++ b/tests/snapshots/asm/vla_scope_reclaim_loop.aarch64.asm @@ -0,0 +1,121 @@ + +vla_scope_reclaim_loop.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x2, lsl #12 // =0x2000 + sub sp, sp, #0x70 + str x19, [sp] + sub x16, x29, #0x50 + str x16, [x16] + mov x0, #0x0 // =0 + stur x0, [x29, #-0x8] + stur w0, [x29, #-0x10] + ldursw x0, [x29, #-0x10] + mov x17, #0x86a0 // =34464 + movk x17, #0x1, lsl #16 + cmp x0, x17 + b.ge + b + ldursw x0, [x29, #-0x10] + add x0, x0, #0x1 + stur w0, [x29, #-0x10] + b + sub x17, x29, #0x50 + ldr x0, [x17] + stur x0, [x29, #-0x38] + mov x0, #0x40 // =64 + stur w0, [x29, #-0x18] + ldursw x0, [x29, #-0x18] + lsl x0, x0, #2 + stur x0, [x29, #-0x28] + add x17, x0, #0xf + and x17, x17, #0xfffffffffffffff0 + sub x16, x29, #0x50 + ldr x0, [x16] + sub x0, x0, x17 + sub x17, x16, #0x2, lsl #12 // =0x2000 + cmp x0, x17 + b.hs + brk #0x1 + str x0, [x16] + stur x0, [x29, #-0x20] + mov x0, #0x0 // =0 + stur w0, [x29, #-0x30] + b + mov x0, #0x0 // =0 + stur x0, [x29, #-0x40] + stur w0, [x29, #-0x48] + b + ldursw x0, [x29, #-0x30] + ldursw x1, [x29, #-0x18] + cmp x0, x1 + b.ge + b + ldursw x0, [x29, #-0x30] + add x0, x0, #0x1 + stur w0, [x29, #-0x30] + b + ldur x0, [x29, #-0x20] + ldursw x1, [x29, #-0x30] + str w1, [x0, x1, lsl #2] + b + ldur x0, [x29, #-0x8] + ldur x1, [x29, #-0x20] + ldursw x2, [x29, #-0x10] + mov x17, #0x3f // =63 + and x2, x2, x17 + ldrsw x1, [x1, x2, lsl #2] + add x0, x0, x1 + stur x0, [x29, #-0x8] + ldur x0, [x29, #-0x38] + sub x17, x29, #0x50 + str x0, [x17] + b + ldursw x0, [x29, #-0x48] + mov x17, #0x86a0 // =34464 + movk x17, #0x1, lsl #16 + cmp x0, x17 + b.ge + b + ldursw x0, [x29, #-0x48] + add x0, x0, #0x1 + stur w0, [x29, #-0x48] + b + ldur x0, [x29, #-0x40] + ldursw x1, [x29, #-0x48] + mov x17, #0x3f // =63 + and x1, x1, x17 + add x0, x0, x1 + stur x0, [x29, #-0x40] + b + ldur x0, [x29, #-0x8] + ldur x1, [x29, #-0x40] + cmp x0, x1 + b.ne + mov x0, #0x0 // =0 + sub x17, x29, #0x2, lsl #12 // =0x2000 + sub x17, x17, #0x58 + str x0, [x17] + b + mov x0, #0x1 // =1 + sub x17, x29, #0x2, lsl #12 // =0x2000 + sub x17, x17, #0x58 + str x0, [x17] + sub x16, x29, #0x2, lsl #12 // =0x2000 + sub x16, x16, #0x58 + ldr x0, [x16] + ldr x19, [sp] + add sp, sp, #0x2, lsl #12 // =0x2000 + add sp, sp, #0x70 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/vla_scope_reclaim_loop.x64.asm b/tests/snapshots/asm/vla_scope_reclaim_loop.x64.asm new file mode 100644 index 000000000..fff4edf10 --- /dev/null +++ b/tests/snapshots/asm/vla_scope_reclaim_loop.x64.asm @@ -0,0 +1,106 @@ + +vla_scope_reclaim_loop.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +
: + pushq %rbp + movq %rsp, %rbp + subq $0x2060, %rsp # imm = 0x2060 + leaq -0x50(%rbp), %r10 + movq %r10, (%r10) + xorq %rax, %rax + movq %rax, -0x8(%rbp) + movl %eax, -0x10(%rbp) + movslq -0x10(%rbp), %rax + cmpq $0x186a0, %rax # imm = 0x186A0 + jge + jmp + movslq -0x10(%rbp), %rax + incq %rax + movl %eax, -0x10(%rbp) + jmp + movq -0x50(%rbp), %rax + movq %rax, -0x38(%rbp) + movl $0x40, %eax + movl %eax, -0x18(%rbp) + movslq -0x18(%rbp), %rax + shlq $0x2, %rax + movq %rax, -0x28(%rbp) + movq %rax, %r10 + addq $0xf, %r10 + andq $-0x10, %r10 + leaq -0x50(%rbp), %r11 + movq (%r11), %rax + subq %r10, %rax + leaq -0x2000(%r11), %r10 + cmpq %r10, %rax + jae + ud2 + movq %rax, (%r11) + movq %rax, -0x20(%rbp) + xorq %rax, %rax + movl %eax, -0x30(%rbp) + jmp + xorq %rax, %rax + movq %rax, -0x40(%rbp) + movl %eax, -0x48(%rbp) + jmp + movslq -0x30(%rbp), %rax + movslq -0x18(%rbp), %rcx + cmpq %rcx, %rax + jge + jmp + movslq -0x30(%rbp), %rax + incq %rax + movl %eax, -0x30(%rbp) + jmp + movq -0x20(%rbp), %rax + movslq -0x30(%rbp), %rcx + movl %ecx, (%rax,%rcx,4) + jmp + movq -0x8(%rbp), %rax + movq -0x20(%rbp), %rcx + movslq -0x10(%rbp), %rdx + andq $0x3f, %rdx + movslq (%rcx,%rdx,4), %rcx + addq %rcx, %rax + movq %rax, -0x8(%rbp) + movq -0x38(%rbp), %rax + movq %rax, -0x50(%rbp) + jmp + movslq -0x48(%rbp), %rax + cmpq $0x186a0, %rax # imm = 0x186A0 + jge + jmp + movslq -0x48(%rbp), %rax + incq %rax + movl %eax, -0x48(%rbp) + jmp + movq -0x40(%rbp), %rax + movslq -0x48(%rbp), %rcx + andq $0x3f, %rcx + addq %rcx, %rax + movq %rax, -0x40(%rbp) + jmp + movq -0x8(%rbp), %rax + movq -0x40(%rbp), %rcx + cmpq %rcx, %rax + jne + xorq %rax, %rax + movq %rax, -0x2058(%rbp) + jmp + movl $0x1, %eax + movq %rax, -0x2058(%rbp) + movq -0x2058(%rbp), %rax + addq $0x2060, %rsp # imm = 0x2060 + popq %rbp + retq + addb %al, (%rax) diff --git a/tests/snapshots/asm/vla_size_from_arg.aarch64.asm b/tests/snapshots/asm/vla_size_from_arg.aarch64.asm new file mode 100644 index 000000000..6a8b6c376 --- /dev/null +++ b/tests/snapshots/asm/vla_size_from_arg.aarch64.asm @@ -0,0 +1,101 @@ + +vla_size_from_arg.aarch64: file format elf64-littleaarch64 + +Disassembly of section .text: + +<.text>: + mov x29, #0x0 // =0 + mov x0, sp + mov x1, #0x220 // =544 + movk x1, #0x0, lsl #16 + b + brk #: + str x0, [sp, #-0x10]! + stp x29, x30, [sp, #-0x10]! + mov x29, sp + sub sp, sp, #0x2, lsl #12 // =0x2000 + sub sp, sp, #0x40 + str x19, [sp] + sub x16, x29, #0x30 + str x16, [x16] + stur w0, [x29, #0x10] + ldursw x0, [x29, #0x10] + stur x0, [x29, #-0x10] + add x17, x0, #0xf + and x17, x17, #0xfffffffffffffff0 + sub x16, x29, #0x30 + ldr x0, [x16] + sub x0, x0, x17 + sub x17, x16, #0x2, lsl #12 // =0x2000 + cmp x0, x17 + b.hs + brk #0x1 + str x0, [x16] + stur x0, [x29, #-0x8] + mov x0, #0x0 // =0 + stur w0, [x29, #-0x18] + ldursw x0, [x29, #-0x18] + ldursw x1, [x29, #0x10] + cmp x0, x1 + b.ge + b + ldursw x0, [x29, #-0x18] + add x0, x0, #0x1 + stur w0, [x29, #-0x18] + b + ldur x0, [x29, #-0x8] + ldursw x1, [x29, #-0x18] + add x0, x0, x1 + add x1, x1, #0x1 + mov x17, #0xff // =255 + and x1, x1, x17 + strb w1, [x0] + b + mov x0, #0x0 // =0 + stur w0, [x29, #-0x20] + stur w0, [x29, #-0x28] + ldursw x0, [x29, #-0x28] + ldursw x1, [x29, #0x10] + cmp x0, x1 + b.ge + b + ldursw x0, [x29, #-0x28] + add x0, x0, #0x1 + stur w0, [x29, #-0x28] + b + ldursw x0, [x29, #-0x20] + ldur x1, [x29, #-0x8] + ldursw x2, [x29, #-0x28] + add x1, x1, x2 + ldrb w1, [x1] + add x0, x0, x1 + stur w0, [x29, #-0x20] + b + ldursw x0, [x29, #-0x20] + ldr x19, [sp] + add sp, sp, #0x2, lsl #12 // =0x2000 + add sp, sp, #0x40 + ldp x29, x30, [sp], #0x10 + add sp, sp, #0x10 + ret + +
: + stp x29, x30, [sp, #-0x10]! + mov x29, sp + mov x0, #0xa // =10 + bl + cmp x0, #0x37 + b.eq + mov x0, #0x1 // =1 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x4 // =4 + bl + cmp x0, #0xa + b.eq + mov x0, #0x2 // =2 + ldp x29, x30, [sp], #0x10 + ret + mov x0, #0x0 // =0 + ldp x29, x30, [sp], #0x10 + ret diff --git a/tests/snapshots/asm/vla_size_from_arg.x64.asm b/tests/snapshots/asm/vla_size_from_arg.x64.asm new file mode 100644 index 000000000..da81a961e --- /dev/null +++ b/tests/snapshots/asm/vla_size_from_arg.x64.asm @@ -0,0 +1,104 @@ + +vla_size_from_arg.x64: file format elf64-x86-64 + +Disassembly of section .text: + +<.text>: + xorl %ebp, %ebp + movq %rsp, %rdi + movl $, %esi + callq + ud2 + +: + popq %r10 + subq $0x10, %rsp + movq %rdi, (%rsp) + pushq %r10 + pushq %rbp + movq %rsp, %rbp + subq $0x2030, %rsp # imm = 0x2030 + leaq -0x30(%rbp), %r10 + movq %r10, (%r10) + movl %edi, 0x10(%rbp) + movslq 0x10(%rbp), %rax + movq %rax, -0x10(%rbp) + movq %rax, %r10 + addq $0xf, %r10 + andq $-0x10, %r10 + leaq -0x30(%rbp), %r11 + movq (%r11), %rax + subq %r10, %rax + leaq -0x2000(%r11), %r10 + cmpq %r10, %rax + jae + ud2 + movq %rax, (%r11) + movq %rax, -0x8(%rbp) + xorq %rax, %rax + movl %eax, -0x18(%rbp) + movslq -0x18(%rbp), %rax + movslq 0x10(%rbp), %rcx + cmpq %rcx, %rax + jge + jmp + movslq -0x18(%rbp), %rax + incq %rax + movl %eax, -0x18(%rbp) + jmp + movq -0x8(%rbp), %rax + movslq -0x18(%rbp), %rcx + addq %rcx, %rax + incq %rcx + movslq %ecx, %rdx + movb %dl, (%rax) + jmp + xorq %rax, %rax + movl %eax, -0x20(%rbp) + movl %eax, -0x28(%rbp) + movslq -0x28(%rbp), %rax + movslq 0x10(%rbp), %rcx + cmpq %rcx, %rax + jge + jmp + movslq -0x28(%rbp), %rax + incq %rax + movl %eax, -0x28(%rbp) + jmp + movslq -0x20(%rbp), %rax + movq -0x8(%rbp), %rcx + movslq -0x28(%rbp), %rdx + addq %rdx, %rcx + movsbq (%rcx), %rcx + addq %rcx, %rax + movl %eax, -0x20(%rbp) + jmp + movslq -0x20(%rbp), %rax + addq $0x2030, %rsp # imm = 0x2030 + popq %rbp + popq %r11 + addq $0x10, %rsp + pushq %r11 + retq + +
: + pushq %rbp + movq %rsp, %rbp + movl $0xa, %edi + callq + cmpq $0x37, %rax + je + movl $0x1, %eax + popq %rbp + retq + movl $0x4, %edi + callq + cmpq $0xa, %rax + je + movl $0x2, %eax + popq %rbp + retq + xorq %rax, %rax + popq %rbp + retq + addb %al, 0x41(%rdx) diff --git a/tests/snapshots/ssa/vla_basic_sum.ssa b/tests/snapshots/ssa/vla_basic_sum.ssa new file mode 100644 index 000000000..7834cfc38 --- /dev/null +++ b/tests/snapshots/ssa/vla_basic_sum.ssa @@ -0,0 +1,136 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=compute +fn ent_pc=0 n_params=1 variadic=false locals=1030 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(6) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 StoreLocal { off=2, value=v1, kind=I32 } -> - + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 BinopI { op=shl, lhs=v3, rhs_imm=2 } -> x0 + v5 StoreLocal { off=-2, value=v4, kind=I64 } -> - + v6 Intrinsic { kind=1, args=[v4] } -> x0 + v7 StoreLocal { off=-1, value=v6, kind=I64 } -> - + v8 Imm(0) -> x0 + v9 StoreLocal { off=-3, value=v8, kind=I32 } -> - + terminator Jmp(b1) (exit_acc=v9) + block 1 start_pc=0 + v10 LoadLocal { off=-3, kind=I32 } -> x0 + v11 LoadLocal { off=2, kind=I32 } -> x1 + v12 Binop { op=lt, lhs=v10, rhs=v11 } -> x0 + terminator Bz { cond=v12, target=b4, fall=b3 } (exit_acc=v12) + block 2 start_pc=0 + v13 LoadLocal { off=-3, kind=I32 } -> x0 + v14 BinopI { op=add, lhs=v13, rhs_imm=1 } -> x0 + v15 StoreLocal { off=-3, value=v14, kind=I32 } -> - + terminator Jmp(b1) (exit_acc=v15) + block 3 start_pc=0 + v16 LoadLocal { off=-1, kind=I64 } -> x0 + v17 LoadLocal { off=-3, kind=I32 } -> x1 + v18 BinopI { op=shl, lhs=v17, rhs_imm=2 } -> x2 + v19 Binop { op=add, lhs=v16, rhs=v18 } -> x2 + v20 BinopI { op=shl, lhs=v17, rhs_imm=1 } -> x2 + v21 BinopI { op=shl, lhs=v20, rhs_imm=32 } -> x6 + v22 Extend { value=v20, kind=I32 } -> x6 + v23 StoreIndexed { base=v16, index=v17, scale=4, value=v20, kind=I32 } -> - + terminator Jmp(b2) (exit_acc=v23) + block 4 start_pc=0 + v24 Imm(0) -> x0 + v25 StoreLocal { off=-4, value=v24, kind=I32 } -> - + v26 StoreLocal { off=-5, value=v24, kind=I32 } -> - + terminator Jmp(b5) (exit_acc=v26) + block 5 start_pc=0 + v27 LoadLocal { off=-5, kind=I32 } -> x0 + v28 LoadLocal { off=2, kind=I32 } -> x1 + v29 Binop { op=lt, lhs=v27, rhs=v28 } -> x0 + terminator Bz { cond=v29, target=b8, fall=b7 } (exit_acc=v29) + block 6 start_pc=0 + v30 LoadLocal { off=-5, kind=I32 } -> x0 + v31 BinopI { op=add, lhs=v30, rhs_imm=1 } -> x0 + v32 StoreLocal { off=-5, value=v31, kind=I32 } -> - + terminator Jmp(b5) (exit_acc=v32) + block 7 start_pc=0 + v33 LoadLocal { off=-4, kind=I32 } -> x0 + v34 LoadLocal { off=-1, kind=I64 } -> x1 + v35 LoadLocal { off=-5, kind=I32 } -> x2 + v36 BinopI { op=shl, lhs=v35, rhs_imm=2 } -> x6 + v37 Binop { op=add, lhs=v34, rhs=v36 } -> x6 + v38 LoadIndexed { base=v34, index=v35, scale=4, kind=I32 } -> x1 + v39 Binop { op=add, lhs=v33, rhs=v38 } -> x0 + v40 StoreLocal { off=-4, value=v39, kind=I32 } -> - + v41 LoadLocal { off=-4, kind=I32 } -> x0 + terminator Jmp(b6) (exit_acc=v41) + block 8 start_pc=0 + v42 LoadLocal { off=-4, kind=I32 } -> x0 + terminator Return(v42) (exit_acc=v42) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(5) -> x7 + v2 Call { target_pc=0, args=[v1], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + v3 BinopI { op=ne, lhs=v2, rhs_imm=20 } -> x0 + terminator Bz { cond=v3, target=b2, fall=b1 } (exit_acc=v3) + block 1 start_pc=0 + v4 Imm(1) -> x0 + terminator Return(v4) (exit_acc=v4) + block 2 start_pc=0 + v5 Imm(1) -> x7 + v6 Call { target_pc=0, args=[v5], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + v7 BinopI { op=ne, lhs=v6, rhs_imm=0 } -> x0 + terminator Bz { cond=v7, target=b4, fall=b3 } (exit_acc=v7) + block 3 start_pc=0 + v8 Imm(2) -> x0 + terminator Return(v8) (exit_acc=v8) + block 4 start_pc=0 + v9 Imm(0) -> x0 + terminator Return(v9) (exit_acc=v9) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/vla_param_decay.ssa b/tests/snapshots/ssa/vla_param_decay.ssa new file mode 100644 index 000000000..5575add63 --- /dev/null +++ b/tests/snapshots/ssa/vla_param_decay.ssa @@ -0,0 +1,125 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=dot +fn ent_pc=0 n_params=3 variadic=false locals=2 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 ParamRef(2, kind=I64) -> x2 + v6 Imm(0) -> x0 + v7 Imm(0) -> x1 + v8 Imm(0) -> x0 + v9 Imm(0) -> x0 + terminator Jmp(b1) (exit_acc=v7) + block 1 start_pc=0 + v10 Phi { incoming=[b0:v7, b2:v16], kind=I64 } -> x1 + v11 Phi { incoming=[b0:v7, b2:v30], kind=I64 } -> x0 + v12 Extend { value=v10, kind=I32 } -> x8 + v13 LoadLocal { off=2, kind=I32 } -> x9 + v14 Binop { op=lt, lhs=v12, rhs=v1 } -> x8 + terminator Bz { cond=v14, target=b4, fall=b3 } (exit_acc=v14) + block 2 start_pc=0 + v15 Extend { value=v10, kind=I32 } -> x1 + v16 BinopI { op=add, lhs=v15, rhs_imm=1 } -> x1 + v17 Imm(0) -> x8 + terminator Jmp(b1) (exit_acc=v16) + block 3 start_pc=0 + v18 Extend { value=v11, kind=I32 } -> x8 + v19 LoadLocal { off=3, kind=I64 } -> x8 + v20 Extend { value=v10, kind=I32 } -> x8 + v21 BinopI { op=shl, lhs=v20, rhs_imm=2 } -> x8 + v22 Binop { op=add, lhs=v3, rhs=v21 } -> x9 + v23 Load { addr=v22, disp=0, kind=I32 } -> x9 + v24 LoadLocal { off=4, kind=I64 } -> x3 + v25 Binop { op=add, lhs=v5, rhs=v21 } -> x8 + v26 Load { addr=v25, disp=0, kind=I32 } -> x8 + v27 Binop { op=mul, lhs=v23, rhs=v26 } -> x8 + v28 BinopI { op=shl, lhs=v27, rhs_imm=32 } -> x9 + v29 Extend { value=v27, kind=I32 } -> x9 + v30 Binop { op=add, lhs=v11, rhs=v27 } -> x0 + v31 Imm(0) -> x8 + v32 Extend { value=v30, kind=I32 } -> x8 + terminator Jmp(b2) (exit_acc=v32) + block 4 start_pc=0 + v33 Extend { value=v11, kind=I32 } -> x0 + terminator Return(v33) (exit_acc=v33) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=8 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 LocalAddr(-2) -> x0 + v2 ImmData(8) -> x1 + v3 Mcpy { dst=v1, src=v2, size=16 } -> x0 + v4 LocalAddr(-4) -> x0 + v5 ImmData(24) -> x1 + v6 Mcpy { dst=v4, src=v5, size=16 } -> x0 + v7 Imm(4) -> x7 + v8 LocalAddr(-2) -> x6 + v9 LocalAddr(-4) -> x2 + v10 Call { target_pc=0, args=[v7, v8, v9], fixed_args=3, fp_return=false, fp_arg_mask=0x0 } -> x0 + v11 BinopI { op=eq, lhs=v10, rhs_imm=70 } -> x0 + terminator Bz { cond=v11, target=b2, fall=b1 } (exit_acc=v11) + block 1 start_pc=0 + v12 Imm(0) -> x1 + v13 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v12) + block 2 start_pc=0 + v14 Imm(1) -> x1 + v15 Imm(0) -> x0 + terminator Jmp(b3) (exit_acc=v14) + block 3 start_pc=0 + v16 Phi { incoming=[b1:v12, b2:v14], kind=I64 } -> x1 + v17 LoadLocal { off=-8, kind=I64 } -> x0 + terminator Return(v16) (exit_acc=v16) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/vla_runtime_sizeof.ssa b/tests/snapshots/ssa/vla_runtime_sizeof.ssa new file mode 100644 index 000000000..ac11cb193 --- /dev/null +++ b/tests/snapshots/ssa/vla_runtime_sizeof.ssa @@ -0,0 +1,94 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=1029 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(5) -> - + v1 Imm(7) -> x0 + v2 StoreLocal { off=-1, value=v1, kind=I32 } -> - + v3 LoadLocal { off=-1, kind=I32 } -> x0 + v4 BinopI { op=shl, lhs=v3, rhs_imm=3 } -> x0 + v5 StoreLocal { off=-3, value=v4, kind=I64 } -> - + v6 Intrinsic { kind=1, args=[v4] } -> x0 + v7 StoreLocal { off=-2, value=v6, kind=I64 } -> - + v8 LoadLocal { off=-3, kind=I64 } -> x0 + v9 StoreLocal { off=-4, value=v8, kind=I64 } -> - + v10 LoadLocal { off=-4, kind=I64 } -> x0 + v11 LoadLocal { off=-1, kind=I32 } -> x1 + v12 BinopI { op=shl, lhs=v11, rhs_imm=3 } -> x1 + v13 Binop { op=ne, lhs=v10, rhs=v12 } -> x0 + terminator Bz { cond=v13, target=b2, fall=b1 } (exit_acc=v13) + block 1 start_pc=0 + v14 Imm(1) -> x0 + terminator Return(v14) (exit_acc=v14) + block 2 start_pc=0 + v15 LoadLocal { off=-4, kind=I64 } -> x0 + v16 Imm(8) -> x1 + v17 BinopI { op=shru, lhs=v15, rhs_imm=3 } -> x0 + v18 LoadLocal { off=-1, kind=I32 } -> x1 + v19 Binop { op=ne, lhs=v17, rhs=v18 } -> x0 + terminator Bz { cond=v19, target=b4, fall=b3 } (exit_acc=v19) + block 3 start_pc=0 + v20 Imm(2) -> x0 + terminator Return(v20) (exit_acc=v20) + block 4 start_pc=0 + v21 Imm(100) -> x0 + v22 StoreLocal { off=-1, value=v21, kind=I32 } -> - + v23 LoadLocal { off=-3, kind=I64 } -> x0 + v24 Imm(56) -> x1 + v25 Imm(240518168576) -> x1 + v26 BinopI { op=ne, lhs=v23, rhs_imm=56 } -> x0 + terminator Bz { cond=v26, target=b6, fall=b5 } (exit_acc=v26) + block 5 start_pc=0 + v27 Imm(3) -> x0 + terminator Return(v27) (exit_acc=v27) + block 6 start_pc=0 + v28 Imm(0) -> x0 + terminator Return(v28) (exit_acc=v28) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/vla_scope_reclaim_loop.ssa b/tests/snapshots/ssa/vla_scope_reclaim_loop.ssa new file mode 100644 index 000000000..f240d8c33 --- /dev/null +++ b/tests/snapshots/ssa/vla_scope_reclaim_loop.ssa @@ -0,0 +1,146 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=main +fn ent_pc=0 n_params=0 variadic=false locals=1035 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(10) -> - + v1 Imm(0) -> x0 + v2 StoreLocal { off=-1, value=v1, kind=I64 } -> - + v3 StoreLocal { off=-2, value=v1, kind=I32 } -> - + terminator Jmp(b1) (exit_acc=v3) + block 1 start_pc=0 + v4 LoadLocal { off=-2, kind=I32 } -> x0 + v5 BinopI { op=lt, lhs=v4, rhs_imm=100000 } -> x0 + terminator Bz { cond=v5, target=b4, fall=b3 } (exit_acc=v5) + block 2 start_pc=0 + v6 LoadLocal { off=-2, kind=I32 } -> x0 + v7 BinopI { op=add, lhs=v6, rhs_imm=1 } -> x0 + v8 StoreLocal { off=-2, value=v7, kind=I32 } -> - + terminator Jmp(b1) (exit_acc=v8) + block 3 start_pc=0 + v9 Intrinsic { kind=46, args=[] } -> x0 + v10 StoreLocal { off=-7, value=v9, kind=I64 } -> - + v11 Imm(64) -> x0 + v12 StoreLocal { off=-3, value=v11, kind=I32 } -> - + v13 LoadLocal { off=-3, kind=I32 } -> x0 + v14 BinopI { op=shl, lhs=v13, rhs_imm=2 } -> x0 + v15 StoreLocal { off=-5, value=v14, kind=I64 } -> - + v16 Intrinsic { kind=1, args=[v14] } -> x0 + v17 StoreLocal { off=-4, value=v16, kind=I64 } -> - + v18 Imm(0) -> x0 + v19 StoreLocal { off=-6, value=v18, kind=I32 } -> - + terminator Jmp(b5) (exit_acc=v19) + block 4 start_pc=0 + v42 Imm(0) -> x0 + v43 StoreLocal { off=-8, value=v42, kind=I64 } -> - + v44 StoreLocal { off=-9, value=v42, kind=I32 } -> - + terminator Jmp(b9) (exit_acc=v44) + block 5 start_pc=0 + v20 LoadLocal { off=-6, kind=I32 } -> x0 + v21 LoadLocal { off=-3, kind=I32 } -> x1 + v22 Binop { op=lt, lhs=v20, rhs=v21 } -> x0 + terminator Bz { cond=v22, target=b8, fall=b7 } (exit_acc=v22) + block 6 start_pc=0 + v23 LoadLocal { off=-6, kind=I32 } -> x0 + v24 BinopI { op=add, lhs=v23, rhs_imm=1 } -> x0 + v25 StoreLocal { off=-6, value=v24, kind=I32 } -> - + terminator Jmp(b5) (exit_acc=v25) + block 7 start_pc=0 + v26 LoadLocal { off=-4, kind=I64 } -> x0 + v27 LoadLocal { off=-6, kind=I32 } -> x1 + v28 BinopI { op=shl, lhs=v27, rhs_imm=2 } -> x2 + v29 Binop { op=add, lhs=v26, rhs=v28 } -> x2 + v30 StoreIndexed { base=v26, index=v27, scale=4, value=v27, kind=I32 } -> - + terminator Jmp(b6) (exit_acc=v30) + block 8 start_pc=0 + v31 LoadLocal { off=-1, kind=I64 } -> x0 + v32 LoadLocal { off=-4, kind=I64 } -> x1 + v33 LoadLocal { off=-2, kind=I32 } -> x2 + v34 BinopI { op=and, lhs=v33, rhs_imm=63 } -> x2 + v35 BinopI { op=shl, lhs=v34, rhs_imm=2 } -> x6 + v36 Binop { op=add, lhs=v32, rhs=v35 } -> x6 + v37 LoadIndexed { base=v32, index=v34, scale=4, kind=I32 } -> x1 + v38 Binop { op=add, lhs=v31, rhs=v37 } -> x0 + v39 StoreLocal { off=-1, value=v38, kind=I64 } -> - + v40 LoadLocal { off=-7, kind=I64 } -> x0 + v41 Intrinsic { kind=47, args=[v40] } -> x0 + terminator Jmp(b2) (exit_acc=v41) + block 9 start_pc=0 + v45 LoadLocal { off=-9, kind=I32 } -> x0 + v46 BinopI { op=lt, lhs=v45, rhs_imm=100000 } -> x0 + terminator Bz { cond=v46, target=b12, fall=b11 } (exit_acc=v46) + block 10 start_pc=0 + v47 LoadLocal { off=-9, kind=I32 } -> x0 + v48 BinopI { op=add, lhs=v47, rhs_imm=1 } -> x0 + v49 StoreLocal { off=-9, value=v48, kind=I32 } -> - + terminator Jmp(b9) (exit_acc=v49) + block 11 start_pc=0 + v50 LoadLocal { off=-8, kind=I64 } -> x0 + v51 LoadLocal { off=-9, kind=I32 } -> x1 + v52 BinopI { op=and, lhs=v51, rhs_imm=63 } -> x1 + v53 Binop { op=add, lhs=v50, rhs=v52 } -> x0 + v54 StoreLocal { off=-8, value=v53, kind=I64 } -> - + terminator Jmp(b10) (exit_acc=v54) + block 12 start_pc=0 + v55 LoadLocal { off=-1, kind=I64 } -> x0 + v56 LoadLocal { off=-8, kind=I64 } -> x1 + v57 Binop { op=eq, lhs=v55, rhs=v56 } -> x0 + terminator Bz { cond=v57, target=b14, fall=b13 } (exit_acc=v57) + block 13 start_pc=0 + v58 Imm(0) -> x0 + v59 StoreLocal { off=-1035, value=v58, kind=I64 } -> - + terminator Jmp(b15) (exit_acc=v59) + block 14 start_pc=0 + v60 Imm(1) -> x0 + v61 StoreLocal { off=-1035, value=v60, kind=I64 } -> - + terminator Jmp(b15) (exit_acc=v61) + block 15 start_pc=0 + v62 LoadLocal { off=-1035, kind=I64 } -> x0 + terminator Return(v62) (exit_acc=v62) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) diff --git a/tests/snapshots/ssa/vla_size_from_arg.ssa b/tests/snapshots/ssa/vla_size_from_arg.ssa new file mode 100644 index 000000000..c250f9f93 --- /dev/null +++ b/tests/snapshots/ssa/vla_size_from_arg.ssa @@ -0,0 +1,135 @@ +; --- SSA dump (ok=true) ent_pc=0 --- +; name=fill_and_sum +fn ent_pc=0 n_params=1 variadic=false locals=1030 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(6) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 StoreLocal { off=2, value=v1, kind=I32 } -> - + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 StoreLocal { off=-2, value=v3, kind=I64 } -> - + v5 Intrinsic { kind=1, args=[v3] } -> x0 + v6 StoreLocal { off=-1, value=v5, kind=I64 } -> - + v7 Imm(0) -> x0 + v8 StoreLocal { off=-3, value=v7, kind=I32 } -> - + terminator Jmp(b1) (exit_acc=v8) + block 1 start_pc=0 + v9 LoadLocal { off=-3, kind=I32 } -> x0 + v10 LoadLocal { off=2, kind=I32 } -> x1 + v11 Binop { op=lt, lhs=v9, rhs=v10 } -> x0 + terminator Bz { cond=v11, target=b4, fall=b3 } (exit_acc=v11) + block 2 start_pc=0 + v12 LoadLocal { off=-3, kind=I32 } -> x0 + v13 BinopI { op=add, lhs=v12, rhs_imm=1 } -> x0 + v14 StoreLocal { off=-3, value=v13, kind=I32 } -> - + terminator Jmp(b1) (exit_acc=v14) + block 3 start_pc=0 + v15 LoadLocal { off=-1, kind=I64 } -> x0 + v16 LoadLocal { off=-3, kind=I32 } -> x1 + v17 Binop { op=add, lhs=v15, rhs=v16 } -> x0 + v18 BinopI { op=add, lhs=v16, rhs_imm=1 } -> x1 + v19 BinopI { op=shl, lhs=v18, rhs_imm=32 } -> x2 + v20 Extend { value=v18, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v18, rhs_imm=56 } -> x1 + v22 Extend { value=v20, kind=I8 } -> x1 + v23 Store { addr=v17, disp=0, value=v20, kind=I8 } -> - + terminator Jmp(b2) (exit_acc=v23) + block 4 start_pc=0 + v24 Imm(0) -> x0 + v25 StoreLocal { off=-4, value=v24, kind=I32 } -> - + v26 StoreLocal { off=-5, value=v24, kind=I32 } -> - + terminator Jmp(b5) (exit_acc=v26) + block 5 start_pc=0 + v27 LoadLocal { off=-5, kind=I32 } -> x0 + v28 LoadLocal { off=2, kind=I32 } -> x1 + v29 Binop { op=lt, lhs=v27, rhs=v28 } -> x0 + terminator Bz { cond=v29, target=b8, fall=b7 } (exit_acc=v29) + block 6 start_pc=0 + v30 LoadLocal { off=-5, kind=I32 } -> x0 + v31 BinopI { op=add, lhs=v30, rhs_imm=1 } -> x0 + v32 StoreLocal { off=-5, value=v31, kind=I32 } -> - + terminator Jmp(b5) (exit_acc=v32) + block 7 start_pc=0 + v33 LoadLocal { off=-4, kind=I32 } -> x0 + v34 LoadLocal { off=-1, kind=I64 } -> x1 + v35 LoadLocal { off=-5, kind=I32 } -> x2 + v36 Binop { op=add, lhs=v34, rhs=v35 } -> x1 + v37 Load { addr=v36, disp=0, kind=I8 } -> x1 + v38 Binop { op=add, lhs=v33, rhs=v37 } -> x0 + v39 StoreLocal { off=-4, value=v38, kind=I32 } -> - + v40 LoadLocal { off=-4, kind=I32 } -> x0 + terminator Jmp(b6) (exit_acc=v40) + block 8 start_pc=0 + v41 LoadLocal { off=-4, kind=I32 } -> x0 + terminator Return(v41) (exit_acc=v41) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=main +fn ent_pc=1 n_params=0 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 Imm(10) -> x7 + v2 Call { target_pc=0, args=[v1], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + v3 BinopI { op=ne, lhs=v2, rhs_imm=55 } -> x0 + terminator Bz { cond=v3, target=b2, fall=b1 } (exit_acc=v3) + block 1 start_pc=0 + v4 Imm(1) -> x0 + terminator Return(v4) (exit_acc=v4) + block 2 start_pc=0 + v5 Imm(4) -> x7 + v6 Call { target_pc=0, args=[v5], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + v7 BinopI { op=ne, lhs=v6, rhs_imm=10 } -> x0 + terminator Bz { cond=v7, target=b4, fall=b3 } (exit_acc=v7) + block 3 start_pc=0 + v8 Imm(2) -> x0 + terminator Return(v8) (exit_acc=v8) + block 4 start_pc=0 + v9 Imm(0) -> x0 + terminator Return(v9) (exit_acc=v9) +; --- SSA dump (ok=true) ent_pc=0 --- +; name=__c5_exit +fn ent_pc=0 n_params=1 variadic=false locals=1 + spill_count=0 gpr_used=[] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I32) -> x7 + v2 Imm(0) -> x0 + v3 LoadLocal { off=2, kind=I32 } -> x0 + v4 CallExt { binding_idx=0, args=[v1], fp_arg_mask=0x0 } -> x0 + v5 Imm(0) -> x0 + terminator Return(v5) (exit_acc=v5) +; --- SSA dump (ok=true) ent_pc=1 --- +; name=__c5_entry +fn ent_pc=1 n_params=2 variadic=false locals=6 + spill_count=0 gpr_used=[3] fp_used=[] + block 0 start_pc=0 + v0 AllocaInit(0) -> - + v1 ParamRef(0, kind=I64) -> x7 + v2 Imm(0) -> x0 + v3 ParamRef(1, kind=I64) -> x6 + v4 Imm(0) -> x0 + v5 LoadLocal { off=3, kind=I64 } -> x0 + v6 BinopI { op=and, lhs=v3, rhs_imm=255 } -> x0 + v7 LoadLocal { off=2, kind=I64 } -> x0 + v8 Imm(0) -> x0 + v9 LoadLocal { off=-1, kind=I64 } -> x0 + v10 Imm(0) -> x3 + v11 Load { addr=v1, disp=0, kind=I64 } -> x0 + v12 BinopI { op=shl, lhs=v11, rhs_imm=32 } -> x1 + v13 Extend { value=v11, kind=I32 } -> x0 + v14 Imm(0) -> x1 + v15 Imm(8) -> x1 + v16 BinopI { op=add, lhs=v1, rhs_imm=8 } -> x6 + v17 Imm(0) -> x1 + v18 ImmData(24) -> x1 + v19 LoadLocal { off=-3, kind=I64 } -> x2 + v20 LoadLocal { off=-2, kind=I32 } -> x2 + v21 BinopI { op=shl, lhs=v13, rhs_imm=3 } -> x2 + v22 Binop { op=add, lhs=v16, rhs=v21 } -> x2 + v23 BinopI { op=add, lhs=v22, rhs_imm=8 } -> x2 + v24 Store { addr=v18, disp=0, value=v23, kind=I64 } -> - + v25 LoadLocal { off=-2, kind=I32 } -> x1 + v26 LoadLocal { off=-3, kind=I64 } -> x1 + v27 Call { target_pc=3, args=[v13, v16], fixed_args=2, fp_return=false, fp_arg_mask=0x0 } -> x7 + v28 Call { target_pc=0, args=[v27], fixed_args=1, fp_return=false, fp_arg_mask=0x0 } -> x0 + terminator Return(v10) (exit_acc=v10) From ae3555d7c0a366b3621d52fc4ce8b1ca507f7c5e Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 02:13:22 -0700 Subject: [PATCH 66/67] tests: compile _Thread_local per target instead of re-emitting a host build The Mach-O TLS path now requires libSystem in the dylib set (a wrong ordinal guess would bind __tlv_bootstrap to the wrong dylib). Emitting a host-compiled program for macOS from a non-macOS host lacks libSystem; compile for each target so its own dylib bindings are present. Co-Authored-By: Claude Fable 5 --- src/c5/tests/parser.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/c5/tests/parser.rs b/src/c5/tests/parser.rs index 1afc19198..4704ff0bc 100644 --- a/src/c5/tests/parser.rs +++ b/src/c5/tests/parser.rs @@ -357,14 +357,12 @@ fn thread_local_compiles_to_op_tlslea() { // those gates. let src = "_Thread_local int counter;\n\ int main() { counter = 42; return counter; }"; - let p = super::Compiler::new(super::with_prelude(src)) - .compile() - .expect("compile failed"); - assert_eq!(p.tls_data.len(), 8, "single 8-byte TLS slot"); // Every supported target now lowers `_Thread_local`. Linux // and Windows have full code paths; macOS arm64 routes // through the Mach-O `__thread_vars` + `__tlv_bootstrap` - // pipeline. + // pipeline, which needs libSystem in the dylib set -- so + // compile per target rather than re-emitting a host-compiled + // program whose dylib bindings are the host's. for target in [ super::super::codegen::Target::LinuxAarch64, super::super::codegen::Target::LinuxX64, @@ -372,6 +370,10 @@ fn thread_local_compiles_to_op_tlslea() { super::super::codegen::Target::WindowsAarch64, super::super::codegen::Target::MacOSAarch64, ] { + let p = super::Compiler::with_target(super::with_prelude(src), target) + .compile() + .unwrap_or_else(|e| panic!("`{target:?}` compile failed: {e}")); + assert_eq!(p.tls_data.len(), 8, "single 8-byte TLS slot for {target:?}"); super::super::object::emit_native_single_tu_for_test( &p, target, From 4e0abcf334ef4f90f7eccb44d1070aca3d4518e3 Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 2 Jul 2026 02:39:30 -0700 Subject: [PATCH 67/67] tests: skip the VLA rejection fixtures in the compile-all smoke The vla_*_rejected.c fixtures assert a clean diagnostic for unsupported VLA forms, so the every-fixture-compiles smoke must not expect them to build. Co-Authored-By: Claude Fable 5 --- tests/cli_fixture_smoke.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/cli_fixture_smoke.rs b/tests/cli_fixture_smoke.rs index b25fb049c..345404de6 100644 --- a/tests/cli_fixture_smoke.rs +++ b/tests/cli_fixture_smoke.rs @@ -48,6 +48,12 @@ const COMPILE_SKIPLIST: &[&str] = &[ "thread_local_initializer.c", "thread_local_per_thread.c", "deferred_jit_thread_local.c", + // VLA fixtures that assert a clean rejection diagnostic rather + // than compiling; the constructs are unsupported by design (C99 + // 6.7.6.2 corners left as TODO). + "vla_multidim_rejected.c", + "vla_file_scope_rejected.c", + "vla_initializer_rejected.c", ]; #[test]