nac3core: handle tuple by value

This commit is contained in:
ychenfo 2022-01-20 04:14:22 +08:00
parent f5ce7376e3
commit 77608346b1
3 changed files with 40 additions and 20 deletions

View File

@ -98,7 +98,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
self.builder.build_store(p, val); 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()), Some((_, Some(static_value), _)) => ValueEnum::Static(static_value.clone()),
None => { None => {
let resolver = ctx.resolver.clone(); 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, .. } => { ExprKind::List { elts, .. } => {
@ -757,7 +769,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
ctx.builder.build_store(ptr, v); ctx.builder.build_store(ptr, v);
} }
} }
tuple_ptr.into() ctx.builder.build_load(tuple_ptr, "tup_val").into()
} }
ExprKind::Attribute { value, attr, .. } => { ExprKind::Attribute { value, attr, .. } => {
// note that we would handle class methods directly in calls // 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, .. } => { 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()) { 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 ty = ctx.get_llvm_type(generator, *ty);
let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero]).into_pointer_value(); let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero]).into_pointer_value();
if let ExprKind::Slice { lower, upper, step } = &slice.node { if let ExprKind::Slice { lower, upper, step } = &slice.node {
@ -1084,13 +1096,21 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
.into_int_value(); .into_int_value();
ctx.build_gep_and_load(arr_ptr, &[index]) ctx.build_gep_and_load(arr_ptr, &[index])
} }
} else { } else if let TypeEnum::TTuple { .. } = &*ctx.unifier.get_ty(value.custom.unwrap()) {
let index = generator let v = generator
.gen_expr(ctx, slice) .gen_expr(ctx, value)
.unwrap() .unwrap()
.to_basic_value_enum(ctx, generator) .to_basic_value_enum(ctx, generator)
.into_int_value(); .into_struct_value();
ctx.build_gep_and_load(v, &[int32.const_zero(), index]) 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(), .into(),

View File

@ -260,7 +260,7 @@ fn get_llvm_type<'ctx>(
.iter() .iter()
.map(|ty| get_llvm_type(ctx, generator, unifier, top_level, type_cache, *ty)) .map(|ty| get_llvm_type(ctx, generator, unifier, top_level, type_cache, *ty))
.collect_vec(); .collect_vec();
ctx.struct_type(&fields, false).ptr_type(AddressSpace::Generic).into() ctx.struct_type(&fields, false).into()
} }
TList { ty } => { TList { ty } => {
// a struct with an integer and a pointer to an array // a struct with an integer and a pointer to an array

View File

@ -13,6 +13,7 @@ use inkwell::{
values::{BasicValue, BasicValueEnum, PointerValue}, values::{BasicValue, BasicValueEnum, PointerValue},
}; };
use nac3parser::ast::{Expr, ExprKind, Stmt, StmtKind}; use nac3parser::ast::{Expr, ExprKind, Stmt, StmtKind};
use std::convert::TryFrom;
pub fn gen_var<'ctx, 'a>( pub fn gen_var<'ctx, 'a>(
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
@ -90,13 +91,12 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
value: ValueEnum<'ctx>, value: ValueEnum<'ctx>,
) { ) {
if let ExprKind::Tuple { elts, .. } = &target.node { if let ExprKind::Tuple { elts, .. } = &target.node {
if let BasicValueEnum::PointerValue(ptr) = value.to_basic_value_enum(ctx, generator) { if let BasicValueEnum::StructValue(v) = value.to_basic_value_enum(ctx, generator) {
let i32_type = ctx.ctx.i32_type();
for (i, elt) in elts.iter().enumerate() { for (i, elt) in elts.iter().enumerate() {
let v = ctx.build_gep_and_load( let v = ctx
ptr, .builder
&[i32_type.const_zero(), i32_type.const_int(i as u64, false)], .build_extract_value(v, u32::try_from(i).unwrap(), "struct_elem")
); .unwrap();
generator.gen_assign(ctx, elt, v.into()); generator.gen_assign(ctx, elt, v.into());
} }
} else { } else {