diff --git a/Cargo.lock b/Cargo.lock index 859b1b663..c655bc73e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/lib/edlang_codegen_llvm/Cargo.toml b/lib/edlang_codegen_llvm/Cargo.toml index 3e18a9e33..fe2b3d3e8 100644 --- a/lib/edlang_codegen_llvm/Cargo.toml +++ b/lib/edlang_codegen_llvm/Cargo.toml @@ -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" } diff --git a/lib/edlang_codegen_llvm/src/codegen.rs b/lib/edlang_codegen_llvm/src/codegen.rs index 75e60771b..64ba4fe24 100644 --- a/lib/edlang_codegen_llvm/src/codegen.rs +++ b/lib/edlang_codegen_llvm/src/codegen.rs @@ -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!(), + } + } } } diff --git a/lib/edlang_ir/src/lib.rs b/lib/edlang_ir/src/lib.rs index 9221bec55..4b6d60089 100644 --- a/lib/edlang_ir/src/lib.rs +++ b/lib/edlang_ir/src/lib.rs @@ -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 }, ConstIndex { index: usize }, } diff --git a/lib/edlang_lowering/src/lib.rs b/lib/edlang_lowering/src/lib.rs index d8c49a823..d4081f63c 100644 --- a/lib/edlang_lowering/src/lib.rs +++ b/lib/edlang_lowering/src/lib.rs @@ -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 {