Skip to content

Commit

Permalink
hack arrays in there
Browse files Browse the repository at this point in the history
  • Loading branch information
andogq committed Aug 25, 2024
1 parent 45388bc commit 1799b7d
Show file tree
Hide file tree
Showing 18 changed files with 332 additions and 62 deletions.
90 changes: 83 additions & 7 deletions src/codegen/llvm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ impl ContextExt for Context {
Ty::Boolean => self.bool_type().into(),
Ty::Unit => todo!(),
Ty::Never => todo!(),
Ty::Array { inner, size } => self.get_ty(inner).array_type(*size).into(),
}
}
}
Expand All @@ -131,6 +132,8 @@ pub struct FunctionGenerator<'module, 'compiler, 'ink> {

/// Resulting values for each of the triples
results: HashMap<TripleRef, Option<IntValue<'ink>>>,
/// WARN: Hack until pointers are better represented
pointers: HashMap<TripleRef, PointerValue<'ink>>,
bindings: HashMap<ScopedBinding, PointerValue<'ink>>,

blocks: HashMap<BasicBlockIdx, BasicBlock<'ink>>,
Expand Down Expand Up @@ -160,6 +163,7 @@ impl<'module, 'compiler, 'ink> FunctionGenerator<'module, 'compiler, 'ink> {
builder,
function,
bindings: HashMap::new(),
pointers: HashMap::new(),
results: HashMap::new(),
blocks: HashMap::new(),
}
Expand Down Expand Up @@ -231,6 +235,21 @@ impl<'module, 'compiler, 'ink> FunctionGenerator<'module, 'compiler, 'ink> {
}
Triple::Load(binding) => Some(self.gen_load(binding)),
Triple::Phi(values) => Some(self.gen_phi(values)),
Triple::Index { value, index } => Some(self.gen_index(*value, *index)),
Triple::SetIndex {
array_ptr,
index,
value,
} => {
self.gen_set_index(*array_ptr, *index, *value);
None
}
Triple::AllocArray(size) => {
let ptr = self.gen_alloc_array(*size);
self.pointers.insert(TripleRef::new(*block_idx, idx), ptr);

None
}
};
self.results.insert(TripleRef::new(*block_idx, idx), result);
}
Expand Down Expand Up @@ -357,13 +376,19 @@ impl<'module, 'compiler, 'ink> FunctionGenerator<'module, 'compiler, 'ink> {
.unwrap();
}

fn gen_assign(&self, ident: &ScopedBinding, value: &Value) {
let value = self
.retrieve_value(value)
.expect("unit value cannot be assigned");
let ptr = self.bindings.get(ident).unwrap();

self.builder.build_store(*ptr, value).unwrap();
fn gen_assign(&mut self, ident: &ScopedBinding, value: &Value) {
if let Value::Pointer(ptr) = value {
// HACK: Override the existing binding for the provided pointer
self.bindings
.insert(*ident, *self.pointers.get(ptr).unwrap());
} else {
let value = self
.retrieve_value(value)
.expect("unit value cannot be assigned");
let ptr = self.bindings.get(ident).unwrap();

self.builder.build_store(*ptr, value).unwrap();
}
}

fn gen_load(&self, binding: &ScopedBinding) -> IntValue<'ink> {
Expand Down Expand Up @@ -439,6 +464,56 @@ impl<'module, 'compiler, 'ink> FunctionGenerator<'module, 'compiler, 'ink> {
.into_int_value()
}

fn gen_index(&mut self, value: ScopedBinding, index: Value) -> IntValue<'ink> {
let index = self.retrieve_value(&index).unwrap();

// WARN: BAD BAD BAD
let pointee_ty = self.module.llvm_ctx.i64_type();

let array_ptr = self.bindings.get(&value).expect("symbol to be defined");
let item_ptr = unsafe {
self.builder
.build_gep(pointee_ty, *array_ptr, &[index], "gep_result")
}
.unwrap();

self.builder
.build_load(pointee_ty, item_ptr, "item_fetch")
.unwrap()
.into_int_value()
}

fn gen_set_index(&mut self, array_ptr: TripleRef, index: Value, value: Value) {
let index = self.retrieve_value(&index).unwrap();

// WARN: BAD BAD BAD
let pointee_ty = self.module.llvm_ctx.i64_type();

let array_ptr = self.pointers.get(&array_ptr).unwrap();
let item_ptr = unsafe {
self.builder
.build_gep(pointee_ty, *array_ptr, &[index], "gep_result")
}
.unwrap();

let value = self.retrieve_value(&value).unwrap();

self.builder.build_store(item_ptr, value).unwrap();
}

fn gen_alloc_array(&mut self, size: u32) -> PointerValue<'ink> {
self.builder
.build_array_alloca(
self.module.llvm_ctx.i64_type(),
self.module
.llvm_ctx
.i64_type()
.const_int(size as u64, false),
"array_alloca",
)
.unwrap()
}

/// Emit an allocation instruction in the entry basic block
fn alloca(&self, ty: Ty, name: &str) -> PointerValue<'ink> {
// Find the entry for this function
Expand Down Expand Up @@ -477,6 +552,7 @@ impl<'module, 'compiler, 'ink> FunctionGenerator<'module, 'compiler, 'ink> {
.expect("triple must exist")
.expect("triple must produce value"),
),
Value::Pointer(_) => None,
Value::Parameter(i) => Some(
self.llvm_function
.get_nth_param(*i as u32)
Expand Down
54 changes: 3 additions & 51 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,12 @@ use lumina::compile_and_run;

fn main() {
let source = r#"
fn fib1(n: int) -> int {
let a = 0;
let b = 1;
let count = 0;
loop {
if count == n {
break;
}
count += 1;
let temp = a;
a = b;
b = b + temp;
}
return a;
}
fn fib2(n: int) -> int {
if n <= 1 {
return n;
}
return fib2(n - 1) + fib2(n - 2);
}
fn main() -> int {
let n = 0;
let counter = 0;
loop {
if counter >= 2 * 2 * 10 / 2 {
break;
}
counter += 1;
if counter == 2 * 5 {
continue;
}
n += 1;
}
let a = [1, 2, 3];
let result1 = fib1(n);
let result2 = fib2(38 / 2);
let b = a[1];
if result1 == result2 {
return result1;
} else {
return 0;
}
return a[2];
}"#;

let result = compile_and_run(source, true);
Expand Down
10 changes: 10 additions & 0 deletions src/repr/ast/base/expression/array.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use super::*;
use crate::ast_node;

ast_node! {
Array<M> {
init: Vec<Expression<M>>,
span,
ty_info,
}
}
11 changes: 11 additions & 0 deletions src/repr/ast/base/expression/index.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use super::*;
use crate::ast_node;

ast_node! {
Index<M> {
value: M::IdentIdentifier,
index: Box<Expression<M>>,
span,
ty_info,
}
}
6 changes: 6 additions & 0 deletions src/repr/ast/base/expression/mod.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
mod array;
mod assign;
mod block;
mod boolean;
mod call;
mod cast;
mod ident;
mod if_else;
mod index;
mod infix;
mod integer;
mod loop_block;

pub use array::*;
pub use assign::*;
pub use block::*;
pub use boolean::*;
pub use call::*;
pub use cast::*;
pub use ident::*;
pub use if_else::*;
pub use index::*;
pub use infix::*;
pub use integer::*;
pub use loop_block::*;
Expand All @@ -26,12 +30,14 @@ use super::{AstMetadata, Statement};

ast_node! {
Expression<M>(
Array,
Infix,
Integer,
Boolean,
Ident,
Block,
If,
Index,
Call,
Loop,
Assign,
Expand Down
2 changes: 2 additions & 0 deletions src/repr/ast/base/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,14 @@ macro_rules! generate_ast {
// Re-export non-typed utilities
pub use ast::InfixOperation;

pub type Array = ast::Array<$metadata>;
pub type Block = ast::Block<$metadata>;
pub type Boolean = ast::Boolean<$metadata>;
pub type Call = ast::Call<$metadata>;
pub type Ident = ast::Ident<$metadata>;
pub type If = ast::If<$metadata>;
pub type Loop = ast::Loop<$metadata>;
pub type Index = ast::Index<$metadata>;
pub type Infix = ast::Infix<$metadata>;
pub type Integer = ast::Integer<$metadata>;
pub type Assign = ast::Assign<$metadata>;
Expand Down
10 changes: 10 additions & 0 deletions src/repr/ir/triple/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ pub enum Triple {
Assign(ScopedBinding, Value),
/// Loads a value from a scoped binding.
Load(ScopedBinding),
/// Allocate an array of the provded size.
AllocArray(u32),
/// Index into the value.
Index { value: ScopedBinding, index: Value },
/// TODO: Must be removed
SetIndex {
array_ptr: TripleRef,
index: Value,
value: Value,
},
/// Merge the listed values from their basic blocks into a single value.
Phi(Vec<(Value, BasicBlockIdx)>),
}
Expand Down
2 changes: 2 additions & 0 deletions src/repr/ir/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pub enum Value {
Constant(ConstantValue),
/// Temporary value representing the result of some triple.
Triple(TripleRef),
/// Pointer produced from some triple.
Pointer(TripleRef),
/// A parameter passed to the current function.
Parameter(usize),
/// No value.
Expand Down
6 changes: 6 additions & 0 deletions src/repr/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ pub enum Token {
LeftBrace,
#[token("}")]
RightBrace,
#[token("[")]
LeftSquare,
#[token("]")]
RightSquare,

/*
* Keywords
Expand Down Expand Up @@ -159,6 +163,8 @@ impl Display for Token {
Token::RightParen => write!(f, "("),
Token::LeftBrace => write!(f, "{{"),
Token::RightBrace => write!(f, "}}"),
Token::LeftSquare => write!(f, "["),
Token::RightSquare => write!(f, "]"),
Token::Fn => write!(f, "fn"),
Token::Return => write!(f, "return"),
Token::Let => write!(f, "let"),
Expand Down
1 change: 1 addition & 0 deletions src/repr/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub enum Ty {
Boolean,
Unit,
Never,
Array { inner: Box<Ty>, size: u32 },
}

impl Ty {
Expand Down
28 changes: 27 additions & 1 deletion src/stage/lower_ir/lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ impl FunctionBuilder {
Function {
identifier: self.idx,
signature: self.signature,
basic_blocks: dbg!(self.basic_blocks)
basic_blocks: self
.basic_blocks
.into_iter()
.map(|builder| ir::BasicBlock {
triples: builder.triples,
Expand Down Expand Up @@ -379,5 +380,30 @@ fn lower_expression(
// Directly lower the inner expression, cast is only for the compiler
lower_expression(compiler, builder, value)
}
ast::Expression::Index(ast::Index { value, index, .. }) => {
let index = lower_expression(compiler, builder, index)?;

Some(Value::Triple(builder.add_triple(Triple::Index {
value: *value,
index,
})))
}
ast::Expression::Array(ast::Array { init, .. }) => {
// Allocate the memory
let ptr = builder.add_triple(Triple::AllocArray(init.len() as u32));

// Initialise each of the items into the memory
init.iter().enumerate().for_each(|(i, expression)| {
let value = lower_expression(compiler, builder, expression).unwrap();

builder.add_triple(Triple::SetIndex {
array_ptr: ptr,
index: Value::integer(i as i64),
value,
});
});

Some(Value::Pointer(ptr))
}
}
}
Loading

0 comments on commit 1799b7d

Please sign in to comment.