struct field

This commit is contained in:
Edgar 2024-02-17 21:31:15 +01:00
parent a9cd4eff86
commit 79c1243f0d
No known key found for this signature in database
GPG key ID: 70ADAE8F35904387
3 changed files with 79 additions and 62 deletions

View file

@ -971,46 +971,9 @@ fn compile_load_operand<'ctx>(
locals: &HashMap<usize, PointerValue<'ctx>>,
op: &ir::Operand,
) -> Result<(BasicValueEnum<'ctx>, TypeInfo), BuilderError> {
// todo: implement projection
let body = ctx.ctx.program.functions.get(&fn_id).unwrap();
Ok(match op {
ir::Operand::Copy(place) => {
let pointee_ty = compile_basic_type(ctx, &body.locals[place.local].ty);
let ptr = *locals.get(&place.local).unwrap();
(
ctx.builder.build_load(pointee_ty, ptr, "")?,
body.locals[place.local].ty.clone(),
)
}
ir::Operand::Move(place) => {
let mut ptr = *locals.get(&place.local).unwrap();
let mut local_ty = body.locals[place.local].ty.clone();
for proj in &place.projection {
match proj {
ir::PlaceElem::Deref => {
ptr = ctx
.builder
.build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")?
.into_pointer_value();
local_ty = match local_ty.kind {
ir::TypeKind::Ptr(inner) => *inner,
ir::TypeKind::Ref(_, inner) => *inner,
_ => unreachable!(),
}
}
ir::PlaceElem::Field { .. } => todo!(),
ir::PlaceElem::Index { .. } => todo!(),
}
}
let pointee_ty = compile_basic_type(ctx, &local_ty);
(
ctx.builder.build_load(pointee_ty, ptr, "")?,
body.locals[place.local].ty.clone(),
)
}
ir::Operand::Copy(place) => compile_load_place(ctx, fn_id, locals, place, true)?,
ir::Operand::Move(place) => compile_load_place(ctx, fn_id, locals, place, false)?,
ir::Operand::Constant(data) => match &data.kind {
ir::ConstKind::Value(value) => (
compile_value(ctx, value, &data.type_info)?,
@ -1021,6 +984,59 @@ fn compile_load_operand<'ctx>(
})
}
fn compile_load_place<'ctx>(
ctx: &ModuleCompileCtx<'ctx, '_>,
fn_id: DefId,
locals: &HashMap<usize, PointerValue<'ctx>>,
place: &ir::Place,
_is_copy: bool,
) -> Result<(BasicValueEnum<'ctx>, TypeInfo), BuilderError> {
let body = ctx.ctx.program.functions.get(&fn_id).unwrap();
let mut ptr = *locals.get(&place.local).unwrap();
let mut local_ty = body.locals[place.local].ty.clone();
for proj in &place.projection {
match proj {
ir::PlaceElem::Deref => {
ptr = ctx
.builder
.build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")?
.into_pointer_value();
local_ty = match local_ty.kind {
ir::TypeKind::Ptr(inner) => *inner,
ir::TypeKind::Ref(_, inner) => *inner,
_ => unreachable!(),
}
}
ir::PlaceElem::Field { field_idx } => {
local_ty = match local_ty.kind {
ir::TypeKind::Struct(id) => {
let struct_body = ctx.ctx.program.structs.get(&id).unwrap();
let ty = struct_body.variants[*field_idx].ty.clone();
let field_name = struct_body.variants[*field_idx].name.clone();
ptr = ctx.builder.build_struct_gep(
compile_basic_type(ctx, &local_ty),
ptr,
(*field_idx).try_into().unwrap(),
&format!("ptr_field_{field_name}"),
)?;
ty
}
_ => unreachable!(),
}
}
ir::PlaceElem::Index { .. } => todo!(),
}
}
let pointee_ty = compile_basic_type(ctx, &local_ty);
Ok((
ctx.builder.build_load(pointee_ty, ptr, "")?,
body.locals[place.local].ty.clone(),
))
}
fn compile_value<'ctx>(
ctx: &ModuleCompileCtx<'ctx, '_>,
val: &ValueTree,

View file

@ -1,6 +1,6 @@
// Based on a cfg
use std::collections::{BTreeMap, HashSet};
use std::collections::{BTreeMap, HashMap, HashSet};
use edlang_span::Span;
use smallvec::SmallVec;
@ -94,6 +94,7 @@ pub struct AdtBody {
pub is_pub: bool,
pub name: String,
pub variants: Vec<AdtVariant>,
pub name_to_idx: HashMap<String, usize>,
pub span: Span,
}
@ -359,7 +360,7 @@ pub struct Place {
#[derive(Debug, Clone, Copy)]
pub enum PlaceElem {
Deref,
Field { field_idx: usize, type_info: usize },
Field { field_idx: usize },
Index { local: usize },
}

View file

@ -103,6 +103,7 @@ fn lower_struct(mut ctx: BuildCtx, info: &ast::Struct, module_id: DefId) -> Buil
is_pub: true, // todo struct pub
name: info.name.name.clone(),
variants: Vec::new(),
name_to_idx: Default::default(),
span: info.span,
};
@ -113,6 +114,8 @@ fn lower_struct(mut ctx: BuildCtx, info: &ast::Struct, module_id: DefId) -> Buil
ty: lower_type(&ctx, &field.r#type, module_id),
};
body.variants.push(variant);
body.name_to_idx
.insert(field.name.name.clone(), body.variants.len() - 1);
}
ctx.body.structs.insert(body.def_id, body);
@ -418,21 +421,6 @@ fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) {
fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) {
let (mut place, mut ty) = lower_path(builder, &info.name);
if let Some(PlaceElem::Deref) = place.projection.last() {
match &ty {
TypeKind::Ptr(inner) => {
ty = inner.kind.clone();
}
TypeKind::Ref(is_mut, inner) => {
if !is_mut {
panic!("trying to mutate non mut ref");
}
ty = inner.kind.clone();
}
_ => unreachable!(),
}
}
for _ in 0..info.deref_times {
match &ty {
TypeKind::Ptr(inner) => {
@ -454,7 +442,7 @@ fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) {
builder.statements.push(Statement {
span: Some(info.name.first.span),
kind: StatementKind::Assign(place, rvalue),
})
});
}
fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option<TypeKind> {
@ -887,7 +875,6 @@ fn lower_value(
},
ast::ValueExpr::Str { value: _, span: _ } => todo!(),
ast::ValueExpr::Path(info) => {
// add deref info to path
let (place, ty) = lower_path(builder, info);
(Operand::Move(place), ty)
}
@ -922,13 +909,26 @@ fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, Ty
.name_to_local
.get(&info.first.name)
.expect("local not found");
let ty = builder.body.locals[local].ty.kind.clone();
let projection = Vec::new();
let mut ty = builder.body.locals[local].ty.kind.clone();
let mut projection = Vec::new();
for extra in &info.extra {
match extra {
ast::PathSegment::Field(_) => todo!(),
ast::PathSegment::Field(name) => {
// is while fine? auto deref
while let TypeKind::Ref(_, inner) = ty {
projection.push(PlaceElem::Deref);
ty = inner.kind;
}
if let TypeKind::Struct(id) = ty {
let struct_body = builder.ctx.body.structs.get(&id).unwrap();
let idx = *struct_body.name_to_idx.get(&name.name).unwrap();
projection.push(PlaceElem::Field { field_idx: idx });
ty = struct_body.variants[idx].ty.kind.clone();
}
}
ast::PathSegment::Index { .. } => todo!(),
}
}
@ -936,7 +936,7 @@ fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, Ty
(
Place {
local,
projection: projection.into(), // todo, field array deref
projection: projection.into(), // todo, array
},
ty,
)