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,18 +971,27 @@ fn compile_load_operand<'ctx>(
locals: &HashMap<usize, PointerValue<'ctx>>, locals: &HashMap<usize, PointerValue<'ctx>>,
op: &ir::Operand, op: &ir::Operand,
) -> Result<(BasicValueEnum<'ctx>, TypeInfo), BuilderError> { ) -> Result<(BasicValueEnum<'ctx>, TypeInfo), BuilderError> {
// todo: implement projection
let body = ctx.ctx.program.functions.get(&fn_id).unwrap();
Ok(match op { Ok(match op {
ir::Operand::Copy(place) => { ir::Operand::Copy(place) => compile_load_place(ctx, fn_id, locals, place, true)?,
let pointee_ty = compile_basic_type(ctx, &body.locals[place.local].ty); ir::Operand::Move(place) => compile_load_place(ctx, fn_id, locals, place, false)?,
let ptr = *locals.get(&place.local).unwrap(); ir::Operand::Constant(data) => match &data.kind {
( ir::ConstKind::Value(value) => (
ctx.builder.build_load(pointee_ty, ptr, "")?, compile_value(ctx, value, &data.type_info)?,
body.locals[place.local].ty.clone(), data.type_info.clone(),
) ),
ir::ConstKind::ZeroSized => todo!(),
},
})
} }
ir::Operand::Move(place) => {
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 ptr = *locals.get(&place.local).unwrap();
let mut local_ty = body.locals[place.local].ty.clone(); let mut local_ty = body.locals[place.local].ty.clone();
@ -999,26 +1008,33 @@ fn compile_load_operand<'ctx>(
_ => unreachable!(), _ => unreachable!(),
} }
} }
ir::PlaceElem::Field { .. } => todo!(), 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!(), ir::PlaceElem::Index { .. } => todo!(),
} }
} }
let pointee_ty = compile_basic_type(ctx, &local_ty); let pointee_ty = compile_basic_type(ctx, &local_ty);
( Ok((
ctx.builder.build_load(pointee_ty, ptr, "")?, ctx.builder.build_load(pointee_ty, ptr, "")?,
body.locals[place.local].ty.clone(), body.locals[place.local].ty.clone(),
) ))
}
ir::Operand::Constant(data) => match &data.kind {
ir::ConstKind::Value(value) => (
compile_value(ctx, value, &data.type_info)?,
data.type_info.clone(),
),
ir::ConstKind::ZeroSized => todo!(),
},
})
} }
fn compile_value<'ctx>( fn compile_value<'ctx>(

View file

@ -1,6 +1,6 @@
// Based on a cfg // Based on a cfg
use std::collections::{BTreeMap, HashSet}; use std::collections::{BTreeMap, HashMap, HashSet};
use edlang_span::Span; use edlang_span::Span;
use smallvec::SmallVec; use smallvec::SmallVec;
@ -94,6 +94,7 @@ pub struct AdtBody {
pub is_pub: bool, pub is_pub: bool,
pub name: String, pub name: String,
pub variants: Vec<AdtVariant>, pub variants: Vec<AdtVariant>,
pub name_to_idx: HashMap<String, usize>,
pub span: Span, pub span: Span,
} }
@ -359,7 +360,7 @@ pub struct Place {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum PlaceElem { pub enum PlaceElem {
Deref, Deref,
Field { field_idx: usize, type_info: usize }, Field { field_idx: usize },
Index { local: 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 is_pub: true, // todo struct pub
name: info.name.name.clone(), name: info.name.name.clone(),
variants: Vec::new(), variants: Vec::new(),
name_to_idx: Default::default(),
span: info.span, 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), ty: lower_type(&ctx, &field.r#type, module_id),
}; };
body.variants.push(variant); 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); 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) { fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) {
let (mut place, mut ty) = lower_path(builder, &info.name); 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 { for _ in 0..info.deref_times {
match &ty { match &ty {
TypeKind::Ptr(inner) => { TypeKind::Ptr(inner) => {
@ -454,7 +442,7 @@ fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) {
builder.statements.push(Statement { builder.statements.push(Statement {
span: Some(info.name.first.span), span: Some(info.name.first.span),
kind: StatementKind::Assign(place, rvalue), kind: StatementKind::Assign(place, rvalue),
}) });
} }
fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option<TypeKind> { 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::Str { value: _, span: _ } => todo!(),
ast::ValueExpr::Path(info) => { ast::ValueExpr::Path(info) => {
// add deref info to path
let (place, ty) = lower_path(builder, info); let (place, ty) = lower_path(builder, info);
(Operand::Move(place), ty) (Operand::Move(place), ty)
} }
@ -922,13 +909,26 @@ fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, Ty
.name_to_local .name_to_local
.get(&info.first.name) .get(&info.first.name)
.expect("local not found"); .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 { for extra in &info.extra {
match 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!(), ast::PathSegment::Index { .. } => todo!(),
} }
} }
@ -936,7 +936,7 @@ fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, Ty
( (
Place { Place {
local, local,
projection: projection.into(), // todo, field array deref projection: projection.into(), // todo, array
}, },
ty, ty,
) )