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);
|
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, .. } => {
|
||||||
|
if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(value.custom.unwrap()) {
|
||||||
let v = generator
|
let v = generator
|
||||||
.gen_expr(ctx, value)
|
.gen_expr(ctx, value)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_basic_value_enum(ctx, generator)
|
.to_basic_value_enum(ctx, generator)
|
||||||
.into_pointer_value();
|
.into_pointer_value();
|
||||||
if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(value.custom.unwrap()) {
|
|
||||||
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(),
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue