new code gen for Cond

This commit is contained in:
Folkert 2020-03-13 01:54:17 +01:00
parent 263e4b4b6c
commit a7af366c3a
4 changed files with 163 additions and 32 deletions

View file

@ -52,16 +52,14 @@ pub fn build_expr<'a, B: Backend>(
Bool(val) => builder.ins().bconst(types::B1, *val),
Byte(val) => builder.ins().iconst(types::I8, *val as i64),
Cond {
cond_lhs,
cond_rhs,
cond,
pass,
fail,
cond_layout,
ret_layout,
} => {
let branch = Branch2 {
cond_lhs,
cond_rhs,
cond,
pass,
fail,
cond_layout,
@ -269,8 +267,7 @@ pub fn build_expr<'a, B: Backend>(
}
struct Branch2<'a> {
cond_lhs: &'a Expr<'a>,
cond_rhs: &'a Expr<'a>,
cond: &'a Expr<'a>,
cond_layout: &'a Layout<'a>,
pass: &'a Expr<'a>,
fail: &'a Expr<'a>,
@ -296,24 +293,13 @@ fn build_branch2<'a, B: Backend>(
builder.declare_var(ret, ret_type);
let lhs = build_expr(env, scope, module, builder, branch.cond_lhs, procs);
let rhs = build_expr(env, scope, module, builder, branch.cond_rhs, procs);
let cond = build_expr(env, scope, module, builder, branch.cond, procs);
let pass_block = builder.create_block();
let fail_block = builder.create_block();
match branch.cond_layout {
Layout::Builtin(Builtin::Float64) => {
// For floats, first do a `fcmp` comparison to get a bool answer about equality,
// then use `brnz` to branch if that bool equality answer was nonzero (aka true).
let is_eq = builder.ins().fcmp(FloatCC::Equal, lhs, rhs);
builder.ins().brnz(is_eq, pass_block, &[]);
}
Layout::Builtin(Builtin::Int64) => {
// For ints, we can compare and branch in the same instruction: `icmp`
builder
.ins()
.br_icmp(IntCC::Equal, lhs, rhs, pass_block, &[]);
Layout::Builtin(Builtin::Bool(_, _)) => {
builder.ins().brnz(cond, pass_block, &[]);
}
other => panic!("I don't know how to build a conditional for {:?}", other),
}
@ -589,6 +575,20 @@ fn call_by_name<'a, B: Backend>(
builder.ins().ineg(num)
}
Symbol::INT_EQ => {
debug_assert!(args.len() == 2);
let a = build_arg(&args[0], env, scope, module, builder, procs);
let b = build_arg(&args[1], env, scope, module, builder, procs);
builder.ins().icmp(IntCC::Equal, a, b)
}
Symbol::FLOAT_EQ => {
debug_assert!(args.len() == 2);
let a = build_arg(&args[0], env, scope, module, builder, procs);
let b = build_arg(&args[1], env, scope, module, builder, procs);
builder.ins().fcmp(FloatCC::Equal, a, b)
}
Symbol::LIST_GET_UNSAFE => {
debug_assert!(args.len() == 2);

View file

@ -46,22 +46,20 @@ pub fn build_expr<'a, 'ctx, 'env>(
Int(num) => env.context.i64_type().const_int(*num as u64, true).into(),
Float(num) => env.context.f64_type().const_float(*num).into(),
Cond {
cond_lhs,
cond_rhs,
cond,
pass,
fail,
ret_layout,
..
} => {
let cond = Branch2 {
cond_lhs,
cond_rhs,
let conditional = Branch2 {
cond,
pass,
fail,
ret_layout: ret_layout.clone(),
};
build_branch2(env, scope, parent, cond, procs)
build_branch2(env, scope, parent, conditional, procs)
}
Branches { .. } => {
panic!("TODO build_branches(env, scope, parent, cond_lhs, branches, procs)");
@ -251,8 +249,7 @@ pub fn build_expr<'a, 'ctx, 'env>(
}
struct Branch2<'a> {
cond_lhs: &'a Expr<'a>,
cond_rhs: &'a Expr<'a>,
cond: &'a Expr<'a>,
pass: &'a Expr<'a>,
fail: &'a Expr<'a>,
ret_layout: Layout<'a>,
@ -269,9 +266,9 @@ fn build_branch2<'a, 'ctx, 'env>(
let ret_layout = cond.ret_layout;
let ret_type = basic_type_from_layout(env.context, &ret_layout);
let lhs = build_expr(env, scope, parent, cond.cond_lhs, procs);
let rhs = build_expr(env, scope, parent, cond.cond_rhs, procs);
let cond_expr = build_expr(env, scope, parent, cond.cond, procs);
/*
match (lhs, rhs) {
(FloatValue(lhs_float), FloatValue(rhs_float)) => {
let comparison =
@ -294,6 +291,17 @@ fn build_branch2<'a, 'ctx, 'env>(
cond.cond_lhs, cond.cond_rhs
),
}
*/
match cond_expr {
IntValue(value) => build_phi2(
env, scope, parent, value, cond.pass, cond.fail, ret_type, procs,
),
_ => panic!(
"Tried to make a branch out of an invalid condition: cond_expr = {:?}",
cond_expr,
),
}
}
struct SwitchArgs<'a, 'ctx> {
@ -600,6 +608,30 @@ fn call_with_args<'a, 'ctx, 'env>(
BasicValueEnum::IntValue(int_val)
}
Symbol::INT_EQ => {
debug_assert!(args.len() == 2);
let int_val = env.builder.build_int_compare(
IntPredicate::EQ,
args[0].into_int_value(),
args[1].into_int_value(),
"cmp_i64",
);
BasicValueEnum::IntValue(int_val)
}
Symbol::FLOAT_EQ => {
debug_assert!(args.len() == 2);
let int_val = env.builder.build_float_compare(
FloatPredicate::OEQ,
args[0].into_float_value(),
args[1].into_float_value(),
"cmp_f64",
);
BasicValueEnum::IntValue(int_val)
}
Symbol::LIST_GET_UNSAFE => {
debug_assert!(args.len() == 2);