Skip to content

Commit

Permalink
struct field
Browse files Browse the repository at this point in the history
  • Loading branch information
edg-l committed Feb 17, 2024
1 parent a9cd4ef commit 79c1243
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 62 deletions.
94 changes: 55 additions & 39 deletions lib/edlang_codegen_llvm/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?,
Expand All @@ -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,
Expand Down
5 changes: 3 additions & 2 deletions lib/edlang_ir/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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,
}

Expand Down Expand Up @@ -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 },
}

Expand Down
42 changes: 21 additions & 21 deletions lib/edlang_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand All @@ -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);
Expand Down Expand Up @@ -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) => {
Expand All @@ -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> {
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -922,21 +909,34 @@ 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!(),
}
}

(
Place {
local,
projection: projection.into(), // todo, field array deref
projection: projection.into(), // todo, array
},
ty,
)
Expand Down

0 comments on commit 79c1243

Please sign in to comment.