//! Pin: the codegen mechanism that emits primitive Eq/Ord //! instance bodies (try_emit_primitive_instance_body) MUST //! attach an `alwaysinline` attribute to the generated LLVM //! function definition so the `-O0` build path inlines the //! single-instruction body at every use site, matching the IR //! shape the deleted `lower_eq` direct-emit produced. Without //! `alwaysinline`, `ail run` (which defaults to -O0) pays a //! function-call overhead per comparison. use std::path::PathBuf; use std::process::Command; #[test] fn prelude_eq_int_carries_alwaysinline_attribute_in_emitted_ir() { let manifest_dir = env!("CARGO_MANIFEST_DIR"); let repo_root = PathBuf::from(manifest_dir).join("../.."); // Use a fixture that invokes the class-method `eq` path so // `prelude.eq__Int` gets monomorphised into the emitted IR. // `eq_ord_user_adt.ail` calls `(app eq …)` on an IntBox whose // user instance body internally calls `(app eq ai bi)` on Int — // class-dispatch resolves both the outer (Eq IntBox) and inner // (Eq Int) calls. The inner Eq Int path is the one we pin here: // its `define i1 @ail_prelude_eq__Int(...) alwaysinline { ... }` // must carry `alwaysinline` so the call folds to a single // `icmp eq i64` at every use site under -O0. let fixture = repo_root.join("examples/eq_ord_user_adt.ail"); let out = Command::new(env!("CARGO_BIN_EXE_ail")) .arg("emit-ir") .arg(&fixture) .output() .expect("ail emit-ir failed to spawn"); assert!( out.status.success(), "ail emit-ir failed: stderr={}", String::from_utf8_lossy(&out.stderr) ); let ir = String::from_utf8_lossy(&out.stdout); // Either form is acceptable: // define i1 @ail_prelude_eq__Int(i64, i64) alwaysinline { ... } // (attribute appended to the define line). The grep checks for // both the symbol presence and the alwaysinline annotation in // the same line as the define. let saw_define_with_alwaysinline = ir .lines() .any(|line| line.contains("define") && line.contains("eq__Int") && line.contains("alwaysinline")); assert!( saw_define_with_alwaysinline, "expected `define … eq__Int … alwaysinline` in emitted IR; full IR follows:\n{ir}" ); }