array indexing

This commit is contained in:
Edgar 2024-05-10 11:25:22 +01:00
parent a6d4bee05a
commit 3e885063df
5 changed files with 153 additions and 34 deletions

4
Cargo.lock generated
View file

@ -507,7 +507,7 @@ dependencies = [
[[package]] [[package]]
name = "inkwell" name = "inkwell"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/TheDan64/inkwell?rev=5d5a531c765a6ad37aa6591c0287d0f9109fff62#5d5a531c765a6ad37aa6591c0287d0f9109fff62" source = "git+https://github.com/TheDan64/inkwell?rev=6c0fb56b3554e939f9ca61b465043d6a84fb7b95#6c0fb56b3554e939f9ca61b465043d6a84fb7b95"
dependencies = [ dependencies = [
"either", "either",
"inkwell_internals", "inkwell_internals",
@ -520,7 +520,7 @@ dependencies = [
[[package]] [[package]]
name = "inkwell_internals" name = "inkwell_internals"
version = "0.9.0" version = "0.9.0"
source = "git+https://github.com/TheDan64/inkwell?rev=5d5a531c765a6ad37aa6591c0287d0f9109fff62#5d5a531c765a6ad37aa6591c0287d0f9109fff62" source = "git+https://github.com/TheDan64/inkwell?rev=6c0fb56b3554e939f9ca61b465043d6a84fb7b95#6c0fb56b3554e939f9ca61b465043d6a84fb7b95"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View file

@ -17,6 +17,6 @@ edlang_ir = { version = "0.0.1-alpha.18", path = "../edlang_ir" }
edlang_parser = { version = "0.0.1-alpha.18", path = "../edlang_parser" } edlang_parser = { version = "0.0.1-alpha.18", path = "../edlang_parser" }
edlang_session = { version = "0.0.1-alpha.18", path = "../edlang_session" } edlang_session = { version = "0.0.1-alpha.18", path = "../edlang_session" }
llvm-sys = "180.0" llvm-sys = "180.0"
inkwell = { git = "https://github.com/TheDan64/inkwell", rev = "5d5a531c765a6ad37aa6591c0287d0f9109fff62", features = ["llvm18-0"] } inkwell = { git = "https://github.com/TheDan64/inkwell", rev = "6c0fb56b3554e939f9ca61b465043d6a84fb7b95", features = ["llvm18-0"] }
tracing = { workspace = true } tracing = { workspace = true }
edlang_span = { version = "0.0.1-alpha.18", path = "../edlang_span" } edlang_span = { version = "0.0.1-alpha.18", path = "../edlang_span" }

View file

@ -21,7 +21,7 @@ use inkwell::{
values::{BasicValue, BasicValueEnum, PointerValue}, values::{BasicValue, BasicValueEnum, PointerValue},
AddressSpace, AddressSpace,
}; };
use ir::{LocalKind, ModuleBody, Place, ProgramBody, TypeInfo, ValueTree}; use ir::{LocalKind, ModuleBody, ProgramBody, TypeInfo, TypeKind, ValueTree};
use llvm_sys::debuginfo::LLVMDIFlagPublic; use llvm_sys::debuginfo::LLVMDIFlagPublic;
use tracing::{info, trace}; use tracing::{info, trace};
@ -462,43 +462,46 @@ fn compile_fn(ctx: &ModuleCompileCtx, fn_id: DefId) -> Result<(), BuilderError>
_ => unreachable!(), _ => unreachable!(),
} }
} }
ir::PlaceElem::Index { local } => { ir::PlaceElem::Index { value } => {
let value = compile_load_place( let (value, _ty) = compile_rvalue(ctx, fn_id, &locals, value)?;
ctx,
fn_id,
&locals,
&Place {
local: *local,
projection: Default::default(),
},
false,
)?;
ptr = unsafe { ptr = unsafe {
ctx.builder.build_in_bounds_gep( ctx.builder.build_in_bounds_gep(
ptr.get_type(), compile_basic_type(ctx, &local_ty),
ptr, ptr,
&[ &[
ctx.ctx.context.i32_type().const_int(0, false), ctx.ctx.context.i32_type().const_int(0, false),
value.0.into_int_value(), value.into_int_value(),
], ],
"constindex", "constindex",
)? )?
}; };
local_ty = match local_ty.kind {
ir::TypeKind::Slice(inner, _) => (*inner).clone(),
_ => unreachable!(),
}
} }
ir::PlaceElem::ConstIndex { index } => { ir::PlaceElem::ConstIndex { index } => {
ptr = unsafe { ptr = unsafe {
ctx.builder.build_in_bounds_gep( ctx.builder.build_in_bounds_gep(
ptr.get_type(), compile_basic_type(ctx, &local_ty),
ptr, ptr,
&[ctx &[
.ctx ctx.ctx.context.i32_type().const_int(0, false),
ctx.ctx
.context .context
.i32_type() .i32_type()
.const_int((*index) as u64, false)], .const_int((*index) as u64, false),
],
"constindex", "constindex",
)? )?
}; };
local_ty = match local_ty.kind {
ir::TypeKind::Slice(inner, _) => (*inner).clone(),
_ => unreachable!(),
}
} }
} }
} }
@ -1073,9 +1076,65 @@ fn compile_rvalue<'ctx>(
.build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")? .build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")?
.into_pointer_value(); .into_pointer_value();
} }
ir::PlaceElem::Field { .. } => todo!(), ir::PlaceElem::Field { field_idx } => {
ir::PlaceElem::Index { .. } => todo!(), local_ty = match local_ty.kind {
ir::PlaceElem::ConstIndex { .. } => todo!(), 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 { value } => {
let (value, _ty) = compile_rvalue(ctx, fn_id, &locals, value)?;
ptr = unsafe {
ctx.builder.build_in_bounds_gep(
compile_basic_type(ctx, &local_ty),
ptr,
&[
ctx.ctx.context.i32_type().const_int(0, false),
value.into_int_value(),
],
"constindex",
)?
};
local_ty = match local_ty.kind {
ir::TypeKind::Slice(inner, _) => (*inner).clone(),
_ => unreachable!(),
}
}
ir::PlaceElem::ConstIndex { index } => {
ptr = unsafe {
ctx.builder.build_in_bounds_gep(
compile_basic_type(ctx, &local_ty),
ptr,
&[
ctx.ctx.context.i32_type().const_int(0, false),
ctx.ctx
.context
.i32_type()
.const_int((*index) as u64, false),
],
"constindex",
)?
};
local_ty = match local_ty.kind {
ir::TypeKind::Slice(inner, _) => (*inner).clone(),
_ => unreachable!(),
}
}
} }
} }
@ -1118,8 +1177,9 @@ fn compile_rvalue<'ctx>(
let target_llvm_ty = compile_basic_type(ctx, &target_ty); let target_llvm_ty = compile_basic_type(ctx, &target_ty);
let (value, ty) = compile_load_operand(ctx, fn_id, locals, op)?; let (value, ty) = compile_load_operand(ctx, fn_id, locals, op)?;
let current_ty = compile_basic_type(ctx, &ty); let current_ty = compile_basic_type(ctx, &ty);
let is_ptr = matches!(ty.kind, TypeKind::Ptr(_, _) | TypeKind::Ref(_, _));
if target_llvm_ty.is_pointer_type() { if is_ptr {
// int to ptr // int to ptr
let target_llvm_ty = target_llvm_ty.into_pointer_type(); let target_llvm_ty = target_llvm_ty.into_pointer_type();
if current_ty.is_int_type() { if current_ty.is_int_type() {
@ -1265,8 +1325,44 @@ fn compile_load_place<'ctx>(
_ => unreachable!(), _ => unreachable!(),
} }
} }
ir::PlaceElem::Index { .. } => todo!(), ir::PlaceElem::Index { value } => {
ir::PlaceElem::ConstIndex { .. } => todo!(), let (value, _ty) = compile_rvalue(ctx, fn_id, locals, value)?;
ptr = unsafe {
ctx.builder.build_in_bounds_gep(
compile_basic_type(ctx, &local_ty),
ptr,
&[
ctx.ctx.context.i32_type().const_int(0, false),
value.into_int_value(),
],
"constindex",
)?
};
local_ty = match local_ty.kind {
ir::TypeKind::Slice(inner, _) => (*inner).clone(),
_ => unreachable!(),
}
}
ir::PlaceElem::ConstIndex { index } => {
ptr = unsafe {
ctx.builder.build_in_bounds_gep(
compile_basic_type(ctx, &local_ty),
ptr,
&[
ctx.ctx.context.i32_type().const_int(0, false),
ctx.ctx.context.i32_type().const_int((*index) as u64, false),
],
"constindex",
)?
};
local_ty = match local_ty.kind {
ir::TypeKind::Slice(inner, _) => (*inner).clone(),
_ => unreachable!(),
}
}
} }
} }

View file

@ -348,7 +348,7 @@ impl fmt::Display for TypeKind {
write!(f, "*{word} {}", inner.kind) write!(f, "*{word} {}", inner.kind)
} }
TypeKind::Ref(is_mut, inner) => { TypeKind::Ref(is_mut, inner) => {
let word = if *is_mut { "mut" } else { "const" }; let word = if *is_mut { "mut " } else { "" };
write!(f, "&{word}{}", inner.kind) write!(f, "&{word}{}", inner.kind)
} }
@ -483,11 +483,11 @@ pub struct Place {
pub projection: SmallVec<[PlaceElem; 1]>, pub projection: SmallVec<[PlaceElem; 1]>,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone)]
pub enum PlaceElem { pub enum PlaceElem {
Deref, Deref,
Field { field_idx: usize }, Field { field_idx: usize },
Index { local: usize }, Index { value: Box<RValue> },
ConstIndex { index: usize }, ConstIndex { index: usize },
} }

View file

@ -1357,7 +1357,30 @@ fn lower_path(
unimplemented!() unimplemented!()
} }
} }
ast::PathSegment::Index { .. } => todo!(), ast::PathSegment::Index { value, span: _ } => {
// auto deref
while let TypeKind::Ref(_, inner) = ty {
place.projection.push(PlaceElem::Deref);
ty = inner.kind;
}
if let ast::Expression::Value(ast::ValueExpr::Int { value, span: _ }) = value {
place.projection.push(PlaceElem::ConstIndex {
index: (*value).try_into().unwrap(),
});
} else {
let (rvalue, _ty, _span) = lower_expr(builder, value, None)?;
place.projection.push(PlaceElem::Index {
value: Box::new(rvalue),
});
}
ty = if let TypeKind::Slice(inner, _) = ty {
inner.kind.clone()
} else {
unreachable!();
}
}
ast::PathSegment::Method { value, span } => { ast::PathSegment::Method { value, span } => {
// is while fine? auto deref // is while fine? auto deref
while let TypeKind::Ref(_, inner) = ty { while let TypeKind::Ref(_, inner) = ty {