Add a preliminary codegen of case statement
This commit is contained in:
parent
47b085e249
commit
83dfd6e618
|
@ -1,4 +1,4 @@
|
||||||
use crate::cst::{Expression, ModuleContext, Statement, Tag, Tools};
|
use crate::cst::{Expression, ModuleContext, Statement, Tag, Tools, UnitContext};
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use llhd::ir::Block;
|
use llhd::ir::Block;
|
||||||
|
|
||||||
|
@ -11,22 +11,109 @@ impl CaseStatement {
|
||||||
pub fn codegen(json: &JsonValue, context: &mut ModuleContext) -> Option<Block> {
|
pub fn codegen(json: &JsonValue, context: &mut ModuleContext) -> Option<Block> {
|
||||||
let (json_expression, json_case_items, json_default_statement) = Self::analyze(json);
|
let (json_expression, json_case_items, json_default_statement) = Self::analyze(json);
|
||||||
|
|
||||||
|
if context.unit_ctx.data.is_none() {
|
||||||
Expression::codegen(json_expression, context);
|
Expression::codegen(json_expression, context);
|
||||||
|
|
||||||
for (json_case_expressions, json_statement) in json_case_items {
|
for (json_case_expressions, json_statement) in json_case_items {
|
||||||
for json_case_expression in json_case_expressions {
|
for json_case_expression in json_case_expressions {
|
||||||
Expression::codegen(json_case_expression, context);
|
Expression::codegen(json_case_expression, context);
|
||||||
}
|
}
|
||||||
Statement::codegen(json_statement, context);
|
Self::visit_case_body(json_statement, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if json_default_statement.is_some() {
|
if json_default_statement.is_some() {
|
||||||
Statement::codegen(json_default_statement.unwrap(), context);
|
Self::visit_case_body(json_default_statement.unwrap(), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
warn!("TODO: finish codegen()");
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let expr = {
|
||||||
|
let e = Expression::codegen(json_expression, context);
|
||||||
|
assert!(e.is_some(), "FIXME: CST node '{}'", json_expression);
|
||||||
|
e.unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut bb_next = {
|
||||||
|
let unit_ctx = &mut context.unit_ctx;
|
||||||
|
let mut builder = UnitContext::builder(&mut unit_ctx.data);
|
||||||
|
builder.block()
|
||||||
|
};
|
||||||
|
|
||||||
|
let case_tails: Vec<_> = json_case_items
|
||||||
|
.iter()
|
||||||
|
.map(|(json_case_expressions, json_statement)| {
|
||||||
|
let case_expressions: Vec<_> = json_case_expressions
|
||||||
|
.iter()
|
||||||
|
.map(|x| Expression::codegen(x, context).unwrap())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let bb_curr = {
|
||||||
|
let unit_ctx = &mut context.unit_ctx;
|
||||||
|
let mut builder = UnitContext::builder(&mut unit_ctx.data);
|
||||||
|
|
||||||
|
let bb_curr = bb_next;
|
||||||
|
bb_next = builder.block();
|
||||||
|
|
||||||
|
builder.append_to(unit_ctx.bb_head.pop().unwrap());
|
||||||
|
unit_ctx.bb_head.push(bb_next); // basic block for the next case
|
||||||
|
|
||||||
|
let case_expr = case_expressions
|
||||||
|
.into_iter()
|
||||||
|
.reduce(|x, y| builder.ins().or(x, y))
|
||||||
|
.unwrap();
|
||||||
|
let cond = builder.ins().eq(expr, case_expr);
|
||||||
|
builder.ins().br_cond(cond, bb_next, bb_curr);
|
||||||
|
|
||||||
|
bb_curr
|
||||||
|
};
|
||||||
|
|
||||||
|
context.unit_ctx.bb_head.push(bb_curr);
|
||||||
|
let stmt = Self::visit_case_body(json_statement, context);
|
||||||
|
context.unit_ctx.bb_head.pop();
|
||||||
|
|
||||||
|
stmt.unwrap()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if json_default_statement.is_some() {
|
||||||
|
let stmt = Self::visit_case_body(json_default_statement.unwrap(), context);
|
||||||
|
let unit_ctx = &mut context.unit_ctx;
|
||||||
|
unit_ctx.bb_head.pop();
|
||||||
|
unit_ctx.bb_head.push(stmt.unwrap()); // basic block for the future statement
|
||||||
|
bb_next = stmt.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let unit_ctx = &mut context.unit_ctx;
|
||||||
|
if unit_ctx.data.is_some() {
|
||||||
|
let mut builder = UnitContext::builder(&mut unit_ctx.data);
|
||||||
|
|
||||||
|
// merge dangling basic blocks at the end of each case
|
||||||
|
for case_tail in case_tails {
|
||||||
|
builder.replace_block_use(case_tail, bb_next);
|
||||||
|
builder.delete_block(case_tail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(bb_next)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_case_body(json: &JsonValue, context: &mut ModuleContext) -> Option<Block> {
|
||||||
|
let stmt = Statement::codegen(json, context);
|
||||||
|
|
||||||
|
if context.unit_ctx.data.is_some() {
|
||||||
|
let unit_ctx = &mut context.unit_ctx;
|
||||||
|
let mut builder = UnitContext::builder(&mut unit_ctx.data);
|
||||||
|
|
||||||
|
let bb_dangled = builder.block();
|
||||||
|
builder.append_to(stmt.unwrap());
|
||||||
|
builder.ins().br(bb_dangled);
|
||||||
|
|
||||||
|
Some(bb_dangled)
|
||||||
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn analyze(
|
fn analyze(
|
||||||
json: &JsonValue,
|
json: &JsonValue,
|
||||||
|
|
Loading…
Reference in New Issue