From 397ea0787019f3f8c468dda9c0ddc78327d52ab4 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Thu, 12 Feb 2026 00:37:29 +0100 Subject: [PATCH 01/54] feat: added IR value class --- commons/src/utils/mod.rs | 3 ++- commons/src/utils/num.rs | 19 ++++++++++++++ ir/src/lib.rs | 3 ++- ir/src/types/typing.rs | 3 ++- ir/src/values.rs | 56 ++++++++++++++++++++++++++++++++++++++++ parser/src/ast/tree.rs | 2 -- 6 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 commons/src/utils/num.rs create mode 100644 ir/src/values.rs diff --git a/commons/src/utils/mod.rs b/commons/src/utils/mod.rs index 36c02b6..7b7c82b 100644 --- a/commons/src/utils/mod.rs +++ b/commons/src/utils/mod.rs @@ -1 +1,2 @@ -pub mod map; \ No newline at end of file +pub mod map; +pub mod num; \ No newline at end of file diff --git a/commons/src/utils/num.rs b/commons/src/utils/num.rs new file mode 100644 index 0000000..f819531 --- /dev/null +++ b/commons/src/utils/num.rs @@ -0,0 +1,19 @@ +pub fn get_signed_highbound(bits: usize) -> i128 { + return 2_i128.pow(bits as u32 - 1) - 1; +} + +pub fn get_signed_lowbound(bits: usize) -> i128 { + return 0 - 2_i128.pow(bits as u32 - 1) - 1; +} + +pub fn get_unsigned_highbound(bits: usize) -> i128 { + return 2_i128.pow(bits as u32) - 1; +} + +pub fn can_num_fit_inbits_signed(bits: usize, num: i128) -> bool { + return num >= get_signed_lowbound(bits) && num <= get_signed_highbound(bits); +} + +pub fn can_num_fit_inbits_unsigned(bits: usize, num: i128) -> bool { + return num >= 0 && num <= get_unsigned_highbound(bits); +} diff --git a/ir/src/lib.rs b/ir/src/lib.rs index a82af7b..ebc5185 100644 --- a/ir/src/lib.rs +++ b/ir/src/lib.rs @@ -1,4 +1,5 @@ //! Quickfall's Intermediate Representation code. Converts the AST into instruction like nodes to pass down to compilation. -pub mod types; \ No newline at end of file +pub mod types; +pub mod values; \ No newline at end of file diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index 43bdb5d..43dc28e 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -24,7 +24,7 @@ pub enum IRType<'a> { Layout(HashMap>>) // fields } -impl IRType<'_> { +impl<'a> IRType<'a> { /// Gets the size in bits of a given IR element pub fn get_bitsize(&self) -> usize { match self { @@ -103,4 +103,5 @@ impl IRType<'_> { return -2_i128.pow(self.get_bitsize() as u32) - 1; } + } \ No newline at end of file diff --git a/ir/src/values.rs b/ir/src/values.rs new file mode 100644 index 0000000..265d8cb --- /dev/null +++ b/ir/src/values.rs @@ -0,0 +1,56 @@ +//! IR value representation definitons + +use std::collections::HashMap; + +use commons::utils::num::{can_num_fit_inbits_signed, can_num_fit_inbits_unsigned}; + +pub enum IRValue { + Signed8(i8), + Signed16(i16), + Signed32(i32), + Signed64(i64), + Signed128(i128), + + Unsigned8(u8), + Unsigned16(u16), + Unsigned32(u32), + Unsigned64(u64), + Unsigned128(u128), + + Bool(bool), + + Struct(HashMap), + Layout(HashMap) +} + +impl IRValue { + pub fn make_signed(sz: usize, val: i128) -> Option { + if !can_num_fit_inbits_signed(sz, val) { + return None; + } + + match sz { + 8 => return Some(IRValue::Signed8(val as i8)), + 16 => return Some(IRValue::Signed16(val as i16)), + 32 => return Some(IRValue::Signed32(val as i32)), + 64 => return Some(IRValue::Signed64(val as i64)), + 128 => return Some(IRValue::Signed128(val as i128)), + _ => return None + } + } + + pub fn make_unsigned(sz: usize, val: i128) -> Option { + if !can_num_fit_inbits_unsigned(sz, val) { + return None; + } + + match sz { + 8 => return Some(IRValue::Unsigned8(val as u8)), + 16 => return Some(IRValue::Unsigned16(val as u16)), + 32 => return Some(IRValue::Unsigned32(val as u32)), + 64 => return Some(IRValue::Unsigned64(val as u64)), + 128 => return Some(IRValue::Unsigned128(val as u128)), + _ => return None + } + } +} \ No newline at end of file diff --git a/parser/src/ast/tree.rs b/parser/src/ast/tree.rs index 804577d..1fe5713 100644 --- a/parser/src/ast/tree.rs +++ b/parser/src/ast/tree.rs @@ -5,8 +5,6 @@ use lexer::toks::{comp::ComparingOperator, math::MathOperator}; use utils::hash::{TypeHash, WithHash}; -use crate::ast::func; - #[derive(Debug, PartialEq, Clone)] pub struct FunctionDeclarationArgument { pub name: WithHash, From 6dd2788d58299feebae014ef54e5d892c67f6530 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Thu, 12 Feb 2026 00:44:50 +0100 Subject: [PATCH 02/54] feat: added positionless errors --- commons/src/err/mod.rs | 25 +++++++++++++++++++++++++ ir/src/lib.rs | 2 +- ir/src/values.rs | 9 +++++++-- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/commons/src/err/mod.rs b/commons/src/err/mod.rs index 4777486..33570a6 100644 --- a/commons/src/err/mod.rs +++ b/commons/src/err/mod.rs @@ -9,6 +9,7 @@ use colored::Colorize; use crate::Position; pub type PositionedResult = Result; +pub type PositionlessResult = Result; /// An error that has a position #[derive(Debug)] @@ -18,6 +19,20 @@ pub struct PositionedError { pub reason: String } +pub struct PositionlessError { + pub reason: String +} + +impl PositionlessError { + pub fn new(reason: String) -> Self { + let err = PositionlessError { reason }; + + println!("{}", err); + + return err; + } +} + impl PositionedError { pub fn new(start: Position, end: Position, reason: String) -> Self { @@ -48,6 +63,16 @@ impl fmt::Display for PositionedError { writeln!(f, "")?; writeln!(f, "{}", self.reason.bright_red())?; + Ok(()) + } +} + +impl fmt::Display for PositionlessError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "{} at ??:??", "ERR".bright_red().bold())?; + + writeln!(f, "{}", self.reason.bright_red())?; + Ok(()) } } \ No newline at end of file diff --git a/ir/src/lib.rs b/ir/src/lib.rs index ebc5185..9fb5bd8 100644 --- a/ir/src/lib.rs +++ b/ir/src/lib.rs @@ -2,4 +2,4 @@ pub mod types; -pub mod values; \ No newline at end of file +pub mod values; diff --git a/ir/src/values.rs b/ir/src/values.rs index 265d8cb..b4e4e75 100644 --- a/ir/src/values.rs +++ b/ir/src/values.rs @@ -19,8 +19,8 @@ pub enum IRValue { Bool(bool), - Struct(HashMap), - Layout(HashMap) + Struct(Vec>, u64), // type hash + Layout(Vec>, u64) // type hash } impl IRValue { @@ -53,4 +53,9 @@ impl IRValue { _ => return None } } + + pub fn make_bool(val: bool) -> IRValue { + return IRValue::Bool(val); + } + } \ No newline at end of file From 3911018257896ade2237c35bf019e584365bb63d Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Thu, 12 Feb 2026 00:50:41 +0100 Subject: [PATCH 03/54] feat: migrated IRValue to PositionlessResult rather than Option --- commons/src/err/mod.rs | 4 ++-- ir/src/values.rs | 34 +++++++++++++++++----------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/commons/src/err/mod.rs b/commons/src/err/mod.rs index 33570a6..416ecf6 100644 --- a/commons/src/err/mod.rs +++ b/commons/src/err/mod.rs @@ -24,8 +24,8 @@ pub struct PositionlessError { } impl PositionlessError { - pub fn new(reason: String) -> Self { - let err = PositionlessError { reason }; + pub fn new(reason: &str) -> Self { + let err = PositionlessError { reason: String::from(reason) }; println!("{}", err); diff --git a/ir/src/values.rs b/ir/src/values.rs index b4e4e75..5bbb27a 100644 --- a/ir/src/values.rs +++ b/ir/src/values.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; -use commons::utils::num::{can_num_fit_inbits_signed, can_num_fit_inbits_unsigned}; +use commons::{err::{PositionedResult, PositionlessError, PositionlessResult}, utils::num::{can_num_fit_inbits_signed, can_num_fit_inbits_unsigned}}; pub enum IRValue { Signed8(i8), @@ -24,33 +24,33 @@ pub enum IRValue { } impl IRValue { - pub fn make_signed(sz: usize, val: i128) -> Option { + pub fn make_signed(sz: usize, val: i128) -> PositionlessResult { if !can_num_fit_inbits_signed(sz, val) { - return None; + return Err(PositionlessError::new(&format!("Cannot fit the given number value {} into {} bits!", val, sz))); } match sz { - 8 => return Some(IRValue::Signed8(val as i8)), - 16 => return Some(IRValue::Signed16(val as i16)), - 32 => return Some(IRValue::Signed32(val as i32)), - 64 => return Some(IRValue::Signed64(val as i64)), - 128 => return Some(IRValue::Signed128(val as i128)), - _ => return None + 8 => return Ok(IRValue::Signed8(val as i8)), + 16 => return Ok(IRValue::Signed16(val as i16)), + 32 => return Ok(IRValue::Signed32(val as i32)), + 64 => return Ok(IRValue::Signed64(val as i64)), + 128 => return Ok(IRValue::Signed128(val as i128)), + _ => return Err(PositionlessError::new(&format!("Invalid bit size! got {}", sz))) } } - pub fn make_unsigned(sz: usize, val: i128) -> Option { + pub fn make_unsigned(sz: usize, val: i128) -> PositionlessResult { if !can_num_fit_inbits_unsigned(sz, val) { - return None; + return Err(PositionlessError::new(&format!("Cannot fit the given number value {} into {} bits!", val, sz))); } match sz { - 8 => return Some(IRValue::Unsigned8(val as u8)), - 16 => return Some(IRValue::Unsigned16(val as u16)), - 32 => return Some(IRValue::Unsigned32(val as u32)), - 64 => return Some(IRValue::Unsigned64(val as u64)), - 128 => return Some(IRValue::Unsigned128(val as u128)), - _ => return None + 8 => return Ok(IRValue::Unsigned8(val as u8)), + 16 => return Ok(IRValue::Unsigned16(val as u16)), + 32 => return Ok(IRValue::Unsigned32(val as u32)), + 64 => return Ok(IRValue::Unsigned64(val as u64)), + 128 => return Ok(IRValue::Unsigned128(val as u128)), + _ => return Err(PositionlessError::new(&format!("Invalid bit size! got {}", sz))) } } From a0c058525ba5192c54dce68cac9d994af99a9074 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Thu, 12 Feb 2026 01:01:24 +0100 Subject: [PATCH 04/54] feat: added expects --- ir/src/values.rs | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/ir/src/values.rs b/ir/src/values.rs index 5bbb27a..8d68d51 100644 --- a/ir/src/values.rs +++ b/ir/src/values.rs @@ -1,9 +1,8 @@ //! IR value representation definitons -use std::collections::HashMap; - -use commons::{err::{PositionedResult, PositionlessError, PositionlessResult}, utils::num::{can_num_fit_inbits_signed, can_num_fit_inbits_unsigned}}; +use commons::{err::{PositionlessError, PositionlessResult}, utils::num::{can_num_fit_inbits_signed, can_num_fit_inbits_unsigned}}; +#[derive(Debug)] pub enum IRValue { Signed8(i8), Signed16(i16), @@ -58,4 +57,43 @@ impl IRValue { return IRValue::Bool(val); } + pub fn expects_numeric_value(&self, sz: usize, signed: bool) -> PositionlessResult { + let val: i128 = match self { + IRValue::Unsigned8(v) => *v as i128, + IRValue::Unsigned16(v) => *v as i128, + IRValue::Unsigned32(v) => *v as i128, + IRValue::Unsigned64(v) => *v as i128, + IRValue::Unsigned128(v) => *v as i128, + + IRValue::Signed8(v) => *v as i128, + IRValue::Signed16(v) => *v as i128, + IRValue::Signed32(v) => *v as i128, + IRValue::Signed64(v) => *v as i128, + IRValue::Signed128(v) => *v as i128, + + _ => return Err(PositionlessError::new(&format!("Expected a numeric value! Got {:#?}", self))) + }; + + if signed { + if !can_num_fit_inbits_signed(sz, val) { + return Err(PositionlessError::new(&format!("Numerical value {} cannot fit in bits!", val))); + } + + return Ok(val); + } + + if !can_num_fit_inbits_unsigned(sz, val) { + return Err(PositionlessError::new(&format!("Numerical value {} cannot fit in bits!", val))); + } + + return Ok(val); + } + + pub fn expects_bool_value(&self) -> PositionlessResult { + match self { + IRValue::Bool(v) => return Ok(*v), + _ => return Err(PositionlessError::new(&format!("Expected a boolean but instead got {:#?}", self))) + } + } + } \ No newline at end of file From 369acf18c37146efafec0b79cfc9588786af2309 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Thu, 12 Feb 2026 01:39:54 +0100 Subject: [PATCH 05/54] feat: started working on the inkwell side of things, sucessfully made the basic int alloc system work, will potentially try to put the inkwell types in a common place if possible --- .gitignore | 3 ++- Cargo.lock | 2 ++ ir/src/types/typing.rs | 43 +++++++++++++++++++++++++++++++++++++++++- test-main/Cargo.toml | 4 +++- test-main/src/main.rs | 37 +++++++++++++++++++++++++++--------- 5 files changed, 77 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 9f97022..8bb58bc 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -target/ \ No newline at end of file +target/ +*.ll \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index f3bf43f..ba27814 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -171,6 +171,8 @@ dependencies = [ name = "test-main" version = "0.1.0" dependencies = [ + "inkwell", + "ir", "lexer", "parser", ] diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index 43dc28e..ae37f58 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -2,7 +2,10 @@ use std::{cell::Ref, collections::HashMap}; -use inkwell::types::IntType; +use commons::err::{PositionlessError, PositionlessResult}; +use inkwell::{builder::{Builder, BuilderError}, types::{IntType, StringRadix}, values::PointerValue}; + +use crate::values::IRValue; /// Types of IR variables pub enum IRType<'a> { @@ -104,4 +107,42 @@ impl<'a> IRType<'a> { return -2_i128.pow(self.get_bitsize() as u32) - 1; } + pub fn get_inkwell_inttype(&self) -> PositionlessResult<&IntType<'a>> { + match self { + IRType::Unsigned8(v) => Ok(v), + IRType::Unsigned16(v) => Ok(v), + IRType::Unsigned32(v) => Ok(v), + IRType::Unsigned64(v) => Ok(v), + IRType::Unsigned128(v) => Ok(v), + IRType::Signed8(v) => Ok(v), + IRType::Signed16(v) => Ok(v), + IRType::Signed32(v) => Ok(v), + IRType::Signed64(v) => Ok(v), + IRType::Signed128(v) => Ok(v), + + _ => return Err(PositionlessError::new("get_inkwell_inttype was used with a non int typed IRType!")) + } + } + + pub fn make_numeric_stackvar(&self, builder: &Builder<'a>, name: String, initial_val: IRValue) -> 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 v = initial_val.expects_numeric_value(self.get_bitsize(), self.is_signed())?; + + let val = match t.const_int_from_string(&v.to_string(), StringRadix::Decimal) { + Some(v) => v, + None => return Err(PositionlessError::new("const_int_from_string failed!!")) + }; + + + if builder.build_store(alloca, val).is_err() { + return Err(PositionlessError::new("build_store failed!!")); + } + + return Ok(alloca); + } } \ No newline at end of file diff --git a/test-main/Cargo.toml b/test-main/Cargo.toml index 3ed57f7..9aae5a2 100644 --- a/test-main/Cargo.toml +++ b/test-main/Cargo.toml @@ -5,4 +5,6 @@ edition = "2024" [dependencies] lexer = { path = "../lexer" } -parser = { path = "../parser" } \ No newline at end of file +parser = { path = "../parser" } +ir = { path = "../ir" } +inkwell = { version = "0.8.0", features = ["llvm21-1"]} diff --git a/test-main/src/main.rs b/test-main/src/main.rs index 8119647..1445472 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -1,16 +1,35 @@ -use std::{env}; - -use lexer::lexer::lexer_parse_file; -use parser::{ast::parse_ast_node, parse_ast_ctx}; +use inkwell::{context::Context, module::Module}; +use ir::{types::{UNSIGNED32_TYPE_HASH, storage::IRTypeStorage}, values::IRValue}; +use parser::ast::func; fn main() { - let args: Vec = env::args().collect(); - let file_path: &String = &args[1]; + //let args: Vec = env::args().collect(); + //let file_path: &String = &args[1]; + + //let lexer_res = lexer_parse_file(file_path).expect("Bad lexer!"); + + //let ctx = parse_ast_ctx(&lexer_res); + + //println!("{:#?}", ctx); + + let context = Context::create(); + let module= context.create_module("main_module"); + let builder = context.create_builder(); + + let storage = IRTypeStorage::new(&context); + + let i32_type = context.i32_type(); - let lexer_res = lexer_parse_file(file_path).expect("Bad lexer!"); + let fn_type = i32_type.fn_type(&[], false); + let function = module.add_function("main", fn_type, None); - let ctx = parse_ast_ctx(&lexer_res); + let entry = context.append_basic_block(function, "entry"); + builder.position_at_end(entry); - println!("{:#?}", ctx); + let testvar= match storage.get(UNSIGNED32_TYPE_HASH).unwrap().make_numeric_stackvar(&builder, String::from("test_var"), IRValue::Unsigned32(44575445_u32)) { + Ok(v) => v, + Err(_) => panic!("Stop") + }; + module.print_to_file("test.ll").unwrap(); } From 8a7c2d82897052c540480a102aa9825dcc594c85 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Sat, 14 Feb 2026 23:37:34 +0100 Subject: [PATCH 06/54] feat: added function return type parsing --- parser/src/ast/func/decl.rs | 9 ++++++++- parser/src/ast/tree.rs | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/parser/src/ast/func/decl.rs b/parser/src/ast/func/decl.rs index 5df13e1..e8ab91f 100644 --- a/parser/src/ast/func/decl.rs +++ b/parser/src/ast/func/decl.rs @@ -15,9 +15,16 @@ pub fn parse_function_declaraction(tokens: &Vec, ind: &mut usize) -> *ind += 1; + let mut retType = None; + + if tokens[*ind].is_keyword() { + retType = Some(tokens[*ind].expects_keyword()?.1); + *ind += 1; + } + tokens[*ind].expects(LexerTokenType::BracketOpen)?; let body = parse_node_body(tokens, ind)?; - return Ok(Box::new(ASTTreeNode::FunctionDeclaration { func_name: WithHash::new(function_name.0), args, body })); + return Ok(Box::new(ASTTreeNode::FunctionDeclaration { func_name: WithHash::new(function_name.0), args, body, returnType: retType })); } \ No newline at end of file diff --git a/parser/src/ast/tree.rs b/parser/src/ast/tree.rs index 1fe5713..6ee057d 100644 --- a/parser/src/ast/tree.rs +++ b/parser/src/ast/tree.rs @@ -47,7 +47,7 @@ pub enum ASTTreeNode { Return { value: Option> }, FunctionCall { func: WithHash, args: Vec> }, - FunctionDeclaration { func_name: WithHash, args: Vec, body: Vec> }, + FunctionDeclaration { func_name: WithHash, args: Vec, body: Vec>, returnType: Option }, StructLRVariable { l: Box, r: Box,}, StructLRFunction { l: Box, r: Box, } @@ -68,7 +68,7 @@ impl ASTTreeNode { pub fn get_tree_name(&self) -> Option> { match self { - ASTTreeNode::FunctionDeclaration { func_name, args, body } => { + ASTTreeNode::FunctionDeclaration { func_name, args, body, returnType } => { return Some(WithHash::new(func_name.val.to_string())); }, From a35de8117414999723b11a402bf7eaa4e3d09eaf Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Sat, 14 Feb 2026 23:51:27 +0100 Subject: [PATCH 07/54] feat: added math IR utils --- Cargo.lock | 1 + ir/Cargo.toml | 3 ++- ir/src/lib.rs | 1 + ir/src/math.rs | 19 +++++++++++++++++++ ir/src/types/typing.rs | 2 +- 5 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 ir/src/math.rs diff --git a/Cargo.lock b/Cargo.lock index ba27814..a294f1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,6 +70,7 @@ version = "0.1.0" dependencies = [ "commons", "inkwell", + "lexer", ] [[package]] diff --git a/ir/Cargo.toml b/ir/Cargo.toml index db53bab..b2b845a 100644 --- a/ir/Cargo.toml +++ b/ir/Cargo.toml @@ -5,4 +5,5 @@ edition = "2024" [dependencies] inkwell = { version = "0.8.0", features = ["llvm21-1"]} -commons = { path = "../commons" } \ No newline at end of file +commons = { path = "../commons" } +lexer = { path = "../lexer" } \ No newline at end of file diff --git a/ir/src/lib.rs b/ir/src/lib.rs index 9fb5bd8..561f5ab 100644 --- a/ir/src/lib.rs +++ b/ir/src/lib.rs @@ -3,3 +3,4 @@ pub mod types; pub mod values; +pub mod math; \ No newline at end of file diff --git a/ir/src/math.rs b/ir/src/math.rs new file mode 100644 index 0000000..a182b7e --- /dev/null +++ b/ir/src/math.rs @@ -0,0 +1,19 @@ +//! Math and arithmetic code + +use commons::err::{PositionlessError, PositionlessResult}; +use inkwell::{builder::Builder, values::IntValue}; +use lexer::toks::math::MathOperator; + +pub fn make_math_operation<'a>(builder: &Builder<'a>, a: IntValue<'a>, b: IntValue<'a>, name: String, operation: MathOperator) -> PositionlessResult> { + let res = match operation { + MathOperator::ADD => builder.build_int_add(a, b, &name), + MathOperator::SUBSTRACT => builder.build_int_sub(a, b, &name), + MathOperator::DIVIDE => builder.build_int_signed_div(a, b, &name), + MathOperator::MULTIPLY => builder.build_int_mul(a, b, &name) + }; + + match res { + Ok(v) => return Ok(v), + Err(_) => return Err(PositionlessError::new("Couldn't fabricate IR math operation!")) + }; +} \ No newline at end of file diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index ae37f58..2672b39 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -3,7 +3,7 @@ use std::{cell::Ref, collections::HashMap}; use commons::err::{PositionlessError, PositionlessResult}; -use inkwell::{builder::{Builder, BuilderError}, types::{IntType, StringRadix}, values::PointerValue}; +use inkwell::{builder::{Builder}, types::{IntType, StringRadix}, values::PointerValue}; use crate::values::IRValue; From 155e35bddec75b610840a18c24be96d6f2b09bbc Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:04:01 +0100 Subject: [PATCH 08/54] feat: added ptr utils to ir --- ir/src/irstruct/mod.rs | 3 +++ ir/src/irstruct/ptr.rs | 32 ++++++++++++++++++++++++++++++++ ir/src/lib.rs | 3 ++- 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 ir/src/irstruct/mod.rs create mode 100644 ir/src/irstruct/ptr.rs diff --git a/ir/src/irstruct/mod.rs b/ir/src/irstruct/mod.rs new file mode 100644 index 0000000..044e37e --- /dev/null +++ b/ir/src/irstruct/mod.rs @@ -0,0 +1,3 @@ +//! Common definitions used internally to structure the IR. + +pub mod ptr; \ No newline at end of file diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs new file mode 100644 index 0000000..ad7aca9 --- /dev/null +++ b/ir/src/irstruct/ptr.rs @@ -0,0 +1,32 @@ +use commons::err::{PositionlessError, PositionlessResult}; +use inkwell::{builder::Builder, values::{BasicValue, IntValue, PointerValue}}; + +use crate::types::typing::IRType; + +pub struct IRPointer<'a> { + inkwell_ptr: PointerValue<'a>, + t: &'a IRType<'a>, + 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 } + } + + pub fn load_val_int(&self, builder: &Builder<'a>) -> PositionlessResult> { + if !self.t.is_numeric_type() { + return Err(PositionlessError::new("Requires a numeric type!")); + } + + match builder.build_load(*self.t.get_inkwell_inttype()?, self.inkwell_ptr, &self.name) { + Ok(v) => return Ok(v.into_int_value()), + Err(_) => return Err(PositionlessError::new("build_load failed!")) + } + } + + pub fn store>(&self, builder: &Builder<'a>, val: V) { + builder.build_store(self.inkwell_ptr, val); + } + +} \ No newline at end of file diff --git a/ir/src/lib.rs b/ir/src/lib.rs index 561f5ab..be3d009 100644 --- a/ir/src/lib.rs +++ b/ir/src/lib.rs @@ -3,4 +3,5 @@ pub mod types; pub mod values; -pub mod math; \ No newline at end of file +pub mod math; +pub mod irstruct; \ No newline at end of file From 24bcf0088df4b0ddcc525e8e20e4d07cdf9ac16d Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:07:02 +0100 Subject: [PATCH 09/54] feat: added util creation of IRPointer::create --- ir/src/irstruct/ptr.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index ad7aca9..cb8602a 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -1,7 +1,7 @@ use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{builder::Builder, values::{BasicValue, IntValue, PointerValue}}; -use crate::types::typing::IRType; +use crate::{types::typing::IRType, values::IRValue}; pub struct IRPointer<'a> { inkwell_ptr: PointerValue<'a>, @@ -14,6 +14,12 @@ impl<'a> IRPointer<'a> { return IRPointer { inkwell_ptr: ptr, name, t } } + pub fn create(builder: &Builder<'a>, name: String, t: &'a IRType<'a>, initial: IRValue) -> PositionlessResult { + let ptr = t.make_numeric_stackvar(builder, name.clone(), initial)?; + + return Ok(IRPointer { inkwell_ptr: ptr, t, name: name }); + } + pub fn load_val_int(&self, builder: &Builder<'a>) -> PositionlessResult> { if !self.t.is_numeric_type() { return Err(PositionlessError::new("Requires a numeric type!")); From d33c679decb45731e6828400e12fafc8ffd37d0f Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:12:42 +0100 Subject: [PATCH 10/54] feat: added ptr test --- commons/src/err/mod.rs | 1 + test-main/src/main.rs | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/commons/src/err/mod.rs b/commons/src/err/mod.rs index 416ecf6..1bb477d 100644 --- a/commons/src/err/mod.rs +++ b/commons/src/err/mod.rs @@ -19,6 +19,7 @@ pub struct PositionedError { pub reason: String } +#[derive(Debug)] pub struct PositionlessError { pub reason: String } diff --git a/test-main/src/main.rs b/test-main/src/main.rs index 1445472..860e0bb 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -1,5 +1,5 @@ use inkwell::{context::Context, module::Module}; -use ir::{types::{UNSIGNED32_TYPE_HASH, storage::IRTypeStorage}, values::IRValue}; +use ir::{irstruct::ptr::IRPointer, types::{UNSIGNED32_TYPE_HASH, storage::IRTypeStorage}, values::IRValue}; use parser::ast::func; fn main() { @@ -26,10 +26,12 @@ fn main() { let entry = context.append_basic_block(function, "entry"); builder.position_at_end(entry); - let testvar= match storage.get(UNSIGNED32_TYPE_HASH).unwrap().make_numeric_stackvar(&builder, String::from("test_var"), IRValue::Unsigned32(44575445_u32)) { - Ok(v) => v, - Err(_) => panic!("Stop") - }; + let t = storage.get(UNSIGNED32_TYPE_HASH).unwrap(); + + let ptr = IRPointer::create(&builder, String::from("test"), t, IRValue::Unsigned32(258)).unwrap(); + + let val = ptr.load_val_int(&builder).unwrap(); + ptr.store(&builder, val); module.print_to_file("test.ll").unwrap(); } From 8485b7cdcc92bcf3dbccef1c753b1399a0993d73 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:40:51 +0100 Subject: [PATCH 11/54] feat: added ir function utils --- ir/src/irstruct/funcs.rs | 60 ++++++++++++++++++++++++++++++++++++++++ ir/src/irstruct/mod.rs | 3 +- ir/src/types/typing.rs | 3 +- test-main/src/main.rs | 16 +++++------ 4 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 ir/src/irstruct/funcs.rs diff --git a/ir/src/irstruct/funcs.rs b/ir/src/irstruct/funcs.rs new file mode 100644 index 0000000..15ea593 --- /dev/null +++ b/ir/src/irstruct/funcs.rs @@ -0,0 +1,60 @@ +use commons::err::{PositionedError, PositionlessError, PositionlessResult}; +use inkwell::{basic_block::BasicBlock, builder::Builder, context::Context, module::Module, values::{BasicValueEnum, FunctionValue, IntValue}}; + +use crate::types::typing::IRType; + +pub struct IRFunction<'a> { + inkwell_func: FunctionValue<'a>, + ret_type: &'a IRType<'a>, + args: Vec<&'a IRType<'a>>, + name: String, + + entry: BasicBlock<'a> +} + +impl<'a> IRFunction<'a> { + pub fn new(ctx: &'a Context, name: String, func: FunctionValue<'a>, ret_type: &'a IRType<'a>, args: Vec<&'a IRType<'a>>) -> Self { + + let block = ctx.append_basic_block(func, "entry"); + + return IRFunction { inkwell_func: func, ret_type, args, name, entry: block } + } + + pub fn create(ctx: &'a Context, name: String, module: &Module<'a>, ret_type: &'a IRType<'a>, args: Vec<&'a IRType<'a>>) -> PositionlessResult { + let mut kargs = vec![]; + + for k in &args { + let irtype = *k.get_inkwell_inttype()?; + kargs.push(irtype.into()); + } + + let t = ret_type.get_inkwell_inttype()?.fn_type(&kargs, false); + + let func = module.add_function(&name, t, None); + + return Ok(IRFunction::new(ctx, name, func, ret_type, args)); + } + + /// Prepares the addition of the function body. + pub fn prepare_body_filling(&self, builder: &Builder<'a>) { + builder.position_at_end(self.entry); + } + + 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); + } + + 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()); + } + +} \ No newline at end of file diff --git a/ir/src/irstruct/mod.rs b/ir/src/irstruct/mod.rs index 044e37e..246401d 100644 --- a/ir/src/irstruct/mod.rs +++ b/ir/src/irstruct/mod.rs @@ -1,3 +1,4 @@ //! Common definitions used internally to structure the IR. -pub mod ptr; \ No newline at end of file +pub mod ptr; +pub mod funcs; \ No newline at end of file diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index 2672b39..facea95 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -3,7 +3,7 @@ use std::{cell::Ref, collections::HashMap}; use commons::err::{PositionlessError, PositionlessResult}; -use inkwell::{builder::{Builder}, types::{IntType, StringRadix}, values::PointerValue}; +use inkwell::{builder::Builder, types::{BasicType, FunctionType, IntType, StringRadix}, values::PointerValue}; use crate::values::IRValue; @@ -145,4 +145,5 @@ impl<'a> IRType<'a> { return Ok(alloca); } + } \ No newline at end of file diff --git a/test-main/src/main.rs b/test-main/src/main.rs index 860e0bb..f7533ee 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -1,5 +1,5 @@ use inkwell::{context::Context, module::Module}; -use ir::{irstruct::ptr::IRPointer, types::{UNSIGNED32_TYPE_HASH, storage::IRTypeStorage}, values::IRValue}; +use ir::{irstruct::{funcs::IRFunction, ptr::IRPointer}, types::{UNSIGNED32_TYPE_HASH, storage::IRTypeStorage}, values::IRValue}; use parser::ast::func; fn main() { @@ -13,20 +13,20 @@ fn main() { //println!("{:#?}", ctx); let context = Context::create(); + + let storage = IRTypeStorage::new(&context); + + let module= context.create_module("main_module"); let builder = context.create_builder(); - let storage = IRTypeStorage::new(&context); + let t = storage.get(UNSIGNED32_TYPE_HASH).unwrap(); let i32_type = context.i32_type(); - let fn_type = i32_type.fn_type(&[], false); - let function = module.add_function("main", fn_type, None); + let func = IRFunction::create(&context, String::from("main"), &module, t, vec![t, t]).expect("Couldn't make IR function"); - let entry = context.append_basic_block(function, "entry"); - builder.position_at_end(entry); - - let t = storage.get(UNSIGNED32_TYPE_HASH).unwrap(); + func.prepare_body_filling(&builder); let ptr = IRPointer::create(&builder, String::from("test"), t, IRValue::Unsigned32(258)).unwrap(); From c91fddcde31cfa15af0f49afc733f3956bd41771 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Sun, 15 Feb 2026 23:32:24 +0100 Subject: [PATCH 12/54] feat: added return statement --- ir/src/irstruct/funcs.rs | 34 ++++++++++++++++++++++++++++------ ir/src/irstruct/ptr.rs | 2 +- ir/src/types/mod.rs | 2 ++ ir/src/types/storage.rs | 6 ++++-- ir/src/types/typing.rs | 30 ++++++++++++++++++++++++++++-- out | Bin 0 -> 15896 bytes out.o | Bin 0 -> 1064 bytes parser/src/ast/func/mod.rs | 10 +++++++++- parser/src/ast/mod.rs | 6 +++++- parser/src/ast/tree.rs | 4 ++-- test-main/src/main.rs | 29 ++++++++++++++++++++++++----- 11 files changed, 103 insertions(+), 20 deletions(-) create mode 100755 out create mode 100644 out.o diff --git a/ir/src/irstruct/funcs.rs b/ir/src/irstruct/funcs.rs index 15ea593..003b212 100644 --- a/ir/src/irstruct/funcs.rs +++ b/ir/src/irstruct/funcs.rs @@ -4,12 +4,12 @@ use inkwell::{basic_block::BasicBlock, builder::Builder, context::Context, modul use crate::types::typing::IRType; pub struct IRFunction<'a> { - inkwell_func: FunctionValue<'a>, + pub inkwell_func: FunctionValue<'a>, ret_type: &'a IRType<'a>, args: Vec<&'a IRType<'a>>, name: String, - entry: BasicBlock<'a> + entry: Option> } impl<'a> IRFunction<'a> { @@ -17,15 +17,32 @@ impl<'a> IRFunction<'a> { let block = ctx.append_basic_block(func, "entry"); - return IRFunction { inkwell_func: func, ret_type, args, name, entry: block } + return IRFunction { inkwell_func: func, ret_type, args, name, entry: Some(block) } + } + + pub fn new_shadow(name: String, func: FunctionValue<'a>, ret_type: &'a IRType<'a>, args: Vec<&'a IRType<'a>>) -> Self { + return IRFunction { inkwell_func: func, ret_type, args, name, entry: None } + } + + pub fn create_shadow(name: String, module: &Module<'a>, ret_type: &'a IRType<'a>, args: Vec<&'a IRType<'a>>) -> PositionlessResult { + let mut kargs = vec![]; + + for k in &args { + kargs.push(k.get_inkwell_basetype()?); + } + + let t = ret_type.get_inkwell_inttype()?.fn_type(&kargs, false); + + let func = module.add_function(&name, t, None); + + return Ok(IRFunction::new_shadow(name, func, ret_type, args)); } pub fn create(ctx: &'a Context, name: String, module: &Module<'a>, ret_type: &'a IRType<'a>, args: Vec<&'a IRType<'a>>) -> PositionlessResult { let mut kargs = vec![]; for k in &args { - let irtype = *k.get_inkwell_inttype()?; - kargs.push(irtype.into()); + kargs.push(k.get_inkwell_basetype()?); } let t = ret_type.get_inkwell_inttype()?.fn_type(&kargs, false); @@ -37,7 +54,11 @@ impl<'a> IRFunction<'a> { /// Prepares the addition of the function body. pub fn prepare_body_filling(&self, builder: &Builder<'a>) { - builder.position_at_end(self.entry); + if self.entry.is_none() { + return; + } + + builder.position_at_end(self.entry.unwrap()); } pub fn get_nth_arg(&self, ind: u32) -> PositionlessResult> { @@ -55,6 +76,7 @@ impl<'a> IRFunction<'a> { } return Ok(self.get_nth_arg(ind)?.into_int_value()); + } } \ No newline at end of file diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index cb8602a..3b9dc98 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -17,7 +17,7 @@ impl<'a> IRPointer<'a> { pub fn create(builder: &Builder<'a>, name: String, t: &'a IRType<'a>, initial: IRValue) -> PositionlessResult { let ptr = t.make_numeric_stackvar(builder, name.clone(), initial)?; - return Ok(IRPointer { inkwell_ptr: ptr, t, name: name }); + return Ok(IRPointer { inkwell_ptr: ptr, t, name: name.clone() }); } pub fn load_val_int(&self, builder: &Builder<'a>) -> PositionlessResult> { diff --git a/ir/src/types/mod.rs b/ir/src/types/mod.rs index c9646bc..f05f3ec 100644 --- a/ir/src/types/mod.rs +++ b/ir/src/types/mod.rs @@ -12,6 +12,8 @@ pub const UNSIGNED32_TYPE_HASH: u64 = 2263434253207377038; pub const UNSIGNED64_TYPE_HASH: u64 = 9321926220436863523; pub const UNSIGNED128_TYPE_HASH: u64 = 9667664784078163512; +pub const POINTER_TYPE_HASH: u64 = 9259207781742941243; + pub const BOOL_TYPE_HASH: u64 = 10699440025065254663; pub mod typing; diff --git a/ir/src/types/storage.rs b/ir/src/types/storage.rs index 402b061..45de7cc 100644 --- a/ir/src/types/storage.rs +++ b/ir/src/types/storage.rs @@ -1,9 +1,9 @@ //! Type storage use commons::utils::map::HashedMap; -use inkwell::context::Context; +use inkwell::{AddressSpace, context::Context}; -use crate::types::{BOOL_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::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}; pub struct IRTypeStorage<'a> { map: HashedMap> @@ -25,6 +25,8 @@ impl<'a> IRTypeStorage<'a> { sto.insert(SIGNED64_TYPE_HASH, IRType::Signed64(ctx.i64_type())); sto.insert(SIGNED128_TYPE_HASH, IRType::Signed128(ctx.i128_type())); + sto.insert(POINTER_TYPE_HASH, IRType::Pointer(ctx.ptr_type(AddressSpace::from(0u16)))); + sto.insert(BOOL_TYPE_HASH, IRType::Bool(ctx.bool_type())); return sto; diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index facea95..fb3763d 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -1,9 +1,9 @@ //! IR Type structures -use std::{cell::Ref, collections::HashMap}; +use std::{cell::Ref, collections::HashMap, ops::Add}; use commons::err::{PositionlessError, PositionlessResult}; -use inkwell::{builder::Builder, types::{BasicType, FunctionType, IntType, StringRadix}, values::PointerValue}; +use inkwell::{AddressSpace, builder::Builder, context::Context, types::{BasicMetadataTypeEnum, BasicType, FunctionType, IntType, PointerType, StringRadix}, values::PointerValue}; use crate::values::IRValue; @@ -21,6 +21,8 @@ pub enum IRType<'a> { Unsigned64(IntType<'a>), Unsigned128(IntType<'a>), + Pointer(PointerType<'a>), + Bool(IntType<'a>), Struct(HashMap>>), // fields @@ -36,6 +38,7 @@ impl<'a> IRType<'a> { IRType::Signed32(_) | IRType::Unsigned32(_) => return 32, IRType::Signed64(_) | IRType::Unsigned64(_) => return 64, IRType::Signed128(_) | IRType::Unsigned128(_) => return 128, + IRType::Pointer(_) => return 64, IRType::Struct(v) => { let mut sz: usize = 0; @@ -107,6 +110,25 @@ impl<'a> IRType<'a> { return -2_i128.pow(self.get_bitsize() as u32) - 1; } + pub fn get_inkwell_basetype(&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)), + + _ => Err(PositionlessError::new("Given IR type doesn't have any Inkwell type!!!")) + } + } + pub fn get_inkwell_inttype(&self) -> PositionlessResult<&IntType<'a>> { match self { IRType::Unsigned8(v) => Ok(v), @@ -124,6 +146,10 @@ 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) -> PositionlessResult> { let t = *self.get_inkwell_inttype()?; let alloca = match builder.build_alloca(t, &name) { diff --git a/out b/out new file mode 100755 index 0000000000000000000000000000000000000000..4599f3d118e7bd8387952186ddb2820e7dee7c76 GIT binary patch literal 15896 zcmeHOZ)_Y_5uZCdjcH>0>@?I#Nb-c-2vB^noy3X=A?v?6S59IQw5A~)xX~YDE;teicbjpy z87F*&;}kCWq!{U%AOg_QJc_UO4$6B2L#E3Jat+I3L25 z)^7L{-1(cnOZERW&Pm28?pU!u;Ro5DaPjvk#8E!)m1KCFV}EyheqH?BgvZzc`K3N+ zteraZ2*j&!m2|=O2T-PTQ~Tr3KK15ze{>=D@Z2|l_vnG!xsJ+v+YV(jGXqBsW!;`^ zCSO_TSvWS(GjJqXE+qSPKh&4>ht+!`vhQqQc^q}Bfqn<-8rgsPF7~r`(SvQ{-K6cZ z@05Hy=VbCwEM@ZkERdS+X#h@5j1LXl{mK61(R%&x5wORnPTQ_m^5!yS-z!a>9?ll> z-jp+w^|05uTp`cB+Qzh@AwV2+)r6PHSPbRe7^^(z%I?eu=xKDb?#Iu48;46AdQm2N z?WCnSjiF%9R|0w-3fk_s0lkbtYFG{E`4y$@!Ll^piY5O9jXo-)3`7}-G7x1T%0QHX zC<9Rjq73{GGVosezJH`HzTJ{~cFT=J0I4ru_2adb)Wx5-ENgGIqrXIT?V(>`*}mVx z8p-q2_NUcatw#91KaVfH{<+lBA5s_pxIQ^G+IO|@M(XF>ZGK7r;G#MW0xRa;#qr?VS?m$m(u-qCDnJ@x84CsVK9Zc4?j zrCz_|@4_DL=N?+QhuQZ1BLLV>l>#9D)f0Qs1}ZxqNiE%6dlK*B+LmpoiG6nYQrI8a zzxA~Z|C858x|`$pCGbkKvfyQ^t*zau)%vbpSSDMY%X;?6V?8GOf4KTK>vkYPADoFtRm4 zI$CFY8+EcK)=f=#eHC>IIkY9l+PWTY-}d>IDxBPX{9}i^KTK-!lf|ouG3Y%4gKde& z+RUmp#Y%nCdL6B?5|NIsh@uQc8Hh3vWgyBxlz}J%Q3j$6L>Y)O@c*6xg^RI7>%8xo zzKw`zFC@`+!|=n&(zRBWCm6SjW!b;Hhh^DEEd8wWer4IWE$x53Q!5bUN|U9L^1V0R zY-HMBNwmW4^zBJh)g{0-=3UHpG8ZO$C)aqNWjtgr-=(zAlITIhpt{Aib#e_;C?g%aT|8EY0LXaNjaYmEFY+tD7twzOD>2vsGX6#XJ*+f}|A%+c zzoh%=fEC<55T-``+|c$rA^iM)t-%S9{qNG(O>O@m$nQY(|HMkC2m#)O2~h!As*h@Y z7qoERM1KVJ3FxZlQ}oAC-x+TMd0&Wrkn|!1_!RdO?%zSZ3fM`ti29Cr7bHUQJVknF zN06mW<$pY1M|}dHy9(Jqhx*QVD-;vPUfx5GkshDB#rgy6`1{V(COvd(|IY7k>ZiUaIa${4x?dR+? zZHq6XrCYG)vV|EZYrB4-RJNVU0;CJMV%GCLH`&|R!k*3KGqzJIIg7TJ_e+Z~TXJ%q z?N)NRMT7(-8!i1!rnH~m&K2AWZpp{^yu7PJ9y>R9dek00Gh*Y`{E-W122YO!OOf(vBPOL6#wD-Ut;_a+f{j9SY?3ZiA0)9hVkD*9p!}L(gaS~y+$aPu{O{Nl z#LIki?H=*8u{Ma8d16bi@hNdi1md?YBbam&zs$$F7$3GLUqNbR|7>1w5`6ggEBGLn zv0DdYc?{c literal 0 HcmV?d00001 diff --git a/out.o b/out.o new file mode 100644 index 0000000000000000000000000000000000000000..78cdaa116d28af80f8af2ab06e33bb79b7c89769 GIT binary patch literal 1064 zcmbu7%}T>S5XUEN)heY_@gV9Uf`SJdtQS2=#7|H}6c36}wl<}~rY-5VR4@7neGH#M z1rNSTuik|^v)QR>(whUxf95wcJG+}aAD$g03$JYgVj_5 zlkWuI$m^3=__+Bz5iZ$=DXWgz5w*5sx-E09JcIdpDnc`!F2U&LjHS#}x`)lgmsLjV zUN(1|O=}XDZA2;f9>g;MNl1*t$Wt+%K{6Mr=RK?-&&8?%=nQ0}N#zAEJ{L`xz~^TW zm>HzigpplYzEcyHbh;8e;nu;bH>6`7pI_%&Qrtg4(|7B#0zsKmEmnNtIjXeiHOlRp z16E7=Qj}01J*9r5ETkY@unKzae`OyR2%nSJd%, ind: &mut usize) -> Po tokens[*ind].expects(LexerTokenType::ParenClose)?; Ok(args) +} + +pub fn parse_function_return_statement(tokens: &Vec, ind: &mut usize) -> PositionedResult> { + *ind += 1; + + let val = parse_ast_value(tokens, ind)?; + + return Ok(Box::new(ASTTreeNode::ReturnStatement { val: Some(val) })) } \ No newline at end of file diff --git a/parser/src/ast/mod.rs b/parser/src/ast/mod.rs index 9bf9a25..c357439 100644 --- a/parser/src/ast/mod.rs +++ b/parser/src/ast/mod.rs @@ -21,7 +21,7 @@ use commons::err::PositionedResult; use lexer::token::{LexerToken, LexerTokenType}; use utils::hash::WithHash; -use crate::{ast::{control::{forloop::parse_for_loop, ifelse::parse_if_statement, whileblock::parse_while_block}, func::{call::parse_function_call, decl::parse_function_declaraction}, literals::{parse_integer_literal, parse_string_literal}, math::parse_math_operation, tree::ASTTreeNode, types::parse_type_declaration, var::decl::parse_variable_declaration}}; +use crate::ast::{control::{forloop::parse_for_loop, ifelse::parse_if_statement, whileblock::parse_while_block}, func::{call::parse_function_call, decl::parse_function_declaraction, parse_function_return_statement}, literals::{parse_integer_literal, parse_string_literal}, math::parse_math_operation, tree::ASTTreeNode, types::parse_type_declaration, var::decl::parse_variable_declaration}; pub mod tree; pub mod func; @@ -228,6 +228,10 @@ pub fn parse_ast_node_in_body(tokens: &Vec, ind: &mut usize) -> Posi LexerTokenType::For => { return parse_for_loop(tokens, ind); + }, + + LexerTokenType::Return => { + return parse_function_return_statement(tokens, ind); } LexerTokenType::KEYWORD(str, _) => { diff --git a/parser/src/ast/tree.rs b/parser/src/ast/tree.rs index 6ee057d..d3e4223 100644 --- a/parser/src/ast/tree.rs +++ b/parser/src/ast/tree.rs @@ -41,11 +41,11 @@ pub enum ASTTreeNode { IfElseStatement { cond: Option>, body: Vec>, else_statement: Option> }, ElseStatement { body: Vec> }, + ReturnStatement { val: Option> }, + WhileBlock { cond: Box, body: Vec> }, ForBlock { initial_state: Box, cond: Box, increment: Box, body: Vec> }, - Return { value: Option> }, - FunctionCall { func: WithHash, args: Vec> }, FunctionDeclaration { func_name: WithHash, args: Vec, body: Vec>, returnType: Option }, diff --git a/test-main/src/main.rs b/test-main/src/main.rs index f7533ee..3971a55 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -1,5 +1,7 @@ +use std::hash::{DefaultHasher, Hash, Hasher}; + use inkwell::{context::Context, module::Module}; -use ir::{irstruct::{funcs::IRFunction, ptr::IRPointer}, types::{UNSIGNED32_TYPE_HASH, storage::IRTypeStorage}, values::IRValue}; +use ir::{irstruct::{funcs::IRFunction, ptr::IRPointer}, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::IRValue}; use parser::ast::func; fn main() { @@ -16,22 +18,39 @@ fn main() { let storage = IRTypeStorage::new(&context); - let module= context.create_module("main_module"); let builder = context.create_builder(); 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 i32_type = context.i32_type(); + + let printf_func = IRFunction::create_shadow(String::from("printf"), &module, int_type, vec![ptr_type]).unwrap(); let func = IRFunction::create(&context, String::from("main"), &module, t, vec![t, t]).expect("Couldn't make IR function"); - func.prepare_body_filling(&builder); + + let fmt_str = builder.build_global_string_ptr("Haiiiii, the value is %d\n", "fmt_str").unwrap(); + let ptr = IRPointer::create(&builder, String::from("test"), t, IRValue::Unsigned32(258)).unwrap(); let val = ptr.load_val_int(&builder).unwrap(); - ptr.store(&builder, val); - module.print_to_file("test.ll").unwrap(); + let _ = builder.build_call( + printf_func.inkwell_func, + &[ + fmt_str.as_pointer_value().into(), + val.into(), + ], + "printf_call" +); + + builder.build_return(Some(&i32_type.const_zero())); + + module.print_to_file("output.ll").unwrap(); + } From 955ab4b55764e75b4251e5dba2af569587a5be32 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Sun, 15 Feb 2026 23:33:01 +0100 Subject: [PATCH 13/54] chore: removed accidental bins --- .gitignore | 5 ++++- out | Bin 15896 -> 0 bytes out.o | Bin 1064 -> 0 bytes 3 files changed, 4 insertions(+), 1 deletion(-) delete mode 100755 out delete mode 100644 out.o diff --git a/.gitignore b/.gitignore index 8bb58bc..9340bbc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ target/ -*.ll \ No newline at end of file +*.ll + +out +out.* \ No newline at end of file diff --git a/out b/out deleted file mode 100755 index 4599f3d118e7bd8387952186ddb2820e7dee7c76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15896 zcmeHOZ)_Y_5uZCdjcH>0>@?I#Nb-c-2vB^noy3X=A?v?6S59IQw5A~)xX~YDE;teicbjpy z87F*&;}kCWq!{U%AOg_QJc_UO4$6B2L#E3Jat+I3L25 z)^7L{-1(cnOZERW&Pm28?pU!u;Ro5DaPjvk#8E!)m1KCFV}EyheqH?BgvZzc`K3N+ zteraZ2*j&!m2|=O2T-PTQ~Tr3KK15ze{>=D@Z2|l_vnG!xsJ+v+YV(jGXqBsW!;`^ zCSO_TSvWS(GjJqXE+qSPKh&4>ht+!`vhQqQc^q}Bfqn<-8rgsPF7~r`(SvQ{-K6cZ z@05Hy=VbCwEM@ZkERdS+X#h@5j1LXl{mK61(R%&x5wORnPTQ_m^5!yS-z!a>9?ll> z-jp+w^|05uTp`cB+Qzh@AwV2+)r6PHSPbRe7^^(z%I?eu=xKDb?#Iu48;46AdQm2N z?WCnSjiF%9R|0w-3fk_s0lkbtYFG{E`4y$@!Ll^piY5O9jXo-)3`7}-G7x1T%0QHX zC<9Rjq73{GGVosezJH`HzTJ{~cFT=J0I4ru_2adb)Wx5-ENgGIqrXIT?V(>`*}mVx z8p-q2_NUcatw#91KaVfH{<+lBA5s_pxIQ^G+IO|@M(XF>ZGK7r;G#MW0xRa;#qr?VS?m$m(u-qCDnJ@x84CsVK9Zc4?j zrCz_|@4_DL=N?+QhuQZ1BLLV>l>#9D)f0Qs1}ZxqNiE%6dlK*B+LmpoiG6nYQrI8a zzxA~Z|C858x|`$pCGbkKvfyQ^t*zau)%vbpSSDMY%X;?6V?8GOf4KTK>vkYPADoFtRm4 zI$CFY8+EcK)=f=#eHC>IIkY9l+PWTY-}d>IDxBPX{9}i^KTK-!lf|ouG3Y%4gKde& z+RUmp#Y%nCdL6B?5|NIsh@uQc8Hh3vWgyBxlz}J%Q3j$6L>Y)O@c*6xg^RI7>%8xo zzKw`zFC@`+!|=n&(zRBWCm6SjW!b;Hhh^DEEd8wWer4IWE$x53Q!5bUN|U9L^1V0R zY-HMBNwmW4^zBJh)g{0-=3UHpG8ZO$C)aqNWjtgr-=(zAlITIhpt{Aib#e_;C?g%aT|8EY0LXaNjaYmEFY+tD7twzOD>2vsGX6#XJ*+f}|A%+c zzoh%=fEC<55T-``+|c$rA^iM)t-%S9{qNG(O>O@m$nQY(|HMkC2m#)O2~h!As*h@Y z7qoERM1KVJ3FxZlQ}oAC-x+TMd0&Wrkn|!1_!RdO?%zSZ3fM`ti29Cr7bHUQJVknF zN06mW<$pY1M|}dHy9(Jqhx*QVD-;vPUfx5GkshDB#rgy6`1{V(COvd(|IY7k>ZiUaIa${4x?dR+? zZHq6XrCYG)vV|EZYrB4-RJNVU0;CJMV%GCLH`&|R!k*3KGqzJIIg7TJ_e+Z~TXJ%q z?N)NRMT7(-8!i1!rnH~m&K2AWZpp{^yu7PJ9y>R9dek00Gh*Y`{E-W122YO!OOf(vBPOL6#wD-Ut;_a+f{j9SY?3ZiA0)9hVkD*9p!}L(gaS~y+$aPu{O{Nl z#LIki?H=*8u{Ma8d16bi@hNdi1md?YBbam&zs$$F7$3GLUqNbR|7>1w5`6ggEBGLn zv0DdYc?{c diff --git a/out.o b/out.o deleted file mode 100644 index 78cdaa116d28af80f8af2ab06e33bb79b7c89769..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1064 zcmbu7%}T>S5XUEN)heY_@gV9Uf`SJdtQS2=#7|H}6c36}wl<}~rY-5VR4@7neGH#M z1rNSTuik|^v)QR>(whUxf95wcJG+}aAD$g03$JYgVj_5 zlkWuI$m^3=__+Bz5iZ$=DXWgz5w*5sx-E09JcIdpDnc`!F2U&LjHS#}x`)lgmsLjV zUN(1|O=}XDZA2;f9>g;MNl1*t$Wt+%K{6Mr=RK?-&&8?%=nQ0}N#zAEJ{L`xz~^TW zm>HzigpplYzEcyHbh;8e;nu;bH>6`7pI_%&Qrtg4(|7B#0zsKmEmnNtIjXeiHOlRp z16E7=Qj}01J*9r5ETkY@unKzae`OyR2%nSJd% Date: Sun, 15 Feb 2026 23:55:27 +0100 Subject: [PATCH 14/54] feat: started working on static var handling --- ir/src/conv/mod.rs | 2 ++ ir/src/ctx.rs | 15 +++++++++++++++ ir/src/irstruct/mod.rs | 3 ++- ir/src/irstruct/staticvars.rs | 24 ++++++++++++++++++++++++ ir/src/lib.rs | 4 +++- 5 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 ir/src/conv/mod.rs create mode 100644 ir/src/ctx.rs create mode 100644 ir/src/irstruct/staticvars.rs diff --git a/ir/src/conv/mod.rs b/ir/src/conv/mod.rs new file mode 100644 index 0000000..3f11bbf --- /dev/null +++ b/ir/src/conv/mod.rs @@ -0,0 +1,2 @@ +//! Critical AST -> IR conversion code module + diff --git a/ir/src/ctx.rs b/ir/src/ctx.rs new file mode 100644 index 0000000..05ff3ab --- /dev/null +++ b/ir/src/ctx.rs @@ -0,0 +1,15 @@ +//! IR context related code + +use commons::utils::map::HashedMap; +use inkwell::context::Context; + +use crate::irstruct::{funcs::IRFunction, ptr::IRPointer}; + +/// 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 functions: HashedMap>, + pub static_vars: HashedMap> + +} \ No newline at end of file diff --git a/ir/src/irstruct/mod.rs b/ir/src/irstruct/mod.rs index 246401d..6f27e18 100644 --- a/ir/src/irstruct/mod.rs +++ b/ir/src/irstruct/mod.rs @@ -1,4 +1,5 @@ //! Common definitions used internally to structure the IR. pub mod ptr; -pub mod funcs; \ No newline at end of file +pub mod funcs; +pub mod staticvars; \ No newline at end of file diff --git a/ir/src/irstruct/staticvars.rs b/ir/src/irstruct/staticvars.rs new file mode 100644 index 0000000..6f1c931 --- /dev/null +++ b/ir/src/irstruct/staticvars.rs @@ -0,0 +1,24 @@ +//! Static variable related code + +use commons::err::{PositionlessError, PositionlessResult}; +use inkwell::{builder::Builder, context::Context, values::GlobalValue}; + +use crate::types::typing::IRType; + +pub struct IRStaticVariable<'a> { + inkwell: Option>, + t: &'a IRType<'a>, + 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) { + Ok(v) => v, + Err(_) => return Err(PositionlessError::new("build_global_string_ptr failed!!")) + }; + + return Ok(IRStaticVariable { inkwell: Some(inkwell), t, name }); + } + +} \ No newline at end of file diff --git a/ir/src/lib.rs b/ir/src/lib.rs index be3d009..635cf17 100644 --- a/ir/src/lib.rs +++ b/ir/src/lib.rs @@ -4,4 +4,6 @@ pub mod types; pub mod values; pub mod math; -pub mod irstruct; \ No newline at end of file +pub mod irstruct; +pub mod conv; +pub mod ctx; \ No newline at end of file From dacd69bb8c22972746ddbaedb03dc40a0d6928da Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 16 Feb 2026 00:06:27 +0100 Subject: [PATCH 15/54] feat: added compiletime replacement for integer based types on global vars --- ir/src/irstruct/staticvars.rs | 38 +++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/ir/src/irstruct/staticvars.rs b/ir/src/irstruct/staticvars.rs index 6f1c931..a70b8ec 100644 --- a/ir/src/irstruct/staticvars.rs +++ b/ir/src/irstruct/staticvars.rs @@ -1,12 +1,13 @@ //! Static variable related code use commons::err::{PositionlessError, PositionlessResult}; -use inkwell::{builder::Builder, context::Context, values::GlobalValue}; +use inkwell::{builder::Builder, context::Context, types::StringRadix, values::{BasicValueEnum, GlobalValue, IntValue}}; use crate::types::typing::IRType; pub struct IRStaticVariable<'a> { inkwell: Option>, + val: Option>, t: &'a IRType<'a>, pub name: String } @@ -18,7 +19,40 @@ impl<'a> IRStaticVariable<'a> { Err(_) => return Err(PositionlessError::new("build_global_string_ptr failed!!")) }; - return Ok(IRStaticVariable { inkwell: Some(inkwell), t, name }); + return Ok(IRStaticVariable { inkwell: Some(inkwell), t, name, val: None }); + } + + pub fn from_int(t: &'a IRType<'a>, name: String, val: i128) -> PositionlessResult> { + let val = match t.get_inkwell_inttype()?.const_int_from_string(&val.to_string(), StringRadix::Decimal) { + Some(v) => v, + None => return Err(PositionlessError::new("const_int_from_string failed!!")) + }; + + return Ok(IRStaticVariable { inkwell: None, val: Some(val.into()), t, name }) + } + + pub fn is_compiletime_replaceable(&self) -> bool { + return self.val.is_some(); + } + + pub fn as_int_val(&self) -> PositionlessResult> { + if !self.is_compiletime_replaceable() { + return Err(PositionlessError::new("Tried using as_int_val on a non-compiletime determined global val")); + } + + if !self.t.is_numeric_type() { + return Err(PositionlessError::new("Tried using as_int_val on a non-integer global value type!")); + } + + return Ok(self.val.unwrap().into_int_value()); + } + + 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()) } } \ No newline at end of file From 56472c21cda81930fa954ec4ad25b1e045008841 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 16 Feb 2026 00:18:25 +0100 Subject: [PATCH 16/54] =?UTF-8?q?feat:=20started=20working=20on=20IRValueR?= =?UTF-8?q?efs=20for=20a=20universal=20value=20handling=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ir/src/lib.rs | 3 ++- ir/src/refs.rs | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 ir/src/refs.rs diff --git a/ir/src/lib.rs b/ir/src/lib.rs index 635cf17..d0b82e8 100644 --- a/ir/src/lib.rs +++ b/ir/src/lib.rs @@ -6,4 +6,5 @@ pub mod values; pub mod math; pub mod irstruct; pub mod conv; -pub mod ctx; \ No newline at end of file +pub mod ctx; +pub mod refs; \ No newline at end of file diff --git a/ir/src/refs.rs b/ir/src/refs.rs new file mode 100644 index 0000000..999f99c --- /dev/null +++ b/ir/src/refs.rs @@ -0,0 +1,21 @@ +//! IR value reference definitions + +use crate::{irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::IRType, values::IRValue}; + +/// 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> { + // TODO: maybe change IRValueRef to host the fields itself rather than having to use Options + ptr: Option>, + val: Option, + global: Option>, + + t: &'a IRType<'a> +} + +impl<'a> IRValueRef<'a> { + /// Determines if aqcuiring the values require a load instruction or any instruction at all to obtain the value from. + pub fn requires_load(&self) -> bool { + return self.ptr.is_some(); + } + +} \ No newline at end of file From 0f24a5a93b45641ae37786aae1c1e783ef757caf Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 16 Feb 2026 00:46:25 +0100 Subject: [PATCH 17/54] feat: added new safe IRValue version --- ir/src/values.rs | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/ir/src/values.rs b/ir/src/values.rs index 8d68d51..6316149 100644 --- a/ir/src/values.rs +++ b/ir/src/values.rs @@ -1,7 +1,11 @@ //! IR value representation definitons use commons::{err::{PositionlessError, PositionlessResult}, utils::num::{can_num_fit_inbits_signed, can_num_fit_inbits_unsigned}}; +use inkwell::{types::StringRadix, values::{BasicValueEnum, IntValue}}; +use crate::types::typing::IRType; + +#[deprecated(note="IRValue is fairly unused and acts as a weird mix of IR and AST value handling. Please use IRNewValue", )] #[derive(Debug)] pub enum IRValue { Signed8(i8), @@ -22,6 +26,7 @@ pub enum IRValue { Layout(Vec>, u64) // type hash } +#[deprecated(note="IRValue is fairly unused and acts as a weird mix of IR and AST value handling. Please use IRNewValue", )] impl IRValue { pub fn make_signed(sz: usize, val: i128) -> PositionlessResult { if !can_num_fit_inbits_signed(sz, val) { @@ -95,5 +100,79 @@ impl IRValue { _ => return Err(PositionlessError::new(&format!("Expected a boolean but instead got {:#?}", self))) } } +} + +/// The new IR value system. Allows for a close interaction with inkwell rather than a more AST-side one. +/// # Safety +/// IRNewValue 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. +pub struct IRNewValue<'a> { + inkwell_val: BasicValueEnum<'a>, + t: &'a IRType<'a>, +} + +impl<'a> IRNewValue<'a> { + /// Creates a new untracked instance + pub fn new(inkwell_val: BasicValueEnum<'a>, t: &'a IRType<'a>) -> Self { + return IRNewValue { inkwell_val, t } + } + + pub fn from_unsigned(t: &'a IRType<'a>, 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!")); + } + + let int_type = t.get_inkwell_inttype()?; + let val = match int_type.const_int_from_string(&v.to_string(), StringRadix::Decimal) { + Some(v) => v, + None => return Err(PositionlessError::new("const_int_from_string failed!")) + }; + + return Ok(IRNewValue::new(val.into(), t)) + } + + pub fn from_signed(t: &'a IRType<'a>, 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!")); + } + + let int_type = t.get_inkwell_inttype()?; + let val = match int_type.const_int_from_string(&v.to_string(), StringRadix::Decimal) { + Some(v) => v, + None => return Err(PositionlessError::new("const_int_from_string failed!")) + }; + + return Ok(IRNewValue::new(val.into(), t)) + } + + pub fn from_bool(val: bool, t: &'a IRType<'a>) -> PositionlessResult { + let inkwell_type = match t { + IRType::Bool(ty) => ty, + _ => return Err(PositionlessError::new("from_bool got fed a non-boolean IRType instance! t != IRType::Bool!")) + }; + + return Ok(IRNewValue::new(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; + } + + /// Obtains the value as an integer value. Returns None if the value is incompatible with integers + pub fn obtain_as_int(&self) -> Option> { + if !self.t.is_numeric_type() { + return None; + } + + return Some(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()), + _ => None + } + } } \ No newline at end of file From b5e32e8c98b9e8c58e38044121bc71bc8e527dac Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 16 Feb 2026 00:55:13 +0100 Subject: [PATCH 18/54] feat: replaced every usage of the IRValue with IRNewValue --- ir/src/irstruct/ptr.rs | 4 ++-- ir/src/refs.rs | 4 ++-- ir/src/types/typing.rs | 16 +++++++--------- ir/src/values.rs | 4 ++-- test-main/src/main.rs | 4 ++-- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index 3b9dc98..24fa21e 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -1,7 +1,7 @@ use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{builder::Builder, values::{BasicValue, IntValue, PointerValue}}; -use crate::{types::typing::IRType, values::IRValue}; +use crate::{types::typing::IRType, values::{IRNewValue}}; pub struct IRPointer<'a> { inkwell_ptr: PointerValue<'a>, @@ -14,7 +14,7 @@ impl<'a> IRPointer<'a> { return IRPointer { inkwell_ptr: ptr, name, t } } - pub fn create(builder: &Builder<'a>, name: String, t: &'a IRType<'a>, initial: IRValue) -> PositionlessResult { + pub fn create(builder: &Builder<'a>, name: String, t: &'a IRType<'a>, initial: IRNewValue<'a>) -> PositionlessResult { let ptr = t.make_numeric_stackvar(builder, name.clone(), initial)?; return Ok(IRPointer { inkwell_ptr: ptr, t, name: name.clone() }); diff --git a/ir/src/refs.rs b/ir/src/refs.rs index 999f99c..364d5be 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -1,12 +1,12 @@ //! IR value reference definitions -use crate::{irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::IRType, values::IRValue}; +use crate::{irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::IRType, values::{IRNewValue}}; /// 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> { // TODO: maybe change IRValueRef to host the fields itself rather than having to use Options ptr: Option>, - val: Option, + val: Option>, global: Option>, t: &'a IRType<'a> diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index fb3763d..3520b6d 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -5,9 +5,10 @@ use std::{cell::Ref, collections::HashMap, ops::Add}; use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{AddressSpace, builder::Builder, context::Context, types::{BasicMetadataTypeEnum, BasicType, FunctionType, IntType, PointerType, StringRadix}, values::PointerValue}; -use crate::values::IRValue; +use crate::values::{IRNewValue}; /// Types of IR variables +#[derive(PartialEq)] pub enum IRType<'a> { Signed8(IntType<'a>), Signed16(IntType<'a>), @@ -25,8 +26,8 @@ pub enum IRType<'a> { Bool(IntType<'a>), - Struct(HashMap>>), // fields - Layout(HashMap>>) // fields + Struct(HashMap>), // fields + Layout(HashMap>) // fields } impl<'a> IRType<'a> { @@ -150,21 +151,18 @@ impl<'a> IRType<'a> { return ctx.ptr_type(AddressSpace::from(0u16)); } - pub fn make_numeric_stackvar(&self, builder: &Builder<'a>, name: String, initial_val: IRValue) -> PositionlessResult> { + pub fn make_numeric_stackvar(&self, builder: &Builder<'a>, name: String, initial_val: IRNewValue<'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 v = initial_val.expects_numeric_value(self.get_bitsize(), self.is_signed())?; - - let val = match t.const_int_from_string(&v.to_string(), StringRadix::Decimal) { + let val = match initial_val.obtain_as_int(self) { Some(v) => v, - None => return Err(PositionlessError::new("const_int_from_string failed!!")) + 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!!")); } diff --git a/ir/src/values.rs b/ir/src/values.rs index 6316149..95c65cb 100644 --- a/ir/src/values.rs +++ b/ir/src/values.rs @@ -159,8 +159,8 @@ impl<'a> IRNewValue<'a> { } /// Obtains the value as an integer value. Returns None if the value is incompatible with integers - pub fn obtain_as_int(&self) -> Option> { - if !self.t.is_numeric_type() { + pub fn obtain_as_int(&self, t: &'a IRType<'a>) -> Option> { + if !self.t.is_numeric_type() || t != self.t { return None; } diff --git a/test-main/src/main.rs b/test-main/src/main.rs index 3971a55..85fbaa2 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -1,7 +1,7 @@ use std::hash::{DefaultHasher, Hash, Hasher}; use inkwell::{context::Context, module::Module}; -use ir::{irstruct::{funcs::IRFunction, ptr::IRPointer}, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::IRValue}; +use ir::{irstruct::{funcs::IRFunction, ptr::IRPointer}, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::{IRNewValue}}; use parser::ast::func; fn main() { @@ -36,7 +36,7 @@ fn main() { let fmt_str = builder.build_global_string_ptr("Haiiiii, the value is %d\n", "fmt_str").unwrap(); - let ptr = IRPointer::create(&builder, String::from("test"), t, IRValue::Unsigned32(258)).unwrap(); + let ptr = IRPointer::create(&builder, String::from("test"), t, IRNewValue::from_unsigned(t, 286).unwrap()).unwrap(); let val = ptr.load_val_int(&builder).unwrap(); From d8ac16da1128b6be420e10cd7efec52d06efb282 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 16 Feb 2026 00:55:46 +0100 Subject: [PATCH 19/54] =?UTF-8?q?=C3=83chore:=20removed=20ir::values::IRVa?= =?UTF-8?q?lue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ir/src/values.rs | 99 +----------------------------------------------- 1 file changed, 1 insertion(+), 98 deletions(-) diff --git a/ir/src/values.rs b/ir/src/values.rs index 95c65cb..fd9ab22 100644 --- a/ir/src/values.rs +++ b/ir/src/values.rs @@ -1,107 +1,10 @@ //! IR value representation definitons -use commons::{err::{PositionlessError, PositionlessResult}, utils::num::{can_num_fit_inbits_signed, can_num_fit_inbits_unsigned}}; +use commons::{err::{PositionlessError, PositionlessResult}}; use inkwell::{types::StringRadix, values::{BasicValueEnum, IntValue}}; use crate::types::typing::IRType; -#[deprecated(note="IRValue is fairly unused and acts as a weird mix of IR and AST value handling. Please use IRNewValue", )] -#[derive(Debug)] -pub enum IRValue { - Signed8(i8), - Signed16(i16), - Signed32(i32), - Signed64(i64), - Signed128(i128), - - Unsigned8(u8), - Unsigned16(u16), - Unsigned32(u32), - Unsigned64(u64), - Unsigned128(u128), - - Bool(bool), - - Struct(Vec>, u64), // type hash - Layout(Vec>, u64) // type hash -} - -#[deprecated(note="IRValue is fairly unused and acts as a weird mix of IR and AST value handling. Please use IRNewValue", )] -impl IRValue { - pub fn make_signed(sz: usize, val: i128) -> PositionlessResult { - if !can_num_fit_inbits_signed(sz, val) { - return Err(PositionlessError::new(&format!("Cannot fit the given number value {} into {} bits!", val, sz))); - } - - match sz { - 8 => return Ok(IRValue::Signed8(val as i8)), - 16 => return Ok(IRValue::Signed16(val as i16)), - 32 => return Ok(IRValue::Signed32(val as i32)), - 64 => return Ok(IRValue::Signed64(val as i64)), - 128 => return Ok(IRValue::Signed128(val as i128)), - _ => return Err(PositionlessError::new(&format!("Invalid bit size! got {}", sz))) - } - } - - pub fn make_unsigned(sz: usize, val: i128) -> PositionlessResult { - if !can_num_fit_inbits_unsigned(sz, val) { - return Err(PositionlessError::new(&format!("Cannot fit the given number value {} into {} bits!", val, sz))); - } - - match sz { - 8 => return Ok(IRValue::Unsigned8(val as u8)), - 16 => return Ok(IRValue::Unsigned16(val as u16)), - 32 => return Ok(IRValue::Unsigned32(val as u32)), - 64 => return Ok(IRValue::Unsigned64(val as u64)), - 128 => return Ok(IRValue::Unsigned128(val as u128)), - _ => return Err(PositionlessError::new(&format!("Invalid bit size! got {}", sz))) - } - } - - pub fn make_bool(val: bool) -> IRValue { - return IRValue::Bool(val); - } - - pub fn expects_numeric_value(&self, sz: usize, signed: bool) -> PositionlessResult { - let val: i128 = match self { - IRValue::Unsigned8(v) => *v as i128, - IRValue::Unsigned16(v) => *v as i128, - IRValue::Unsigned32(v) => *v as i128, - IRValue::Unsigned64(v) => *v as i128, - IRValue::Unsigned128(v) => *v as i128, - - IRValue::Signed8(v) => *v as i128, - IRValue::Signed16(v) => *v as i128, - IRValue::Signed32(v) => *v as i128, - IRValue::Signed64(v) => *v as i128, - IRValue::Signed128(v) => *v as i128, - - _ => return Err(PositionlessError::new(&format!("Expected a numeric value! Got {:#?}", self))) - }; - - if signed { - if !can_num_fit_inbits_signed(sz, val) { - return Err(PositionlessError::new(&format!("Numerical value {} cannot fit in bits!", val))); - } - - return Ok(val); - } - - if !can_num_fit_inbits_unsigned(sz, val) { - return Err(PositionlessError::new(&format!("Numerical value {} cannot fit in bits!", val))); - } - - return Ok(val); - } - - pub fn expects_bool_value(&self) -> PositionlessResult { - match self { - IRValue::Bool(v) => return Ok(*v), - _ => return Err(PositionlessError::new(&format!("Expected a boolean but instead got {:#?}", self))) - } - } -} - /// The new IR value system. Allows for a close interaction with inkwell rather than a more AST-side one. /// # Safety /// IRNewValue 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. From dd01e59ce65608c8882a2744afae720210a9b774 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 16 Feb 2026 00:56:25 +0100 Subject: [PATCH 20/54] chore: renamed ir::values::IRNewValue -> ir::values::IRValue --- ir/src/irstruct/ptr.rs | 4 ++-- ir/src/refs.rs | 4 ++-- ir/src/types/typing.rs | 4 ++-- ir/src/values.rs | 14 +++++++------- test-main/src/main.rs | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index 24fa21e..152fc58 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -1,7 +1,7 @@ use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{builder::Builder, values::{BasicValue, IntValue, PointerValue}}; -use crate::{types::typing::IRType, values::{IRNewValue}}; +use crate::{types::typing::IRType, values::{IRValue}}; pub struct IRPointer<'a> { inkwell_ptr: PointerValue<'a>, @@ -14,7 +14,7 @@ impl<'a> IRPointer<'a> { return IRPointer { inkwell_ptr: ptr, name, t } } - pub fn create(builder: &Builder<'a>, name: String, t: &'a IRType<'a>, initial: IRNewValue<'a>) -> PositionlessResult { + pub fn create(builder: &Builder<'a>, name: String, t: &'a IRType<'a>, initial: IRValue<'a>) -> PositionlessResult { let ptr = t.make_numeric_stackvar(builder, name.clone(), initial)?; return Ok(IRPointer { inkwell_ptr: ptr, t, name: name.clone() }); diff --git a/ir/src/refs.rs b/ir/src/refs.rs index 364d5be..a263113 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -1,12 +1,12 @@ //! IR value reference definitions -use crate::{irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::IRType, values::{IRNewValue}}; +use crate::{irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::IRType, values::{IRValue}}; /// 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> { // TODO: maybe change IRValueRef to host the fields itself rather than having to use Options ptr: Option>, - val: Option>, + val: Option>, global: Option>, t: &'a IRType<'a> diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index 3520b6d..cbbc553 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -5,7 +5,7 @@ use std::{cell::Ref, collections::HashMap, ops::Add}; use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{AddressSpace, builder::Builder, context::Context, types::{BasicMetadataTypeEnum, BasicType, FunctionType, IntType, PointerType, StringRadix}, values::PointerValue}; -use crate::values::{IRNewValue}; +use crate::values::{IRValue}; /// Types of IR variables #[derive(PartialEq)] @@ -151,7 +151,7 @@ impl<'a> IRType<'a> { return ctx.ptr_type(AddressSpace::from(0u16)); } - pub fn make_numeric_stackvar(&self, builder: &Builder<'a>, name: String, initial_val: IRNewValue<'a>) -> PositionlessResult> { + 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, diff --git a/ir/src/values.rs b/ir/src/values.rs index fd9ab22..c9f34fc 100644 --- a/ir/src/values.rs +++ b/ir/src/values.rs @@ -7,16 +7,16 @@ use crate::types::typing::IRType; /// The new IR value system. Allows for a close interaction with inkwell rather than a more AST-side one. /// # Safety -/// IRNewValue 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. -pub struct IRNewValue<'a> { +/// 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. +pub struct IRValue<'a> { inkwell_val: BasicValueEnum<'a>, t: &'a IRType<'a>, } -impl<'a> IRNewValue<'a> { +impl<'a> IRValue<'a> { /// Creates a new untracked instance pub fn new(inkwell_val: BasicValueEnum<'a>, t: &'a IRType<'a>) -> Self { - return IRNewValue { inkwell_val, t } + return IRValue { inkwell_val, t } } pub fn from_unsigned(t: &'a IRType<'a>, v: u128) -> PositionlessResult { @@ -30,7 +30,7 @@ impl<'a> IRNewValue<'a> { None => return Err(PositionlessError::new("const_int_from_string failed!")) }; - return Ok(IRNewValue::new(val.into(), t)) + return Ok(IRValue::new(val.into(), t)) } pub fn from_signed(t: &'a IRType<'a>, v: i128) -> PositionlessResult { @@ -44,7 +44,7 @@ impl<'a> IRNewValue<'a> { None => return Err(PositionlessError::new("const_int_from_string failed!")) }; - return Ok(IRNewValue::new(val.into(), t)) + return Ok(IRValue::new(val.into(), t)) } pub fn from_bool(val: bool, t: &'a IRType<'a>) -> PositionlessResult { @@ -53,7 +53,7 @@ impl<'a> IRNewValue<'a> { _ => return Err(PositionlessError::new("from_bool got fed a non-boolean IRType instance! t != IRType::Bool!")) }; - return Ok(IRNewValue::new(inkwell_type.const_int(val as u64, false).into(), t)) + return Ok(IRValue::new(inkwell_type.const_int(val as u64, false).into(), t)) } /// Typeless obtain. Can be considered as an unsafe handle. Doesn't perform type checking diff --git a/test-main/src/main.rs b/test-main/src/main.rs index 85fbaa2..ade8856 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -1,7 +1,7 @@ use std::hash::{DefaultHasher, Hash, Hasher}; use inkwell::{context::Context, module::Module}; -use ir::{irstruct::{funcs::IRFunction, ptr::IRPointer}, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::{IRNewValue}}; +use ir::{irstruct::{funcs::IRFunction, ptr::IRPointer}, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::{IRValue}}; use parser::ast::func; fn main() { @@ -36,7 +36,7 @@ fn main() { let fmt_str = builder.build_global_string_ptr("Haiiiii, the value is %d\n", "fmt_str").unwrap(); - let ptr = IRPointer::create(&builder, String::from("test"), t, IRNewValue::from_unsigned(t, 286).unwrap()).unwrap(); + let ptr = IRPointer::create(&builder, String::from("test"), t, IRValue::from_unsigned(t, 286).unwrap()).unwrap(); let val = ptr.load_val_int(&builder).unwrap(); From 6b14e8d738ba79eebde67da42380423e542e86e8 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 16 Feb 2026 01:05:24 +0100 Subject: [PATCH 21/54] feat: made IRPointer::load_int standart into IRPointer::load --- ir/src/irstruct/ptr.rs | 10 +++++----- ir/src/refs.rs | 8 ++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index 152fc58..93df220 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -1,5 +1,5 @@ use commons::err::{PositionlessError, PositionlessResult}; -use inkwell::{builder::Builder, values::{BasicValue, IntValue, PointerValue}}; +use inkwell::{builder::Builder, values::{BasicValue, BasicValueEnum, IntValue, PointerValue}}; use crate::{types::typing::IRType, values::{IRValue}}; @@ -20,13 +20,13 @@ impl<'a> IRPointer<'a> { return Ok(IRPointer { inkwell_ptr: ptr, t, name: name.clone() }); } - pub fn load_val_int(&self, builder: &Builder<'a>) -> PositionlessResult> { - if !self.t.is_numeric_type() { - return Err(PositionlessError::new("Requires a numeric type!")); + pub fn load(&self, builder: &Builder<'a>, t: &'a IRType<'a>) -> PositionlessResult> { + if self.t != t { + return Err(PositionlessError::new("Provided IRType isn't the same!")); } match builder.build_load(*self.t.get_inkwell_inttype()?, self.inkwell_ptr, &self.name) { - Ok(v) => return Ok(v.into_int_value()), + Ok(v) => return Ok(IRValue::new(v, t)), Err(_) => return Err(PositionlessError::new("build_load failed!")) } } diff --git a/ir/src/refs.rs b/ir/src/refs.rs index a263113..8746061 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -1,5 +1,7 @@ //! IR value reference definitions +use inkwell::types::AnyTypeEnum; + use crate::{irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::IRType, values::{IRValue}}; /// The IR value reference. Basically represents any value whatsoever, can handle every shape of values and is used for uniform handling. @@ -18,4 +20,10 @@ impl<'a> IRValueRef<'a> { return self.ptr.is_some(); } + pub fn obtain(&self) -> AnyTypeEnum<'a> { + if self.ptr.is_some() { + + } + } + } \ No newline at end of file From ddcedb1495f8e5f3cf2c0e9249816d3ea115833d Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 16 Feb 2026 01:19:44 +0100 Subject: [PATCH 22/54] feat: finished IRPointer --- ir/src/irstruct/staticvars.rs | 15 +++++---------- ir/src/refs.rs | 31 ++++++++++++++++++++++--------- ir/src/values.rs | 1 + test-main/src/main.rs | 2 +- 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/ir/src/irstruct/staticvars.rs b/ir/src/irstruct/staticvars.rs index a70b8ec..db29ed9 100644 --- a/ir/src/irstruct/staticvars.rs +++ b/ir/src/irstruct/staticvars.rs @@ -3,7 +3,7 @@ use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{builder::Builder, context::Context, types::StringRadix, values::{BasicValueEnum, GlobalValue, IntValue}}; -use crate::types::typing::IRType; +use crate::{types::typing::IRType, values::IRValue}; pub struct IRStaticVariable<'a> { inkwell: Option>, @@ -22,20 +22,15 @@ impl<'a> IRStaticVariable<'a> { return Ok(IRStaticVariable { inkwell: Some(inkwell), t, name, val: None }); } - pub fn from_int(t: &'a IRType<'a>, name: String, val: i128) -> PositionlessResult> { - let val = match t.get_inkwell_inttype()?.const_int_from_string(&val.to_string(), StringRadix::Decimal) { - Some(v) => v, - None => return Err(PositionlessError::new("const_int_from_string failed!!")) - }; - - return Ok(IRStaticVariable { inkwell: None, val: Some(val.into()), t, name }) + pub fn from_val(name: String, t: &'a IRType<'a>, val: IRValue<'a>) -> PositionlessResult> { + return Ok(IRStaticVariable { val: Some(val.obtain()), inkwell: None, t, name }) } pub fn is_compiletime_replaceable(&self) -> bool { return self.val.is_some(); } - pub fn as_int_val(&self) -> PositionlessResult> { + pub fn as_val(&self) -> PositionlessResult> { if !self.is_compiletime_replaceable() { return Err(PositionlessError::new("Tried using as_int_val on a non-compiletime determined global val")); } @@ -44,7 +39,7 @@ impl<'a> IRStaticVariable<'a> { return Err(PositionlessError::new("Tried using as_int_val on a non-integer global value type!")); } - return Ok(self.val.unwrap().into_int_value()); + return Ok(self.val.unwrap()); } pub fn as_string_ref(&self) -> PositionlessResult> { diff --git a/ir/src/refs.rs b/ir/src/refs.rs index 8746061..51983e7 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -1,15 +1,20 @@ //! IR value reference definitions -use inkwell::types::AnyTypeEnum; +use commons::err::{PositionlessError, PositionlessResult}; +use inkwell::{builder::Builder, types::{AnyTypeEnum, BasicTypeEnum}}; use crate::{irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::IRType, values::{IRValue}}; -/// The IR value reference. Basically represents any value whatsoever, can handle every shape of values and is used for uniform handling. +pub enum IRValueRefKind<'a> { + Ptr(IRPointer<'a>), + Val(IRValue<'a>), + Global(IRStaticVariable<'a>) +} + +/// 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> { // TODO: maybe change IRValueRef to host the fields itself rather than having to use Options - ptr: Option>, - val: Option>, - global: Option>, + kind: IRValueRefKind<'a>, t: &'a IRType<'a> } @@ -17,12 +22,20 @@ pub struct IRValueRef<'a> { impl<'a> IRValueRef<'a> { /// Determines if aqcuiring the values require a load instruction or any instruction at all to obtain the value from. pub fn requires_load(&self) -> bool { - return self.ptr.is_some(); + return matches!(self.kind, IRValueRefKind::Ptr(_)) } - pub fn obtain(&self) -> AnyTypeEnum<'a> { - if self.ptr.is_some() { - + pub fn obtain(&self, builder: &'a Builder<'a>) -> PositionlessResult> { + match &self.kind { + IRValueRefKind::Ptr(ptr) => { + ptr.load(builder, self.t) + }, + + IRValueRefKind::Val(v) => Ok(IRValue::clone(v)), + + IRValueRefKind::Global(global) => { + Ok(IRValue::new(global.as_val()?, self.t)) + } } } diff --git a/ir/src/values.rs b/ir/src/values.rs index c9f34fc..08156bd 100644 --- a/ir/src/values.rs +++ b/ir/src/values.rs @@ -8,6 +8,7 @@ use crate::types::typing::IRType; /// 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>, t: &'a IRType<'a>, diff --git a/test-main/src/main.rs b/test-main/src/main.rs index ade8856..4edd4e2 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -38,7 +38,7 @@ fn main() { let ptr = IRPointer::create(&builder, String::from("test"), t, IRValue::from_unsigned(t, 286).unwrap()).unwrap(); - let val = ptr.load_val_int(&builder).unwrap(); + let val = ptr.load(&builder).unwrap().obtain(); let _ = builder.build_call( printf_func.inkwell_func, From a3b113af0169fa5a4f23e688360dd6c39e7f37f4 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 16 Feb 2026 01:20:47 +0100 Subject: [PATCH 23/54] feat: added support for IRValueRef instead of IRValue on IRPointer::create --- ir/src/irstruct/ptr.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index 93df220..c387cc6 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -1,7 +1,7 @@ use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{builder::Builder, values::{BasicValue, BasicValueEnum, IntValue, PointerValue}}; -use crate::{types::typing::IRType, values::{IRValue}}; +use crate::{refs::IRValueRef, types::typing::IRType, values::IRValue}; pub struct IRPointer<'a> { inkwell_ptr: PointerValue<'a>, @@ -14,8 +14,8 @@ impl<'a> IRPointer<'a> { return IRPointer { inkwell_ptr: ptr, name, t } } - pub fn create(builder: &Builder<'a>, name: String, t: &'a IRType<'a>, initial: IRValue<'a>) -> PositionlessResult { - let ptr = t.make_numeric_stackvar(builder, name.clone(), initial)?; + pub fn create(builder: &'a Builder<'a>, name: String, t: &'a IRType<'a>, initial: IRValueRef<'a>) -> PositionlessResult { + let ptr = t.make_numeric_stackvar(builder, name.clone(), initial.obtain(builder)?)?; return Ok(IRPointer { inkwell_ptr: ptr, t, name: name.clone() }); } From 4c1093e8dc821bb6ce407afcc0e84924fdb2652d Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 16 Feb 2026 01:26:29 +0100 Subject: [PATCH 24/54] chore: cleaned ast value refs a little --- ir/src/refs.rs | 20 +++++++++++--------- test-main/src/main.rs | 6 +++--- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/ir/src/refs.rs b/ir/src/refs.rs index 51983e7..471c758 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -6,35 +6,37 @@ use inkwell::{builder::Builder, types::{AnyTypeEnum, BasicTypeEnum}}; use crate::{irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::IRType, values::{IRValue}}; pub enum IRValueRefKind<'a> { - Ptr(IRPointer<'a>), + Ptr(&'a IRType<'a>, IRPointer<'a>), Val(IRValue<'a>), - Global(IRStaticVariable<'a>) + Global(&'a IRType<'a>, IRStaticVariable<'a>) } /// 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> { // TODO: maybe change IRValueRef to host the fields itself rather than having to use Options kind: IRValueRefKind<'a>, - - t: &'a IRType<'a> } impl<'a> IRValueRef<'a> { + pub fn from_val(val: IRValue<'a>) -> Self { + return IRValueRef { kind: IRValueRefKind::Val(val) } + } + /// Determines if aqcuiring the values require a load instruction or any instruction at all to obtain the value from. pub fn requires_load(&self) -> bool { - return matches!(self.kind, IRValueRefKind::Ptr(_)) + return matches!(self.kind, IRValueRefKind::Ptr(_, _)) } pub fn obtain(&self, builder: &'a Builder<'a>) -> PositionlessResult> { match &self.kind { - IRValueRefKind::Ptr(ptr) => { - ptr.load(builder, self.t) + IRValueRefKind::Ptr(t, ptr) => { + ptr.load(builder, t) }, IRValueRefKind::Val(v) => Ok(IRValue::clone(v)), - IRValueRefKind::Global(global) => { - Ok(IRValue::new(global.as_val()?, self.t)) + IRValueRefKind::Global(t, global) => { + Ok(IRValue::new(global.as_val()?, t)) } } } diff --git a/test-main/src/main.rs b/test-main/src/main.rs index 4edd4e2..7565919 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -1,7 +1,7 @@ use std::hash::{DefaultHasher, Hash, Hasher}; use inkwell::{context::Context, module::Module}; -use ir::{irstruct::{funcs::IRFunction, ptr::IRPointer}, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::{IRValue}}; +use ir::{irstruct::{funcs::IRFunction, ptr::IRPointer}, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::IRValue}; use parser::ast::func; fn main() { @@ -36,9 +36,9 @@ fn main() { let fmt_str = builder.build_global_string_ptr("Haiiiii, the value is %d\n", "fmt_str").unwrap(); - let ptr = IRPointer::create(&builder, String::from("test"), t, IRValue::from_unsigned(t, 286).unwrap()).unwrap(); + let ptr = IRPointer::create(&builder, String::from("test"), t, IRValueRef::from_val(IRValue::from_unsigned(t, 286).unwrap())).unwrap(); - let val = ptr.load(&builder).unwrap().obtain(); + let val = ptr.load(&builder, t).unwrap().obtain(); let _ = builder.build_call( printf_func.inkwell_func, From 3de494d064a6c9d4624ba139c32f072cb229f822 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 15:35:18 +0100 Subject: [PATCH 25/54] feat: added parser dependency on ir --- Cargo.lock | 1 + ir/Cargo.toml | 3 ++- ir/src/conv/mod.rs | 1 + ir/src/conv/vals.rs | 0 ir/src/irstruct/staticvars.rs | 2 +- 5 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 ir/src/conv/vals.rs diff --git a/Cargo.lock b/Cargo.lock index a294f1d..9aab5f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,6 +71,7 @@ dependencies = [ "commons", "inkwell", "lexer", + "parser", ] [[package]] diff --git a/ir/Cargo.toml b/ir/Cargo.toml index b2b845a..7b48c9a 100644 --- a/ir/Cargo.toml +++ b/ir/Cargo.toml @@ -6,4 +6,5 @@ edition = "2024" [dependencies] inkwell = { version = "0.8.0", features = ["llvm21-1"]} commons = { path = "../commons" } -lexer = { path = "../lexer" } \ No newline at end of file +lexer = { path = "../lexer" } +parser = { path = "../parser" } \ No newline at end of file diff --git a/ir/src/conv/mod.rs b/ir/src/conv/mod.rs index 3f11bbf..7cf45ea 100644 --- a/ir/src/conv/mod.rs +++ b/ir/src/conv/mod.rs @@ -1,2 +1,3 @@ //! Critical AST -> IR conversion code module +pub mod vals; \ No newline at end of file diff --git a/ir/src/conv/vals.rs b/ir/src/conv/vals.rs new file mode 100644 index 0000000..e69de29 diff --git a/ir/src/irstruct/staticvars.rs b/ir/src/irstruct/staticvars.rs index db29ed9..43cf26b 100644 --- a/ir/src/irstruct/staticvars.rs +++ b/ir/src/irstruct/staticvars.rs @@ -1,7 +1,7 @@ //! Static variable related code use commons::err::{PositionlessError, PositionlessResult}; -use inkwell::{builder::Builder, context::Context, types::StringRadix, values::{BasicValueEnum, GlobalValue, IntValue}}; +use inkwell::{builder::Builder, values::{BasicValueEnum, GlobalValue}}; use crate::{types::typing::IRType, values::IRValue}; From 344fe861a482d737d898ade2103b98f1f82177a2 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 15:52:33 +0100 Subject: [PATCH 26/54] chore: made functions return types compatible with non IntType<'a> types --- ir/src/conv/mod.rs | 2 -- ir/src/conv/vals.rs | 0 ir/src/irstruct/funcs.rs | 10 +++++----- ir/src/irstruct/mod.rs | 3 ++- ir/src/irstruct/structs.rs | 33 +++++++++++++++++++++++++++++++++ ir/src/types/typing.rs | 23 +++++++++++++++++++++-- test-main/src/main.rs | 1 - 7 files changed, 61 insertions(+), 11 deletions(-) delete mode 100644 ir/src/conv/vals.rs create mode 100644 ir/src/irstruct/structs.rs diff --git a/ir/src/conv/mod.rs b/ir/src/conv/mod.rs index 7cf45ea..a76f81e 100644 --- a/ir/src/conv/mod.rs +++ b/ir/src/conv/mod.rs @@ -1,3 +1 @@ //! Critical AST -> IR conversion code module - -pub mod vals; \ No newline at end of file diff --git a/ir/src/conv/vals.rs b/ir/src/conv/vals.rs deleted file mode 100644 index e69de29..0000000 diff --git a/ir/src/irstruct/funcs.rs b/ir/src/irstruct/funcs.rs index 003b212..4e8a1c5 100644 --- a/ir/src/irstruct/funcs.rs +++ b/ir/src/irstruct/funcs.rs @@ -1,5 +1,5 @@ use commons::err::{PositionedError, PositionlessError, PositionlessResult}; -use inkwell::{basic_block::BasicBlock, builder::Builder, context::Context, module::Module, values::{BasicValueEnum, FunctionValue, IntValue}}; +use inkwell::{basic_block::BasicBlock, builder::Builder, context::Context, module::Module, types::BasicType, values::{BasicValueEnum, FunctionValue, IntValue}}; use crate::types::typing::IRType; @@ -28,10 +28,10 @@ impl<'a> IRFunction<'a> { let mut kargs = vec![]; for k in &args { - kargs.push(k.get_inkwell_basetype()?); + kargs.push(k.get_inkwell_base_metadatatype()?); } - let t = ret_type.get_inkwell_inttype()?.fn_type(&kargs, false); + let t = ret_type.get_inkwell_basetype()?.fn_type(&kargs, false); let func = module.add_function(&name, t, None); @@ -42,10 +42,10 @@ impl<'a> IRFunction<'a> { let mut kargs = vec![]; for k in &args { - kargs.push(k.get_inkwell_basetype()?); + kargs.push(k.get_inkwell_base_metadatatype()?); } - let t = ret_type.get_inkwell_inttype()?.fn_type(&kargs, false); + let t = ret_type.get_inkwell_basetype()?.fn_type(&kargs, false); let func = module.add_function(&name, t, None); diff --git a/ir/src/irstruct/mod.rs b/ir/src/irstruct/mod.rs index 6f27e18..5ad68ad 100644 --- a/ir/src/irstruct/mod.rs +++ b/ir/src/irstruct/mod.rs @@ -2,4 +2,5 @@ pub mod ptr; pub mod funcs; -pub mod staticvars; \ No newline at end of file +pub mod staticvars; +pub mod structs; \ No newline at end of file diff --git a/ir/src/irstruct/structs.rs b/ir/src/irstruct/structs.rs new file mode 100644 index 0000000..3607401 --- /dev/null +++ b/ir/src/irstruct/structs.rs @@ -0,0 +1,33 @@ +//! IR representation of structure types (structs, layouts...) + +use commons::{err::PositionlessResult, utils::map::HashedMap}; +use inkwell::{context::Context, types::{BasicTypeEnum, StructType}}; + +use crate::types::typing::IRType; + +pub struct IRStructuredType<'a> { + pub inkwell_type: StructType<'a>, + pub field_to_index: HashedMap, + pub name: String, + pub is_layout: bool +} + +impl<'a> IRStructuredType<'a> { + pub fn new(ctx: &'a Context, name: String, layout: bool, fields: Vec<(u64, &'a IRType<'a>)>) -> PositionlessResult { + let mut map = HashedMap::new(fields.len()); + let mut typeVec: Vec> = Vec::new(); + + let mut ind = 0; + for entry in fields { + map.put(entry.0, ind); + + typeVec.push(entry.1.get_inkwell_basetype()?.into()); + + ind += ind; + } + + let inkwell_type = ctx.struct_type(&typeVec, !layout); + + + } +} \ No newline at end of file diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index cbbc553..2ef7a50 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -3,7 +3,7 @@ use std::{cell::Ref, collections::HashMap, ops::Add}; use commons::err::{PositionlessError, PositionlessResult}; -use inkwell::{AddressSpace, builder::Builder, context::Context, types::{BasicMetadataTypeEnum, BasicType, FunctionType, IntType, PointerType, StringRadix}, values::PointerValue}; +use inkwell::{AddressSpace, builder::Builder, context::Context, types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, IntType, PointerType, StringRadix}, values::PointerValue}; use crate::values::{IRValue}; @@ -111,7 +111,26 @@ 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)), + + _ => Err(PositionlessError::new("Given IR type doesn't have any Inkwell type!!!")) + } + } + + pub fn get_inkwell_base_metadatatype(&self) -> PositionlessResult> { match self { IRType::Unsigned8(v) => Ok(BasicMetadataTypeEnum::from(*v)), IRType::Unsigned16(v) => Ok(BasicMetadataTypeEnum::from(*v)), diff --git a/test-main/src/main.rs b/test-main/src/main.rs index 7565919..6d80824 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -25,7 +25,6 @@ fn main() { let int_type = storage.get(SIGNED32_TYPE_HASH).unwrap(); let ptr_type = storage.get(POINTER_TYPE_HASH).unwrap(); - let i32_type = context.i32_type(); let printf_func = IRFunction::create_shadow(String::from("printf"), &module, int_type, vec![ptr_type]).unwrap(); From ddaa343a4511512956fd33246202839ede3f65e2 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:12:22 +0100 Subject: [PATCH 27/54] feat: added sample struct type --- ir/src/irstruct/ptr.rs | 15 +++++++++++++-- ir/src/irstruct/structs.rs | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index c387cc6..0551b5f 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -1,5 +1,5 @@ use commons::err::{PositionlessError, PositionlessResult}; -use inkwell::{builder::Builder, values::{BasicValue, BasicValueEnum, IntValue, PointerValue}}; +use inkwell::{builder::Builder, types::BasicTypeEnum, values::{BasicValue, BasicValueEnum, IntValue, PointerValue}}; use crate::{refs::IRValueRef, types::typing::IRType, values::IRValue}; @@ -25,12 +25,23 @@ impl<'a> IRPointer<'a> { return Err(PositionlessError::new("Provided IRType isn't the same!")); } - match builder.build_load(*self.t.get_inkwell_inttype()?, self.inkwell_ptr, &self.name) { + match builder.build_load(self.t.get_inkwell_basetype()?, self.inkwell_ptr, &self.name) { Ok(v) => return Ok(IRValue::new(v, t)), Err(_) => return Err(PositionlessError::new("build_load failed!")) } } + pub fn load_from_inkwell_type(&self, builder: &'a Builder<'a>, t: BasicTypeEnum<'a>) -> PositionlessResult> { + if self.t.get_inkwell_basetype()? != t { + return Err(PositionlessError::new("Provided type isn't the same!")); + } + + match 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) { builder.build_store(self.inkwell_ptr, val); } diff --git a/ir/src/irstruct/structs.rs b/ir/src/irstruct/structs.rs index 3607401..e18283c 100644 --- a/ir/src/irstruct/structs.rs +++ b/ir/src/irstruct/structs.rs @@ -1,13 +1,14 @@ //! IR representation of structure types (structs, layouts...) -use commons::{err::PositionlessResult, utils::map::HashedMap}; -use inkwell::{context::Context, types::{BasicTypeEnum, StructType}}; +use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap}; +use inkwell::{builder::Builder, context::Context, types::{BasicTypeEnum, StructType}, values::PointerValue}; -use crate::types::typing::IRType; +use crate::{irstruct::ptr::IRPointer, types::typing::IRType}; pub struct IRStructuredType<'a> { pub inkwell_type: StructType<'a>, pub field_to_index: HashedMap, + pub field_types: Vec<&'a IRType<'a>>, pub name: String, pub is_layout: bool } @@ -16,11 +17,13 @@ impl<'a> IRStructuredType<'a> { pub fn new(ctx: &'a Context, name: String, layout: bool, fields: Vec<(u64, &'a IRType<'a>)>) -> 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 ind = 0; for entry in fields { map.put(entry.0, ind); + field_types.push(entry.1); typeVec.push(entry.1.get_inkwell_basetype()?.into()); ind += ind; @@ -28,6 +31,30 @@ impl<'a> IRStructuredType<'a> { let inkwell_type = ctx.struct_type(&typeVec, !layout); - + return Ok(Self { inkwell_type, field_to_index: map, name, is_layout: layout, field_types }) } -} \ No newline at end of file + + pub fn get_pointer_for_field_index(&'a self, builder: &'a Builder<'a>, instance: &'a IRPointer<'a>, ind: u32) -> PositionlessResult> { + if ind <= 0 || ind >= self.field_types.len() as u32 { + return Err(PositionlessError::new("Invalid index given to get_pointer_for_field_index")); + } + + let field_ptr = match builder.build_struct_gep(self.inkwell_type, instance.load_from_inkwell_type(builder, self.inkwell_type.into())?.obtain().into_pointer_value(), ind, "field_ptr") { + Ok(v) => v, + Err(_) => return Err(PositionlessError::new("build_struct_gep failed!")) + }; + + let field_type = self.field_types[ind as usize]; + + return Ok(IRPointer::new(field_ptr, field_type, String::from("__inner_field_ptr"))); + } + + pub fn get_pointer_for_field(&'a self, builder: &'a Builder<'a>, instance: &'a IRPointer<'a>, 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))) + }; + + return self.get_pointer_for_field_index(builder, instance, k); + } +} From e94a5e804f35523d1d5ba302f75e40dce15041c9 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:22:08 +0100 Subject: [PATCH 28/54] feat: added IRType::iks_same to avoid using PartialEq --- ir/src/irstruct/structs.rs | 1 + ir/src/types/typing.rs | 31 +++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/ir/src/irstruct/structs.rs b/ir/src/irstruct/structs.rs index e18283c..6013e3d 100644 --- a/ir/src/irstruct/structs.rs +++ b/ir/src/irstruct/structs.rs @@ -5,6 +5,7 @@ use inkwell::{builder::Builder, context::Context, types::{BasicTypeEnum, StructT use crate::{irstruct::ptr::IRPointer, types::typing::IRType}; +#[derive(PartialEq)] pub struct IRStructuredType<'a> { pub inkwell_type: StructType<'a>, pub field_to_index: HashedMap, diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index 2ef7a50..fa87d95 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -5,10 +5,9 @@ use std::{cell::Ref, collections::HashMap, ops::Add}; use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{AddressSpace, builder::Builder, context::Context, types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, IntType, PointerType, StringRadix}, values::PointerValue}; -use crate::values::{IRValue}; +use crate::{irstruct::structs::IRStructuredType, values::IRValue}; /// Types of IR variables -#[derive(PartialEq)] pub enum IRType<'a> { Signed8(IntType<'a>), Signed16(IntType<'a>), @@ -26,8 +25,8 @@ pub enum IRType<'a> { Bool(IntType<'a>), - Struct(HashMap>), // fields - Layout(HashMap>) // fields + Struct(IRStructuredType<'a>), + Layout(IRStructuredType<'a>) } impl<'a> IRType<'a> { @@ -189,4 +188,28 @@ impl<'a> IRType<'a> { return Ok(alloca); } + /// 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) { + (IRType::Signed8(_), IRType::Signed8(_)) => true, + (IRType::Signed16(_), IRType::Signed16(_)) => true, + (IRType::Signed32(_), IRType::Signed32(_)) => true, + (IRType::Signed64(_), IRType::Signed64(_)) => true, + (IRType::Signed128(_), IRType::Signed128(_)) => true, + + (IRType::Unsigned8(_), IRType::Unsigned8(_)) => true, + (IRType::Unsigned16(_), IRType::Unsigned16(_)) => true, + (IRType::Unsigned32(_), IRType::Unsigned32(_)) => true, + (IRType::Unsigned64(_), IRType::Unsigned64(_)) => true, + (IRType::Unsigned128(_), IRType::Unsigned128(_)) => true, + + (IRType::Bool(_), IRType::Bool(_)) => true, + + (IRType::Struct(a), IRType::Struct(b)) => a.name == b.name && a.is_layout == b.is_layout, + (IRType::Layout(a), IRType::Layout(b)) => a.name == b.name && a.is_layout == b.is_layout + + _ => false + } + } + } \ No newline at end of file From fb36f570a4e1384d34380efe78d9a21b06992f30 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:24:14 +0100 Subject: [PATCH 29/54] feat: fully migrated IRType::Struct & IRType::Layout to use the better IRStructuredType --- ir/src/irstruct/structs.rs | 3 +-- ir/src/types/typing.rs | 10 +++++----- ir/src/values.rs | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/ir/src/irstruct/structs.rs b/ir/src/irstruct/structs.rs index 6013e3d..c919951 100644 --- a/ir/src/irstruct/structs.rs +++ b/ir/src/irstruct/structs.rs @@ -1,11 +1,10 @@ //! IR representation of structure types (structs, layouts...) use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap}; -use inkwell::{builder::Builder, context::Context, types::{BasicTypeEnum, StructType}, values::PointerValue}; +use inkwell::{builder::Builder, context::Context, types::{BasicTypeEnum, StructType}}; use crate::{irstruct::ptr::IRPointer, types::typing::IRType}; -#[derive(PartialEq)] pub struct IRStructuredType<'a> { pub inkwell_type: StructType<'a>, pub field_to_index: HashedMap, diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index fa87d95..81bced7 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -45,8 +45,8 @@ impl<'a> IRType<'a> { // TODO: add bool compacting - for (_, ir_type) in v { - sz += ir_type.get_bitsize(); + for t in &v.field_types { + sz += t.get_bitsize(); } return sz; @@ -55,8 +55,8 @@ impl<'a> IRType<'a> { IRType::Layout(v) => { let mut sz: usize = 0; - for (_, ir_type) in v { - sz += ir_type.get_bitsize(); + for t in &v.field_types { + sz += t.get_bitsize(); } return sz; @@ -206,7 +206,7 @@ impl<'a> IRType<'a> { (IRType::Bool(_), IRType::Bool(_)) => true, (IRType::Struct(a), IRType::Struct(b)) => a.name == b.name && a.is_layout == b.is_layout, - (IRType::Layout(a), IRType::Layout(b)) => a.name == b.name && a.is_layout == b.is_layout + (IRType::Layout(a), IRType::Layout(b)) => a.name == b.name && a.is_layout == b.is_layout, _ => false } diff --git a/ir/src/values.rs b/ir/src/values.rs index 08156bd..ccdd7c3 100644 --- a/ir/src/values.rs +++ b/ir/src/values.rs @@ -64,7 +64,7 @@ impl<'a> IRValue<'a> { /// 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() || t != self.t { + if !self.t.is_numeric_type() || !self.t.is_same(t) { return None; } From c3e7dcf54daf85991d598feda83cecc042f41583 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:24:47 +0100 Subject: [PATCH 30/54] fix: fixed IRPointer to use the new is_same --- ir/src/irstruct/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index 0551b5f..6ca4b54 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -21,7 +21,7 @@ impl<'a> IRPointer<'a> { } pub fn load(&self, builder: &Builder<'a>, t: &'a IRType<'a>) -> PositionlessResult> { - if self.t != t { + if !self.t.is_same(t) { return Err(PositionlessError::new("Provided IRType isn't the same!")); } From da270c9d160debdb3e53f242a9af61f8ad32c55f Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:36:27 +0100 Subject: [PATCH 31/54] feat: made IRPointer::create work with any IRType rather than just int ones! Also made initial value optional! --- ir/src/irstruct/ptr.rs | 21 +++++++++++++++++---- test-main/src/main.rs | 7 +++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index 6ca4b54..fd4a1b6 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -14,8 +14,18 @@ impl<'a> IRPointer<'a> { return IRPointer { inkwell_ptr: ptr, name, t } } - pub fn create(builder: &'a Builder<'a>, name: String, t: &'a IRType<'a>, initial: IRValueRef<'a>) -> PositionlessResult { - let ptr = t.make_numeric_stackvar(builder, name.clone(), initial.obtain(builder)?)?; + pub fn create(builder: &'a Builder<'a>, name: String, t: &'a IRType<'a>, initial: Option>) -> PositionlessResult { + let ptr = match builder.build_alloca(t.get_inkwell_basetype()?, &name) { + Ok(v) => v, + Err(_) => return Err(PositionlessError::new("build_alloca failed!")) + }; + + if initial.is_some() { + match builder.build_store(ptr, initial.unwrap().obtain(builder)?.obtain()) { + Err(_) => return Err(PositionlessError::new("build_store failed!")), + Ok(_) => {} + }; + } return Ok(IRPointer { inkwell_ptr: ptr, t, name: name.clone() }); } @@ -42,8 +52,11 @@ impl<'a> IRPointer<'a> { } } - pub fn store>(&self, builder: &Builder<'a>, val: V) { - builder.build_store(self.inkwell_ptr, val); + pub fn store>(&self, builder: &Builder<'a>, val: V) -> bool { + return match builder.build_store(self.inkwell_ptr, val) { + Ok(_) => true, + Err(_) => false + } } } \ No newline at end of file diff --git a/test-main/src/main.rs b/test-main/src/main.rs index 6d80824..1de272e 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -1,7 +1,7 @@ use std::hash::{DefaultHasher, Hash, Hasher}; use inkwell::{context::Context, module::Module}; -use ir::{irstruct::{funcs::IRFunction, ptr::IRPointer}, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::IRValue}; +use ir::{irstruct::{funcs::IRFunction, ptr::IRPointer, structs::IRStructuredType}, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::IRValue}; use parser::ast::func; fn main() { @@ -16,7 +16,7 @@ fn main() { let context = Context::create(); - let storage = IRTypeStorage::new(&context); + let mut storage = IRTypeStorage::new(&context); let module= context.create_module("main_module"); let builder = context.create_builder(); @@ -25,6 +25,9 @@ fn main() { let int_type = storage.get(SIGNED32_TYPE_HASH).unwrap(); let ptr_type = storage.get(POINTER_TYPE_HASH).unwrap(); + let sample_struct_test_type = IRStructuredType::new(&context, String::from("myTestStruct"), true, vec![(8417845746417243860, int_type)]).unwrap(); + //storage.insert(15869126390205824132, IRType::Struct(sample_struct_test_type)); + let i32_type = context.i32_type(); let printf_func = IRFunction::create_shadow(String::from("printf"), &module, int_type, vec![ptr_type]).unwrap(); From 00c84c6168bc2fae0db3522383ad642559d5c8c1 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:48:09 +0100 Subject: [PATCH 32/54] =?UTF-8?q?feat:=20added=20struct=20&=20layout=20sup?= =?UTF-8?q?port=20for=20get=5Finkwell=5Fbase=5Fmetadatatype=20and=20get?= =?UTF-8?q?=C3=83=5Finkwell=5Fbasetype?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ir/src/types/typing.rs | 16 +++++++++++++++- test-main/src/main.rs | 22 +++++++++++++++------- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index 81bced7..f508619 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -124,6 +124,9 @@ impl<'a> IRType<'a> { 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)), _ => Err(PositionlessError::new("Given IR type doesn't have any Inkwell type!!!")) } @@ -143,7 +146,10 @@ impl<'a> IRType<'a> { 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)), + _ => Err(PositionlessError::new("Given IR type doesn't have any Inkwell type!!!")) } } @@ -212,4 +218,12 @@ impl<'a> IRType<'a> { } } + pub fn get_structured_type_descriptor(&'a self) -> PositionlessResult<&'a IRStructuredType<'a>> { + return match self { + IRType::Struct(e) => Ok(e), + IRType::Layout(e) => Ok(e), + _ => Err(PositionlessError::new("Given IRType doesn't have a structured type descriptor!")) + } + } + } \ No newline at end of file diff --git a/test-main/src/main.rs b/test-main/src/main.rs index 1de272e..e9c0889 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -25,8 +25,11 @@ fn main() { let int_type = storage.get(SIGNED32_TYPE_HASH).unwrap(); let ptr_type = storage.get(POINTER_TYPE_HASH).unwrap(); - let sample_struct_test_type = IRStructuredType::new(&context, String::from("myTestStruct"), true, vec![(8417845746417243860, int_type)]).unwrap(); - //storage.insert(15869126390205824132, IRType::Struct(sample_struct_test_type)); + let sample_struct = IRType::Struct( + IRStructuredType::new(&context, String::from("myTestStruct"), true, vec![(8417845746417243860, int_type)]).unwrap() + ); + //storage.insert(15869126390205824132, sample_struct); + let i32_type = context.i32_type(); @@ -35,13 +38,18 @@ fn main() { let func = IRFunction::create(&context, String::from("main"), &module, t, vec![t, t]).expect("Couldn't make IR function"); func.prepare_body_filling(&builder); - let fmt_str = builder.build_global_string_ptr("Haiiiii, the value is %d\n", "fmt_str").unwrap(); - let ptr = IRPointer::create(&builder, String::from("test"), t, IRValueRef::from_val(IRValue::from_unsigned(t, 286).unwrap())).unwrap(); - - let val = ptr.load(&builder, t).unwrap().obtain(); + // Struct test + let structInstance = IRPointer::create(&builder, String::from("test"), &sample_struct, None).unwrap(); + let firstFieldPointer = sample_struct.get_structured_type_descriptor().unwrap().get_pointer_for_field_index(&builder, &structInstance, 0).unwrap(); + firstFieldPointer.store(&builder, int_type.get_inkwell_inttype().unwrap().const_int(125, false)); + + let val = (&firstFieldPointer).load(&builder, &int_type).unwrap().obtain(); + + // End struct test + let _ = builder.build_call( printf_func.inkwell_func, &[ @@ -49,7 +57,7 @@ fn main() { val.into(), ], "printf_call" -); + ); builder.build_return(Some(&i32_type.const_zero())); From e4385e73e6e743f066105d8c8154a674831c4334 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:48:46 +0100 Subject: [PATCH 33/54] fix: fixed gett_pointer_for_field doing a wrong and useless index check --- ir/src/irstruct/structs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ir/src/irstruct/structs.rs b/ir/src/irstruct/structs.rs index c919951..5640990 100644 --- a/ir/src/irstruct/structs.rs +++ b/ir/src/irstruct/structs.rs @@ -35,7 +35,7 @@ impl<'a> IRStructuredType<'a> { } pub fn get_pointer_for_field_index(&'a self, builder: &'a Builder<'a>, instance: &'a IRPointer<'a>, ind: u32) -> PositionlessResult> { - if ind <= 0 || ind >= self.field_types.len() as u32 { + if ind >= self.field_types.len() as u32 { return Err(PositionlessError::new("Invalid index given to get_pointer_for_field_index")); } From 8235bc154dab6058d161fd59fbac7b7a5dd37aa4 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 17:05:02 +0100 Subject: [PATCH 34/54] feat: added function to get the IRType's used type for loads --- ir/src/irstruct/ptr.rs | 12 ++++++------ ir/src/irstruct/structs.rs | 10 +++++----- ir/src/types/typing.rs | 14 ++++++++++++++ test-main/src/main.rs | 4 +++- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index fd4a1b6..65f14ff 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -1,5 +1,5 @@ use commons::err::{PositionlessError, PositionlessResult}; -use inkwell::{builder::Builder, types::BasicTypeEnum, values::{BasicValue, BasicValueEnum, IntValue, PointerValue}}; +use inkwell::{builder::Builder, context::Context, types::BasicTypeEnum, values::{BasicValue, BasicValueEnum, IntValue, PointerValue}}; use crate::{refs::IRValueRef, types::typing::IRType, values::IRValue}; @@ -30,20 +30,20 @@ impl<'a> IRPointer<'a> { return Ok(IRPointer { inkwell_ptr: ptr, t, name: name.clone() }); } - pub fn load(&self, builder: &Builder<'a>, t: &'a IRType<'a>) -> PositionlessResult> { + pub fn load(&self, ctx: &'a Context, builder: &Builder<'a>, t: &'a IRType<'a>) -> PositionlessResult> { if !self.t.is_same(t) { return Err(PositionlessError::new("Provided IRType isn't the same!")); } - match builder.build_load(self.t.get_inkwell_basetype()?, self.inkwell_ptr, &self.name) { + match builder.build_load(self.t.get_inkwell_instance_basetype(ctx)?, self.inkwell_ptr, &self.name) { Ok(v) => return Ok(IRValue::new(v, t)), Err(_) => return Err(PositionlessError::new("build_load failed!")) } } - pub fn load_from_inkwell_type(&self, builder: &'a Builder<'a>, t: BasicTypeEnum<'a>) -> PositionlessResult> { - if self.t.get_inkwell_basetype()? != t { - return Err(PositionlessError::new("Provided type isn't the same!")); + pub fn load_from_inkwell_type(&self, ctx: &'a Context, builder: &'a Builder<'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 builder.build_load(t, self.inkwell_ptr, &self.name) { diff --git a/ir/src/irstruct/structs.rs b/ir/src/irstruct/structs.rs index 5640990..1529fa1 100644 --- a/ir/src/irstruct/structs.rs +++ b/ir/src/irstruct/structs.rs @@ -1,7 +1,7 @@ //! IR representation of structure types (structs, layouts...) use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap}; -use inkwell::{builder::Builder, context::Context, types::{BasicTypeEnum, StructType}}; +use inkwell::{AddressSpace, builder::Builder, context::Context, types::{BasicTypeEnum, StructType}}; use crate::{irstruct::ptr::IRPointer, types::typing::IRType}; @@ -34,12 +34,12 @@ impl<'a> IRStructuredType<'a> { return Ok(Self { inkwell_type, field_to_index: map, name, is_layout: layout, field_types }) } - pub fn get_pointer_for_field_index(&'a self, builder: &'a Builder<'a>, instance: &'a IRPointer<'a>, ind: u32) -> PositionlessResult> { + pub fn get_pointer_for_field_index(&'a self, ctx: &'a Context, builder: &'a Builder<'a>, instance: &'a IRPointer<'a>, ind: u32) -> PositionlessResult> { if ind >= self.field_types.len() as u32 { return Err(PositionlessError::new("Invalid index given to get_pointer_for_field_index")); } - let field_ptr = match builder.build_struct_gep(self.inkwell_type, instance.load_from_inkwell_type(builder, self.inkwell_type.into())?.obtain().into_pointer_value(), ind, "field_ptr") { + let field_ptr = match builder.build_struct_gep(self.inkwell_type, instance.load_from_inkwell_type(builder, ctx.ptr_type(AddressSpace::from(0)).into())?.obtain().into_pointer_value(), ind, "field_ptr") { Ok(v) => v, Err(_) => return Err(PositionlessError::new("build_struct_gep failed!")) }; @@ -49,12 +49,12 @@ impl<'a> IRStructuredType<'a> { return Ok(IRPointer::new(field_ptr, field_type, String::from("__inner_field_ptr"))); } - pub fn get_pointer_for_field(&'a self, builder: &'a Builder<'a>, instance: &'a IRPointer<'a>, hash: u64) -> PositionlessResult> { + pub fn get_pointer_for_field(&'a self, ctx: &'a Context, builder: &'a Builder<'a>, instance: &'a IRPointer<'a>, 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))) }; - return self.get_pointer_for_field_index(builder, instance, k); + return self.get_pointer_for_field_index(ctx, builder, instance, k); } } diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index f508619..cbfb06c 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -132,6 +132,13 @@ impl<'a> IRType<'a> { } } + pub fn get_inkwell_instance_basetype(&self, ctx: &'a Context) -> PositionlessResult> { + match self { + IRType::Struct(_) | IRType::Layout(_) => Ok(ctx.ptr_type(AddressSpace::from(0)).into()), + _ => self.get_inkwell_basetype() + } + } + pub fn get_inkwell_base_metadatatype(&self) -> PositionlessResult> { match self { IRType::Unsigned8(v) => Ok(BasicMetadataTypeEnum::from(*v)), @@ -226,4 +233,11 @@ impl<'a> IRType<'a> { } } + pub fn has_structured_type_descriptor(&'a self) -> bool { + return match self { + IRType::Struct(_) | IRType::Layout(_) => true, + _ => false + } + } + } \ No newline at end of file diff --git a/test-main/src/main.rs b/test-main/src/main.rs index e9c0889..3eab906 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -42,7 +42,9 @@ fn main() { // Struct test let structInstance = IRPointer::create(&builder, String::from("test"), &sample_struct, None).unwrap(); - let firstFieldPointer = sample_struct.get_structured_type_descriptor().unwrap().get_pointer_for_field_index(&builder, &structInstance, 0).unwrap(); + + + let firstFieldPointer = sample_struct.get_structured_type_descriptor().unwrap().get_pointer_for_field_index(&context, &builder, &structInstance, 0).unwrap(); firstFieldPointer.store(&builder, int_type.get_inkwell_inttype().unwrap().const_int(125, false)); From 15a3fc12efc23406ebd1ce847f386079abd26395 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 17:07:28 +0100 Subject: [PATCH 35/54] feat: started working on passing IRContext on every function that needs it --- ir/src/ctx.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ir/src/ctx.rs b/ir/src/ctx.rs index 05ff3ab..09e150a 100644 --- a/ir/src/ctx.rs +++ b/ir/src/ctx.rs @@ -1,7 +1,9 @@ //! IR context related code +use std::ops::Add; + use commons::utils::map::HashedMap; -use inkwell::context::Context; +use inkwell::{AddressSpace, builder::Builder, context::Context, types::PointerType}; use crate::irstruct::{funcs::IRFunction, ptr::IRPointer}; @@ -9,7 +11,15 @@ use crate::irstruct::{funcs::IRFunction, ptr::IRPointer}; /// 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 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) } + } } \ No newline at end of file From 4023b426cee3b8648fa3943330640946ab1d87ea Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 17:13:14 +0100 Subject: [PATCH 36/54] feat: changed every raw reference to LLVM context to use IRContext --- ir/src/irstruct/ptr.rs | 16 ++++++++-------- ir/src/irstruct/structs.rs | 14 +++++++------- ir/src/refs.rs | 6 +++--- ir/src/types/typing.rs | 6 +++--- test-main/src/main.rs | 22 ++++++++++++---------- 5 files changed, 33 insertions(+), 31 deletions(-) diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index 65f14ff..9c801f7 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -1,7 +1,7 @@ use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{builder::Builder, context::Context, types::BasicTypeEnum, values::{BasicValue, BasicValueEnum, IntValue, PointerValue}}; -use crate::{refs::IRValueRef, types::typing::IRType, values::IRValue}; +use crate::{ctx::IRContext, refs::IRValueRef, types::typing::IRType, values::IRValue}; pub struct IRPointer<'a> { inkwell_ptr: PointerValue<'a>, @@ -14,14 +14,14 @@ impl<'a> IRPointer<'a> { return IRPointer { inkwell_ptr: ptr, name, t } } - pub fn create(builder: &'a Builder<'a>, name: String, t: &'a IRType<'a>, initial: Option>) -> PositionlessResult { - let ptr = match builder.build_alloca(t.get_inkwell_basetype()?, &name) { + 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) { Ok(v) => v, Err(_) => return Err(PositionlessError::new("build_alloca failed!")) }; if initial.is_some() { - match builder.build_store(ptr, initial.unwrap().obtain(builder)?.obtain()) { + match ctx.builder.build_store(ptr, initial.unwrap().obtain(ctx)?.obtain()) { Err(_) => return Err(PositionlessError::new("build_store failed!")), Ok(_) => {} }; @@ -30,23 +30,23 @@ impl<'a> IRPointer<'a> { return Ok(IRPointer { inkwell_ptr: ptr, t, name: name.clone() }); } - pub fn load(&self, ctx: &'a Context, builder: &Builder<'a>, t: &'a IRType<'a>) -> PositionlessResult> { + pub fn load(&self, ctx: &'a IRContext<'a>, t: &'a IRType<'a>) -> PositionlessResult> { if !self.t.is_same(t) { return Err(PositionlessError::new("Provided IRType isn't the same!")); } - match builder.build_load(self.t.get_inkwell_instance_basetype(ctx)?, self.inkwell_ptr, &self.name) { + 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)), Err(_) => return Err(PositionlessError::new("build_load failed!")) } } - pub fn load_from_inkwell_type(&self, ctx: &'a Context, builder: &'a Builder<'a>, t: BasicTypeEnum<'a>) -> PositionlessResult> { + 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 builder.build_load(t, self.inkwell_ptr, &self.name) { + 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!")) } diff --git a/ir/src/irstruct/structs.rs b/ir/src/irstruct/structs.rs index 1529fa1..2119405 100644 --- a/ir/src/irstruct/structs.rs +++ b/ir/src/irstruct/structs.rs @@ -3,7 +3,7 @@ use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap}; use inkwell::{AddressSpace, builder::Builder, context::Context, types::{BasicTypeEnum, StructType}}; -use crate::{irstruct::ptr::IRPointer, types::typing::IRType}; +use crate::{ctx::IRContext, irstruct::ptr::IRPointer, types::typing::IRType}; pub struct IRStructuredType<'a> { pub inkwell_type: StructType<'a>, @@ -14,7 +14,7 @@ pub struct IRStructuredType<'a> { } impl<'a> IRStructuredType<'a> { - pub fn new(ctx: &'a Context, name: String, layout: bool, fields: Vec<(u64, &'a IRType<'a>)>) -> PositionlessResult { + pub fn new(ctx: &'a IRContext<'a>, name: String, layout: bool, fields: Vec<(u64, &'a IRType<'a>)>) -> PositionlessResult { let mut map = HashedMap::new(fields.len()); let mut typeVec: Vec> = Vec::new(); let mut field_types: Vec<&'a IRType<'a>> = Vec::new(); @@ -29,17 +29,17 @@ impl<'a> IRStructuredType<'a> { ind += ind; } - let inkwell_type = ctx.struct_type(&typeVec, !layout); + 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 }) } - pub fn get_pointer_for_field_index(&'a self, ctx: &'a Context, builder: &'a Builder<'a>, instance: &'a IRPointer<'a>, ind: u32) -> PositionlessResult> { + pub fn get_pointer_for_field_index(&'a self, ctx: &'a IRContext<'a>, instance: &'a IRPointer<'a>, ind: u32) -> PositionlessResult> { if ind >= self.field_types.len() as u32 { return Err(PositionlessError::new("Invalid index given to get_pointer_for_field_index")); } - let field_ptr = match builder.build_struct_gep(self.inkwell_type, instance.load_from_inkwell_type(builder, ctx.ptr_type(AddressSpace::from(0)).into())?.obtain().into_pointer_value(), ind, "field_ptr") { + let field_ptr = match ctx.builder.build_struct_gep(self.inkwell_type, instance.load_from_inkwell_type(ctx, ctx.ptr_type.into())?.obtain().into_pointer_value(), ind, "field_ptr") { Ok(v) => v, Err(_) => return Err(PositionlessError::new("build_struct_gep failed!")) }; @@ -49,12 +49,12 @@ impl<'a> IRStructuredType<'a> { return Ok(IRPointer::new(field_ptr, field_type, String::from("__inner_field_ptr"))); } - pub fn get_pointer_for_field(&'a self, ctx: &'a Context, builder: &'a Builder<'a>, instance: &'a IRPointer<'a>, hash: u64) -> PositionlessResult> { + pub fn get_pointer_for_field(&'a self, ctx: &'a IRContext<'a>, instance: &'a IRPointer<'a>, 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))) }; - return self.get_pointer_for_field_index(ctx, builder, instance, k); + return self.get_pointer_for_field_index(ctx, instance, k); } } diff --git a/ir/src/refs.rs b/ir/src/refs.rs index 471c758..1d6efa4 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -3,7 +3,7 @@ use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{builder::Builder, types::{AnyTypeEnum, BasicTypeEnum}}; -use crate::{irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::IRType, values::{IRValue}}; +use crate::{ctx::IRContext, irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::IRType, values::IRValue}; pub enum IRValueRefKind<'a> { Ptr(&'a IRType<'a>, IRPointer<'a>), @@ -27,10 +27,10 @@ impl<'a> IRValueRef<'a> { return matches!(self.kind, IRValueRefKind::Ptr(_, _)) } - pub fn obtain(&self, builder: &'a Builder<'a>) -> PositionlessResult> { + pub fn obtain(&self, ctx: &'a IRContext<'a>) -> PositionlessResult> { match &self.kind { IRValueRefKind::Ptr(t, ptr) => { - ptr.load(builder, t) + ptr.load(ctx, t) }, IRValueRefKind::Val(v) => Ok(IRValue::clone(v)), diff --git a/ir/src/types/typing.rs b/ir/src/types/typing.rs index cbfb06c..43d6461 100644 --- a/ir/src/types/typing.rs +++ b/ir/src/types/typing.rs @@ -5,7 +5,7 @@ use std::{cell::Ref, collections::HashMap, ops::Add}; use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{AddressSpace, builder::Builder, context::Context, types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, IntType, PointerType, StringRadix}, values::PointerValue}; -use crate::{irstruct::structs::IRStructuredType, values::IRValue}; +use crate::{ctx::IRContext, irstruct::structs::IRStructuredType, values::IRValue}; /// Types of IR variables pub enum IRType<'a> { @@ -132,9 +132,9 @@ impl<'a> IRType<'a> { } } - pub fn get_inkwell_instance_basetype(&self, ctx: &'a Context) -> PositionlessResult> { + pub fn get_inkwell_instance_basetype(&self, ctx: &'a IRContext<'a>) -> PositionlessResult> { match self { - IRType::Struct(_) | IRType::Layout(_) => Ok(ctx.ptr_type(AddressSpace::from(0)).into()), + IRType::Struct(_) | IRType::Layout(_) => Ok(ctx.ptr_type.into()), _ => self.get_inkwell_basetype() } } diff --git a/test-main/src/main.rs b/test-main/src/main.rs index 3eab906..ad18276 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -1,7 +1,7 @@ use std::hash::{DefaultHasher, Hash, Hasher}; use inkwell::{context::Context, module::Module}; -use ir::{irstruct::{funcs::IRFunction, ptr::IRPointer, structs::IRStructuredType}, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::IRValue}; +use ir::{ctx::IRContext, irstruct::{funcs::IRFunction, ptr::IRPointer, structs::IRStructuredType}, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::IRValue}; use parser::ast::func; fn main() { @@ -21,12 +21,14 @@ fn main() { let module= context.create_module("main_module"); let builder = context.create_builder(); + let irctx = IRContext::new(builder, &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 sample_struct = IRType::Struct( - IRStructuredType::new(&context, String::from("myTestStruct"), true, vec![(8417845746417243860, int_type)]).unwrap() + IRStructuredType::new(&irctx, String::from("myTestStruct"), true, vec![(8417845746417243860, int_type)]).unwrap() ); //storage.insert(15869126390205824132, sample_struct); @@ -36,23 +38,23 @@ fn main() { let printf_func = IRFunction::create_shadow(String::from("printf"), &module, int_type, vec![ptr_type]).unwrap(); let func = IRFunction::create(&context, String::from("main"), &module, t, vec![t, t]).expect("Couldn't make IR function"); - func.prepare_body_filling(&builder); + func.prepare_body_filling(&irctx.builder); - let fmt_str = builder.build_global_string_ptr("Haiiiii, the value is %d\n", "fmt_str").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(&builder, String::from("test"), &sample_struct, None).unwrap(); + let structInstance = IRPointer::create(&irctx, String::from("test"), &sample_struct, None).unwrap(); - let firstFieldPointer = sample_struct.get_structured_type_descriptor().unwrap().get_pointer_for_field_index(&context, &builder, &structInstance, 0).unwrap(); + let firstFieldPointer = sample_struct.get_structured_type_descriptor().unwrap().get_pointer_for_field_index(&irctx, &structInstance, 0).unwrap(); - firstFieldPointer.store(&builder, int_type.get_inkwell_inttype().unwrap().const_int(125, false)); + firstFieldPointer.store(&irctx.builder, int_type.get_inkwell_inttype().unwrap().const_int(125, false)); - let val = (&firstFieldPointer).load(&builder, &int_type).unwrap().obtain(); + let val = (&firstFieldPointer).load(&irctx, &int_type).unwrap().obtain(); // End struct test - let _ = builder.build_call( + let _ = irctx.builder.build_call( printf_func.inkwell_func, &[ fmt_str.as_pointer_value().into(), @@ -61,7 +63,7 @@ fn main() { "printf_call" ); - builder.build_return(Some(&i32_type.const_zero())); + irctx.builder.build_return(Some(&i32_type.const_zero())); module.print_to_file("output.ll").unwrap(); From abe5265af7361a5b66450acce84c111cf2011f40 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 17:28:51 +0100 Subject: [PATCH 37/54] fix: removed a useless pointer load when trying to use get_pointer_for_field_index --- ir/src/irstruct/ptr.rs | 2 +- ir/src/irstruct/structs.rs | 2 +- test-main/src/main.rs | 15 +++++++++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index 9c801f7..623558f 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -4,7 +4,7 @@ use inkwell::{builder::Builder, context::Context, types::BasicTypeEnum, values:: use crate::{ctx::IRContext, refs::IRValueRef, types::typing::IRType, values::IRValue}; pub struct IRPointer<'a> { - inkwell_ptr: PointerValue<'a>, + pub inkwell_ptr: PointerValue<'a>, // Only use this directly within structs t: &'a IRType<'a>, pub name: String } diff --git a/ir/src/irstruct/structs.rs b/ir/src/irstruct/structs.rs index 2119405..642c066 100644 --- a/ir/src/irstruct/structs.rs +++ b/ir/src/irstruct/structs.rs @@ -39,7 +39,7 @@ impl<'a> IRStructuredType<'a> { return Err(PositionlessError::new("Invalid index given to get_pointer_for_field_index")); } - let field_ptr = match ctx.builder.build_struct_gep(self.inkwell_type, instance.load_from_inkwell_type(ctx, ctx.ptr_type.into())?.obtain().into_pointer_value(), ind, "field_ptr") { + let field_ptr = match ctx.builder.build_struct_gep(self.inkwell_type, instance.inkwell_ptr, ind, "field_ptr") { Ok(v) => v, Err(_) => return Err(PositionlessError::new("build_struct_gep failed!")) }; diff --git a/test-main/src/main.rs b/test-main/src/main.rs index ad18276..1d65aaa 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -27,9 +27,14 @@ fn main() { let int_type = storage.get(SIGNED32_TYPE_HASH).unwrap(); let ptr_type = storage.get(POINTER_TYPE_HASH).unwrap(); + let sample_substruct = IRType::Struct( + IRStructuredType::new(&irctx, String::from("uwuStruct"), true, vec![(8417845746417243860, int_type)]).unwrap() + ); + let sample_struct = IRType::Struct( - IRStructuredType::new(&irctx, String::from("myTestStruct"), true, vec![(8417845746417243860, int_type)]).unwrap() + IRStructuredType::new(&irctx, String::from("myTestStruct"), true, vec![(8417845746417243860, &sample_substruct)]).unwrap() ); + //storage.insert(15869126390205824132, sample_struct); @@ -45,12 +50,14 @@ fn main() { // Struct test let structInstance = IRPointer::create(&irctx, String::from("test"), &sample_struct, 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 firstFieldPointer = sample_struct.get_structured_type_descriptor().unwrap().get_pointer_for_field_index(&irctx, &structInstance, 0).unwrap(); + subStructVarPtr.store(&irctx.builder, int_type.get_inkwell_inttype().unwrap().const_int(1288, false)); - firstFieldPointer.store(&irctx.builder, int_type.get_inkwell_inttype().unwrap().const_int(125, false)); + let val = subStructVarPtr.load(&irctx, int_type).unwrap().obtain(); - let val = (&firstFieldPointer).load(&irctx, &int_type).unwrap().obtain(); + //firstFieldPointer.store(&irctx.builder, int_type.get_inkwell_inttype().unwrap().const_int(125, false)); // End struct test From 16f31a81645f46fd0165684574502e6cfee21166 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 18:46:59 +0100 Subject: [PATCH 38/54] feat: added get_variable_ref --- commons/src/utils/map.rs | 15 ++++++ ir/src/conv/mod.rs | 2 + ir/src/conv/val.rs | 22 ++++++++ ir/src/ctx.rs | 94 +++++++++++++++++++++++++++++++++-- ir/src/irstruct/ptr.rs | 3 +- ir/src/irstruct/staticvars.rs | 3 +- ir/src/refs.rs | 17 ++++++- test-main/src/main.rs | 15 +++--- 8 files changed, 157 insertions(+), 14 deletions(-) create mode 100644 ir/src/conv/val.rs diff --git a/commons/src/utils/map.rs b/commons/src/utils/map.rs index 24501b1..3a3881e 100644 --- a/commons/src/utils/map.rs +++ b/commons/src/utils/map.rs @@ -114,6 +114,21 @@ impl HashedMap { return None; } + pub fn entries(&self) -> Vec<&(u64, V)> { + let mut vec = Vec::new(); + + for i in 0..self.capacity { + if self.meta[i] == BUCKET_EMPTY || self.meta[i] == BUCKET_TOMBSTONE { + continue; + } + + unsafe { vec.push(self.buckets[i].assume_init_ref()); } + } + + return vec; + } + + pub fn erase(&mut self, key: u64) { let index = self.index_from_hash(key); let fingerprint = self.fingerprint_from_hash(key); diff --git a/ir/src/conv/mod.rs b/ir/src/conv/mod.rs index a76f81e..065eaa4 100644 --- a/ir/src/conv/mod.rs +++ b/ir/src/conv/mod.rs @@ -1 +1,3 @@ //! Critical AST -> IR conversion code module + +pub mod val; \ No newline at end of file diff --git a/ir/src/conv/val.rs b/ir/src/conv/val.rs new file mode 100644 index 0000000..1353167 --- /dev/null +++ b/ir/src/conv/val.rs @@ -0,0 +1,22 @@ +//! AST value -> IR value conversion + +use commons::err::{PositionedError, PositionedResult, PositionlessError, PositionlessResult}; +use parser::ast::tree::ASTTreeNode; + +use crate::{ctx::{IRContext, IRLocalContext}, irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, refs::IRValueRef}; + +pub fn get_variable_ref<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, hash: u64) -> PositionlessResult> { + match ctx.get_variable(hash) { + Ok(v) => return Ok(IRValueRef::from_static(IRStaticVariable::clone(v))), + Err(_) => {} + }; + + match lctx.get_variable(hash) { + Ok(v) => return Ok(IRValueRef::from_pointer(IRPointer::clone(v))), + Err(_) => return Err(PositionlessError::new(&format!("Cannot find variable with hash {} in the current context", hash))) + }; +} + +pub fn parse_ir_chain_access<'a>(node: Box, lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>) -> PositionlessResult { + +} \ No newline at end of file diff --git a/ir/src/ctx.rs b/ir/src/ctx.rs index 09e150a..5d75365 100644 --- a/ir/src/ctx.rs +++ b/ir/src/ctx.rs @@ -1,13 +1,14 @@ //! IR context related code +use core::hash; use std::ops::Add; -use commons::utils::map::HashedMap; +use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap}; use inkwell::{AddressSpace, builder::Builder, context::Context, types::PointerType}; -use crate::irstruct::{funcs::IRFunction, ptr::IRPointer}; +use crate::irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}; -/// The global IR context. +/// 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, @@ -15,11 +16,96 @@ pub struct IRContext<'a> { pub ptr_type: PointerType<'a>, pub functions: HashedMap>, - pub static_vars: 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) } } + + pub fn add_variable(&'a mut self, hash: u64, var: IRStaticVariable<'a>) -> PositionlessResult { + if self.static_vars.get(hash).is_some() { + return Err(PositionlessError::new(&format!("Variable named {} is already registered in the current context.", hash))); + } + + self.static_vars.put(hash, var); + return Ok(true); + } + + pub fn get_variable(&'a self, hash: u64) -> PositionlessResult<&'a IRStaticVariable<'a>> { + return match self.static_vars.get(hash) { + Some(v) => Ok(v), + None => return Err(PositionlessError::new("Invalid variable name")) + }; + } +} + +pub struct LocalIRVariable<'a> { + pub ptr: IRPointer<'a>, + 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 current_depth: usize // Starts at 0 where 0 is function body +} + +impl<'a> IRLocalContext<'a> { + 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 { + if self.vars.get(hash).is_some() { + return Err(PositionlessError::new(&format!("Variable named {} is already registered in the current context.", hash))); + } + + self.vars.put(hash, LocalIRVariable { ptr: var, depth: self.current_depth }); + return Ok(true); + } + + pub fn get_variable(&'a self, hash: u64) -> PositionlessResult<&'a IRPointer<'a>> { + return match self.vars.get(hash) { + Some(v) => Ok(&v.ptr), + None => return Err(PositionlessError::new("Invalid variable name")) + }; + } + + pub fn increment_body_depth(&mut self) { + self.current_depth += 1; + } + + /// Ends the current nested body. Is responsible for removing non-valid variable indices + /// Example: + /// ``` + /// func test() { + /// // body of depth 0 starts + /// if(true) { + /// // body of depth 1 starts + /// // body of depth 1 ends + /// } + /// + /// // body of depth 0 ends + /// } + /// ``` + pub fn end_nested_body_depth(&mut self) { + self.current_depth -= 1; + + let mut hashToRemove: Vec = vec![]; + + for entry in self.vars.entries() { + if entry.1.depth > self.current_depth { + hashToRemove.push(entry.0); + } + } + + for hash in hashToRemove { + self.vars.erase(hash); + } + } + } \ No newline at end of file diff --git a/ir/src/irstruct/ptr.rs b/ir/src/irstruct/ptr.rs index 623558f..b51e616 100644 --- a/ir/src/irstruct/ptr.rs +++ b/ir/src/irstruct/ptr.rs @@ -3,9 +3,10 @@ use inkwell::{builder::Builder, context::Context, types::BasicTypeEnum, values:: use crate::{ctx::IRContext, refs::IRValueRef, types::typing::IRType, values::IRValue}; +#[derive(Clone)] pub struct IRPointer<'a> { pub inkwell_ptr: PointerValue<'a>, // Only use this directly within structs - t: &'a IRType<'a>, + pub t: &'a IRType<'a>, pub name: String } diff --git a/ir/src/irstruct/staticvars.rs b/ir/src/irstruct/staticvars.rs index 43cf26b..350cfdf 100644 --- a/ir/src/irstruct/staticvars.rs +++ b/ir/src/irstruct/staticvars.rs @@ -5,10 +5,11 @@ use inkwell::{builder::Builder, values::{BasicValueEnum, GlobalValue}}; use crate::{types::typing::IRType, values::IRValue}; +#[derive(Clone)] pub struct IRStaticVariable<'a> { inkwell: Option>, val: Option>, - t: &'a IRType<'a>, + pub t: &'a IRType<'a>, pub name: String } diff --git a/ir/src/refs.rs b/ir/src/refs.rs index 1d6efa4..4549626 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -1,7 +1,7 @@ //! IR value reference definitions use commons::err::{PositionlessError, PositionlessResult}; -use inkwell::{builder::Builder, types::{AnyTypeEnum, BasicTypeEnum}}; +use inkwell::{builder::Builder, types::{AnyTypeEnum, BasicTypeEnum}, values::PointerValue}; use crate::{ctx::IRContext, irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::IRType, values::IRValue}; @@ -22,6 +22,14 @@ impl<'a> IRValueRef<'a> { 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_pointer(ptr: IRPointer<'a>) -> Self { + return IRValueRef { kind: IRValueRefKind::Ptr(ptr.t, ptr) } + } + /// Determines if aqcuiring the values require a load instruction or any instruction at all to obtain the value from. pub fn requires_load(&self) -> bool { return matches!(self.kind, IRValueRefKind::Ptr(_, _)) @@ -41,4 +49,11 @@ impl<'a> IRValueRef<'a> { } } + pub fn obtain_pointer(&self, ctx: &'a IRContext<'a>) -> PositionlessResult> { + match &self.kind { + IRValueRefKind::Ptr(_, ptr) => return Ok(ptr.inkwell_ptr), + _ => return Err(PositionlessError::new("Cannot obtain pointer from this IR value kind!")) + } + } + } \ No newline at end of file diff --git a/test-main/src/main.rs b/test-main/src/main.rs index 1d65aaa..fe952bc 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -1,18 +1,19 @@ -use std::hash::{DefaultHasher, Hash, Hasher}; +use std::{env, hash::{DefaultHasher, Hash, Hasher}}; use inkwell::{context::Context, module::Module}; use ir::{ctx::IRContext, irstruct::{funcs::IRFunction, ptr::IRPointer, structs::IRStructuredType}, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::IRValue}; -use parser::ast::func; +use lexer::lexer::lexer_parse_file; +use parser::{ast::func, parse_ast_ctx}; fn main() { - //let args: Vec = env::args().collect(); - //let file_path: &String = &args[1]; + let args: Vec = env::args().collect(); + let file_path: &String = &args[1]; - //let lexer_res = lexer_parse_file(file_path).expect("Bad lexer!"); + let lexer_res = lexer_parse_file(file_path).expect("Bad lexer!"); - //let ctx = parse_ast_ctx(&lexer_res); + let ctx = parse_ast_ctx(&lexer_res); - //println!("{:#?}", ctx); + println!("{:#?}", ctx); let context = Context::create(); From cacce297326064dbc7f095e17a5641e1c96bba33 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 18:52:05 +0100 Subject: [PATCH 39/54] feat: made obtain_pointer work with values --- ir/src/refs.rs | 7 +++++++ ir/src/values.rs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ir/src/refs.rs b/ir/src/refs.rs index 4549626..8e9eb8c 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -52,6 +52,13 @@ impl<'a> IRValueRef<'a> { pub fn obtain_pointer(&self, ctx: &'a IRContext<'a>) -> PositionlessResult> { match &self.kind { IRValueRefKind::Ptr(_, ptr) => return Ok(ptr.inkwell_ptr), + + IRValueRefKind::Val(v) => { + let ptr = IRPointer::create(&ctx, String::from("_val_toptr"), v.t, Some(IRValueRef::from_val(IRValue::clone(v))))?; + + return Ok(ptr.inkwell_ptr); + } + _ => return Err(PositionlessError::new("Cannot obtain pointer from this IR value kind!")) } } diff --git a/ir/src/values.rs b/ir/src/values.rs index ccdd7c3..6c5753f 100644 --- a/ir/src/values.rs +++ b/ir/src/values.rs @@ -11,7 +11,7 @@ use crate::types::typing::IRType; #[derive(Clone)] pub struct IRValue<'a> { inkwell_val: BasicValueEnum<'a>, - t: &'a IRType<'a>, + pub t: &'a IRType<'a>, } impl<'a> IRValue<'a> { From a0840b17efe277aacfa3a1fc8acf9d890eeb3fd2 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 18:53:21 +0100 Subject: [PATCH 40/54] =?UTF-8?q?feat:=20made=20obtain=C3=83=5Fpointer=20w?= =?UTF-8?q?ork=20with=20statics?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ir/src/refs.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ir/src/refs.rs b/ir/src/refs.rs index 8e9eb8c..ce48a3d 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -59,7 +59,9 @@ impl<'a> IRValueRef<'a> { return Ok(ptr.inkwell_ptr); } - _ => return Err(PositionlessError::new("Cannot obtain pointer from this IR value kind!")) + IRValueRefKind::Global(_, g) => { + return Ok(g.as_string_ref()?.as_pointer_value()); + } } } From bc5ba6fea5c7c16ed6c064f5297c4be76a81fdf6 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 17 Feb 2026 18:54:23 +0100 Subject: [PATCH 41/54] feat: made obtain_pointer work with statics --- ir/src/refs.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ir/src/refs.rs b/ir/src/refs.rs index ce48a3d..faaa81e 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -60,6 +60,10 @@ impl<'a> IRValueRef<'a> { } IRValueRefKind::Global(_, g) => { + if g.is_compiletime_replaceable() { + return Ok(g.as_val()?.into_pointer_value()) + } + return Ok(g.as_string_ref()?.as_pointer_value()); } } From a254e38a28f1b1bffd17b6d82dc92196f1957c57 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 18 Feb 2026 15:38:18 +0100 Subject: [PATCH 42/54] feat: added IRFunction::call --- ir/src/conv/val.rs | 36 ++++++++++++++++++++++++++++++++--- ir/src/ctx.rs | 6 ++++-- ir/src/irstruct/funcs.rs | 26 ++++++++++++++++++++++++- ir/src/irstruct/staticvars.rs | 10 +++------- test-main/src/main.rs | 17 ++++++----------- utils/src/hash.rs | 2 +- 6 files changed, 72 insertions(+), 25 deletions(-) diff --git a/ir/src/conv/val.rs b/ir/src/conv/val.rs index 1353167..55cb4b0 100644 --- a/ir/src/conv/val.rs +++ b/ir/src/conv/val.rs @@ -3,7 +3,7 @@ use commons::err::{PositionedError, PositionedResult, PositionlessError, PositionlessResult}; use parser::ast::tree::ASTTreeNode; -use crate::{ctx::{IRContext, IRLocalContext}, irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, refs::IRValueRef}; +use crate::{ctx::{IRContext, IRLocalContext}, irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED64_TYPE_HASH}, values::IRValue}; pub fn get_variable_ref<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, hash: u64) -> PositionlessResult> { match ctx.get_variable(hash) { @@ -17,6 +17,36 @@ pub fn get_variable_ref<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a> }; } -pub fn parse_ir_chain_access<'a>(node: Box, lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>) -> PositionlessResult { - +pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, node: Box) -> PositionlessResult> { + match node.as_ref() { + ASTTreeNode::IntegerLit(v) => { + let t = ctx.type_storage.get(SIGNED64_TYPE_HASH); + + if !t.is_some() { + return Err(PositionlessError::new("Invalid type storage! si64 not found!")); + } + + return Ok(IRValueRef::from_val(IRValue::from_signed(t.unwrap(), *v as i128)?)); + }, + + ASTTreeNode::StringLit(v) => { + let t = ctx.type_storage.get(POINTER_TYPE_HASH); + + if !t.is_some() { + return Err(PositionlessError::new("Invalid type storage! pointer not found!")); + } + + let global = IRStaticVariable::from_str(&ctx.builder, v, String::from("__string_literal"), t.unwrap())?; + + return Ok(IRValueRef::from_static(global)); + }, + + ASTTreeNode::VariableReference(e) => { + let var = get_variable_ref(lctx, ctx, e.hash)?; + + return Ok(var); + }, + + _ => return Err(PositionlessError::new("The given node cannot be parsed as a value!")) + } } \ No newline at end of file diff --git a/ir/src/ctx.rs b/ir/src/ctx.rs index 5d75365..4cd792a 100644 --- a/ir/src/ctx.rs +++ b/ir/src/ctx.rs @@ -6,7 +6,7 @@ use std::ops::Add; use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap}; use inkwell::{AddressSpace, builder::Builder, context::Context, types::PointerType}; -use crate::irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}; +use crate::{irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, types::storage::IRTypeStorage}; /// The global IR context. /// Basically holds anything related to the current IR compilation (eg: functions, types, global vars) @@ -15,13 +15,15 @@ pub struct IRContext<'a> { pub builder: Builder<'a>, pub ptr_type: PointerType<'a>, + pub type_storage: IRTypeStorage<'a>, + 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) } + 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) } } pub fn add_variable(&'a mut self, hash: u64, var: IRStaticVariable<'a>) -> PositionlessResult { diff --git a/ir/src/irstruct/funcs.rs b/ir/src/irstruct/funcs.rs index 4e8a1c5..e0dd2e6 100644 --- a/ir/src/irstruct/funcs.rs +++ b/ir/src/irstruct/funcs.rs @@ -1,7 +1,7 @@ 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::types::typing::IRType; +use crate::{ctx::IRContext, irstruct::ptr::IRPointer, refs::IRValueRef, types::typing::IRType, values::IRValue}; pub struct IRFunction<'a> { pub inkwell_func: FunctionValue<'a>, @@ -52,6 +52,30 @@ 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>) -> PositionlessResult>> { + let mut inkwell_args = vec![]; + + for arg in args { + inkwell_args.push(arg.obtain(ctx)?.obtain().into()); + } + + let call = match ctx.builder.build_call(self.inkwell_func, &inkwell_args, &self.name) { + Ok(v) => v, + Err(_) => return Err(PositionlessError::new("build_call failed!")) + }; + + let val = match call.try_as_basic_value().basic() { + Some(v) => v, + None => return Ok(None) + }; + + let val = IRValue::new(val, self.ret_type); + + let pointer = IRPointer::create(ctx, format!("function_ret_{}", self.name), self.ret_type, Some(IRValueRef::from_val(val)))?; + + return Ok(Some(pointer)); + } + /// Prepares the addition of the function body. pub fn prepare_body_filling(&self, builder: &Builder<'a>) { if self.entry.is_none() { diff --git a/ir/src/irstruct/staticvars.rs b/ir/src/irstruct/staticvars.rs index 350cfdf..ee8f446 100644 --- a/ir/src/irstruct/staticvars.rs +++ b/ir/src/irstruct/staticvars.rs @@ -32,15 +32,11 @@ impl<'a> IRStaticVariable<'a> { } pub fn as_val(&self) -> PositionlessResult> { - if !self.is_compiletime_replaceable() { - return Err(PositionlessError::new("Tried using as_int_val on a non-compiletime determined global val")); + if self.val.is_some() { + return Ok(self.val.unwrap()); } - if !self.t.is_numeric_type() { - return Err(PositionlessError::new("Tried using as_int_val on a non-integer global value type!")); - } - - return Ok(self.val.unwrap()); + return Ok(self.as_string_ref()?.as_pointer_value().into()) } pub fn as_string_ref(&self) -> PositionlessResult> { diff --git a/test-main/src/main.rs b/test-main/src/main.rs index fe952bc..6d63c29 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -1,7 +1,8 @@ +use core::fmt; use std::{env, hash::{DefaultHasher, Hash, Hasher}}; use inkwell::{context::Context, module::Module}; -use ir::{ctx::IRContext, irstruct::{funcs::IRFunction, ptr::IRPointer, structs::IRStructuredType}, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED32_TYPE_HASH, UNSIGNED32_TYPE_HASH, storage::IRTypeStorage, typing::IRType}, values::IRValue}; +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}; use lexer::lexer::lexer_parse_file; use parser::{ast::func, parse_ast_ctx}; @@ -46,7 +47,8 @@ fn main() { let func = IRFunction::create(&context, String::from("main"), &module, t, vec![t, t]).expect("Couldn't make IR function"); func.prepare_body_filling(&irctx.builder); - let fmt_str = &irctx.builder.build_global_string_ptr("Haiiiii, the value is %d\n", "fmt_str").unwrap(); + let fmt_str = IRStaticVariable::from_str(&irctx.builder, "Haiiiii, the value is %d\n", String::from("fmt_str"), int_type).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(); @@ -62,15 +64,8 @@ fn main() { // End struct test - let _ = irctx.builder.build_call( - printf_func.inkwell_func, - &[ - fmt_str.as_pointer_value().into(), - val.into(), - ], - "printf_call" - ); - + printf_func.call(&irctx, vec![IRValueRef::from_static(fmt_str), IRValueRef::from_pointer(structInstance)]); + irctx.builder.build_return(Some(&i32_type.const_zero())); module.print_to_file("output.ll").unwrap(); diff --git a/utils/src/hash.rs b/utils/src/hash.rs index bac5f7a..1acdc0d 100644 --- a/utils/src/hash.rs +++ b/utils/src/hash.rs @@ -14,7 +14,7 @@ pub type TypeHash = u64; #[derive(Debug, PartialEq, Clone)] pub struct WithHash { pub val: K, - hash: u64 + pub hash: u64 } impl WithHash { From 6de3f336cf9972dadac8cea8f061f4732f13384c Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 18 Feb 2026 15:39:06 +0100 Subject: [PATCH 43/54] feat: added flag to make return grabbing optional --- ir/src/irstruct/funcs.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ir/src/irstruct/funcs.rs b/ir/src/irstruct/funcs.rs index e0dd2e6..286312c 100644 --- a/ir/src/irstruct/funcs.rs +++ b/ir/src/irstruct/funcs.rs @@ -52,7 +52,7 @@ 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>) -> PositionlessResult>> { + pub fn call(&'a self, ctx: &'a IRContext<'a>, args: Vec>, grab_return: bool) -> PositionlessResult>> { let mut inkwell_args = vec![]; for arg in args { @@ -64,6 +64,10 @@ impl<'a> IRFunction<'a> { Err(_) => return Err(PositionlessError::new("build_call failed!")) }; + if !grab_return { + return Ok(None); + } + let val = match call.try_as_basic_value().basic() { Some(v) => v, None => return Ok(None) From 4e48c5c4a0c1711a07a31cda6c586ed845988ec9 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 18 Feb 2026 15:45:29 +0100 Subject: [PATCH 44/54] feat: added the support for optional return types! --- ir/src/ctx.rs | 5 +++-- ir/src/irstruct/funcs.rs | 31 +++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/ir/src/ctx.rs b/ir/src/ctx.rs index 4cd792a..51713d0 100644 --- a/ir/src/ctx.rs +++ b/ir/src/ctx.rs @@ -4,7 +4,7 @@ use core::hash; use std::ops::Add; use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap}; -use inkwell::{AddressSpace, builder::Builder, context::Context, types::PointerType}; +use inkwell::{AddressSpace, builder::Builder, context::Context, types::{PointerType, VoidType}}; use crate::{irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, types::storage::IRTypeStorage}; @@ -14,6 +14,7 @@ pub struct IRContext<'a> { pub inkwell_ctx: &'a Context, pub builder: Builder<'a>, pub ptr_type: PointerType<'a>, + pub void_type: VoidType<'a>, pub type_storage: IRTypeStorage<'a>, @@ -23,7 +24,7 @@ pub struct IRContext<'a> { 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) } + 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() } } pub fn add_variable(&'a mut self, hash: u64, var: IRStaticVariable<'a>) -> PositionlessResult { diff --git a/ir/src/irstruct/funcs.rs b/ir/src/irstruct/funcs.rs index 286312c..bdb9858 100644 --- a/ir/src/irstruct/funcs.rs +++ b/ir/src/irstruct/funcs.rs @@ -5,7 +5,7 @@ use crate::{ctx::IRContext, irstruct::ptr::IRPointer, refs::IRValueRef, types::t pub struct IRFunction<'a> { pub inkwell_func: FunctionValue<'a>, - ret_type: &'a IRType<'a>, + ret_type: Option<&'a IRType<'a>>, args: Vec<&'a IRType<'a>>, name: String, @@ -13,39 +13,45 @@ pub struct IRFunction<'a> { } impl<'a> IRFunction<'a> { - pub fn new(ctx: &'a Context, name: String, func: FunctionValue<'a>, ret_type: &'a IRType<'a>, args: Vec<&'a IRType<'a>>) -> Self { + pub fn new(ctx: &'a IRContext, name: String, func: FunctionValue<'a>, ret_type: Option<&'a IRType<'a>>, args: Vec<&'a IRType<'a>>) -> Self { - let block = ctx.append_basic_block(func, "entry"); + let block = ctx.inkwell_ctx.append_basic_block(func, "entry"); return IRFunction { inkwell_func: func, ret_type, args, name, entry: Some(block) } } - pub fn new_shadow(name: String, func: FunctionValue<'a>, ret_type: &'a IRType<'a>, args: Vec<&'a IRType<'a>>) -> Self { + 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 } } - pub fn create_shadow(name: String, module: &Module<'a>, ret_type: &'a IRType<'a>, args: Vec<&'a IRType<'a>>) -> PositionlessResult { + pub fn create_shadow(ctx: &'a IRContext, name: String, module: &Module<'a>, ret_type: Option<&'a IRType<'a>>, args: Vec<&'a IRType<'a>>) -> PositionlessResult { let mut kargs = vec![]; for k in &args { kargs.push(k.get_inkwell_base_metadatatype()?); } - let t = ret_type.get_inkwell_basetype()?.fn_type(&kargs, false); + 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)); } - pub fn create(ctx: &'a Context, name: String, module: &Module<'a>, ret_type: &'a IRType<'a>, args: Vec<&'a IRType<'a>>) -> PositionlessResult { + pub fn create(ctx: &'a IRContext, name: String, module: &Module<'a>, ret_type: Option<&'a IRType<'a>>, args: Vec<&'a IRType<'a>>) -> PositionlessResult { let mut kargs = vec![]; for k in &args { kargs.push(k.get_inkwell_base_metadatatype()?); } - let t = ret_type.get_inkwell_basetype()?.fn_type(&kargs, false); + 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); @@ -68,14 +74,19 @@ impl<'a> IRFunction<'a> { return Ok(None); } + let return_type = match self.ret_type { + Some(ret) => ret, + None => return Ok(None) + }; + let val = match call.try_as_basic_value().basic() { Some(v) => v, None => return Ok(None) }; - let val = IRValue::new(val, self.ret_type); + let val = IRValue::new(val, return_type); - let pointer = IRPointer::create(ctx, format!("function_ret_{}", self.name), self.ret_type, Some(IRValueRef::from_val(val)))?; + let pointer = IRPointer::create(ctx, format!("function_ret_{}", self.name), return_type, Some(IRValueRef::from_val(val)))?; return Ok(Some(pointer)); } From 2f1e3bbfcf8f8bcd1348a9baaf5a448bd245315c Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 18 Feb 2026 15:55:28 +0100 Subject: [PATCH 45/54] feat: added add_function & get_function to IRContext and made it so static variables and functions cannot have the same name --- ast.txt | 198 ++++++++++++++++++++++++++++++++++++++++++ ir/src/conv/val.rs | 9 ++ ir/src/ctx.rs | 28 ++++-- test-main/src/main.rs | 9 +- 4 files changed, 235 insertions(+), 9 deletions(-) create mode 100644 ast.txt diff --git a/ast.txt b/ast.txt new file mode 100644 index 0000000..4da05e4 --- /dev/null +++ b/ast.txt @@ -0,0 +1,198 @@ +Calling function call parsing on kwd abc +Tok: Dot +Tok: Var +Calling function call parsing on kwd abs +Tok: ComparingOperator( + HigherEqual, +) +Calling function call parsing on kwd def +Tok: If +Ok( + ParserCtx { + map: { + "main": FunctionDeclaration { + func_name: WithHash { + val: "main", + hash: 14467718814232352107, + }, + args: [ + FunctionDeclarationArgument { + name: WithHash { + val: "myTestArg", + hash: 14273091031817137443, + }, + argument_type: 11583643502875509928, + }, + FunctionDeclarationArgument { + name: WithHash { + val: "age", + hash: 11942856677619760021, + }, + argument_type: 11583643502875509928, + }, + ], + body: [ + VarDeclaration { + var_name: WithHash { + val: "test", + hash: 14402189752926126668, + }, + var_type: 11583643502875509928, + value: Some( + StructLRVariable { + l: StructLRFunction { + l: VariableReference( + WithHash { + val: "test", + hash: 14402189752926126668, + }, + ), + r: FunctionCall { + func: WithHash { + val: "abc", + hash: 17224545590736200989, + }, + args: [], + }, + }, + r: VariableReference( + WithHash { + val: "test", + hash: 14402189752926126668, + }, + ), + }, + ), + }, + VarDeclaration { + var_name: WithHash { + val: "test2", + hash: 12720938724704517959, + }, + var_type: 11583643502875509928, + value: Some( + OperatorBasedConditionMember { + lval: StructLRFunction { + l: VariableReference( + WithHash { + val: "test", + hash: 14402189752926126668, + }, + ), + r: FunctionCall { + func: WithHash { + val: "abs", + hash: 10550511239753159873, + }, + args: [], + }, + }, + rval: StructLRFunction { + l: VariableReference( + WithHash { + val: "test", + hash: 14402189752926126668, + }, + ), + r: FunctionCall { + func: WithHash { + val: "def", + hash: 9341360902760800985, + }, + args: [], + }, + }, + operator: HigherEqual, + }, + ), + }, + IfStatement { + cond: OperatorBasedConditionMember { + lval: VariableReference( + WithHash { + val: "test2", + hash: 12720938724704517959, + }, + ), + rval: VariableReference( + WithHash { + val: "test", + hash: 14402189752926126668, + }, + ), + operator: HigherEqual, + }, + body: [ + VarDeclaration { + var_name: WithHash { + val: "age", + hash: 11942856677619760021, + }, + var_type: 11583643502875509928, + value: Some( + IntegerLit( + 0, + ), + ), + }, + ], + else_statement: Some( + IfElseStatement { + cond: Some( + OperatorBasedConditionMember { + lval: VariableReference( + WithHash { + val: "test2", + hash: 12720938724704517959, + }, + ), + rval: VariableReference( + WithHash { + val: "test", + hash: 14402189752926126668, + }, + ), + operator: Equal, + }, + ), + body: [ + VarDeclaration { + var_name: WithHash { + val: "age", + hash: 11942856677619760021, + }, + var_type: 11583643502875509928, + value: Some( + IntegerLit( + 63, + ), + ), + }, + ], + else_statement: Some( + ElseStatement { + body: [ + VarDeclaration { + var_name: WithHash { + val: "age", + hash: 11942856677619760021, + }, + var_type: 11583643502875509928, + value: Some( + IntegerLit( + 68, + ), + ), + }, + ], + }, + ), + }, + ), + }, + ], + returnType: None, + }, + }, + }, +) \ No newline at end of file diff --git a/ir/src/conv/val.rs b/ir/src/conv/val.rs index 55cb4b0..fd0cce6 100644 --- a/ir/src/conv/val.rs +++ b/ir/src/conv/val.rs @@ -47,6 +47,15 @@ pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, return Ok(var); }, + ASTTreeNode::FunctionCall { func, args } => { + let mut arguments = vec![]; + + for arg in *args { + arguments.push(parse_ir_value(lctx, ctx, arg)?); + } + + } + _ => return Err(PositionlessError::new("The given node cannot be parsed as a value!")) } } \ No newline at end of file diff --git a/ir/src/ctx.rs b/ir/src/ctx.rs index 51713d0..12eaeb0 100644 --- a/ir/src/ctx.rs +++ b/ir/src/ctx.rs @@ -1,8 +1,5 @@ //! IR context related code -use core::hash; -use std::ops::Add; - use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap}; use inkwell::{AddressSpace, builder::Builder, context::Context, types::{PointerType, VoidType}}; @@ -28,8 +25,8 @@ impl<'a> IRContext<'a> { } pub fn add_variable(&'a mut self, hash: u64, var: IRStaticVariable<'a>) -> PositionlessResult { - if self.static_vars.get(hash).is_some() { - return Err(PositionlessError::new(&format!("Variable named {} is already registered in the current context.", hash))); + if self.is_key_taken(hash) { + return Err(PositionlessError::new("There already is an element named like this!")); } self.static_vars.put(hash, var); @@ -42,6 +39,27 @@ impl<'a> IRContext<'a> { None => return Err(PositionlessError::new("Invalid variable name")) }; } + + pub fn is_key_taken(&'a self, hash: u64) -> bool { + 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>> { + return match self.functions.get(hash) { + Some(v) => Ok(v), + None => Err(PositionlessError::new("Invalid function name!")) + } + } + + pub fn add_function(&'a mut self, hash: u64, func: IRFunction<'a>) -> PositionlessResult { + if self.is_key_taken(hash) { + return Err(PositionlessError::new("There already is an element named like this!")); + } + + self.functions.put(hash, func); + return Ok(true); + } + } pub struct LocalIRVariable<'a> { diff --git a/test-main/src/main.rs b/test-main/src/main.rs index 6d63c29..7b702c2 100644 --- a/test-main/src/main.rs +++ b/test-main/src/main.rs @@ -29,6 +29,9 @@ fn main() { let int_type = storage.get(SIGNED32_TYPE_HASH).unwrap(); let ptr_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 sample_substruct = IRType::Struct( IRStructuredType::new(&irctx, String::from("uwuStruct"), true, vec![(8417845746417243860, int_type)]).unwrap() ); @@ -42,9 +45,7 @@ fn main() { let i32_type = context.i32_type(); - let printf_func = IRFunction::create_shadow(String::from("printf"), &module, int_type, vec![ptr_type]).unwrap(); - - let func = IRFunction::create(&context, String::from("main"), &module, t, vec![t, t]).expect("Couldn't make IR function"); + 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 fmt_str = IRStaticVariable::from_str(&irctx.builder, "Haiiiii, the value is %d\n", String::from("fmt_str"), int_type).unwrap(); @@ -64,7 +65,7 @@ fn main() { // End struct test - printf_func.call(&irctx, vec![IRValueRef::from_static(fmt_str), IRValueRef::from_pointer(structInstance)]); + printf_func.call(&irctx, vec![IRValueRef::from_static(fmt_str), IRValueRef::from_pointer(structInstance)], false); irctx.builder.build_return(Some(&i32_type.const_zero())); From 3115f93399a6f21c405ca028e4ab197cc4618179 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 18 Feb 2026 16:04:00 +0100 Subject: [PATCH 46/54] feat: started working on struct functions --- ir/src/conv/val.rs | 17 ++++++++++++++--- ir/src/irstruct/structs.rs | 27 ++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/ir/src/conv/val.rs b/ir/src/conv/val.rs index fd0cce6..02c4768 100644 --- a/ir/src/conv/val.rs +++ b/ir/src/conv/val.rs @@ -50,10 +50,21 @@ pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, ASTTreeNode::FunctionCall { func, args } => { let mut arguments = vec![]; - for arg in *args { - arguments.push(parse_ir_value(lctx, ctx, arg)?); + // TODO: support struct functions here + + for arg in &args[0..args.len()] { + arguments.push(parse_ir_value(lctx, ctx, arg.clone())?); + } + + let f = ctx.get_funtion(func.hash)?; + + let res = f.call(ctx, arguments, true)?; + + if res.is_none() { + return Err(PositionlessError::new(&format!("Cannot use the result of function {} as a value as it is void!", func.val))); } - + + return Ok(IRValueRef::from_pointer(res.unwrap())); } _ => return Err(PositionlessError::new("The given node cannot be parsed as a value!")) diff --git a/ir/src/irstruct/structs.rs b/ir/src/irstruct/structs.rs index 642c066..f8679ae 100644 --- a/ir/src/irstruct/structs.rs +++ b/ir/src/irstruct/structs.rs @@ -1,14 +1,15 @@ //! IR representation of structure types (structs, layouts...) use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap}; -use inkwell::{AddressSpace, builder::Builder, context::Context, types::{BasicTypeEnum, StructType}}; +use inkwell::{types::{BasicTypeEnum, StructType}}; -use crate::{ctx::IRContext, irstruct::ptr::IRPointer, types::typing::IRType}; +use crate::{ctx::IRContext, irstruct::{funcs::IRFunction, ptr::IRPointer}, types::typing::IRType}; pub struct IRStructuredType<'a> { pub inkwell_type: StructType<'a>, pub field_to_index: HashedMap, pub field_types: Vec<&'a IRType<'a>>, + pub functions: HashedMap>, pub name: String, pub is_layout: bool } @@ -31,7 +32,27 @@ impl<'a> IRStructuredType<'a> { 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 }) + return Ok(Self { 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 { + if self.is_layout { + return Err(PositionlessError::new("Cannot declare functions inside of a layout!")); + } + + self.functions.put(hash, func); + return Ok(true); + } + + pub fn get_function(&'a self, hash: u64) -> PositionlessResult<&'a IRFunction<'a>> { + 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), + 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> { From a8f615ec5e41e130c0e7a61042f1e8fe073fdd02 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 18 Feb 2026 16:10:17 +0100 Subject: [PATCH 47/54] feat: added working _struct functions --- ir/src/conv/val.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/ir/src/conv/val.rs b/ir/src/conv/val.rs index 02c4768..42bf6e0 100644 --- a/ir/src/conv/val.rs +++ b/ir/src/conv/val.rs @@ -17,7 +17,7 @@ pub fn get_variable_ref<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a> }; } -pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, node: Box) -> PositionlessResult> { +pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, node: Box, left: Option<&'a IRPointer<'a>>) -> PositionlessResult> { match node.as_ref() { ASTTreeNode::IntegerLit(v) => { let t = ctx.type_storage.get(SIGNED64_TYPE_HASH); @@ -50,15 +50,29 @@ pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, ASTTreeNode::FunctionCall { func, args } => { let mut arguments = vec![]; + if left.is_some() { + arguments.push(IRValueRef::from_pointer(IRPointer::clone(left.unwrap()))); + } + // TODO: support struct functions here for arg in &args[0..args.len()] { - arguments.push(parse_ir_value(lctx, ctx, arg.clone())?); + arguments.push(parse_ir_value(lctx, ctx, arg.clone(), None)?); } - let f = ctx.get_funtion(func.hash)?; + let res: Option>; + + if left.is_some() { + let descriptor = left.unwrap().t.get_structured_type_descriptor()?; + + let f = descriptor.get_function(func.hash)?; - let res = f.call(ctx, arguments, true)?; + res = f.call(ctx, arguments, true)?; + } else { + let f = ctx.get_funtion(func.hash)?; + + res = f.call(ctx, arguments, true)?; + } if res.is_none() { return Err(PositionlessError::new(&format!("Cannot use the result of function {} as a value as it is void!", func.val))); From d54d2593685deb2ae5619c68397ba4c8c872f1da Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 18 Feb 2026 16:12:57 +0100 Subject: [PATCH 48/54] feat: added field access support in parse_ir_value --- ir/src/conv/val.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ir/src/conv/val.rs b/ir/src/conv/val.rs index 42bf6e0..b716361 100644 --- a/ir/src/conv/val.rs +++ b/ir/src/conv/val.rs @@ -42,6 +42,16 @@ pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, }, ASTTreeNode::VariableReference(e) => { + if left.is_some() { + let instance_ptr = left.unwrap(); + + let struct_t = instance_ptr.t.get_structured_type_descriptor()?; + + let ptr = struct_t.get_pointer_for_field(ctx, instance_ptr, e.hash)?; + + return Ok(IRValueRef::from_pointer(ptr)); + } + let var = get_variable_ref(lctx, ctx, e.hash)?; return Ok(var); From 08a90887736728e7c8e8addaa941861c376218de Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 18 Feb 2026 18:25:09 +0100 Subject: [PATCH 49/54] feat: added struct lr var and function conversion --- ir/src/conv/val.rs | 32 +++++++++++++++++++++----------- ir/src/ctx.rs | 2 +- ir/src/irstruct/structs.rs | 24 ++++++++++++++++++++++++ ir/src/refs.rs | 7 +++++++ ir/src/values.rs | 2 +- 5 files changed, 54 insertions(+), 13 deletions(-) diff --git a/ir/src/conv/val.rs b/ir/src/conv/val.rs index b716361..40dd48e 100644 --- a/ir/src/conv/val.rs +++ b/ir/src/conv/val.rs @@ -17,7 +17,7 @@ pub fn get_variable_ref<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a> }; } -pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, node: Box, left: Option<&'a IRPointer<'a>>) -> PositionlessResult> { +pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, node: Box, left: Option>) -> PositionlessResult> { match node.as_ref() { ASTTreeNode::IntegerLit(v) => { let t = ctx.type_storage.get(SIGNED64_TYPE_HASH); @@ -42,12 +42,10 @@ pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, }, ASTTreeNode::VariableReference(e) => { - if left.is_some() { - let instance_ptr = left.unwrap(); - - let struct_t = instance_ptr.t.get_structured_type_descriptor()?; + if left.as_ref().is_some() { + let struct_t = left.as_ref().unwrap().t.get_structured_type_descriptor()?; - let ptr = struct_t.get_pointer_for_field(ctx, instance_ptr, e.hash)?; + let ptr = struct_t.get_pointer_for_field_noref(ctx, left.unwrap(), e.hash)?; return Ok(IRValueRef::from_pointer(ptr)); } @@ -60,12 +58,10 @@ pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, ASTTreeNode::FunctionCall { func, args } => { let mut arguments = vec![]; - if left.is_some() { - arguments.push(IRValueRef::from_pointer(IRPointer::clone(left.unwrap()))); + if left.as_ref().is_some() { + arguments.push(IRValueRef::from_pointer(left.as_ref().unwrap().clone())); } - // TODO: support struct functions here - for arg in &args[0..args.len()] { arguments.push(parse_ir_value(lctx, ctx, arg.clone(), None)?); } @@ -73,7 +69,7 @@ pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, let res: Option>; if left.is_some() { - let descriptor = left.unwrap().t.get_structured_type_descriptor()?; + let descriptor = left.as_ref().unwrap().t.get_structured_type_descriptor()?; let f = descriptor.get_function(func.hash)?; @@ -89,6 +85,20 @@ pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, } return Ok(IRValueRef::from_pointer(res.unwrap())); + }, + + ASTTreeNode::StructLRFunction { l, r } => { + let l_val = parse_ir_value(lctx, ctx, l.clone(), None)?; + let l_ptr = l_val.as_pointer()?; + + return parse_ir_value(lctx, ctx, r.clone(), Some(l_ptr)); + }, + + ASTTreeNode::StructLRVariable { l, r } => { + let l_val = parse_ir_value(lctx, ctx, l.clone(), None)?; + let l_ptr = l_val.as_pointer()?; + + return parse_ir_value(lctx, ctx, r.clone(), Some(l_ptr)); } _ => return Err(PositionlessError::new("The given node cannot be parsed as a value!")) diff --git a/ir/src/ctx.rs b/ir/src/ctx.rs index 12eaeb0..38a88d1 100644 --- a/ir/src/ctx.rs +++ b/ir/src/ctx.rs @@ -71,7 +71,7 @@ pub struct LocalIRVariable<'a> { /// Holds anything held and created in the given body (eg: vars). pub struct IRLocalContext<'a> { pub vars: HashedMap>, - pub current_depth: usize // Starts at 0 where 0 is function body + pub current_depth: usize, // Starts at 0 where 0 is function body } impl<'a> IRLocalContext<'a> { diff --git a/ir/src/irstruct/structs.rs b/ir/src/irstruct/structs.rs index f8679ae..b22825e 100644 --- a/ir/src/irstruct/structs.rs +++ b/ir/src/irstruct/structs.rs @@ -70,6 +70,30 @@ impl<'a> IRStructuredType<'a> { return Ok(IRPointer::new(field_ptr, 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> { + if ind >= self.field_types.len() as u32 { + return Err(PositionlessError::new("Invalid index given to get_pointer_for_field_index")); + } + + let field_ptr = match ctx.builder.build_struct_gep(self.inkwell_type, instance.inkwell_ptr, ind, "field_ptr") { + Ok(v) => v, + Err(_) => return Err(PositionlessError::new("build_struct_gep failed!")) + }; + + let field_type = self.field_types[ind as usize]; + + return Ok(IRPointer::new(field_ptr, 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> { + 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))) + }; + + 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> { let k = match self.field_to_index.get(hash) { Some(v) => *v, diff --git a/ir/src/refs.rs b/ir/src/refs.rs index faaa81e..03a0266 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -49,6 +49,13 @@ impl<'a> IRValueRef<'a> { } } + 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> { match &self.kind { IRValueRefKind::Ptr(_, ptr) => return Ok(ptr.inkwell_ptr), diff --git a/ir/src/values.rs b/ir/src/values.rs index 6c5753f..de40e57 100644 --- a/ir/src/values.rs +++ b/ir/src/values.rs @@ -3,7 +3,7 @@ use commons::{err::{PositionlessError, PositionlessResult}}; use inkwell::{types::StringRadix, values::{BasicValueEnum, IntValue}}; -use crate::types::typing::IRType; +use crate::{irstruct::ptr::IRPointer, types::typing::IRType}; /// The new IR value system. Allows for a close interaction with inkwell rather than a more AST-side one. /// # Safety From 6d9912f238fc3ca61e9455965125862aced772dd Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 18 Feb 2026 18:35:32 +0100 Subject: [PATCH 50/54] feat: added support for math operations --- ir/src/conv/val.rs | 33 ++++++++++++++++++++++++++++++++- ir/src/refs.rs | 8 ++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/ir/src/conv/val.rs b/ir/src/conv/val.rs index 40dd48e..dec278b 100644 --- a/ir/src/conv/val.rs +++ b/ir/src/conv/val.rs @@ -1,9 +1,10 @@ //! AST value -> IR value conversion use commons::err::{PositionedError, PositionedResult, PositionlessError, PositionlessResult}; +use inkwell::values::BasicValue; use parser::ast::tree::ASTTreeNode; -use crate::{ctx::{IRContext, IRLocalContext}, irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED64_TYPE_HASH}, values::IRValue}; +use crate::{ctx::{IRContext, IRLocalContext}, irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, math::make_math_operation, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED64_TYPE_HASH}, values::IRValue}; pub fn get_variable_ref<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, hash: u64) -> PositionlessResult> { match ctx.get_variable(hash) { @@ -87,6 +88,36 @@ pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, return Ok(IRValueRef::from_pointer(res.unwrap())); }, + ASTTreeNode::MathResult { lval, rval, operator, assigns } => { + let left = parse_ir_value(lctx, ctx, lval.clone(), None)?; + let right = parse_ir_value(lctx, ctx, rval.clone(), None)?; + + let t = left.get_type(); + + let l_val = match left.obtain(ctx)?.obtain_as_int(t) { + 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, + None => return Err(PositionlessError::new("lval on math operation wasn't a number!")), + }; + + let out = make_math_operation(&ctx.builder, l_val, r_val, String::from("_math"), operator.clone())?; + + if *assigns { + if left.as_pointer().is_err() { + return Err(PositionlessError::new("Assignments were enabled on math operation while left value wasn't a variable!")); + } + + let ptr = left.as_pointer()?; + ptr.store(&ctx.builder, out.as_basic_value_enum()); + } + + return Ok(IRValueRef::from_val(IRValue::new(out.into(), t))); + } + ASTTreeNode::StructLRFunction { l, r } => { let l_val = parse_ir_value(lctx, ctx, l.clone(), None)?; let l_ptr = l_val.as_pointer()?; diff --git a/ir/src/refs.rs b/ir/src/refs.rs index 03a0266..32b2eac 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -49,6 +49,14 @@ impl<'a> IRValueRef<'a> { } } + pub fn get_type(&self) -> &'a IRType<'a> { + return match &self.kind { + IRValueRefKind::Val(v) => v.t, + IRValueRefKind::Ptr(t, _) => return *t, + IRValueRefKind::Global(t, _) => return *t + } + } + pub fn as_pointer(&self) -> PositionlessResult> { match &self.kind { IRValueRefKind::Ptr(t, ptr) => return Ok(ptr.clone()), From 92d4aa44ee38c2308bed97093737e9383f7c36a9 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 18 Feb 2026 18:46:28 +0100 Subject: [PATCH 51/54] feat: added bool xor operation --- ir/src/bools.rs | 27 +++++++++++++++++++++++++++ ir/src/lib.rs | 3 ++- parser/src/ast/math.rs | 2 +- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 ir/src/bools.rs diff --git a/ir/src/bools.rs b/ir/src/bools.rs new file mode 100644 index 0000000..7233d8e --- /dev/null +++ b/ir/src/bools.rs @@ -0,0 +1,27 @@ +//! Everything related to boolean handling and generation + +use commons::err::{PositionlessError, PositionlessResult}; + +use crate::{ctx::IRContext, refs::IRValueRef, types::BOOL_TYPE_HASH, values::IRValue}; + +pub fn make_bool_xor<'a>(ctx: &'a IRContext<'a>, b: IRValueRef<'a>) -> PositionlessResult> { + let val = b.obtain(ctx)?; + let inkwell = match val.obtain_as_bool() { + Some(v) => v, + None => return Err(PositionlessError::new("Cannot obtain boolean from the provided boolean value reference!")) + }; + + let bool_t = match ctx.type_storage.get(BOOL_TYPE_HASH) { + Some(v) => v, + None => return Err(PositionlessError::new("Cannot find boolean type in type storage!")) + }; + + let one = bool_t.get_inkwell_inttype()?.const_int(1, false); + + let xor_v = match ctx.builder.build_xor(inkwell, one, "xor_") { + Ok(v) => v, + Err(_) => return Err(PositionlessError::new("build_xor failed!")) + }; + + return Ok(IRValue::new(xor_v.into(), bool_t)); +} \ No newline at end of file diff --git a/ir/src/lib.rs b/ir/src/lib.rs index d0b82e8..3bf721e 100644 --- a/ir/src/lib.rs +++ b/ir/src/lib.rs @@ -7,4 +7,5 @@ pub mod math; pub mod irstruct; pub mod conv; pub mod ctx; -pub mod refs; \ No newline at end of file +pub mod refs; +pub mod bools; \ No newline at end of file diff --git a/parser/src/ast/math.rs b/parser/src/ast/math.rs index 49961ca..5d5279c 100644 --- a/parser/src/ast/math.rs +++ b/parser/src/ast/math.rs @@ -17,4 +17,4 @@ pub fn parse_math_operation(tokens: &Vec, ind: &mut usize, original: let right_member = parse_ast_value(tokens, ind)?; return Ok(Box::new(ASTTreeNode::MathResult { lval: original, rval: right_member, operator: oper.0, assigns: oper.1 })) -} \ No newline at end of file +} From 1bef895aaa2dae354735306273a758bcd173a5bf Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 18 Feb 2026 18:55:09 +0100 Subject: [PATCH 52/54] feat: added bool comparing creation --- ir/src/bools.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/ir/src/bools.rs b/ir/src/bools.rs index 7233d8e..d21ec42 100644 --- a/ir/src/bools.rs +++ b/ir/src/bools.rs @@ -1,6 +1,8 @@ //! Everything related to boolean handling and generation 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}; @@ -24,4 +26,55 @@ pub fn make_bool_xor<'a>(ctx: &'a IRContext<'a>, b: IRValueRef<'a>) -> Positionl }; return Ok(IRValue::new(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> { + let a_val = a.obtain(ctx)?; + let b_val = b.obtain(ctx)?; + + let t = a_val.t; + + let a_int = match a_val.obtain_as_int(t) { + 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) { + Some(v) => v, + None => return Err(PositionlessError::new("Value b wasn't an int when trying to use comp!")) + }; + + let predicate: IntPredicate; + + if t.is_signed() { + predicate = match comp { + ComparingOperator::Equal => IntPredicate::EQ, + ComparingOperator::NotEqual => IntPredicate::NE, + ComparingOperator::Higher => IntPredicate::SGT, + ComparingOperator::HigherEqual => IntPredicate::SGE, + ComparingOperator::Lower => IntPredicate::SLT, + ComparingOperator::LowerEqual => IntPredicate::SLE + }; + } else { + predicate = match comp { + ComparingOperator::Equal => IntPredicate::EQ, + ComparingOperator::NotEqual => IntPredicate::NE, + ComparingOperator::Higher => IntPredicate::ULT, + ComparingOperator::HigherEqual => IntPredicate::UGT, + ComparingOperator::Lower => IntPredicate::ULE, + ComparingOperator::LowerEqual => IntPredicate::UGE + } + } + + 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!")) + }; + + let bool_t = match ctx.type_storage.get(BOOL_TYPE_HASH) { + Some(v) => v, + None => return Err(PositionlessError::new("boolean type wasn't found!")) + }; + + return Ok(IRValue::new(cmp.into(), bool_t)); } \ No newline at end of file From 16cda26ef6192f278dd0517d182c00a73375da3d Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 18 Feb 2026 18:59:18 +0100 Subject: [PATCH 53/54] feat: added bool ir parsing --- ir/src/conv/val.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/ir/src/conv/val.rs b/ir/src/conv/val.rs index dec278b..55d4d63 100644 --- a/ir/src/conv/val.rs +++ b/ir/src/conv/val.rs @@ -4,7 +4,7 @@ use commons::err::{PositionedError, PositionedResult, PositionlessError, Positio use inkwell::values::BasicValue; use parser::ast::tree::ASTTreeNode; -use crate::{ctx::{IRContext, IRLocalContext}, irstruct::{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::{ptr::IRPointer, staticvars::IRStaticVariable}, math::make_math_operation, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED64_TYPE_HASH}, values::IRValue}; pub fn get_variable_ref<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, hash: u64) -> PositionlessResult> { match ctx.get_variable(hash) { @@ -116,6 +116,25 @@ pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, } return Ok(IRValueRef::from_val(IRValue::new(out.into(), t))); + }, + + ASTTreeNode::OperatorBasedConditionMember { lval, rval, operator } => { + let l_val = parse_ir_value(lctx, ctx, lval.clone(), None)?; + let r_val = parse_ir_value(lctx, ctx, rval.clone(), None)?; + + let cmp = make_bool_cmp_int(ctx, l_val, r_val, operator.clone())?; + + return Ok(IRValueRef::from_val(cmp)); + }, + + ASTTreeNode::BooleanBasedConditionMember { val, negate } => { + let v = parse_ir_value(lctx, ctx, val.clone(), None)?; + + if *negate { + return Ok(IRValueRef::from_val(make_bool_xor(ctx, v)?)) + } + + return Ok(v); } ASTTreeNode::StructLRFunction { l, r } => { From e3e61bc7c8cfc67cf35cf7f908fc33b93ae0548d Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 18 Feb 2026 20:11:16 +0100 Subject: [PATCH 54/54] bump: bump before fixes --- ir/src/conv/func.rs | 62 ++++++++++++++++++++++++++++++++++++++++ ir/src/conv/mod.rs | 3 +- ir/src/conv/val.rs | 8 +++--- ir/src/ctx.rs | 8 ++++-- ir/src/irstruct/funcs.rs | 10 +++++-- ir/src/values.rs | 8 ++++-- 6 files changed, 85 insertions(+), 14 deletions(-) create mode 100644 ir/src/conv/func.rs diff --git a/ir/src/conv/func.rs b/ir/src/conv/func.rs new file mode 100644 index 0000000..0c65624 --- /dev/null +++ b/ir/src/conv/func.rs @@ -0,0 +1,62 @@ +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> { + 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![]; + + for k in args { + let t = match ctx.type_storage.get(k.argument_type) { + Some(v) => v, + None => return Err(PositionlessError::new(&format!("Cannot get type with hash {} for argument {}!", k.argument_type, k.name.val))) + }; + + arguments.push(t); + } + + let func = IRFunction::create(ctx, func_name.val, &ctx.module, return_type, arguments)?; + + return Ok(func); + } + + 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(); + + match *node { + ASTTreeNode::VarDeclaration { var_name, var_type, value } => { + let var_t = match ctx.type_storage.get(var_type) { + Some(v) => v, + None => return Err(PositionlessError::new(&format!("Cannot find variable type {} in type storage!", var_name.val))) + }; + + { + let initial = if let Some(v) = value { + Some(parse_ir_value(&mut 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, var_t, None)?; + + lctx.add_variable(var_name.hash, ptr); + + return Ok(true); + }, + + _ => return Err(PositionlessError::new("Cannot parse said ASTNode as a function body member!")) + }; +} \ No newline at end of file diff --git a/ir/src/conv/mod.rs b/ir/src/conv/mod.rs index 065eaa4..ac739a8 100644 --- a/ir/src/conv/mod.rs +++ b/ir/src/conv/mod.rs @@ -1,3 +1,4 @@ //! Critical AST -> IR conversion code module -pub mod val; \ No newline at end of file +pub mod val; +pub mod func; \ No newline at end of file diff --git a/ir/src/conv/val.rs b/ir/src/conv/val.rs index 55d4d63..8a4a02e 100644 --- a/ir/src/conv/val.rs +++ b/ir/src/conv/val.rs @@ -1,10 +1,10 @@ //! AST value -> IR value conversion -use commons::err::{PositionedError, PositionedResult, PositionlessError, PositionlessResult}; +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::{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}, values::IRValue}; pub fn get_variable_ref<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, hash: u64) -> PositionlessResult> { match ctx.get_variable(hash) { @@ -18,7 +18,7 @@ pub fn get_variable_ref<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a> }; } -pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, node: Box, left: Option>) -> PositionlessResult> { +pub fn parse_ir_value<'a>(func: Option<&'a IRFunction<'a>>, ctx: &'a IRContext<'a>, node: Box, left: Option>) -> PositionlessResult> { match node.as_ref() { ASTTreeNode::IntegerLit(v) => { let t = ctx.type_storage.get(SIGNED64_TYPE_HASH); @@ -51,7 +51,7 @@ pub fn parse_ir_value<'a>(lctx: &'a IRLocalContext<'a>, ctx: &'a IRContext<'a>, return Ok(IRValueRef::from_pointer(ptr)); } - let var = get_variable_ref(lctx, ctx, e.hash)?; + let var = get_variable_ref(&func.unwrap().lctx.borrow(), ctx, e.hash)?; return Ok(var); }, diff --git a/ir/src/ctx.rs b/ir/src/ctx.rs index 38a88d1..55cf580 100644 --- a/ir/src/ctx.rs +++ b/ir/src/ctx.rs @@ -1,7 +1,7 @@ //! IR context related code use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap}; -use inkwell::{AddressSpace, builder::Builder, context::Context, types::{PointerType, VoidType}}; +use inkwell::{AddressSpace, builder::Builder, context::Context, module::Module, types::{PointerType, VoidType}}; use crate::{irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, types::storage::IRTypeStorage}; @@ -13,6 +13,8 @@ pub struct IRContext<'a> { pub ptr_type: PointerType<'a>, pub void_type: VoidType<'a>, + pub module: Module<'a>, + pub type_storage: IRTypeStorage<'a>, pub functions: HashedMap>, @@ -21,7 +23,7 @@ pub struct IRContext<'a> { 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() } + 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") } } pub fn add_variable(&'a mut self, hash: u64, var: IRStaticVariable<'a>) -> PositionlessResult { @@ -40,7 +42,7 @@ impl<'a> IRContext<'a> { }; } - pub fn is_key_taken(&'a self, hash: u64) -> bool { + pub fn is_key_taken(&self, hash: u64) -> bool { return self.functions.get(hash).is_some() || self.static_vars.get(hash).is_some() || self.type_storage.get(hash).is_some(); } diff --git a/ir/src/irstruct/funcs.rs b/ir/src/irstruct/funcs.rs index bdb9858..30f4e6a 100644 --- a/ir/src/irstruct/funcs.rs +++ b/ir/src/irstruct/funcs.rs @@ -1,7 +1,9 @@ +use std::cell::RefCell; + 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, irstruct::ptr::IRPointer, refs::IRValueRef, types::typing::IRType, values::IRValue}; +use crate::{ctx::{IRContext, IRLocalContext}, irstruct::ptr::IRPointer, refs::IRValueRef, types::typing::IRType, values::IRValue}; pub struct IRFunction<'a> { pub inkwell_func: FunctionValue<'a>, @@ -9,6 +11,8 @@ pub struct IRFunction<'a> { args: Vec<&'a IRType<'a>>, name: String, + pub lctx: RefCell>, + entry: Option> } @@ -17,11 +21,11 @@ impl<'a> IRFunction<'a> { let block = ctx.inkwell_ctx.append_basic_block(func, "entry"); - return IRFunction { inkwell_func: func, ret_type, args, name, entry: Some(block) } + return IRFunction { inkwell_func: func, ret_type, args, name, entry: Some(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 } + return IRFunction { inkwell_func: 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 { diff --git a/ir/src/values.rs b/ir/src/values.rs index de40e57..b4f3ab6 100644 --- a/ir/src/values.rs +++ b/ir/src/values.rs @@ -1,5 +1,7 @@ //! IR value representation definitons +use std::cell::{Ref, RefCell}; + use commons::{err::{PositionlessError, PositionlessResult}}; use inkwell::{types::StringRadix, values::{BasicValueEnum, IntValue}}; @@ -11,13 +13,13 @@ use crate::{irstruct::ptr::IRPointer, types::typing::IRType}; #[derive(Clone)] pub struct IRValue<'a> { inkwell_val: BasicValueEnum<'a>, - pub t: &'a IRType<'a>, + pub t: IRType<'a>, } impl<'a> IRValue<'a> { /// Creates a new untracked instance - pub fn new(inkwell_val: BasicValueEnum<'a>, t: &'a IRType<'a>) -> Self { - return IRValue { inkwell_val, t } + pub fn new(inkwell_val: BasicValueEnum<'a>, t: &IRType<'a>) -> Self { + return IRValue { inkwell_val, t: t.clone() } } pub fn from_unsigned(t: &'a IRType<'a>, v: u128) -> PositionlessResult {