standalone: Prepend statement type to basic block label names

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 size_t = generator.get_size_type(ctx.ctx);
let zero = int32.const_zero();
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
let test_bb = ctx.ctx.append_basic_block(current, "test");
let body_bb = ctx.ctx.append_basic_block(current, "body");
let cont_bb = ctx.ctx.append_basic_block(current, "cont");
let current = ctx.builder.get_insert_block().and_then(|bb| bb.get_parent()).unwrap();
let test_bb = ctx.ctx.append_basic_block(current, "for.cond");
let body_bb = ctx.ctx.append_basic_block(current, "for.body");
let cont_bb = ctx.ctx.append_basic_block(current, "for.end");
// if there is no orelse, we just go to cont_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
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 i = generator.gen_var_alloc(ctx, int32.into())?;
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_unconditional_branch(test_bb);
ctx.builder.position_at_end(test_bb);
let sign = ctx.builder.build_int_compare(
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(user_i, tmp);
// // 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
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 neg = ctx.builder.build_and(ctx.builder.build_not(sign, "inv"), cmp2, "neg");
ctx.builder.build_conditional_branch(
@ -268,6 +269,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
body_bb,
orelse_bb,
);
ctx.builder.position_at_end(body_bb);
} else {
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();
ctx.builder.build_unconditional_branch(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_int_add(tmp, size_t.const_int(1, false), "inc");
ctx.builder.build_store(counter, tmp);
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.position_at_end(body_bb);
let arr_ptr = ctx
.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())?;
for (k, (_, _, counter)) in var_assignment.iter() {
let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap();
if counter != counter2 {
*static_val = None;
}
}
if !ctx.is_terminated() {
ctx.builder.build_unconditional_branch(test_bb);
}
if !orelse.is_empty() {
ctx.builder.position_at_end(orelse_bb);
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);
}
}
for (k, (_, _, counter)) in var_assignment.iter() {
let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap();
if counter != counter2 {
*static_val = None;
}
}
ctx.builder.position_at_end(cont_bb);
ctx.loop_target = loop_bb;
} else {
@ -336,12 +345,12 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator>(
let var_assignment = ctx.var_assignment.clone();
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
let test_bb = ctx.ctx.append_basic_block(current, "test");
let body_bb = ctx.ctx.append_basic_block(current, "body");
let cont_bb = ctx.ctx.append_basic_block(current, "cont");
let test_bb = ctx.ctx.append_basic_block(current, "while.test");
let body_bb = ctx.ctx.append_basic_block(current, "while.body");
let cont_bb = ctx.ctx.append_basic_block(current, "while.cont");
// if there is no orelse, we just go to cont_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
let loop_bb = ctx.loop_target.replace((test_bb, cont_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 current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
let test_bb = ctx.ctx.append_basic_block(current, "test");
let body_bb = ctx.ctx.append_basic_block(current, "body");
let test_bb = ctx.ctx.append_basic_block(current, "if.test");
let body_bb = ctx.ctx.append_basic_block(current, "if.body");
let mut cont_bb = None;
// if there is no orelse, we just go to cont_bb
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()
} 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.position_at_end(test_bb);