From deb325de4f29916d5a94912eec63a67f41ee66d2 Mon Sep 17 00:00:00 2001 From: David Mak Date: Mon, 11 Mar 2024 15:09:33 +0800 Subject: [PATCH] core: Extract codegen portion of gen_binop_expr This allows binops to be generated internally using LLVM values as input. Required in a future change. --- nac3core/src/codegen/expr.rs | 76 ++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index c110d0c..10916c0 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -1089,34 +1089,22 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>( Ok(Some(list.as_ptr_value().into())) } -/// Generates LLVM IR for a [binary operator expression][expr]. -/// -/// * `left` - The left-hand side of the binary operator. -/// * `op` - The operator applied on the operands. -/// * `right` - The right-hand side of the binary operator. -/// * `loc` - The location of the full expression. -/// * `is_aug_assign` - Whether the binary operator expression is also an assignment operator. -pub fn gen_binop_expr<'ctx, G: CodeGenerator>( +/// Generates LLVM IR for a binary operator expression using the [`Type`] and +/// [LLVM value][`BasicValueEnum`] of the operands. +pub fn gen_binop_expr_with_values<'ctx, G: CodeGenerator>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, - left: &Expr>, + left: (&Option, BasicValueEnum<'ctx>), op: &Operator, - right: &Expr>, + right: (&Option, BasicValueEnum<'ctx>), loc: Location, is_aug_assign: bool, ) -> Result>, String> { - let ty1 = ctx.unifier.get_representative(left.custom.unwrap()); - let ty2 = ctx.unifier.get_representative(right.custom.unwrap()); - let left_val = if let Some(v) = generator.gen_expr(ctx, left)? { - v.to_basic_value_enum(ctx, generator, left.custom.unwrap())? - } else { - return Ok(None) - }; - let right_val = if let Some(v) = generator.gen_expr(ctx, right)? { - v.to_basic_value_enum(ctx, generator, right.custom.unwrap())? - } else { - return Ok(None) - }; + let (left_ty, left_val) = left; + let (right_ty, right_val) = right; + + let ty1 = ctx.unifier.get_representative(left_ty.unwrap()); + let ty2 = ctx.unifier.get_representative(right_ty.unwrap()); // we can directly compare the types, because we've got their representatives // which would be unchanged until further unification, which we would never do @@ -1141,7 +1129,7 @@ pub fn gen_binop_expr<'ctx, G: CodeGenerator>( ); Ok(Some(res.into())) } else { - let left_ty_enum = ctx.unifier.get_ty_immutable(left.custom.unwrap()); + let left_ty_enum = ctx.unifier.get_ty_immutable(left_ty.unwrap()); let TypeEnum::TObj { fields, obj_id, .. } = left_ty_enum.as_ref() else { unreachable!("must be tobj") }; @@ -1161,7 +1149,7 @@ pub fn gen_binop_expr<'ctx, G: CodeGenerator>( let signature = if let Some(call) = ctx.calls.get(&loc.into()) { ctx.unifier.get_call_signature(*call).unwrap() } else { - let left_enum_ty = ctx.unifier.get_ty_immutable(left.custom.unwrap()); + let left_enum_ty = ctx.unifier.get_ty_immutable(left_ty.unwrap()); let TypeEnum::TObj { fields, .. } = left_enum_ty.as_ref() else { unreachable!("must be tobj") }; @@ -1186,13 +1174,51 @@ pub fn gen_binop_expr<'ctx, G: CodeGenerator>( generator .gen_call( ctx, - Some((left.custom.unwrap(), left_val.into())), + Some((left_ty.unwrap(), left_val.into())), (&signature, fun_id), vec![(None, right_val.into())], ).map(|f| f.map(Into::into)) } } +/// Generates LLVM IR for a [binary operator expression][expr]. +/// +/// * `left` - The left-hand side of the binary operator. +/// * `op` - The operator applied on the operands. +/// * `right` - The right-hand side of the binary operator. +/// * `loc` - The location of the full expression. +/// * `is_aug_assign` - Whether the binary operator expression is also an assignment operator. +pub fn gen_binop_expr<'ctx, G: CodeGenerator>( + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + left: &Expr>, + op: &Operator, + right: &Expr>, + loc: Location, + is_aug_assign: bool, +) -> Result>, String> { + let left_val = if let Some(v) = generator.gen_expr(ctx, left)? { + v.to_basic_value_enum(ctx, generator, left.custom.unwrap())? + } else { + return Ok(None) + }; + let right_val = if let Some(v) = generator.gen_expr(ctx, right)? { + v.to_basic_value_enum(ctx, generator, right.custom.unwrap())? + } else { + return Ok(None) + }; + + gen_binop_expr_with_values( + generator, + ctx, + (&left.custom, left_val), + op, + (&right.custom, right_val), + loc, + is_aug_assign, + ) +} + /// Generates code for a subscript expression on an `ndarray`. /// /// * `ty` - The `Type` of the `NDArray` elements.