pr 05
This commit is contained in:
parent
8240785160
commit
4bd3484c85
@ -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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +1,3 @@
|
|||||||
pub mod lowering;
|
|
||||||
pub mod emit_bytecode;
|
pub mod emit_bytecode;
|
||||||
pub mod artifacts;
|
pub mod artifacts;
|
||||||
|
|
||||||
|
|||||||
@ -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),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
85
crates/prometeu-compiler/src/lowering/core_to_vm.rs
Normal file
85
crates/prometeu-compiler/src/lowering/core_to_vm.rs
Normal 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)
|
||||||
|
}
|
||||||
3
crates/prometeu-compiler/src/lowering/mod.rs
Normal file
3
crates/prometeu-compiler/src/lowering/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub mod core_to_vm;
|
||||||
|
|
||||||
|
pub use core_to_vm::lower_program;
|
||||||
@ -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"
|
||||||
|
|||||||
87
crates/prometeu-compiler/tests/lowering_tests.rs
Normal file
87
crates/prometeu-compiler/tests/lowering_tests.rs
Normal 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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user