diff --git a/ir/src/bools.rs b/ir/src/bools.rs index d21ec42..0c64507 100644 --- a/ir/src/bools.rs +++ b/ir/src/bools.rs @@ -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> { +pub fn make_bool_xor(ctx: &IRContext, b: IRValueRef) -> PositionlessResult { let val = b.obtain(ctx)?; let inkwell = match val.obtain_as_bool() { Some(v) => v, @@ -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> { +pub fn make_bool_cmp_int(ctx: &IRContext, a: IRValueRef, b: IRValueRef, comp: ComparingOperator) -> PositionlessResult { 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!")) }; @@ -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!")) }; @@ -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)); } \ No newline at end of file diff --git a/ir/src/conv/func.rs b/ir/src/conv/func.rs index 0c65624..bacc2d4 100644 --- a/ir/src/conv/func.rs +++ b/ir/src/conv/func.rs @@ -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) -> PositionlessResult> { +pub fn parse_ir_function_decl<'a>(ctx: &mut IRContext, node: Box) -> PositionlessResult> { 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> = vec![]; for k in args { let t = match ctx.type_storage.get(k.argument_type) { @@ -23,16 +25,15 @@ pub fn parse_ir_function_decl<'a>(ctx: &'a IRContext<'a>, node: Box 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) -> PositionlessResult { - - let mut lctx = func.lctx.borrow_mut(); - +pub fn parse_ir_function_body_member<'a>(ctx: &IRContext, func: &mut IRFunction, node: Box) -> PositionlessResult { match *node { ASTTreeNode::VarDeclaration { var_name, var_type, value } => { let var_t = match ctx.type_storage.get(var_type) { @@ -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); }, diff --git a/ir/src/conv/val.rs b/ir/src/conv/val.rs index 8a4a02e..9dfda67 100644 --- a/ir/src/conv/val.rs +++ b/ir/src/conv/val.rs @@ -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> { +pub fn get_variable_ref(lctx: &IRLocalContext, ctx: &IRContext, hash: u64) -> PositionlessResult { 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(_) => {} }; @@ -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, left: Option>) -> PositionlessResult> { +pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node: Box, left: Option) -> PositionlessResult { match node.as_ref() { ASTTreeNode::IntegerLit(v) => { let t = ctx.type_storage.get(SIGNED64_TYPE_HASH); @@ -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) => { @@ -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) => { @@ -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); }, @@ -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>; + let res: Option; 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)?; @@ -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!")), }; @@ -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 } => { diff --git a/ir/src/ctx.rs b/ir/src/ctx.rs index 55cf580..42a93a5 100644 --- a/ir/src/ctx.rs +++ b/ir/src/ctx.rs @@ -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, + 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, - pub functions: HashedMap>, - pub static_vars: HashedMap> + pub functions: HashedMap>, + pub static_vars: HashedMap> } -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) -> Self { + + let ptr_type = unsafe { transmute::>(ctx.ptr_type(AddressSpace::from(0))) }; + let void_type = unsafe { transmute::>(ctx.void_type()) }; + let module = unsafe { transmute::>(ctx.create_module("quickfall_module")) }; + + let mut ir = IRContext { + inkwell_ctx: ctx.clone(), + builder: unsafe { transmute::>(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 { + pub fn add_variable(&mut self, hash: u64, var: IRStaticVariable) -> PositionlessResult { 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> { return match self.static_vars.get(hash) { - Some(v) => Ok(v), + Some(v) => Ok(v.clone()), None => return Err(PositionlessError::new("Invalid variable name")) }; } @@ -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> { 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 { + pub fn add_function(&mut self, hash: u64, func: IRFunction) -> PositionlessResult { 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>, +pub struct IRLocalContext { + pub vars: HashedMap, 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 { + pub fn add_variable(&mut self, hash: u64, var: IRPointer) -> PositionlessResult { if self.vars.get(hash).is_some() { return Err(PositionlessError::new(&format!("Variable named {} is already registered in the current context.", hash))); } @@ -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")) diff --git a/ir/src/irstruct/funcs.rs b/ir/src/irstruct/funcs.rs index 30f4e6a..21d0e00 100644 --- a/ir/src/irstruct/funcs.rs +++ b/ir/src/irstruct/funcs.rs @@ -1,58 +1,60 @@ -use std::cell::RefCell; +use std::{cell::RefCell, mem::transmute, ops::{Deref, DerefMut}, rc::Rc}; use commons::err::{PositionedError, PositionlessError, PositionlessResult}; use inkwell::{basic_block::BasicBlock, builder::Builder, context::Context, module::Module, types::BasicType, values::{BasicValueEnum, FunctionValue, IntValue}}; -use crate::{ctx::{IRContext, IRLocalContext}, irstruct::ptr::IRPointer, refs::IRValueRef, types::typing::IRType, values::IRValue}; +use crate::{ctx::{IRContext, IRLocalContext}, irstruct::ptr::IRPointer, refs::IRValueRef, types::typing::{IRType, OwnedIntValue, OwnedValueEnum}, values::IRValue}; -pub struct IRFunction<'a> { - pub inkwell_func: FunctionValue<'a>, - ret_type: Option<&'a IRType<'a>>, - args: Vec<&'a IRType<'a>>, +pub struct IRFunction { + pub owned: Rc, + + pub inkwell_func: FunctionValue<'static>, + ret_type: Option>, + args: Vec>, name: String, - pub lctx: RefCell>, + pub lctx: IRLocalContext, - entry: Option> + entry: Option> } -impl<'a> IRFunction<'a> { - pub fn new(ctx: &'a IRContext, name: String, func: FunctionValue<'a>, ret_type: Option<&'a IRType<'a>>, args: Vec<&'a IRType<'a>>) -> Self { +impl IRFunction { + pub fn new(ctx: &IRContext, name: String, func: FunctionValue, ret_type: Option>, args: Vec>) -> Self { let block = ctx.inkwell_ctx.append_basic_block(func, "entry"); - return IRFunction { inkwell_func: func, ret_type, args, name, entry: Some(block), lctx: IRLocalContext::new().into() } + return IRFunction { owned: ctx.inkwell_ctx.clone(), inkwell_func: unsafe { transmute(func)}, ret_type, args, name, entry: Some(unsafe { transmute(block) }), lctx: IRLocalContext::new().into() } } - pub fn new_shadow(name: String, func: FunctionValue<'a>, ret_type: Option<&'a IRType<'a>>, args: Vec<&'a IRType<'a>>) -> Self { - return IRFunction { inkwell_func: func, ret_type, args, name, entry: None, lctx: IRLocalContext::new().into() } + pub fn new_shadow(ctx: &IRContext, name: String, func: FunctionValue, ret_type: Option>, args: Vec>) -> Self { + return IRFunction { owned: ctx.inkwell_ctx.clone(), inkwell_func: unsafe { transmute(func)}, ret_type, args, name, entry: None, lctx: IRLocalContext::new().into() } } - pub fn create_shadow(ctx: &'a IRContext, name: String, module: &Module<'a>, ret_type: Option<&'a IRType<'a>>, args: Vec<&'a IRType<'a>>) -> PositionlessResult { + pub fn create_shadow(ctx: &IRContext, name: String, module: &Module, ret_type: Option>, args: Vec>) -> PositionlessResult { let mut kargs = vec![]; for k in &args { - kargs.push(k.get_inkwell_base_metadatatype()?); + kargs.push(*k.get_inkwell_base_metadatatype()?); } - let t = match ret_type { + let t = match &ret_type { Some(ret) => ret.get_inkwell_basetype()?.fn_type(&kargs, false), None => ctx.void_type.fn_type(&kargs, false) }; let func = module.add_function(&name, t, None); - return Ok(IRFunction::new_shadow(name, func, ret_type, args)); + return Ok(IRFunction::new_shadow(ctx, name, func, ret_type, args)); } - pub fn create(ctx: &'a IRContext, name: String, module: &Module<'a>, ret_type: Option<&'a IRType<'a>>, args: Vec<&'a IRType<'a>>) -> PositionlessResult { + pub fn create(ctx: &IRContext, name: String, module: &Module, ret_type: Option>, args: Vec>) -> PositionlessResult { let mut kargs = vec![]; for k in &args { - kargs.push(k.get_inkwell_base_metadatatype()?); + kargs.push(*k.get_inkwell_base_metadatatype()?); } - let t = match ret_type { + let t = match &ret_type { Some(ret) => ret.get_inkwell_basetype()?.fn_type(&kargs, false), None => ctx.void_type.fn_type(&kargs, false) }; @@ -62,11 +64,11 @@ impl<'a> IRFunction<'a> { return Ok(IRFunction::new(ctx, name, func, ret_type, args)); } - pub fn call(&'a self, ctx: &'a IRContext<'a>, args: Vec>, grab_return: bool) -> PositionlessResult>> { + pub fn call(&self, ctx: &IRContext, args: Vec, grab_return: bool) -> PositionlessResult> { let mut inkwell_args = vec![]; for arg in args { - inkwell_args.push(arg.obtain(ctx)?.obtain().into()); + inkwell_args.push(arg.obtain(ctx)?.obtain().inner.into()); } let call = match ctx.builder.build_call(self.inkwell_func, &inkwell_args, &self.name) { @@ -78,8 +80,8 @@ impl<'a> IRFunction<'a> { return Ok(None); } - let return_type = match self.ret_type { - Some(ret) => ret, + let return_type = match self.ret_type.as_ref() { + Some(ret) => ret.clone(), None => return Ok(None) }; @@ -88,7 +90,7 @@ impl<'a> IRFunction<'a> { None => return Ok(None) }; - let val = IRValue::new(val, return_type); + let val = IRValue::new(OwnedValueEnum::new(&ctx.inkwell_ctx, val), return_type.clone()); let pointer = IRPointer::create(ctx, format!("function_ret_{}", self.name), return_type, Some(IRValueRef::from_val(val)))?; @@ -96,29 +98,29 @@ impl<'a> IRFunction<'a> { } /// Prepares the addition of the function body. - pub fn prepare_body_filling(&self, builder: &Builder<'a>) { + pub fn prepare_body_filling(&self, ctx: &IRContext) { if self.entry.is_none() { return; } - builder.position_at_end(self.entry.unwrap()); + ctx.builder.position_at_end(self.entry.unwrap()); } - pub fn get_nth_arg(&self, ind: u32) -> PositionlessResult> { + pub fn get_nth_arg(&self, ind: u32) -> PositionlessResult { let res = match self.inkwell_func.get_nth_param(ind) { Some(v) => v, None => return Err(PositionlessError::new("Couldn't get nth param using get_nth_param")) }; - return Ok(res); + return Ok(OwnedValueEnum::new(&self.owned, res)); } - pub fn get_nth_arg_int(&self, ind: u32) -> PositionlessResult> { + pub fn get_nth_arg_int(&self, ind: u32) -> PositionlessResult { if !self.args[ind as usize].is_numeric_type() { return Err(PositionlessError::new("Tried getting nth argument but given argument's type isn't numeric!")); } - return Ok(self.get_nth_arg(ind)?.into_int_value()); + return Ok(OwnedIntValue::new(&self.owned, self.get_nth_arg(ind)?.into_int_value())); } diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index b51e616..3b843f3 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -1,60 +1,52 @@ +use std::rc::Rc; + use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{builder::Builder, context::Context, types::BasicTypeEnum, values::{BasicValue, BasicValueEnum, IntValue, PointerValue}}; -use crate::{ctx::IRContext, refs::IRValueRef, types::typing::IRType, values::IRValue}; +use crate::{ctx::IRContext, refs::IRValueRef, types::typing::{IRType, OwnedTypeEnum, OwnedValueEnum}, values::IRValue}; #[derive(Clone)] -pub struct IRPointer<'a> { - pub inkwell_ptr: PointerValue<'a>, // Only use this directly within structs - pub t: &'a IRType<'a>, +pub struct IRPointer { + owned: Rc, + pub inkwell_ptr: PointerValue<'static>, // Only use this directly within structs + pub t: Rc, pub name: String } -impl<'a> IRPointer<'a> { - pub fn new(ptr: PointerValue<'a>, t: &'a IRType<'a>, name: String) -> Self { - return IRPointer { inkwell_ptr: ptr, name, t } +impl IRPointer { + pub fn new(ptr: PointerValue<'static>, ctx: &IRContext, t: Rc, name: String) -> Self { + return IRPointer { inkwell_ptr: ptr, owned: ctx.inkwell_ctx.clone(), name, t } } - pub fn create(ctx: &'a IRContext<'a>, name: String, t: &'a IRType<'a>, initial: Option>) -> PositionlessResult { - let ptr = match ctx.builder.build_alloca(t.get_inkwell_basetype()?, &name) { + pub fn create(ctx: &IRContext, name: String, t: Rc, initial: Option) -> PositionlessResult { + let ptr = match ctx.builder.build_alloca(t.get_inkwell_basetype()?.inner, &name) { Ok(v) => v, Err(_) => return Err(PositionlessError::new("build_alloca failed!")) }; if initial.is_some() { - match ctx.builder.build_store(ptr, initial.unwrap().obtain(ctx)?.obtain()) { + match ctx.builder.build_store(ptr, *initial.unwrap().obtain(ctx)?.obtain()) { Err(_) => return Err(PositionlessError::new("build_store failed!")), Ok(_) => {} }; } - return Ok(IRPointer { inkwell_ptr: ptr, t, name: name.clone() }); + return Ok(IRPointer { owned: ctx.inkwell_ctx.clone(), inkwell_ptr: ptr, t, name: name.clone() }); } - pub fn load(&self, ctx: &'a IRContext<'a>, t: &'a IRType<'a>) -> PositionlessResult> { - if !self.t.is_same(t) { + pub fn load(&self, ctx: &IRContext, t: Rc) -> PositionlessResult { + if !self.t.is_same(&t) { return Err(PositionlessError::new("Provided IRType isn't the same!")); } - match ctx.builder.build_load(self.t.get_inkwell_instance_basetype(ctx)?, self.inkwell_ptr, &self.name) { - Ok(v) => return Ok(IRValue::new(v, t)), + match ctx.builder.build_load(*self.t.get_inkwell_instance_basetype(ctx)?, self.inkwell_ptr, &self.name) { + Ok(v) => return Ok(IRValue::new(OwnedValueEnum::new(&ctx.inkwell_ctx, v), t)), Err(_) => return Err(PositionlessError::new("build_load failed!")) } } - - pub fn load_from_inkwell_type(&self, ctx: &'a IRContext<'a>, t: BasicTypeEnum<'a>) -> PositionlessResult> { - if self.t.get_inkwell_instance_basetype(ctx)? != t { - return Err(PositionlessError::new("Given types aren't the same!")) - } - - match ctx.builder.build_load(t, self.inkwell_ptr, &self.name) { - Ok(v) => return Ok(IRValue::new(v, self.t)), - Err(_) => return Err(PositionlessError::new("build_load failed!")) - } - } - - pub fn store>(&self, builder: &Builder<'a>, val: V) -> bool { - return match builder.build_store(self.inkwell_ptr, val) { + + pub fn store(&self, ctx: &IRContext, val: BasicValueEnum) -> bool { + return match ctx.builder.build_store(self.inkwell_ptr, val) { Ok(_) => true, Err(_) => false } diff --git a/ir/src/irstruct/staticvars.rs b/ir/src/irstruct/staticvars.rs index ee8f446..e03be29 100644 --- a/ir/src/irstruct/staticvars.rs +++ b/ir/src/irstruct/staticvars.rs @@ -1,29 +1,31 @@ //! Static variable related code +use std::rc::Rc; + use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{builder::Builder, values::{BasicValueEnum, GlobalValue}}; -use crate::{types::typing::IRType, values::IRValue}; +use crate::{ctx::IRContext, types::typing::{IRType, OwnedGlobalValue, OwnedValueEnum}, values::IRValue}; #[derive(Clone)] -pub struct IRStaticVariable<'a> { - inkwell: Option>, - val: Option>, - pub t: &'a IRType<'a>, +pub struct IRStaticVariable { + inkwell: Option, + val: Option, + pub t: Rc, pub name: String } -impl<'a> IRStaticVariable<'a> { - pub fn from_str(ctx: &'a Builder<'a>, str: &str, name: String, t: &'a IRType<'a>) -> PositionlessResult> { - let inkwell = match ctx.build_global_string_ptr(str, &name) { +impl IRStaticVariable { + pub fn from_str(ctx: &IRContext, str: &str, name: String, t: Rc) -> PositionlessResult { + let inkwell = match ctx.builder.build_global_string_ptr(str, &name) { Ok(v) => v, Err(_) => return Err(PositionlessError::new("build_global_string_ptr failed!!")) }; - return Ok(IRStaticVariable { inkwell: Some(inkwell), t, name, val: None }); + return Ok(IRStaticVariable { inkwell: Some(OwnedGlobalValue::new(&ctx.inkwell_ctx, inkwell)), t, name, val: None }); } - pub fn from_val(name: String, t: &'a IRType<'a>, val: IRValue<'a>) -> PositionlessResult> { + pub fn from_val(name: String, t: Rc, val: IRValue) -> PositionlessResult { return Ok(IRStaticVariable { val: Some(val.obtain()), inkwell: None, t, name }) } @@ -31,20 +33,20 @@ impl<'a> IRStaticVariable<'a> { return self.val.is_some(); } - pub fn as_val(&self) -> PositionlessResult> { + pub fn as_val(&self) -> PositionlessResult { if self.val.is_some() { - return Ok(self.val.unwrap()); + return Ok(self.val.as_ref().unwrap().clone()); } - return Ok(self.as_string_ref()?.as_pointer_value().into()) + return Ok(OwnedValueEnum::new(&self.inkwell.as_ref().unwrap().owned, self.as_string_ref()?.as_pointer_value().into())); } - pub fn as_string_ref(&self) -> PositionlessResult> { + pub fn as_string_ref(&self) -> PositionlessResult { if self.is_compiletime_replaceable() { return Err(PositionlessError::new("Tried using as_string_ref on a compiletime determined global var")); } - return Ok(self.inkwell.unwrap()) + return Ok(self.inkwell.clone().unwrap()) } } \ No newline at end of file diff --git a/ir/src/irstruct/structs.rs b/ir/src/irstruct/structs.rs index b22825e..22a4c78 100644 --- a/ir/src/irstruct/structs.rs +++ b/ir/src/irstruct/structs.rs @@ -1,61 +1,64 @@ //! IR representation of structure types (structs, layouts...) +use std::{mem::transmute, rc::Rc}; + use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap}; -use inkwell::{types::{BasicTypeEnum, StructType}}; +use inkwell::{context::Context, types::{BasicTypeEnum, StructType}}; -use crate::{ctx::IRContext, irstruct::{funcs::IRFunction, ptr::IRPointer}, types::typing::IRType}; +use crate::{ctx::IRContext, irstruct::{funcs::IRFunction, ptr::IRPointer}, types::typing::{IRType, OwnedTypeEnum}}; -pub struct IRStructuredType<'a> { - pub inkwell_type: StructType<'a>, +pub struct IRStructuredType { + pub owned: Rc, + pub inkwell_type: StructType<'static>, pub field_to_index: HashedMap, - pub field_types: Vec<&'a IRType<'a>>, - pub functions: HashedMap>, + pub field_types: Vec>, + pub functions: HashedMap>, pub name: String, pub is_layout: bool } -impl<'a> IRStructuredType<'a> { - pub fn new(ctx: &'a IRContext<'a>, name: String, layout: bool, fields: Vec<(u64, &'a IRType<'a>)>) -> PositionlessResult { +impl IRStructuredType { + pub fn new(ctx: &IRContext, name: String, layout: bool, fields: Vec<(u64, Rc)>) -> PositionlessResult { let mut map = HashedMap::new(fields.len()); - let mut typeVec: Vec> = Vec::new(); - let mut field_types: Vec<&'a IRType<'a>> = Vec::new(); + let mut typeVec: Vec = Vec::new(); + let mut field_types: Vec> = Vec::new(); let mut ind = 0; for entry in fields { map.put(entry.0, ind); - field_types.push(entry.1); - typeVec.push(entry.1.get_inkwell_basetype()?.into()); + field_types.push(entry.1.clone()); + typeVec.push(entry.1.as_ref().get_inkwell_basetype()?.inner.into()); ind += ind; } let inkwell_type = ctx.inkwell_ctx.struct_type(&typeVec, !layout); - return Ok(Self { inkwell_type, field_to_index: map, name, is_layout: layout, field_types, functions: HashedMap::new(0) }) + return Ok(Self { owned: ctx.inkwell_ctx.clone(), inkwell_type: unsafe { transmute(inkwell_type) }, field_to_index: map, name, is_layout: layout, field_types, functions: HashedMap::new(0) }) } - pub fn append_function(&'a mut self, hash: u64, func: IRFunction<'a>) -> PositionlessResult { + pub fn append_function(&mut self, hash: u64, func: IRFunction) -> PositionlessResult { if self.is_layout { return Err(PositionlessError::new("Cannot declare functions inside of a layout!")); } - self.functions.put(hash, func); + self.functions.put(hash, Rc::new(func)); return Ok(true); } - pub fn get_function(&'a self, hash: u64) -> PositionlessResult<&'a IRFunction<'a>> { + pub fn get_function(&self, hash: u64) -> PositionlessResult> { if self.is_layout { return Err(PositionlessError::new("Cannot use typed-functions inside of a layout!")); } return match self.functions.get(hash) { - Some(v) => Ok(v), + Some(v) => Ok(v.clone()), None => Err(PositionlessError::new("Function was not founc within the struct!")) } } - pub fn get_pointer_for_field_index(&'a self, ctx: &'a IRContext<'a>, instance: &'a IRPointer<'a>, ind: u32) -> PositionlessResult> { + pub fn get_pointer_for_field_index(&self, ctx: &IRContext, instance: &IRPointer, ind: u32) -> PositionlessResult { if ind >= self.field_types.len() as u32 { return Err(PositionlessError::new("Invalid index given to get_pointer_for_field_index")); } @@ -65,12 +68,12 @@ impl<'a> IRStructuredType<'a> { Err(_) => return Err(PositionlessError::new("build_struct_gep failed!")) }; - let field_type = self.field_types[ind as usize]; + let field_type = self.field_types[ind as usize].clone(); - return Ok(IRPointer::new(field_ptr, field_type, String::from("__inner_field_ptr"))); + return Ok(IRPointer::new(field_ptr, ctx, field_type, String::from("__inner_field_ptr"))); } - pub fn get_pointer_for_field_index_noref(&'a self, ctx: &'a IRContext<'a>, instance: IRPointer<'a>, ind: u32) -> PositionlessResult> { + pub fn get_pointer_for_field_index_noref(&self, ctx: &IRContext, instance: IRPointer, ind: u32) -> PositionlessResult { if ind >= self.field_types.len() as u32 { return Err(PositionlessError::new("Invalid index given to get_pointer_for_field_index")); } @@ -80,12 +83,12 @@ impl<'a> IRStructuredType<'a> { Err(_) => return Err(PositionlessError::new("build_struct_gep failed!")) }; - let field_type = self.field_types[ind as usize]; + let field_type = self.field_types[ind as usize].clone(); - return Ok(IRPointer::new(field_ptr, field_type, String::from("__inner_field_ptr"))); + return Ok(IRPointer::new(field_ptr, ctx, field_type, String::from("__inner_field_ptr"))); } - pub fn get_pointer_for_field_noref(&'a self, ctx: &'a IRContext<'a>, instance: IRPointer<'a>, hash: u64) -> PositionlessResult> { + pub fn get_pointer_for_field_noref(&self, ctx: &IRContext, instance: IRPointer, hash: u64) -> PositionlessResult { let k = match self.field_to_index.get(hash) { Some(v) => *v, None => return Err(PositionlessError::new(&format!("The given string hash {} doesn't represent any field in the struct {}", hash, self.name))) @@ -94,7 +97,7 @@ impl<'a> IRStructuredType<'a> { return self.get_pointer_for_field_index_noref(ctx, instance, k); } - pub fn get_pointer_for_field(&'a self, ctx: &'a IRContext<'a>, instance: &'a IRPointer<'a>, hash: u64) -> PositionlessResult> { + pub fn get_pointer_for_field(&self, ctx: &IRContext, instance: &IRPointer, hash: u64) -> PositionlessResult { let k = match self.field_to_index.get(hash) { Some(v) => *v, None => return Err(PositionlessError::new(&format!("The given string hash {} doesn't represent any field in the struct {}", hash, self.name))) diff --git a/ir/src/lib.rs b/ir/src/lib.rs index 3bf721e..33168c9 100644 --- a/ir/src/lib.rs +++ b/ir/src/lib.rs @@ -8,4 +8,5 @@ pub mod irstruct; pub mod conv; pub mod ctx; pub mod refs; -pub mod bools; \ No newline at end of file +pub mod bools; +pub mod utils; \ No newline at end of file diff --git a/ir/src/refs.rs b/ir/src/refs.rs index 32b2eac..f7cceac 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -1,33 +1,35 @@ //! IR value reference definitions +use std::rc::Rc; + use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{builder::Builder, types::{AnyTypeEnum, BasicTypeEnum}, values::PointerValue}; -use crate::{ctx::IRContext, irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::IRType, values::IRValue}; +use crate::{ctx::IRContext, irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::{IRType, OwnedPointerValue}, values::IRValue}; -pub enum IRValueRefKind<'a> { - Ptr(&'a IRType<'a>, IRPointer<'a>), - Val(IRValue<'a>), - Global(&'a IRType<'a>, IRStaticVariable<'a>) +pub enum IRValueRefKind { + Ptr(Rc, IRPointer), + Val(IRValue), + Global(Rc, Rc) } /// The IR value reference. Basically represents any value whatsoever, can handle every shape of values and is used for uniform handling. -pub struct IRValueRef<'a> { +pub struct IRValueRef { // TODO: maybe change IRValueRef to host the fields itself rather than having to use Options - kind: IRValueRefKind<'a>, + kind: IRValueRefKind, } -impl<'a> IRValueRef<'a> { - pub fn from_val(val: IRValue<'a>) -> Self { +impl IRValueRef { + pub fn from_val(val: IRValue) -> Self { return IRValueRef { kind: IRValueRefKind::Val(val) } } - pub fn from_static(val: IRStaticVariable<'a>) -> Self { - return IRValueRef { kind: IRValueRefKind::Global(val.t, val) } + pub fn from_static(val: Rc) -> Self { + return IRValueRef { kind: IRValueRefKind::Global(val.t.clone(), val) } } - pub fn from_pointer(ptr: IRPointer<'a>) -> Self { - return IRValueRef { kind: IRValueRefKind::Ptr(ptr.t, ptr) } + pub fn from_pointer(ptr: IRPointer) -> Self { + return IRValueRef { kind: IRValueRefKind::Ptr(ptr.t.clone(), ptr) } } /// Determines if aqcuiring the values require a load instruction or any instruction at all to obtain the value from. @@ -35,51 +37,51 @@ impl<'a> IRValueRef<'a> { return matches!(self.kind, IRValueRefKind::Ptr(_, _)) } - pub fn obtain(&self, ctx: &'a IRContext<'a>) -> PositionlessResult> { + pub fn obtain(&self, ctx: &IRContext) -> PositionlessResult { match &self.kind { IRValueRefKind::Ptr(t, ptr) => { - ptr.load(ctx, t) + ptr.load(ctx, t.clone()) }, IRValueRefKind::Val(v) => Ok(IRValue::clone(v)), IRValueRefKind::Global(t, global) => { - Ok(IRValue::new(global.as_val()?, t)) + Ok(IRValue::new(global.as_val()?, t.clone())) } } } - pub fn get_type(&self) -> &'a IRType<'a> { + pub fn get_type(&self) -> Rc { return match &self.kind { - IRValueRefKind::Val(v) => v.t, - IRValueRefKind::Ptr(t, _) => return *t, - IRValueRefKind::Global(t, _) => return *t + IRValueRefKind::Val(v) => v.t.clone(), + IRValueRefKind::Ptr(t, _) => return t.clone(), + IRValueRefKind::Global(t, _) => return t.clone() } } - pub fn as_pointer(&self) -> PositionlessResult> { + pub fn as_pointer(&self) -> PositionlessResult { match &self.kind { IRValueRefKind::Ptr(t, ptr) => return Ok(ptr.clone()), _ => return Err(PositionlessError::new("Cannot cast said value reference as a pointer!")) }; } - pub fn obtain_pointer(&self, ctx: &'a IRContext<'a>) -> PositionlessResult> { + pub fn obtain_pointer(&self, ctx: &IRContext) -> PositionlessResult { match &self.kind { - IRValueRefKind::Ptr(_, ptr) => return Ok(ptr.inkwell_ptr), + IRValueRefKind::Ptr(_, ptr) => return Ok(OwnedPointerValue::new(&ctx.inkwell_ctx, ptr.inkwell_ptr)), IRValueRefKind::Val(v) => { - let ptr = IRPointer::create(&ctx, String::from("_val_toptr"), v.t, Some(IRValueRef::from_val(IRValue::clone(v))))?; + let ptr = IRPointer::create(&ctx, String::from("_val_toptr"), v.t.clone(), Some(IRValueRef::from_val(IRValue::clone(v))))?; - return Ok(ptr.inkwell_ptr); + return Ok(OwnedPointerValue::new(&ctx.inkwell_ctx, ptr.inkwell_ptr)); } IRValueRefKind::Global(_, g) => { if g.is_compiletime_replaceable() { - return Ok(g.as_val()?.into_pointer_value()) + return Ok(OwnedPointerValue::new(&ctx.inkwell_ctx, g.as_val()?.into_pointer_value())) } - return Ok(g.as_string_ref()?.as_pointer_value()); + return Ok(OwnedPointerValue::new(&ctx.inkwell_ctx, g.as_string_ref()?.as_pointer_value())); } } } diff --git a/ir/src/types/storage.rs b/ir/src/types/storage.rs index 45de7cc..f0817da 100644 --- a/ir/src/types/storage.rs +++ b/ir/src/types/storage.rs @@ -1,42 +1,53 @@ //! Type storage +use std::{cell::Ref, mem::transmute, ops::Add, rc::Rc}; + use commons::utils::map::HashedMap; -use inkwell::{AddressSpace, context::Context}; +use inkwell::{AddressSpace, context::Context, types::{IntType, PointerType}}; -use crate::types::{BOOL_TYPE_HASH, POINTER_TYPE_HASH, SIGNED8_TYPE_HASH, SIGNED16_TYPE_HASH, SIGNED32_TYPE_HASH, SIGNED64_TYPE_HASH, SIGNED128_TYPE_HASH, UNSIGNED8_TYPE_HASH, UNSIGNED16_TYPE_HASH, UNSIGNED32_TYPE_HASH, UNSIGNED64_TYPE_HASH, UNSIGNED128_TYPE_HASH, typing::IRType}; +use crate::{ctx::IRContext, types::{BOOL_TYPE_HASH, POINTER_TYPE_HASH, SIGNED8_TYPE_HASH, SIGNED16_TYPE_HASH, SIGNED32_TYPE_HASH, SIGNED64_TYPE_HASH, SIGNED128_TYPE_HASH, UNSIGNED8_TYPE_HASH, UNSIGNED16_TYPE_HASH, UNSIGNED32_TYPE_HASH, UNSIGNED64_TYPE_HASH, UNSIGNED128_TYPE_HASH, typing::{IRType, OwnedIntType, OwnedPointerType}}}; -pub struct IRTypeStorage<'a> { - map: HashedMap> +pub struct IRTypeStorage { + map: HashedMap> } -impl<'a> IRTypeStorage<'a> { - pub fn new(ctx: &'a Context) -> Self { +impl IRTypeStorage { + pub fn new(ctx: &IRContext) -> Self { let mut sto = IRTypeStorage {map: HashedMap::new(12)}; // 12 primitive types - sto.insert(UNSIGNED8_TYPE_HASH, IRType::Unsigned8(ctx.i8_type())); - sto.insert(UNSIGNED16_TYPE_HASH, IRType::Unsigned16(ctx.i16_type())); - sto.insert(UNSIGNED32_TYPE_HASH, IRType::Unsigned32(ctx.i32_type())); - sto.insert(UNSIGNED64_TYPE_HASH, IRType::Unsigned64(ctx.i64_type())); - sto.insert(UNSIGNED128_TYPE_HASH, IRType::Unsigned128(ctx.i128_type())); + let int8 = unsafe { transmute::>(ctx.inkwell_ctx.i8_type())}; + let int16 = unsafe { transmute::>(ctx.inkwell_ctx.i16_type())}; + let int32 = unsafe { transmute::>(ctx.inkwell_ctx.i32_type())}; + let int64 = unsafe { transmute::>(ctx.inkwell_ctx.i64_type())}; + let int128 = unsafe { transmute::>(ctx.inkwell_ctx.i128_type())}; + + let ptr = unsafe { transmute::>(ctx.inkwell_ctx.ptr_type(AddressSpace::from(0))) }; + let bool = unsafe { transmute::>(ctx.inkwell_ctx.bool_type()) }; + + sto.insert(UNSIGNED8_TYPE_HASH, IRType::Unsigned8(OwnedIntType::new_ref(&ctx.inkwell_ctx, &int8))); + sto.insert(UNSIGNED16_TYPE_HASH, IRType::Unsigned16(OwnedIntType::new(&ctx.inkwell_ctx, int16))); + sto.insert(UNSIGNED32_TYPE_HASH, IRType::Unsigned32(OwnedIntType::new(&ctx.inkwell_ctx, int32))); + sto.insert(UNSIGNED64_TYPE_HASH, IRType::Unsigned64(OwnedIntType::new(&ctx.inkwell_ctx, int64))); + sto.insert(UNSIGNED128_TYPE_HASH, IRType::Unsigned128(OwnedIntType::new(&ctx.inkwell_ctx, int128))); - sto.insert(SIGNED8_TYPE_HASH, IRType::Signed8(ctx.i8_type())); - sto.insert(SIGNED16_TYPE_HASH, IRType::Signed16(ctx.i16_type())); - sto.insert(SIGNED32_TYPE_HASH, IRType::Signed32(ctx.i32_type())); - sto.insert(SIGNED64_TYPE_HASH, IRType::Signed64(ctx.i64_type())); - sto.insert(SIGNED128_TYPE_HASH, IRType::Signed128(ctx.i128_type())); + sto.insert(SIGNED8_TYPE_HASH, IRType::Signed8(OwnedIntType::new_ref(&ctx.inkwell_ctx, &int8))); + sto.insert(SIGNED16_TYPE_HASH, IRType::Signed16(OwnedIntType::new(&ctx.inkwell_ctx, int16))); + sto.insert(SIGNED32_TYPE_HASH, IRType::Signed32(OwnedIntType::new(&ctx.inkwell_ctx, int32))); + sto.insert(SIGNED64_TYPE_HASH, IRType::Signed64(OwnedIntType::new(&ctx.inkwell_ctx, int64))); + sto.insert(SIGNED128_TYPE_HASH, IRType::Signed128(OwnedIntType::new(&ctx.inkwell_ctx, int128))); - sto.insert(POINTER_TYPE_HASH, IRType::Pointer(ctx.ptr_type(AddressSpace::from(0u16)))); + sto.insert(POINTER_TYPE_HASH, IRType::Pointer(OwnedPointerType::new(&ctx.inkwell_ctx, ptr))); - sto.insert(BOOL_TYPE_HASH, IRType::Bool(ctx.bool_type())); + sto.insert(BOOL_TYPE_HASH, IRType::Bool(OwnedIntType::new(&ctx.inkwell_ctx, bool))); return sto; } - pub fn insert(&mut self, hash: u64, t: IRType<'a>) { - self.map.put(hash, t); + pub fn insert(&mut self, hash: u64, t: IRType) { + self.map.put(hash, Rc::new(t)); } - pub fn get(&self, hash: u64) -> Option<&IRType<'a>> { - return self.map.get(hash); + pub fn get(&self, hash: u64) -> Option> { + return self.map.get(hash).cloned(); } } \ No newline at end of file diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index 43d6461..f8c783d 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -1,35 +1,47 @@ //! IR Type structures -use std::{cell::Ref, collections::HashMap, ops::Add}; +use std::{cell::Ref, collections::HashMap, mem::transmute, ops::Add, rc::Rc}; use commons::err::{PositionlessError, PositionlessResult}; -use inkwell::{AddressSpace, builder::Builder, context::Context, types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, IntType, PointerType, StringRadix}, values::PointerValue}; +use inkwell::{AddressSpace, builder::Builder, context::Context, types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, IntType, PointerType, StringRadix}, values::{BasicValueEnum, GlobalValue, IntValue, PointerValue}}; -use crate::{ctx::IRContext, irstruct::structs::IRStructuredType, values::IRValue}; +use crate::{ctx::IRContext, irstruct::structs::IRStructuredType, utils::OwnedType, values::IRValue}; + +pub type OwnedIntType = OwnedType>; +pub type OwnedPointerType = OwnedType>; +pub type OwnedTypeEnum = OwnedType>; +pub type OwnedMetadataTypeEnum = OwnedType>; + +pub type OwnedValueEnum = OwnedType>; +pub type OwnedIntValue = OwnedType>; +pub type OwnedPointerValue = OwnedType>; + +pub type OwnedGlobalValue = OwnedType>; /// Types of IR variables -pub enum IRType<'a> { - Signed8(IntType<'a>), - Signed16(IntType<'a>), - Signed32(IntType<'a>), - Signed64(IntType<'a>), - Signed128(IntType<'a>), - - Unsigned8(IntType<'a>), - Unsigned16(IntType<'a>), - Unsigned32(IntType<'a>), - Unsigned64(IntType<'a>), - Unsigned128(IntType<'a>), - - Pointer(PointerType<'a>), - - Bool(IntType<'a>), +#[derive(Clone)] +pub enum IRType { + Signed8(OwnedIntType), + Signed16(OwnedIntType), + Signed32(OwnedIntType), + Signed64(OwnedIntType), + Signed128(OwnedIntType), + + Unsigned8(OwnedIntType), + Unsigned16(OwnedIntType), + Unsigned32(OwnedIntType), + Unsigned64(OwnedIntType), + Unsigned128(OwnedIntType), + + Pointer(OwnedPointerType), + + Bool(OwnedIntType), - Struct(IRStructuredType<'a>), - Layout(IRStructuredType<'a>) + Struct(Rc), + Layout(Rc) } -impl<'a> IRType<'a> { +impl IRType { /// Gets the size in bits of a given IR element pub fn get_bitsize(&self) -> usize { match self { @@ -110,58 +122,58 @@ impl<'a> IRType<'a> { return -2_i128.pow(self.get_bitsize() as u32) - 1; } - pub fn get_inkwell_basetype(&self) -> PositionlessResult> { + pub fn get_inkwell_basetype(&self) -> PositionlessResult { match self { - IRType::Unsigned8(v) => Ok(BasicTypeEnum::from(*v)), - IRType::Unsigned16(v) => Ok(BasicTypeEnum::from(*v)), - IRType::Unsigned32(v) => Ok(BasicTypeEnum::from(*v)), - IRType::Unsigned64(v) => Ok(BasicTypeEnum::from(*v)), - IRType::Unsigned128(v) => Ok(BasicTypeEnum::from(*v)), - IRType::Signed8(v) => Ok(BasicTypeEnum::from(*v)), - IRType::Signed16(v) => Ok(BasicTypeEnum::from(*v)), - IRType::Signed32(v) => Ok(BasicTypeEnum::from(*v)), - IRType::Signed64(v) => Ok(BasicTypeEnum::from(*v)), - IRType::Signed128(v) => Ok(BasicTypeEnum::from(*v)), - - IRType::Pointer(v) => Ok(BasicTypeEnum::from(*v)), - - IRType::Struct(a) => Ok(BasicTypeEnum::from(a.inkwell_type)), - IRType::Layout(a) => Ok(BasicTypeEnum::from(a.inkwell_type)), + IRType::Unsigned8(v) => Ok(OwnedTypeEnum::new(&v.owned, BasicTypeEnum::from(v.inner))), + IRType::Unsigned16(v) => Ok(OwnedTypeEnum::new(&v.owned, BasicTypeEnum::from(v.inner))), + IRType::Unsigned32(v) => Ok(OwnedTypeEnum::new(&v.owned, BasicTypeEnum::from(v.inner))), + IRType::Unsigned64(v) => Ok(OwnedTypeEnum::new(&v.owned, BasicTypeEnum::from(v.inner))), + IRType::Unsigned128(v) => Ok(OwnedTypeEnum::new(&v.owned, BasicTypeEnum::from(v.inner))), + IRType::Signed8(v) => Ok(OwnedTypeEnum::new(&v.owned, BasicTypeEnum::from(v.inner))), + IRType::Signed16(v) => Ok(OwnedTypeEnum::new(&v.owned, BasicTypeEnum::from(v.inner))), + IRType::Signed32(v) => Ok(OwnedTypeEnum::new(&v.owned, BasicTypeEnum::from(v.inner))), + IRType::Signed64(v) => Ok(OwnedTypeEnum::new(&v.owned, BasicTypeEnum::from(v.inner))), + IRType::Signed128(v) => Ok(OwnedTypeEnum::new(&v.owned, BasicTypeEnum::from(v.inner))), + + IRType::Pointer(v) => Ok(OwnedTypeEnum::new(&v.owned, BasicTypeEnum::from(v.inner))), + + IRType::Struct(a) => Ok(OwnedTypeEnum::new(&a.owned, BasicTypeEnum::from(a.inkwell_type))), + IRType::Layout(a) => Ok(OwnedTypeEnum::new(&a.owned, BasicTypeEnum::from(a.inkwell_type))), _ => Err(PositionlessError::new("Given IR type doesn't have any Inkwell type!!!")) } } - pub fn get_inkwell_instance_basetype(&self, ctx: &'a IRContext<'a>) -> PositionlessResult> { + pub fn get_inkwell_instance_basetype(&self, ctx: &IRContext) -> PositionlessResult { match self { - IRType::Struct(_) | IRType::Layout(_) => Ok(ctx.ptr_type.into()), + IRType::Struct(_) | IRType::Layout(_) => Ok(OwnedTypeEnum::new(&ctx.inkwell_ctx, ctx.ptr_type.into())), _ => self.get_inkwell_basetype() } } - pub fn get_inkwell_base_metadatatype(&self) -> PositionlessResult> { + pub fn get_inkwell_base_metadatatype(&self) -> PositionlessResult { match self { - IRType::Unsigned8(v) => Ok(BasicMetadataTypeEnum::from(*v)), - IRType::Unsigned16(v) => Ok(BasicMetadataTypeEnum::from(*v)), - IRType::Unsigned32(v) => Ok(BasicMetadataTypeEnum::from(*v)), - IRType::Unsigned64(v) => Ok(BasicMetadataTypeEnum::from(*v)), - IRType::Unsigned128(v) => Ok(BasicMetadataTypeEnum::from(*v)), - IRType::Signed8(v) => Ok(BasicMetadataTypeEnum::from(*v)), - IRType::Signed16(v) => Ok(BasicMetadataTypeEnum::from(*v)), - IRType::Signed32(v) => Ok(BasicMetadataTypeEnum::from(*v)), - IRType::Signed64(v) => Ok(BasicMetadataTypeEnum::from(*v)), - IRType::Signed128(v) => Ok(BasicMetadataTypeEnum::from(*v)), - - IRType::Pointer(v) => Ok(BasicMetadataTypeEnum::from(*v)), - - IRType::Struct(a) => Ok(BasicMetadataTypeEnum::from(a.inkwell_type)), - IRType::Layout(a) => Ok(BasicMetadataTypeEnum::from(a.inkwell_type)), + IRType::Unsigned8(v) => Ok(OwnedMetadataTypeEnum::new(&v.owned, BasicMetadataTypeEnum::from(v.inner))), + IRType::Unsigned16(v) => Ok(OwnedMetadataTypeEnum::new(&v.owned, BasicMetadataTypeEnum::from(v.inner))), + IRType::Unsigned32(v) => Ok(OwnedMetadataTypeEnum::new(&v.owned, BasicMetadataTypeEnum::from(v.inner))), + IRType::Unsigned64(v) => Ok(OwnedMetadataTypeEnum::new(&v.owned, BasicMetadataTypeEnum::from(v.inner))), + IRType::Unsigned128(v) => Ok(OwnedMetadataTypeEnum::new(&v.owned, BasicMetadataTypeEnum::from(v.inner))), + IRType::Signed8(v) => Ok(OwnedMetadataTypeEnum::new(&v.owned, BasicMetadataTypeEnum::from(v.inner))), + IRType::Signed16(v) => Ok(OwnedMetadataTypeEnum::new(&v.owned, BasicMetadataTypeEnum::from(v.inner))), + IRType::Signed32(v) => Ok(OwnedMetadataTypeEnum::new(&v.owned, BasicMetadataTypeEnum::from(v.inner))), + IRType::Signed64(v) => Ok(OwnedMetadataTypeEnum::new(&v.owned, BasicMetadataTypeEnum::from(v.inner))), + IRType::Signed128(v) => Ok(OwnedMetadataTypeEnum::new(&v.owned, BasicMetadataTypeEnum::from(v.inner))), + + IRType::Pointer(v) => Ok(OwnedMetadataTypeEnum::new(&v.owned, BasicMetadataTypeEnum::from(v.inner))), + + IRType::Struct(a) => Ok(OwnedMetadataTypeEnum::new(&a.owned, BasicMetadataTypeEnum::from(a.inkwell_type))), + IRType::Layout(a) => Ok(OwnedMetadataTypeEnum::new(&a.owned, BasicMetadataTypeEnum::from(a.inkwell_type))), _ => Err(PositionlessError::new("Given IR type doesn't have any Inkwell type!!!")) } } - pub fn get_inkwell_inttype(&self) -> PositionlessResult<&IntType<'a>> { + pub fn get_inkwell_inttype(&self) -> PositionlessResult<&OwnedIntType> { match self { IRType::Unsigned8(v) => Ok(v), IRType::Unsigned16(v) => Ok(v), @@ -178,32 +190,13 @@ impl<'a> IRType<'a> { } } - pub fn get_inkwell_pointertype(ctx: &'a Context) -> PointerType<'a> { - return ctx.ptr_type(AddressSpace::from(0u16)); - } - - pub fn make_numeric_stackvar(&self, builder: &Builder<'a>, name: String, initial_val: IRValue<'a>) -> PositionlessResult> { - let t = *self.get_inkwell_inttype()?; - let alloca = match builder.build_alloca(t, &name) { - Ok(v) => v, - Err(_) => return Err(PositionlessError::new("build_alloca failed!!")) - }; - - let val = match initial_val.obtain_as_int(self) { - Some(v) => v, - None => return Err(PositionlessError::new("Value is incompatible with type!")) - }; - - if builder.build_store(alloca, val).is_err() { - return Err(PositionlessError::new("build_store failed!!")); - } - - return Ok(alloca); + pub fn get_inkwell_pointertype(ctx: &IRContext) -> OwnedPointerType { + return OwnedPointerType::new(&ctx.inkwell_ctx, ctx.ptr_type); } /// Checks if the given type instance is the same type as the given one without having to use `PartialEq` - pub fn is_same(&'a self, t: &'a IRType<'a>) -> bool { - return match(self, t) { + pub fn is_same(&self, t: &Rc) -> bool { + return match(self, t.as_ref()) { (IRType::Signed8(_), IRType::Signed8(_)) => true, (IRType::Signed16(_), IRType::Signed16(_)) => true, (IRType::Signed32(_), IRType::Signed32(_)) => true, @@ -225,15 +218,15 @@ impl<'a> IRType<'a> { } } - pub fn get_structured_type_descriptor(&'a self) -> PositionlessResult<&'a IRStructuredType<'a>> { + pub fn get_structured_type_descriptor(&self) -> PositionlessResult> { return match self { - IRType::Struct(e) => Ok(e), - IRType::Layout(e) => Ok(e), + IRType::Struct(e) => Ok(e.clone()), + IRType::Layout(e) => Ok(e.clone()), _ => Err(PositionlessError::new("Given IRType doesn't have a structured type descriptor!")) } } - pub fn has_structured_type_descriptor(&'a self) -> bool { + pub fn has_structured_type_descriptor(&self) -> bool { return match self { IRType::Struct(_) | IRType::Layout(_) => true, _ => false diff --git a/ir/src/utils.rs b/ir/src/utils.rs new file mode 100644 index 0000000..b294c28 --- /dev/null +++ b/ir/src/utils.rs @@ -0,0 +1,58 @@ +//! Codebase wide utilities. Are mostly used to escape the Inkwell lifecycle hell + +use std::{mem::transmute, ops::Deref, rc::Rc}; + +use inkwell::context::Context; + +/// A type containing a counted reference to the Inkwell context. +/// This allows for the type to have the 'static lifecycle safely, allowing to safely use without annoying lifecycles. +#[derive(Clone)] +pub struct OwnedType { + pub inner: T, + pub owned: Rc +} + +impl OwnedType { + pub fn new(ctx: &Rc, inner: K) -> Self { + return OwnedType { inner: unsafe { transmute(inner)} , owned: ctx.clone() } + } + + pub fn new_ref(ctx: &Rc, inner: &K) -> Self { + return OwnedType { inner: unsafe { transmute(K::clone(inner)) }, owned: ctx.clone() } + } + + pub fn new_ownership(ctx: Rc, inner: K) -> Self { + return OwnedType { inner: unsafe {transmute(inner) }, owned: ctx } + } +} + +impl Deref for OwnedType { + type Target = T; + + fn deref(&self) -> &Self::Target { + return &self.inner; + } +} + +/// Warning: unsafe temporary struct +pub struct LateInit { + inner: Option +} + +impl Deref for LateInit { + type Target = K; + + fn deref(&self) -> &Self::Target { + return &self.inner.as_ref().unwrap(); + } +} + +impl LateInit { + pub fn new() -> Self { + return LateInit { inner: None }; + } + + pub fn fill(&mut self, inner: K) { + self.inner = Some(inner); + } +} \ No newline at end of file diff --git a/ir/src/values.rs b/ir/src/values.rs index b4f3ab6..ec58bd3 100644 --- a/ir/src/values.rs +++ b/ir/src/values.rs @@ -1,28 +1,28 @@ //! IR value representation definitons -use std::cell::{Ref, RefCell}; +use std::{cell::{Ref, RefCell}, rc::Rc}; use commons::{err::{PositionlessError, PositionlessResult}}; use inkwell::{types::StringRadix, values::{BasicValueEnum, IntValue}}; -use crate::{irstruct::ptr::IRPointer, types::typing::IRType}; +use crate::{ctx::IRContext, irstruct::ptr::IRPointer, types::typing::{IRType, OwnedIntType, OwnedIntValue, OwnedValueEnum}}; /// The new IR value system. Allows for a close interaction with inkwell rather than a more AST-side one. /// # Safety /// IRValue enforces a strict typing system for values. An instance of `IRType` is required for every gather and will fail if the provided type isn't the variable's. #[derive(Clone)] -pub struct IRValue<'a> { - inkwell_val: BasicValueEnum<'a>, - pub t: IRType<'a>, +pub struct IRValue { + inkwell_val: OwnedValueEnum, + pub t: Rc, } -impl<'a> IRValue<'a> { +impl IRValue { /// Creates a new untracked instance - pub fn new(inkwell_val: BasicValueEnum<'a>, t: &IRType<'a>) -> Self { + pub fn new(inkwell_val: OwnedValueEnum, t: Rc) -> Self { return IRValue { inkwell_val, t: t.clone() } } - pub fn from_unsigned(t: &'a IRType<'a>, v: u128) -> PositionlessResult { + pub fn from_unsigned(ctx: &IRContext, t: Rc, v: u128) -> PositionlessResult { if !t.is_numeric_type() || t.is_signed() { return Err(PositionlessError::new("The given type cannot be applied to make an unsigned!")); } @@ -33,10 +33,10 @@ impl<'a> IRValue<'a> { None => return Err(PositionlessError::new("const_int_from_string failed!")) }; - return Ok(IRValue::new(val.into(), t)) + return Ok(IRValue::new(OwnedValueEnum::new(&ctx.inkwell_ctx, val.into()), t)); } - pub fn from_signed(t: &'a IRType<'a>, v: i128) -> PositionlessResult { + pub fn from_signed(ctx: &IRContext, t: Rc, v: i128) -> PositionlessResult { if !t.is_numeric_type() || !t.is_signed() { return Err(PositionlessError::new("The given type cannot be applied to make a signed!")); } @@ -47,36 +47,36 @@ impl<'a> IRValue<'a> { None => return Err(PositionlessError::new("const_int_from_string failed!")) }; - return Ok(IRValue::new(val.into(), t)) + return Ok(IRValue::new(OwnedValueEnum::new(&ctx.inkwell_ctx, val.into()), t)); } - pub fn from_bool(val: bool, t: &'a IRType<'a>) -> PositionlessResult { - let inkwell_type = match t { + pub fn from_bool(val: bool, ctx: &IRContext, t: Rc) -> PositionlessResult { + let inkwell_type = match t.as_ref() { IRType::Bool(ty) => ty, _ => return Err(PositionlessError::new("from_bool got fed a non-boolean IRType instance! t != IRType::Bool!")) }; - return Ok(IRValue::new(inkwell_type.const_int(val as u64, false).into(), t)) + return Ok(IRValue::new(OwnedValueEnum::new(&ctx.inkwell_ctx, inkwell_type.const_int(val as u64, false).into()),t)); } /// Typeless obtain. Can be considered as an unsafe handle. Doesn't perform type checking - pub fn obtain(&self) -> BasicValueEnum<'a> { - return self.inkwell_val; + pub fn obtain(&self) -> OwnedValueEnum { + return self.inkwell_val.clone(); } /// Obtains the value as an integer value. Returns None if the value is incompatible with integers - pub fn obtain_as_int(&self, t: &'a IRType<'a>) -> Option> { - if !self.t.is_numeric_type() || !self.t.is_same(t) { + pub fn obtain_as_int(&self, ctx: &IRContext, t: Rc) -> Option { + if !self.t.is_numeric_type() || !self.t.is_same(&t) { return None; } - return Some(self.inkwell_val.into_int_value()); + return Some(OwnedIntValue::new(&ctx.inkwell_ctx, self.inkwell_val.into_int_value())); } /// Obtains the value as an bool value. Returns None if the value is incompatible with booleans - pub fn obtain_as_bool(&self) -> Option> { - return match self.t { - IRType::Bool(_) => Some(self.inkwell_val.into_int_value()), + pub fn obtain_as_bool(&self) -> Option { + return match self.t.as_ref() { + IRType::Bool(v) => Some(OwnedIntValue::new(&v.owned, self.inkwell_val.into_int_value())), _ => None } } diff --git a/test-main/src/main.rs b/test-main/src/main.rs index 7b702c2..6cc014c 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -1,5 +1,5 @@ use core::fmt; -use std::{env, hash::{DefaultHasher, Hash, Hasher}}; +use std::{env, hash::{DefaultHasher, Hash, Hasher}, rc::Rc}; use inkwell::{context::Context, module::Module}; use ir::{ctx::IRContext, irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable, structs::IRStructuredType}, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::IRValue}; @@ -16,48 +16,43 @@ fn main() { println!("{:#?}", ctx); - let context = Context::create(); - - let mut storage = IRTypeStorage::new(&context); - - let module= context.create_module("main_module"); - let builder = context.create_builder(); - - let irctx = IRContext::new(builder, &context); + let context = Rc::new(Context::create()); + + let irctx = IRContext::new(context); - let t = storage.get(UNSIGNED32_TYPE_HASH).unwrap(); - let int_type = storage.get(SIGNED32_TYPE_HASH).unwrap(); - let ptr_type = storage.get(POINTER_TYPE_HASH).unwrap(); + let t = irctx.type_storage.get(UNSIGNED32_TYPE_HASH).unwrap(); + let int_type = irctx.type_storage.get(SIGNED32_TYPE_HASH).unwrap(); + let ptr_type = irctx.type_storage.get(POINTER_TYPE_HASH).unwrap(); - let printf_func = IRFunction::create_shadow(&irctx, String::from("printf"), &module, Some(int_type), vec![ptr_type]).unwrap(); + let printf_func = IRFunction::create_shadow(&irctx, String::from("printf"), &irctx.module, Some(int_type.clone()), vec![ptr_type]).unwrap(); - let sample_substruct = IRType::Struct( - IRStructuredType::new(&irctx, String::from("uwuStruct"), true, vec![(8417845746417243860, int_type)]).unwrap() - ); + let sample_substruct = Rc::new(IRType::Struct( + Rc::new(IRStructuredType::new(&irctx, String::from("uwuStruct"), true, vec![(8417845746417243860, int_type.clone())]).unwrap()) + )); - let sample_struct = IRType::Struct( - IRStructuredType::new(&irctx, String::from("myTestStruct"), true, vec![(8417845746417243860, &sample_substruct)]).unwrap() - ); + let sample_struct = Rc::new(IRType::Struct( + Rc::new(IRStructuredType::new(&irctx, String::from("myTestStruct"), true, vec![(8417845746417243860, sample_substruct.clone())]).unwrap()) + )); //storage.insert(15869126390205824132, sample_struct); - let i32_type = context.i32_type(); + let i32_type = irctx.inkwell_ctx.i32_type(); - let func = IRFunction::create(&irctx, String::from("main"), &module, Some(t), vec![t, t]).expect("Couldn't make IR function"); - func.prepare_body_filling(&irctx.builder); + let func = IRFunction::create(&irctx, String::from("main"), &irctx.module, Some(t.clone()), vec![t.clone(), t.clone()]).expect("Couldn't make IR function"); + func.prepare_body_filling(&irctx); - let fmt_str = IRStaticVariable::from_str(&irctx.builder, "Haiiiii, the value is %d\n", String::from("fmt_str"), int_type).unwrap(); + let fmt_str = IRStaticVariable::from_str(&irctx, "Haiiiii, the value is %d\n", String::from("fmt_str"), int_type.clone()).unwrap(); //let fmt_str = &irctx.builder.build_global_string_ptr("Haiiiii, the value is %d\n", "fmt_str").unwrap(); // Struct test - let structInstance = IRPointer::create(&irctx, String::from("test"), &sample_struct, None).unwrap(); + let structInstance = IRPointer::create(&irctx, String::from("test"), sample_struct.clone(), None).unwrap(); let subStructPtr = sample_struct.get_structured_type_descriptor().unwrap().get_pointer_for_field_index(&irctx, &structInstance, 0).unwrap(); - let subStructVarPtr = sample_substruct.get_structured_type_descriptor().unwrap().get_pointer_for_field_index(&irctx, &subStructPtr, 0).unwrap(); + let subStructVarPtr = sample_substruct.clone().get_structured_type_descriptor().unwrap().get_pointer_for_field_index(&irctx, &subStructPtr, 0).unwrap(); - subStructVarPtr.store(&irctx.builder, int_type.get_inkwell_inttype().unwrap().const_int(1288, false)); + subStructVarPtr.store(&irctx, int_type.clone().get_inkwell_inttype().unwrap().const_int(1288, false).into()); let val = subStructVarPtr.load(&irctx, int_type).unwrap().obtain(); @@ -65,10 +60,10 @@ fn main() { // End struct test - printf_func.call(&irctx, vec![IRValueRef::from_static(fmt_str), IRValueRef::from_pointer(structInstance)], false); + printf_func.call(&irctx, vec![IRValueRef::from_static(Rc::new(fmt_str)), IRValueRef::from_pointer(structInstance)], true); irctx.builder.build_return(Some(&i32_type.const_zero())); - module.print_to_file("output.ll").unwrap(); + irctx.module.print_to_file("output.ll").unwrap(); }