standalone: Prepend statement type to basic block label names

This commit is contained in:
David Mak 2023-09-05 09:41:05 +08:00
parent 91749bb01b
commit 1e27986864
1 changed files with 25 additions and 16 deletions

View File

@ -219,13 +219,13 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
let int32 = ctx.ctx.i32_type(); let int32 = ctx.ctx.i32_type();
let size_t = generator.get_size_type(ctx.ctx); let size_t = generator.get_size_type(ctx.ctx);
let zero = int32.const_zero(); let zero = int32.const_zero();
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current = ctx.builder.get_insert_block().and_then(|bb| bb.get_parent()).unwrap();
let test_bb = ctx.ctx.append_basic_block(current, "test"); let test_bb = ctx.ctx.append_basic_block(current, "for.cond");
let body_bb = ctx.ctx.append_basic_block(current, "body"); let body_bb = ctx.ctx.append_basic_block(current, "for.body");
let cont_bb = ctx.ctx.append_basic_block(current, "cont"); let cont_bb = ctx.ctx.append_basic_block(current, "for.end");
// if there is no orelse, we just go to cont_bb // if there is no orelse, we just go to cont_bb
let orelse_bb = let orelse_bb =
if orelse.is_empty() { cont_bb } else { ctx.ctx.append_basic_block(current, "orelse") }; if orelse.is_empty() { cont_bb } else { ctx.ctx.append_basic_block(current, "for.orelse") };
// store loop bb information and restore it later // store loop bb information and restore it later
let loop_bb = ctx.loop_target.replace((test_bb, cont_bb)); let loop_bb = ctx.loop_target.replace((test_bb, cont_bb));
@ -239,9 +239,10 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
let iter_val = iter_val.into_pointer_value(); let iter_val = iter_val.into_pointer_value();
let i = generator.gen_var_alloc(ctx, int32.into())?; let i = generator.gen_var_alloc(ctx, int32.into())?;
let user_i = generator.gen_store_target(ctx, target)?; let user_i = generator.gen_store_target(ctx, target)?;
let (start, end, step) = destructure_range(ctx, iter_val); let (start, stop, step) = destructure_range(ctx, iter_val);
ctx.builder.build_store(i, ctx.builder.build_int_sub(start, step, "start_init")); ctx.builder.build_store(i, ctx.builder.build_int_sub(start, step, "start_init"));
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
ctx.builder.position_at_end(test_bb); ctx.builder.position_at_end(test_bb);
let sign = ctx.builder.build_int_compare( let sign = ctx.builder.build_int_compare(
inkwell::IntPredicate::SGT, inkwell::IntPredicate::SGT,
@ -258,9 +259,9 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
ctx.builder.build_store(i, tmp); ctx.builder.build_store(i, tmp);
ctx.builder.build_store(user_i, tmp); ctx.builder.build_store(user_i, tmp);
// // if step > 0, continue when i < end // // if step > 0, continue when i < end
let cmp1 = ctx.builder.build_int_compare(inkwell::IntPredicate::SLT, tmp, end, "cmp1"); let cmp1 = ctx.builder.build_int_compare(inkwell::IntPredicate::SLT, tmp, stop, "cmp1");
// if step < 0, continue when i > end // if step < 0, continue when i > end
let cmp2 = ctx.builder.build_int_compare(inkwell::IntPredicate::SGT, tmp, end, "cmp2"); let cmp2 = ctx.builder.build_int_compare(inkwell::IntPredicate::SGT, tmp, stop, "cmp2");
let pos = ctx.builder.build_and(sign, cmp1, "pos"); let pos = ctx.builder.build_and(sign, cmp1, "pos");
let neg = ctx.builder.build_and(ctx.builder.build_not(sign, "inv"), cmp2, "neg"); let neg = ctx.builder.build_and(ctx.builder.build_not(sign, "inv"), cmp2, "neg");
ctx.builder.build_conditional_branch( ctx.builder.build_conditional_branch(
@ -268,6 +269,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
body_bb, body_bb,
orelse_bb, orelse_bb,
); );
ctx.builder.position_at_end(body_bb); ctx.builder.position_at_end(body_bb);
} else { } else {
let counter = generator.gen_var_alloc(ctx, size_t.into())?; let counter = generator.gen_var_alloc(ctx, size_t.into())?;
@ -280,12 +282,14 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
) )
.into_int_value(); .into_int_value();
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
ctx.builder.position_at_end(test_bb); ctx.builder.position_at_end(test_bb);
let tmp = ctx.builder.build_load(counter, "i").into_int_value(); let tmp = ctx.builder.build_load(counter, "i").into_int_value();
let tmp = ctx.builder.build_int_add(tmp, size_t.const_int(1, false), "inc"); let tmp = ctx.builder.build_int_add(tmp, size_t.const_int(1, false), "inc");
ctx.builder.build_store(counter, tmp); ctx.builder.build_store(counter, tmp);
let cmp = ctx.builder.build_int_compare(inkwell::IntPredicate::SLT, tmp, len, "cmp"); let cmp = ctx.builder.build_int_compare(inkwell::IntPredicate::SLT, tmp, len, "cmp");
ctx.builder.build_conditional_branch(cmp, body_bb, orelse_bb); ctx.builder.build_conditional_branch(cmp, body_bb, orelse_bb);
ctx.builder.position_at_end(body_bb); ctx.builder.position_at_end(body_bb);
let arr_ptr = ctx let arr_ptr = ctx
.build_gep_and_load(iter_val.into_pointer_value(), &[zero, zero]) .build_gep_and_load(iter_val.into_pointer_value(), &[zero, zero])
@ -295,15 +299,18 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
} }
gen_block(generator, ctx, body.iter())?; gen_block(generator, ctx, body.iter())?;
for (k, (_, _, counter)) in var_assignment.iter() { for (k, (_, _, counter)) in var_assignment.iter() {
let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap(); let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap();
if counter != counter2 { if counter != counter2 {
*static_val = None; *static_val = None;
} }
} }
if !ctx.is_terminated() { if !ctx.is_terminated() {
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
} }
if !orelse.is_empty() { if !orelse.is_empty() {
ctx.builder.position_at_end(orelse_bb); ctx.builder.position_at_end(orelse_bb);
gen_block(generator, ctx, orelse.iter())?; gen_block(generator, ctx, orelse.iter())?;
@ -311,12 +318,14 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb);
} }
} }
for (k, (_, _, counter)) in var_assignment.iter() { for (k, (_, _, counter)) in var_assignment.iter() {
let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap(); let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap();
if counter != counter2 { if counter != counter2 {
*static_val = None; *static_val = None;
} }
} }
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
ctx.loop_target = loop_bb; ctx.loop_target = loop_bb;
} else { } else {
@ -336,12 +345,12 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator>(
let var_assignment = ctx.var_assignment.clone(); let var_assignment = ctx.var_assignment.clone();
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
let test_bb = ctx.ctx.append_basic_block(current, "test"); let test_bb = ctx.ctx.append_basic_block(current, "while.test");
let body_bb = ctx.ctx.append_basic_block(current, "body"); let body_bb = ctx.ctx.append_basic_block(current, "while.body");
let cont_bb = ctx.ctx.append_basic_block(current, "cont"); let cont_bb = ctx.ctx.append_basic_block(current, "while.cont");
// if there is no orelse, we just go to cont_bb // if there is no orelse, we just go to cont_bb
let orelse_bb = let orelse_bb =
if orelse.is_empty() { cont_bb } else { ctx.ctx.append_basic_block(current, "orelse") }; if orelse.is_empty() { cont_bb } else { ctx.ctx.append_basic_block(current, "while.orelse") };
// store loop bb information and restore it later // store loop bb information and restore it later
let loop_bb = ctx.loop_target.replace((test_bb, cont_bb)); let loop_bb = ctx.loop_target.replace((test_bb, cont_bb));
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
@ -399,15 +408,15 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator>(
let var_assignment = ctx.var_assignment.clone(); let var_assignment = ctx.var_assignment.clone();
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
let test_bb = ctx.ctx.append_basic_block(current, "test"); let test_bb = ctx.ctx.append_basic_block(current, "if.test");
let body_bb = ctx.ctx.append_basic_block(current, "body"); let body_bb = ctx.ctx.append_basic_block(current, "if.body");
let mut cont_bb = None; let mut cont_bb = None;
// if there is no orelse, we just go to cont_bb // if there is no orelse, we just go to cont_bb
let orelse_bb = if orelse.is_empty() { let orelse_bb = if orelse.is_empty() {
cont_bb = Some(ctx.ctx.append_basic_block(current, "cont")); cont_bb = Some(ctx.ctx.append_basic_block(current, "if.cont"));
cont_bb.unwrap() cont_bb.unwrap()
} else { } else {
ctx.ctx.append_basic_block(current, "orelse") ctx.ctx.append_basic_block(current, "if.orelse")
}; };
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
ctx.builder.position_at_end(test_bb); ctx.builder.position_at_end(test_bb);