Fix a bug in case statement

This commit is contained in:
Guojie Luo 2022-04-01 10:01:04 +08:00
parent 929abdaf85
commit 7ab655df9b
4 changed files with 47 additions and 22 deletions

View File

@ -1,10 +1,10 @@
use crate::cst::{Expression, ModuleContext, Statement, SymbolKind, Tag, Tools, UnitContext};
use json::JsonValue;
use linked_hash_map::LinkedHashMap as HashMap;
use llhd::{
ir::{Block, Inst, Opcode, Signature, UnitId, UnitKind, UnitName, Value},
ty::{int_ty, signal_ty},
};
use std::collections::HashMap;
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};

View File

@ -1,6 +1,6 @@
use crate::cst::{Expression, ModuleContext, Statement, Tag, Tools, UnitContext};
use json::JsonValue;
use llhd::ir::Block;
use llhd::ir::{Block, Unit};
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
@ -34,10 +34,21 @@ impl CaseStatement {
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_body_name = |unit: Unit| -> String {
let prefix = "case_body";
let count = unit
.blocks()
.filter(|x| {
let bb_name = unit.get_block_name(*x);
bb_name.is_some() && bb_name.unwrap().to_string().starts_with(prefix)
})
.count();
if count > 0 {
format!("{}{}", prefix, count)
} else {
String::from(prefix)
}
};
let case_tails: Vec<_> = json_case_items
@ -52,8 +63,15 @@ impl CaseStatement {
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();
let bb_curr = builder.named_block(case_body_name(builder.unit()));
let bb_next = builder.block();
debug!(
"case br_cond (true {}; false {}) in block {}",
bb_curr.dump(&builder.unit()),
bb_next.dump(&builder.unit()),
unit_ctx.bb_head.last().unwrap().dump(&builder.unit())
);
builder.append_to(unit_ctx.bb_head.pop().unwrap());
unit_ctx.bb_head.push(bb_next); // basic block for the next case
@ -76,13 +94,16 @@ impl CaseStatement {
})
.collect();
if json_default_statement.is_some() {
let bb_last = 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();
}
stmt.unwrap()
} else {
let unit_ctx = &mut context.unit_ctx;
*unit_ctx.bb_head.last().unwrap() // WARN: double check
};
let unit_ctx = &mut context.unit_ctx;
if unit_ctx.data.is_some() {
@ -90,12 +111,12 @@ impl CaseStatement {
// 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.replace_block_use(case_tail, bb_last);
builder.delete_block(case_tail);
}
}
Some(bb_next)
Some(bb_last)
}
fn visit_case_body(json: &JsonValue, context: &mut ModuleContext) -> Option<Block> {

View File

@ -24,16 +24,16 @@ impl ConditionalStatement {
let unit_ctx = &mut context.unit_ctx;
let mut builder = UnitContext::builder(&mut unit_ctx.data);
let unit = &builder.unit();
let count = unit
.blocks()
.filter(|x| {
let bb_name = unit.get_block_name(*x);
bb_name.is_some() && bb_name.unwrap().to_string().starts_with("if_true")
})
.count();
let (if_true_name, if_false_name) = {
let unit = &builder.unit();
let count = unit
.blocks()
.filter(|x| {
let bb_name = unit.get_block_name(*x);
bb_name.is_some() && bb_name.unwrap().to_string().starts_with("if_true")
})
.count();
if count > 0 {
(format!("if_true{}", count), format!("if_false{}", count))
} else {

View File

@ -163,6 +163,10 @@ impl ModuleDeclaration {
}
context.module.add_unit(entity_data);
debug!(
"module codegen >>>>>>>>>\n{}<<<<<<<<<",
context.module.dump()
);
context.module
}