docs/ci: selfhost bootstrap/exe-first workflows; add ny-llvmc scaffolding + JSON v0 schema validation; plan: unify to Nyash ABI v2 (no backwards compat)

This commit is contained in:
Selfhosting Dev
2025-09-17 20:33:19 +09:00
parent a5054a271b
commit 4ea3ca2685
56 changed files with 2275 additions and 1623 deletions

View File

@ -105,7 +105,7 @@ impl MirOptimizer {
// Pass 7 (optional): Core-13 pure normalization
if crate::config::env::mir_core13_pure() {
stats.merge(self.normalize_pure_core13(module));
stats.merge(crate::mir::optimizer_passes::normalize_core13_pure::normalize_pure_core13(self, module));
}
if self.debug {
@ -147,200 +147,7 @@ impl MirOptimizer {
/// Neg x => BinOp(Sub, Const 0, x)
/// Not x => Compare(Eq, x, Const false)
/// BitNot x => BinOp(BitXor, x, Const(-1))
fn normalize_pure_core13(&mut self, module: &mut MirModule) -> OptimizationStats {
use super::instruction::ConstValue;
use super::{BinaryOp, CompareOp, MirInstruction as I};
let mut stats = OptimizationStats::new();
for (_fname, function) in &mut module.functions {
for (_bb, block) in &mut function.blocks {
let mut out: Vec<I> = Vec::with_capacity(block.instructions.len() + 8);
let old = std::mem::take(&mut block.instructions);
for inst in old.into_iter() {
match inst {
I::Load { dst, ptr } => {
out.push(I::ExternCall {
dst: Some(dst),
iface_name: "env.local".to_string(),
method_name: "get".to_string(),
args: vec![ptr],
effects: super::EffectMask::READ,
});
stats.intrinsic_optimizations += 1;
}
I::Store { value, ptr } => {
out.push(I::ExternCall {
dst: None,
iface_name: "env.local".to_string(),
method_name: "set".to_string(),
args: vec![ptr, value],
effects: super::EffectMask::WRITE,
});
stats.intrinsic_optimizations += 1;
}
I::NewBox {
dst,
box_type,
mut args,
} => {
// prepend type name as Const String
let ty_id = super::ValueId::new(function.next_value_id);
function.next_value_id += 1;
out.push(I::Const {
dst: ty_id,
value: ConstValue::String(box_type),
});
let mut call_args = Vec::with_capacity(1 + args.len());
call_args.push(ty_id);
call_args.append(&mut args);
out.push(I::ExternCall {
dst: Some(dst),
iface_name: "env.box".to_string(),
method_name: "new".to_string(),
args: call_args,
effects: super::EffectMask::PURE, // constructor is logically alloc; conservatively PURE here
});
stats.intrinsic_optimizations += 1;
}
I::UnaryOp { dst, op, operand } => {
match op {
super::UnaryOp::Neg => {
let zero = super::ValueId::new(function.next_value_id);
function.next_value_id += 1;
out.push(I::Const {
dst: zero,
value: ConstValue::Integer(0),
});
out.push(I::BinOp {
dst,
op: BinaryOp::Sub,
lhs: zero,
rhs: operand,
});
}
super::UnaryOp::Not => {
let f = super::ValueId::new(function.next_value_id);
function.next_value_id += 1;
out.push(I::Const {
dst: f,
value: ConstValue::Bool(false),
});
out.push(I::Compare {
dst,
op: CompareOp::Eq,
lhs: operand,
rhs: f,
});
}
super::UnaryOp::BitNot => {
let all1 = super::ValueId::new(function.next_value_id);
function.next_value_id += 1;
out.push(I::Const {
dst: all1,
value: ConstValue::Integer(-1),
});
out.push(I::BinOp {
dst,
op: BinaryOp::BitXor,
lhs: operand,
rhs: all1,
});
}
}
stats.intrinsic_optimizations += 1;
}
other => out.push(other),
}
}
block.instructions = out;
if let Some(term) = block.terminator.take() {
block.terminator = Some(match term {
I::Load { dst, ptr } => I::ExternCall {
dst: Some(dst),
iface_name: "env.local".to_string(),
method_name: "get".to_string(),
args: vec![ptr],
effects: super::EffectMask::READ,
},
I::Store { value, ptr } => I::ExternCall {
dst: None,
iface_name: "env.local".to_string(),
method_name: "set".to_string(),
args: vec![ptr, value],
effects: super::EffectMask::WRITE,
},
I::NewBox {
dst,
box_type,
mut args,
} => {
let ty_id = super::ValueId::new(function.next_value_id);
function.next_value_id += 1;
block.instructions.push(I::Const {
dst: ty_id,
value: ConstValue::String(box_type),
});
let mut call_args = Vec::with_capacity(1 + args.len());
call_args.push(ty_id);
call_args.append(&mut args);
I::ExternCall {
dst: Some(dst),
iface_name: "env.box".to_string(),
method_name: "new".to_string(),
args: call_args,
effects: super::EffectMask::PURE,
}
}
I::UnaryOp { dst, op, operand } => match op {
super::UnaryOp::Neg => {
let zero = super::ValueId::new(function.next_value_id);
function.next_value_id += 1;
block.instructions.push(I::Const {
dst: zero,
value: ConstValue::Integer(0),
});
I::BinOp {
dst,
op: BinaryOp::Sub,
lhs: zero,
rhs: operand,
}
}
super::UnaryOp::Not => {
let f = super::ValueId::new(function.next_value_id);
function.next_value_id += 1;
block.instructions.push(I::Const {
dst: f,
value: ConstValue::Bool(false),
});
I::Compare {
dst,
op: CompareOp::Eq,
lhs: operand,
rhs: f,
}
}
super::UnaryOp::BitNot => {
let all1 = super::ValueId::new(function.next_value_id);
function.next_value_id += 1;
block.instructions.push(I::Const {
dst: all1,
value: ConstValue::Integer(-1),
});
I::BinOp {
dst,
op: BinaryOp::BitXor,
lhs: operand,
rhs: all1,
}
}
},
other => other,
});
}
}
}
stats
}
// normalize_pure_core13 moved to optimizer_passes::normalize_core13_pure
/// Eliminate dead code in a single function
fn eliminate_dead_code_in_function(&mut self, function: &mut MirFunction) -> usize {