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]]
name = "inkwell"
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 = [
"either",
"inkwell_internals",
@ -520,7 +520,7 @@ dependencies = [
[[package]]
name = "inkwell_internals"
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 = [
"proc-macro2",
"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_session = { version = "0.0.1-alpha.18", path = "../edlang_session" }
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 }
edlang_span = { version = "0.0.1-alpha.18", path = "../edlang_span" }

View file

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

View file

@ -348,9 +348,9 @@ impl fmt::Display for TypeKind {
write!(f, "*{word} {}", inner.kind)
}
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)
}
TypeKind::Struct(_, name) => write!(f, "{}", name),
TypeKind::Slice(inner, size) => {
@ -483,11 +483,11 @@ pub struct Place {
pub projection: SmallVec<[PlaceElem; 1]>,
}
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone)]
pub enum PlaceElem {
Deref,
Field { field_idx: usize },
Index { local: usize },
Index { value: Box<RValue> },
ConstIndex { index: usize },
}

View file

@ -1357,7 +1357,30 @@ fn lower_path(
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 } => {
// is while fine? auto deref
while let TypeKind::Ref(_, inner) = ty {