From 77608346b13a5a81dccbff7640a5bf5e5ff0fca9 Mon Sep 17 00:00:00 2001 From: ychenfo Date: Thu, 20 Jan 2022 04:14:22 +0800 Subject: [PATCH] nac3core: handle tuple by value --- nac3core/src/codegen/expr.rs | 46 ++++++++++++++++++++++++++---------- nac3core/src/codegen/mod.rs | 2 +- nac3core/src/codegen/stmt.rs | 12 +++++----- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index 12d3207e..a1fdba21 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -98,7 +98,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> { self.builder.build_store(p, val); } } - ptr.into() + self.builder.build_load(ptr, "tup_val") } } } @@ -705,7 +705,19 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( Some((_, Some(static_value), _)) => ValueEnum::Static(static_value.clone()), None => { let resolver = ctx.resolver.clone(); - resolver.get_symbol_value(*id, ctx).unwrap() + let val = resolver.get_symbol_value(*id, ctx).unwrap(); + // if is tuple, need to deref it to handle tuple as value + if let (TypeEnum::TTuple { .. }, BasicValueEnum::PointerValue(ptr)) = ( + &*ctx.unifier.get_ty(expr.custom.unwrap()), + resolver + .get_symbol_value(*id, ctx) + .unwrap() + .to_basic_value_enum(ctx, generator), + ) { + ctx.builder.build_load(ptr, "tup_val").into() + } else { + val + } } }, ExprKind::List { elts, .. } => { @@ -757,7 +769,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( ctx.builder.build_store(ptr, v); } } - tuple_ptr.into() + ctx.builder.build_load(tuple_ptr, "tup_val").into() } ExprKind::Attribute { value, attr, .. } => { // note that we would handle class methods directly in calls @@ -1032,12 +1044,12 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( } } ExprKind::Subscript { value, slice, .. } => { - let v = generator - .gen_expr(ctx, value) - .unwrap() - .to_basic_value_enum(ctx, generator) - .into_pointer_value(); if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(value.custom.unwrap()) { + let v = generator + .gen_expr(ctx, value) + .unwrap() + .to_basic_value_enum(ctx, generator) + .into_pointer_value(); let ty = ctx.get_llvm_type(generator, *ty); let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero]).into_pointer_value(); if let ExprKind::Slice { lower, upper, step } = &slice.node { @@ -1084,13 +1096,21 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( .into_int_value(); ctx.build_gep_and_load(arr_ptr, &[index]) } - } else { - let index = generator - .gen_expr(ctx, slice) + } else if let TypeEnum::TTuple { .. } = &*ctx.unifier.get_ty(value.custom.unwrap()) { + let v = generator + .gen_expr(ctx, value) .unwrap() .to_basic_value_enum(ctx, generator) - .into_int_value(); - ctx.build_gep_and_load(v, &[int32.const_zero(), index]) + .into_struct_value(); + let index: u32 = + if let ExprKind::Constant { value: ast::Constant::Int(v), .. } = &slice.node { + v.unwrap().try_into().unwrap() + } else { + unreachable!("tuple subscript must be const int after type check"); + }; + ctx.builder.build_extract_value(v, index, "tup_elem").unwrap() + } else { + unreachable!("should not be other subscriptable types after type check"); } } .into(), diff --git a/nac3core/src/codegen/mod.rs b/nac3core/src/codegen/mod.rs index 427b3a0a..ead7b0c2 100644 --- a/nac3core/src/codegen/mod.rs +++ b/nac3core/src/codegen/mod.rs @@ -260,7 +260,7 @@ fn get_llvm_type<'ctx>( .iter() .map(|ty| get_llvm_type(ctx, generator, unifier, top_level, type_cache, *ty)) .collect_vec(); - ctx.struct_type(&fields, false).ptr_type(AddressSpace::Generic).into() + ctx.struct_type(&fields, false).into() } TList { ty } => { // a struct with an integer and a pointer to an array diff --git a/nac3core/src/codegen/stmt.rs b/nac3core/src/codegen/stmt.rs index 3b539005..46ee62f9 100644 --- a/nac3core/src/codegen/stmt.rs +++ b/nac3core/src/codegen/stmt.rs @@ -13,6 +13,7 @@ use inkwell::{ values::{BasicValue, BasicValueEnum, PointerValue}, }; use nac3parser::ast::{Expr, ExprKind, Stmt, StmtKind}; +use std::convert::TryFrom; pub fn gen_var<'ctx, 'a>( ctx: &mut CodeGenContext<'ctx, 'a>, @@ -90,13 +91,12 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>( value: ValueEnum<'ctx>, ) { if let ExprKind::Tuple { elts, .. } = &target.node { - if let BasicValueEnum::PointerValue(ptr) = value.to_basic_value_enum(ctx, generator) { - let i32_type = ctx.ctx.i32_type(); + if let BasicValueEnum::StructValue(v) = value.to_basic_value_enum(ctx, generator) { for (i, elt) in elts.iter().enumerate() { - let v = ctx.build_gep_and_load( - ptr, - &[i32_type.const_zero(), i32_type.const_int(i as u64, false)], - ); + let v = ctx + .builder + .build_extract_value(v, u32::try_from(i).unwrap(), "struct_elem") + .unwrap(); generator.gen_assign(ctx, elt, v.into()); } } else {