forked from M-Labs/nac3
nac3core: handle tuple by value
This commit is contained in:
parent
f5ce7376e3
commit
77608346b1
|
@ -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, .. } => {
|
||||
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();
|
||||
if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(value.custom.unwrap()) {
|
||||
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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue