xenia-analysis: unify disasm via xenia-cpu, split ingest/analyze, add sinks
The old src/ppc.rs that re-implemented PPC formatting collapses into a 30-line shim that delegates to xenia-cpu's single-source-of-truth disasm. A new disasm.rs wraps the shared iterator and feeds enriched items (analysis context: function membership, xrefs, mnemonics) into pluggable sinks. Sinks split: text.rs (objdump-like output), json.rs (JSONL stream matching the new xenia dis --json mode), duckdb.rs (the analysis DB ingest). db.rs is restructured into ingest_instructions + write_analysis_results so a run can stop after raw ingest, and a new target_hex column lands on the instructions table. sql_views.rs adds five additive views layered on top of the raw tables. Tests: assert-based JSON-fixture goldens (disasm_goldens) and a PRAGMA-table_info schema golden (db_schema_golden) covering all ingested tables and the SQL views. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
37
crates/xenia-analysis/src/sinks/duckdb.rs
Normal file
37
crates/xenia-analysis/src/sinks/duckdb.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
//! DuckDB sink — appends rich disasm items to the `instructions` table.
|
||||
//!
|
||||
//! Column layout matches [`crate::db`]: address, raw, mnemonic, operands,
|
||||
//! disasm, ext_mnemonic, ext_operands, ext_disasm, section, function, label.
|
||||
|
||||
use duckdb::{Appender, params};
|
||||
|
||||
use crate::disasm::RichDisasmItem;
|
||||
|
||||
/// Append every item to the appender. Returns the number of rows written.
|
||||
/// Does NOT flush — the caller decides when to flush, since multiple
|
||||
/// section iterators typically share one appender.
|
||||
pub fn append_instructions<'a>(
|
||||
appender: &mut Appender<'_>,
|
||||
items: impl IntoIterator<Item = RichDisasmItem<'a>>,
|
||||
) -> duckdb::Result<u64> {
|
||||
let mut count: u64 = 0;
|
||||
for ri in items {
|
||||
let t = &ri.item.text;
|
||||
appender.append_row(params![
|
||||
ri.item.addr as i64,
|
||||
ri.item.raw as i64,
|
||||
t.mnemonic.as_str(),
|
||||
t.operands.as_str(),
|
||||
t.disasm.as_str(),
|
||||
t.ext_mnemonic.as_deref(),
|
||||
t.ext_operands.as_deref(),
|
||||
t.ext_disasm.as_deref(),
|
||||
t.branch_target.map(|t| t as i64),
|
||||
ri.section,
|
||||
ri.function.map(|f| f as i64),
|
||||
ri.label,
|
||||
])?;
|
||||
count += 1;
|
||||
}
|
||||
Ok(count)
|
||||
}
|
||||
Reference in New Issue
Block a user