Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions ir/src/bools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use commons::err::{PositionlessError, PositionlessResult};
use inkwell::IntPredicate;
use lexer::toks::comp::ComparingOperator;

use crate::{ctx::IRContext, refs::IRValueRef, types::BOOL_TYPE_HASH, values::IRValue};
use crate::{ctx::IRContext, refs::IRValueRef, types::{BOOL_TYPE_HASH, typing::{OwnedIntType, OwnedIntValue, OwnedValueEnum}}, values::IRValue};

pub fn make_bool_xor<'a>(ctx: &'a IRContext<'a>, b: IRValueRef<'a>) -> PositionlessResult<IRValue<'a>> {
pub fn make_bool_xor(ctx: &IRContext, b: IRValueRef) -> PositionlessResult<IRValue> {
let val = b.obtain(ctx)?;
let inkwell = match val.obtain_as_bool() {
Some(v) => v,
Expand All @@ -20,26 +20,26 @@ pub fn make_bool_xor<'a>(ctx: &'a IRContext<'a>, b: IRValueRef<'a>) -> Positionl

let one = bool_t.get_inkwell_inttype()?.const_int(1, false);

let xor_v = match ctx.builder.build_xor(inkwell, one, "xor_") {
let xor_v = match ctx.builder.build_xor(inkwell.inner, one, "xor_") {
Ok(v) => v,
Err(_) => return Err(PositionlessError::new("build_xor failed!"))
};

return Ok(IRValue::new(xor_v.into(), bool_t));
return Ok(IRValue::new(OwnedValueEnum::new(&ctx.inkwell_ctx, xor_v.into()), bool_t));
}

pub fn make_bool_cmp_int<'a>(ctx: &'a IRContext<'a>, a: IRValueRef<'a>, b: IRValueRef<'a>, comp: ComparingOperator) -> PositionlessResult<IRValue<'a>> {
pub fn make_bool_cmp_int(ctx: &IRContext, a: IRValueRef, b: IRValueRef, comp: ComparingOperator) -> PositionlessResult<IRValue> {
let a_val = a.obtain(ctx)?;
let b_val = b.obtain(ctx)?;

let t = a_val.t;
let t = a_val.t.clone();

let a_int = match a_val.obtain_as_int(t) {
let a_int = match a_val.obtain_as_int(ctx, t.clone()) {
Some(v) => v,
None => return Err(PositionlessError::new("Value a wasn't an int when trying to use comp!"))
};

let b_int = match b_val.obtain_as_int(t) {
let b_int = match b_val.obtain_as_int(ctx, t.clone()) {
Some(v) => v,
None => return Err(PositionlessError::new("Value b wasn't an int when trying to use comp!"))
};
Expand All @@ -66,7 +66,7 @@ pub fn make_bool_cmp_int<'a>(ctx: &'a IRContext<'a>, a: IRValueRef<'a>, b: IRVal
}
}

let cmp = match ctx.builder.build_int_compare(predicate, a_int, b_int, "_cmp") {
let cmp = match ctx.builder.build_int_compare(predicate, *a_int, *b_int, "_cmp") {
Ok(v) => v,
Err(_) => return Err(PositionlessError::new("build_int_compare failed!"))
};
Expand All @@ -76,5 +76,5 @@ pub fn make_bool_cmp_int<'a>(ctx: &'a IRContext<'a>, a: IRValueRef<'a>, b: IRVal
None => return Err(PositionlessError::new("boolean type wasn't found!"))
};

return Ok(IRValue::new(cmp.into(), bool_t));
return Ok(IRValue::new(OwnedValueEnum::new(&ctx.inkwell_ctx,cmp.into()), bool_t));
}
21 changes: 11 additions & 10 deletions ir/src/conv/func.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
use std::rc::Rc;

use commons::err::{PositionlessError, PositionlessResult};
use parser::ast::tree::ASTTreeNode;

use crate::{conv::val::parse_ir_value, ctx::IRContext, irstruct::{funcs::IRFunction, ptr::IRPointer}, refs::IRValueRef, types::typing::IRType};

pub fn parse_ir_function_decl<'a>(ctx: &'a IRContext<'a>, node: Box<ASTTreeNode>) -> PositionlessResult<IRFunction<'a>> {
pub fn parse_ir_function_decl<'a>(ctx: &mut IRContext, node: Box<ASTTreeNode>) -> PositionlessResult<Rc<IRFunction>> {
if let ASTTreeNode::FunctionDeclaration { func_name, args, body, returnType } = *node {
let return_type = match returnType {
Some(h) => ctx.type_storage.get(h),
None => None
};

let mut arguments: Vec<&'a IRType<'a>> = vec![];
let mut arguments: Vec<Rc<IRType>> = vec![];

for k in args {
let t = match ctx.type_storage.get(k.argument_type) {
Expand All @@ -23,16 +25,15 @@ pub fn parse_ir_function_decl<'a>(ctx: &'a IRContext<'a>, node: Box<ASTTreeNode>

let func = IRFunction::create(ctx, func_name.val, &ctx.module, return_type, arguments)?;

return Ok(func);
ctx.add_function(func_name.hash, func);

return ctx.get_funtion(func_name.hash);
}

return Err(PositionlessError::new("Given node in parse_ir_function_decl wasn't a function decl!"));
}

pub fn parse_ir_function_body_member<'a>(ctx: &'a IRContext<'a>, func: &'a mut IRFunction<'a>, node: Box<ASTTreeNode>) -> PositionlessResult<bool> {

let mut lctx = func.lctx.borrow_mut();

pub fn parse_ir_function_body_member<'a>(ctx: &IRContext, func: &mut IRFunction, node: Box<ASTTreeNode>) -> PositionlessResult<bool> {
match *node {
ASTTreeNode::VarDeclaration { var_name, var_type, value } => {
let var_t = match ctx.type_storage.get(var_type) {
Expand All @@ -42,17 +43,17 @@ pub fn parse_ir_function_body_member<'a>(ctx: &'a IRContext<'a>, func: &'a mut I

{
let initial = if let Some(v) = value {
Some(parse_ir_value(&mut lctx, ctx, v, None)?)
Some(parse_ir_value(Some(&func.lctx), ctx, v, None)?)
} else {
None
};
}

let ptr = IRPointer::create(ctx, var_name.val.clone(), var_t, None)?;
let ptr = IRPointer::create(ctx, var_name.val.clone(), var_t.clone(), None)?;

let ptr = IRPointer::create(ctx, var_name.val, var_t, None)?;

lctx.add_variable(var_name.hash, ptr);
func.lctx.add_variable(var_name.hash, ptr);

return Ok(true);
},
Expand Down
35 changes: 19 additions & 16 deletions ir/src/conv/val.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
//! AST value -> IR value conversion

use std::rc::Rc;

use commons::err::{PositionlessError, PositionlessResult};
use inkwell::values::BasicValue;
use parser::ast::tree::ASTTreeNode;

use crate::{bools::{make_bool_cmp_int, make_bool_xor}, ctx::{IRContext, IRLocalContext}, irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, math::make_math_operation, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED64_TYPE_HASH}, values::IRValue};
use crate::{bools::{make_bool_cmp_int, make_bool_xor}, ctx::{IRContext, IRLocalContext}, irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, math::make_math_operation, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED64_TYPE_HASH, typing::OwnedValueEnum}, values::IRValue};

pub fn get_variable_ref<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, hash: u64) -> PositionlessResult<IRValueRef<'a>> {
pub fn get_variable_ref(lctx: &IRLocalContext, ctx: &IRContext, hash: u64) -> PositionlessResult<IRValueRef> {
match ctx.get_variable(hash) {
Ok(v) => return Ok(IRValueRef::from_static(IRStaticVariable::clone(v))),
Ok(v) => return Ok(IRValueRef::from_static(v.clone())),
Err(_) => {}
};

Expand All @@ -18,7 +20,7 @@ pub fn get_variable_ref<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>
};
}

pub fn parse_ir_value<'a>(func: Option<&'a IRFunction<'a>>, ctx: &'a IRContext<'a>, node: Box<ASTTreeNode>, left: Option<IRPointer<'a>>) -> PositionlessResult<IRValueRef<'a>> {
pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node: Box<ASTTreeNode>, left: Option<IRPointer>) -> PositionlessResult<IRValueRef> {
match node.as_ref() {
ASTTreeNode::IntegerLit(v) => {
let t = ctx.type_storage.get(SIGNED64_TYPE_HASH);
Expand All @@ -27,7 +29,7 @@ pub fn parse_ir_value<'a>(func: Option<&'a IRFunction<'a>>, ctx: &'a IRContext<'
return Err(PositionlessError::new("Invalid type storage! si64 not found!"));
}

return Ok(IRValueRef::from_val(IRValue::from_signed(t.unwrap(), *v as i128)?));
return Ok(IRValueRef::from_val(IRValue::from_signed(ctx, t.unwrap(), *v as i128)?));
},

ASTTreeNode::StringLit(v) => {
Expand All @@ -37,9 +39,9 @@ pub fn parse_ir_value<'a>(func: Option<&'a IRFunction<'a>>, ctx: &'a IRContext<'
return Err(PositionlessError::new("Invalid type storage! pointer not found!"));
}

let global = IRStaticVariable::from_str(&ctx.builder, v, String::from("__string_literal"), t.unwrap())?;
let global = IRStaticVariable::from_str(&ctx, v, String::from("__string_literal"), t.unwrap())?;

return Ok(IRValueRef::from_static(global));
return Ok(IRValueRef::from_static(Rc::new(global)));
},

ASTTreeNode::VariableReference(e) => {
Expand All @@ -51,7 +53,7 @@ pub fn parse_ir_value<'a>(func: Option<&'a IRFunction<'a>>, ctx: &'a IRContext<'
return Ok(IRValueRef::from_pointer(ptr));
}

let var = get_variable_ref(&func.unwrap().lctx.borrow(), ctx, e.hash)?;
let var = get_variable_ref(&lctx.unwrap(), ctx, e.hash)?;

return Ok(var);
},
Expand All @@ -67,10 +69,11 @@ pub fn parse_ir_value<'a>(func: Option<&'a IRFunction<'a>>, ctx: &'a IRContext<'
arguments.push(parse_ir_value(lctx, ctx, arg.clone(), None)?);
}

let res: Option<IRPointer<'a>>;
let res: Option<IRPointer>;

if left.is_some() {
let descriptor = left.as_ref().unwrap().t.get_structured_type_descriptor()?;
let t = left.as_ref().unwrap().t.clone();
let descriptor = t.get_structured_type_descriptor()?;

let f = descriptor.get_function(func.hash)?;

Expand All @@ -94,13 +97,13 @@ pub fn parse_ir_value<'a>(func: Option<&'a IRFunction<'a>>, ctx: &'a IRContext<'

let t = left.get_type();

let l_val = match left.obtain(ctx)?.obtain_as_int(t) {
Some(v) => v,
let l_val = match left.obtain(ctx)?.obtain_as_int(ctx, t.clone()) {
Some(v) => *v,
None => return Err(PositionlessError::new("lval on math operation wasn't a number!")),
};

let r_val = match right.obtain(ctx)?.obtain_as_int(t) {
Some(v) => v,
let r_val = match right.obtain(ctx)?.obtain_as_int(ctx, t.clone()) {
Some(v) => *v,
None => return Err(PositionlessError::new("lval on math operation wasn't a number!")),
};

Expand All @@ -112,10 +115,10 @@ pub fn parse_ir_value<'a>(func: Option<&'a IRFunction<'a>>, ctx: &'a IRContext<'
}

let ptr = left.as_pointer()?;
ptr.store(&ctx.builder, out.as_basic_value_enum());
ptr.store(ctx, out.as_basic_value_enum());
}

return Ok(IRValueRef::from_val(IRValue::new(out.into(), t)));
return Ok(IRValueRef::from_val(IRValue::new(OwnedValueEnum::new(&ctx.inkwell_ctx, out.into()), t)));
},

ASTTreeNode::OperatorBasedConditionMember { lval, rval, operator } => {
Expand Down
76 changes: 48 additions & 28 deletions ir/src/ctx.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,63 @@
//! IR context related code

use std::{mem::transmute, ops::{Add, Deref, DerefMut}, rc::Rc};

use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap};
use inkwell::{AddressSpace, builder::Builder, context::Context, module::Module, types::{PointerType, VoidType}};

use crate::{irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, types::storage::IRTypeStorage};
use crate::{irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, types::storage::IRTypeStorage, utils::LateInit};

/// The global IR context.
/// Basically holds anything related to the current IR compilation (eg: functions, types, global vars)
pub struct IRContext<'a> {
pub inkwell_ctx: &'a Context,
pub builder: Builder<'a>,
pub ptr_type: PointerType<'a>,
pub void_type: VoidType<'a>,
pub struct IRContext {
pub inkwell_ctx: Rc<Context>,
pub builder: Builder<'static>,
pub ptr_type: PointerType<'static>,
pub void_type: VoidType<'static>,

pub module: Module<'a>,
pub module: Module<'static>,

pub type_storage: IRTypeStorage<'a>,
pub type_storage: LateInit<IRTypeStorage>,

pub functions: HashedMap<IRFunction<'a>>,
pub static_vars: HashedMap<IRStaticVariable<'a>>
pub functions: HashedMap<Rc<IRFunction>>,
pub static_vars: HashedMap<Rc<IRStaticVariable>>
}

impl<'a> IRContext<'a> {
pub fn new(builder: Builder<'a>, ctx: &'a Context) -> Self {
return IRContext { inkwell_ctx: ctx, builder, ptr_type: ctx.ptr_type(AddressSpace::from(0)), functions: HashedMap::new(0), static_vars: HashedMap::new(0), type_storage: IRTypeStorage::new(&ctx), void_type: ctx.void_type(), module: ctx.create_module("quickfall_module") }
impl IRContext {
pub fn new(ctx: Rc<Context>) -> Self {

let ptr_type = unsafe { transmute::<PointerType, PointerType<'static>>(ctx.ptr_type(AddressSpace::from(0))) };
let void_type = unsafe { transmute::<VoidType, VoidType<'static>>(ctx.void_type()) };
let module = unsafe { transmute::<Module, Module<'static>>(ctx.create_module("quickfall_module")) };

let mut ir = IRContext {
inkwell_ctx: ctx.clone(),
builder: unsafe { transmute::<Builder, Builder<'static>>(ctx.create_builder()) },
ptr_type,
functions: HashedMap::new(0),
static_vars: HashedMap::new(0),
type_storage: LateInit::new(),
void_type,
module
};

ir.type_storage.fill(IRTypeStorage::new(&ir));

return ir;
}

pub fn add_variable(&'a mut self, hash: u64, var: IRStaticVariable<'a>) -> PositionlessResult<bool> {
pub fn add_variable(&mut self, hash: u64, var: IRStaticVariable) -> PositionlessResult<bool> {
if self.is_key_taken(hash) {
return Err(PositionlessError::new("There already is an element named like this!"));
}

self.static_vars.put(hash, var);
self.static_vars.put(hash, Rc::new(var));
return Ok(true);
}

pub fn get_variable(&'a self, hash: u64) -> PositionlessResult<&'a IRStaticVariable<'a>> {
pub fn get_variable(&self, hash: u64) -> PositionlessResult<Rc<IRStaticVariable>> {
return match self.static_vars.get(hash) {
Some(v) => Ok(v),
Some(v) => Ok(v.clone()),
None => return Err(PositionlessError::new("Invalid variable name"))
};
}
Expand All @@ -46,43 +66,43 @@ impl<'a> IRContext<'a> {
return self.functions.get(hash).is_some() || self.static_vars.get(hash).is_some() || self.type_storage.get(hash).is_some();
}

pub fn get_funtion(&'a self, hash: u64) -> PositionlessResult<&'a IRFunction<'a>> {
pub fn get_funtion(&self, hash: u64) -> PositionlessResult<Rc<IRFunction>> {
return match self.functions.get(hash) {
Some(v) => Ok(v),
Some(v) => Ok(v.clone()),
None => Err(PositionlessError::new("Invalid function name!"))
}
}

pub fn add_function(&'a mut self, hash: u64, func: IRFunction<'a>) -> PositionlessResult<bool> {
pub fn add_function(&mut self, hash: u64, func: IRFunction) -> PositionlessResult<bool> {
if self.is_key_taken(hash) {
return Err(PositionlessError::new("There already is an element named like this!"));
}

self.functions.put(hash, func);
self.functions.put(hash, Rc::new(func));
return Ok(true);
}

}

pub struct LocalIRVariable<'a> {
pub ptr: IRPointer<'a>,
pub struct LocalIRVariable {
pub ptr: IRPointer,
pub depth: usize // Depth is depth in body.
}

/// The local IR context.
/// Holds anything held and created in the given body (eg: vars).
pub struct IRLocalContext<'a> {
pub vars: HashedMap<LocalIRVariable<'a>>,
pub struct IRLocalContext {
pub vars: HashedMap<LocalIRVariable>,
pub current_depth: usize, // Starts at 0 where 0 is function body
}

impl<'a> IRLocalContext<'a> {
impl IRLocalContext {
pub fn new() -> Self {
return IRLocalContext { vars: HashedMap::new(0), current_depth: 0 }
}

/// Attempts to add a variable in the current local context. Will return an error if the operation is impossible
pub fn add_variable(&mut self, hash: u64, var: IRPointer<'a>) -> PositionlessResult<bool> {
pub fn add_variable(&mut self, hash: u64, var: IRPointer) -> PositionlessResult<bool> {
if self.vars.get(hash).is_some() {
return Err(PositionlessError::new(&format!("Variable named {} is already registered in the current context.", hash)));
}
Expand All @@ -91,7 +111,7 @@ impl<'a> IRLocalContext<'a> {
return Ok(true);
}

pub fn get_variable(&'a self, hash: u64) -> PositionlessResult<&'a IRPointer<'a>> {
pub fn get_variable(&self, hash: u64) -> PositionlessResult<&IRPointer> {
return match self.vars.get(hash) {
Some(v) => Ok(&v.ptr),
None => return Err(PositionlessError::new("Invalid variable name"))
Expand Down
Loading