Add the ability to call functions

This commit is contained in:
Sofia 2025-06-24 23:30:29 +03:00
parent 5f93b7c9c2
commit d0aa3e1410
2 changed files with 56 additions and 7 deletions

View File

@ -6,9 +6,16 @@ pub fn main() {
let mainfunc = IRFunction::new(&module, &"mainfunc".to_owned());
let secondary_func = IRFunction::new(&module, &"secondary".to_owned());
let secondary_block = IRBlock::new(&context, &"secondaryblock".to_owned());
secondary_block.ret(&secondary_func, IRValue::from_const(&context, 54).into());
let block = IRBlock::new(&context, &"mainblock".to_owned());
let lhs_cmp = IRValue::from_const(&context, 100);
let lhs_1 = IRValue::from_const(&context, 100);
let lhs_2 = block.call(&secondary_func);
let lhs_cmp = block.add(lhs_1.into(), lhs_2.into()).unwrap();
let rhs_cmp = IRValue::from_const(&context, 200);
let compare = block.less_than(lhs_cmp.into(), rhs_cmp.into()).unwrap();

View File

@ -61,6 +61,8 @@ impl IRType for i32 {
}
}
pub struct IROpaqueValue(LLVMTypeRef, LLVMValueRef);
pub struct IRValue<T: IRType>(PhantomData<T>, IROpaqueValue);
impl<T: IRType> IRValue<T> {
@ -85,8 +87,6 @@ impl<T: IRType> From<IRValue<T>> for IROpaqueValue {
}
}
pub struct IROpaqueValue(LLVMTypeRef, LLVMValueRef);
pub struct IRContext {
context: *mut LLVMContext,
builder: *mut LLVMBuilder,
@ -209,8 +209,10 @@ impl<'a> Drop for IRModule<'a> {
}
pub struct IRFunction<'a> {
pub name: String,
pub module: &'a IRModule<'a>,
pub functionref: *mut LLVMValue,
pub function_ref: *mut LLVMValue,
pub function_type: *mut LLVMType,
}
impl<'a> IRFunction<'a> {
@ -222,12 +224,17 @@ impl<'a> IRFunction<'a> {
let func_type =
LLVMFunctionType(return_type, argts.as_mut_ptr(), argts.len() as u32, 0);
let functionref =
let function_ref =
LLVMAddFunction(module.module, into_cstring(name).as_ptr(), func_type);
let function_type =
LLVMFunctionType(return_type, argts.as_mut_ptr(), argts.len() as u32, 0);
IRFunction {
name: name.clone(),
module,
functionref,
function_ref,
function_type,
}
}
}
@ -253,6 +260,41 @@ impl<'a> IRBlock<'a> {
}
}
pub fn call(&self, function: &IRFunction) -> IROpaqueValue {
unsafe {
let builder = self.context.builder;
LLVMPositionBuilderAtEnd(builder, self.blockref);
// Add way to check and use parameters
let mut args = [];
let value = LLVMBuildCall2(
builder,
function.function_type,
function.function_ref,
args.as_mut_ptr(),
args.len() as u32,
into_cstring(&function.name).as_ptr(),
);
IROpaqueValue(i32::llvm_type(&self.context), value)
}
}
pub fn add(&self, lhs: IROpaqueValue, rhs: IROpaqueValue) -> Result<IROpaqueValue, ()> {
let IROpaqueValue(t1, lhs) = lhs;
let IROpaqueValue(t2, rhs) = rhs;
if t1 != t2 {
Err(())
} else {
unsafe {
let builder = self.context.builder;
LLVMPositionBuilderAtEnd(builder, self.blockref);
let value = LLVMBuildAdd(builder, lhs, rhs, c"add".as_ptr());
Ok(IROpaqueValue(t1, value))
}
}
}
pub fn less_than(&self, lhs: IROpaqueValue, rhs: IROpaqueValue) -> Result<IRValue<bool>, ()> {
let IROpaqueValue(t1, lhs) = lhs;
let IROpaqueValue(t2, rhs) = rhs;
@ -302,7 +344,7 @@ impl<'a> IRBlock<'a> {
unsafe fn append(mut self, function: &IRFunction<'a>) {
unsafe {
LLVMAppendExistingBasicBlock(function.functionref, self.blockref);
LLVMAppendExistingBasicBlock(function.function_ref, self.blockref);
self.inserted = true;
}
}