[core] codegen: Add bool_to_int_type to replace bool_to_{i1,i8}

Unifies the implementation for both functions.
This commit is contained in:
David Mak 2025-02-07 14:01:10 +08:00
parent f52ba9f151
commit 529fa67855
3 changed files with 35 additions and 39 deletions

View File

@ -2001,7 +2001,7 @@ pub fn gen_cmpop_expr_with_values<'ctx, G: CodeGenerator>(
).into_int_value(); ).into_int_value();
let result = call_string_eq(ctx, lhs_ptr, lhs_len, rhs_ptr, rhs_len); let result = call_string_eq(ctx, lhs_ptr, lhs_len, rhs_ptr, rhs_len);
if *op == Cmpop::NotEq { if *op == Cmpop::NotEq {
ctx.builder.build_not(result, "").unwrap() ctx.builder.build_not(result, "").unwrap()
} else { } else {
result result
} }

View File

@ -7,7 +7,7 @@ use inkwell::{
use nac3parser::ast::{Expr, Stmt, StrRef}; use nac3parser::ast::{Expr, Stmt, StrRef};
use super::{bool_to_i1, bool_to_i8, expr::*, stmt::*, values::ArraySliceValue, CodeGenContext}; use super::{bool_to_int_type, expr::*, stmt::*, values::ArraySliceValue, CodeGenContext};
use crate::{ use crate::{
symbol_resolver::ValueEnum, symbol_resolver::ValueEnum,
toplevel::{DefinitionId, TopLevelDef}, toplevel::{DefinitionId, TopLevelDef},
@ -248,22 +248,32 @@ pub trait CodeGenerator {
gen_block(self, ctx, stmts) gen_block(self, ctx, stmts)
} }
/// See [`bool_to_i1`]. /// Converts the value of a boolean-like value `bool_value` into an `i1`.
fn bool_to_i1<'ctx>( fn bool_to_i1<'ctx>(
&self, &self,
ctx: &CodeGenContext<'ctx, '_>, ctx: &CodeGenContext<'ctx, '_>,
bool_value: IntValue<'ctx>, bool_value: IntValue<'ctx>,
) -> IntValue<'ctx> { ) -> IntValue<'ctx> {
bool_to_i1(&ctx.builder, bool_value) self.bool_to_int_type(ctx, bool_value, ctx.ctx.bool_type())
} }
/// See [`bool_to_i8`]. /// Converts the value of a boolean-like value `bool_value` into an `i8`.
fn bool_to_i8<'ctx>( fn bool_to_i8<'ctx>(
&self, &self,
ctx: &CodeGenContext<'ctx, '_>, ctx: &CodeGenContext<'ctx, '_>,
bool_value: IntValue<'ctx>, bool_value: IntValue<'ctx>,
) -> IntValue<'ctx> { ) -> IntValue<'ctx> {
bool_to_i8(&ctx.builder, ctx.ctx, bool_value) self.bool_to_int_type(ctx, bool_value, ctx.ctx.i8_type())
}
/// See [`bool_to_int_type`].
fn bool_to_int_type<'ctx>(
&self,
ctx: &CodeGenContext<'ctx, '_>,
bool_value: IntValue<'ctx>,
ty: IntType<'ctx>,
) -> IntValue<'ctx> {
bool_to_int_type(&ctx.builder, bool_value, ty)
} }
} }

View File

@ -933,7 +933,7 @@ pub fn gen_func_impl<
let param_val = param.into_int_value(); let param_val = param.into_int_value();
if expected_ty.get_bit_width() == 8 && param_val.get_type().get_bit_width() == 1 { if expected_ty.get_bit_width() == 8 && param_val.get_type().get_bit_width() == 1 {
bool_to_i8(&builder, context, param_val) bool_to_int_type(&builder, param_val, context.i8_type())
} else { } else {
param_val param_val
} }
@ -1103,43 +1103,29 @@ pub fn gen_func<'ctx, G: CodeGenerator>(
}) })
} }
/// Converts the value of a boolean-like value `bool_value` into an `i1`. /// Converts the value of a boolean-like value `value` into an arbitrary [`IntType`].
fn bool_to_i1<'ctx>(builder: &Builder<'ctx>, bool_value: IntValue<'ctx>) -> IntValue<'ctx> { ///
if bool_value.get_type().get_bit_width() == 1 { /// This has the same semantics as `(ty)(value != 0)` in C.
bool_value ///
} else { /// The returned value is guaranteed to either be `0` or `1`, except for `ty == i1` where only the
builder /// least-significant bit would be guaranteed to be `0` or `1`.
.build_int_compare( fn bool_to_int_type<'ctx>(
IntPredicate::NE,
bool_value,
bool_value.get_type().const_zero(),
"tobool",
)
.unwrap()
}
}
/// Converts the value of a boolean-like value `bool_value` into an `i8`.
fn bool_to_i8<'ctx>(
builder: &Builder<'ctx>, builder: &Builder<'ctx>,
ctx: &'ctx Context, value: IntValue<'ctx>,
bool_value: IntValue<'ctx>, ty: IntType<'ctx>,
) -> IntValue<'ctx> { ) -> IntValue<'ctx> {
let value_bits = bool_value.get_type().get_bit_width(); // i1 -> i1 : %value ; no-op
match value_bits { // i1 -> i<N> : zext i1 %value to i<N> ; guaranteed to be 0 or 1 - see docs
8 => bool_value, // i<M> -> i<N>: zext i1 (icmp eq i<M> %value, 0) to i<N> ; same as i<M> -> i1 -> i<N>
1 => builder.build_int_z_extend(bool_value, ctx.i8_type(), "frombool").unwrap(), match (value.get_type().get_bit_width(), ty.get_bit_width()) {
_ => bool_to_i8( (1, 1) => value,
(1, _) => builder.build_int_z_extend(value, ty, "frombool").unwrap(),
_ => bool_to_int_type(
builder, builder,
ctx,
builder builder
.build_int_compare( .build_int_compare(IntPredicate::NE, value, value.get_type().const_zero(), "tobool")
IntPredicate::NE,
bool_value,
bool_value.get_type().const_zero(),
"",
)
.unwrap(), .unwrap(),
ty,
), ),
} }
} }