This commit is contained in:
Nilton Constantino 2026-01-27 13:51:12 +00:00
parent 8240785160
commit 4bd3484c85
No known key found for this signature in database
9 changed files with 185 additions and 67 deletions

View File

@ -1,62 +0,0 @@
use crate::ir;
use crate::ir_core;
use anyhow::Result;
pub fn lower_program(program: &ir_core::Program) -> Result<ir::Module> {
// For now, we just lower the first module as a smoke test
if let Some(core_module) = program.modules.first() {
let mut vm_module = ir::Module::new(core_module.name.clone());
vm_module.const_pool = program.const_pool.clone();
for core_func in &core_module.functions {
let mut vm_func = ir::Function {
id: core_func.id,
name: core_func.name.clone(),
params: vec![], // TODO: lower params
return_type: ir::Type::Null, // TODO: lower return type
body: vec![],
};
for block in &core_func.blocks {
// Label for the block
vm_func.body.push(ir::Instruction::new(
ir::InstrKind::Label(ir::Label(format!("block_{}", block.id))),
None,
));
for instr in &block.instrs {
match instr {
ir_core::Instr::PushConst(id) => {
vm_func.body.push(ir::Instruction::new(
ir::InstrKind::PushConst(*id),
None,
));
}
ir_core::Instr::Call(id) => {
vm_func.body.push(ir::Instruction::new(
ir::InstrKind::Call { func_id: *id, arg_count: 0 },
None,
));
}
}
}
match &block.terminator {
ir_core::Terminator::Return => {
vm_func.body.push(ir::Instruction::new(ir::InstrKind::Ret, None));
}
ir_core::Terminator::Jump(target) => {
vm_func.body.push(ir::Instruction::new(
ir::InstrKind::Jmp(ir::Label(format!("block_{}", target))),
None,
));
}
}
}
vm_module.functions.push(vm_func);
}
Ok(vm_module)
} else {
anyhow::bail!("No modules in core program")
}
}

View File

@ -1,4 +1,3 @@
pub mod lowering;
pub mod emit_bytecode; pub mod emit_bytecode;
pub mod artifacts; pub mod artifacts;

View File

@ -7,5 +7,7 @@ pub enum Instr {
/// Placeholder for constant loading. /// Placeholder for constant loading.
PushConst(ConstId), PushConst(ConstId),
/// Placeholder for function calls. /// Placeholder for function calls.
Call(FunctionId), Call(FunctionId, u32),
/// Host calls (syscalls).
Syscall(u32),
} }

View File

@ -40,6 +40,7 @@
pub mod common; pub mod common;
pub mod ir; pub mod ir;
pub mod ir_core; pub mod ir_core;
pub mod lowering;
pub mod backend; pub mod backend;
pub mod frontends; pub mod frontends;
pub mod compiler; pub mod compiler;

View File

@ -0,0 +1,85 @@
use crate::ir;
use crate::ir_core;
use anyhow::Result;
/// Lowers a Core IR program into a VM IR module.
pub fn lower_program(program: &ir_core::Program) -> Result<ir::Module> {
// For now, we assume a single module program or lower the first one.
// In the future, we might want to lower all modules and link them.
if let Some(core_module) = program.modules.first() {
lower_module(core_module, &program.const_pool)
} else {
anyhow::bail!("No modules in core program")
}
}
/// Lowers a single Core IR module into a VM IR module.
pub fn lower_module(core_module: &ir_core::Module, const_pool: &ir_core::ConstPool) -> Result<ir::Module> {
let mut vm_module = ir::Module::new(core_module.name.clone());
vm_module.const_pool = const_pool.clone();
for core_func in &core_module.functions {
vm_module.functions.push(lower_function(core_func)?);
}
Ok(vm_module)
}
/// Lowers a Core IR function into a VM IR function.
pub fn lower_function(core_func: &ir_core::Function) -> Result<ir::Function> {
let mut vm_func = ir::Function {
id: core_func.id,
name: core_func.name.clone(),
params: vec![], // Params are not yet represented in Core IR Function
return_type: ir::Type::Null, // Return type is not yet represented in Core IR Function
body: vec![],
};
for block in &core_func.blocks {
// Core blocks map to labels in the flat VM IR instruction list.
vm_func.body.push(ir::Instruction::new(
ir::InstrKind::Label(ir::Label(format!("block_{}", block.id))),
None,
));
for instr in &block.instrs {
match instr {
ir_core::Instr::PushConst(id) => {
vm_func.body.push(ir::Instruction::new(
ir::InstrKind::PushConst(*id),
None,
));
}
ir_core::Instr::Call(func_id, arg_count) => {
vm_func.body.push(ir::Instruction::new(
ir::InstrKind::Call {
func_id: *func_id,
arg_count: *arg_count
},
None,
));
}
ir_core::Instr::Syscall(id) => {
vm_func.body.push(ir::Instruction::new(
ir::InstrKind::Syscall(*id),
None,
));
}
}
}
match &block.terminator {
ir_core::Terminator::Return => {
vm_func.body.push(ir::Instruction::new(ir::InstrKind::Ret, None));
}
ir_core::Terminator::Jump(target) => {
vm_func.body.push(ir::Instruction::new(
ir::InstrKind::Jmp(ir::Label(format!("block_{}", target))),
None,
));
}
}
}
Ok(vm_func)
}

View File

@ -0,0 +1,3 @@
pub mod core_to_vm;
pub use core_to_vm::lower_program;

View File

@ -17,7 +17,7 @@ fn test_ir_core_manual_construction() {
id: 0, id: 0,
instrs: vec![ instrs: vec![
Instr::PushConst(ConstId(0)), Instr::PushConst(ConstId(0)),
Instr::Call(FunctionId(11)), Instr::Call(FunctionId(11), 0),
], ],
terminator: Terminator::Return, terminator: Terminator::Return,
}], }],
@ -51,7 +51,10 @@ fn test_ir_core_manual_construction() {
"PushConst": 0 "PushConst": 0
}, },
{ {
"Call": 11 "Call": [
11,
0
]
} }
], ],
"terminator": "Return" "terminator": "Return"

View File

@ -0,0 +1,87 @@
use prometeu_compiler::ir_core;
use prometeu_compiler::ir_core::*;
use prometeu_compiler::lowering::lower_program;
use prometeu_compiler::ir::*;
#[test]
fn test_full_lowering() {
let mut const_pool = ConstPool::new();
const_pool.insert(ConstantValue::Int(100)); // ConstId(0)
let program = Program {
const_pool,
modules: vec![ir_core::Module {
name: "test_mod".to_string(),
functions: vec![ir_core::Function {
id: FunctionId(1),
name: "main".to_string(),
blocks: vec![
Block {
id: 0,
instrs: vec![
Instr::PushConst(ConstId(0)),
Instr::Call(FunctionId(2), 1),
],
terminator: Terminator::Jump(1),
},
Block {
id: 1,
instrs: vec![
Instr::Syscall(42),
],
terminator: Terminator::Return,
},
],
}],
}],
};
let vm_module = lower_program(&program).expect("Lowering failed");
assert_eq!(vm_module.name, "test_mod");
let func = &vm_module.functions[0];
assert_eq!(func.name, "main");
// Instructions expected:
// 0: Label block_0
// 1: PushConst 0
// 2: Call { func_id: 2, arg_count: 1 }
// 3: Jmp block_1
// 4: Label block_1
// 5: Syscall 42
// 6: Ret
assert_eq!(func.body.len(), 7);
match &func.body[0].kind {
InstrKind::Label(Label(l)) => assert_eq!(l, "block_0"),
_ => panic!("Expected label block_0"),
}
match &func.body[1].kind {
InstrKind::PushConst(id) => assert_eq!(id.0, 0),
_ => panic!("Expected PushConst 0"),
}
match &func.body[2].kind {
InstrKind::Call { func_id, arg_count } => {
assert_eq!(func_id.0, 2);
assert_eq!(*arg_count, 1);
}
_ => panic!("Expected Call"),
}
match &func.body[3].kind {
InstrKind::Jmp(Label(l)) => assert_eq!(l, "block_1"),
_ => panic!("Expected Jmp block_1"),
}
match &func.body[4].kind {
InstrKind::Label(Label(l)) => assert_eq!(l, "block_1"),
_ => panic!("Expected label block_1"),
}
match &func.body[5].kind {
InstrKind::Syscall(id) => assert_eq!(*id, 42),
_ => panic!("Expected Syscall 42"),
}
match &func.body[6].kind {
InstrKind::Ret => (),
_ => panic!("Expected Ret"),
}
}

View File

@ -74,7 +74,7 @@ fn test_vm_ir_serialization() {
#[test] #[test]
fn test_lowering_smoke() { fn test_lowering_smoke() {
use prometeu_compiler::ir_core; use prometeu_compiler::ir_core;
use prometeu_compiler::backend::lowering::lower_program; use prometeu_compiler::lowering::lower_program;
let mut const_pool = ir_core::ConstPool::new(); let mut const_pool = ir_core::ConstPool::new();
const_pool.insert(ir_core::ConstantValue::Int(42)); const_pool.insert(ir_core::ConstantValue::Int(42));