Move context.rs to lib.rs

This commit is contained in:
Sofia 2025-06-28 18:49:54 +03:00
parent 85564c74c9
commit 02d8b37424
4 changed files with 310 additions and 578 deletions

View File

@ -1,8 +1,4 @@
use reid_lib::{ use reid_lib::{Comparison, Context, types::BasicType};
context::{Comparison, Context},
types::BasicType,
*,
};
pub fn main() { pub fn main() {
// Notes from inkwell: // Notes from inkwell:

View File

@ -1,358 +0,0 @@
use std::{ffi::CString, ptr::null_mut};
use llvm_sys::{
LLVMBuilder, LLVMContext,
analysis::LLVMVerifyModule,
core::*,
prelude::*,
target::{
LLVM_InitializeAllAsmParsers, LLVM_InitializeAllAsmPrinters, LLVM_InitializeAllTargetInfos,
LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout,
},
target_machine::{
LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine,
LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToFile,
},
};
use crate::{
OpaqueValue,
types::{BasicType, FunctionType, IntegerType},
util::{ErrorMessageHolder, from_cstring, into_cstring},
};
pub enum Comparison {
LessThan,
}
pub struct Context {
pub(crate) context_ref: *mut LLVMContext,
pub(crate) builder_ref: *mut LLVMBuilder,
}
impl Context {
pub fn new() -> Context {
unsafe {
// Set up a context, module and builder in that context.
let context = LLVMContextCreate();
let builder = LLVMCreateBuilderInContext(context);
Context {
context_ref: context,
builder_ref: builder,
}
}
}
pub fn integer_type<'a, const T: u32>(&'a self) -> IntegerType<'a, T> {
IntegerType::in_context(&self)
}
pub fn module<T: Into<String>>(&self, name: T) -> Module {
Module::with_name(self, name.into())
}
}
impl Drop for Context {
fn drop(&mut self) {
// Clean up. Values created in the context mostly get cleaned up there.
unsafe {
LLVMDisposeBuilder(self.builder_ref);
LLVMContextDispose(self.context_ref);
}
}
}
pub struct Module<'ctx> {
context: &'ctx Context,
module_ref: LLVMModuleRef,
name: CString,
}
impl<'ctx> Module<'ctx> {
fn with_name(context: &'ctx Context, name: String) -> Module<'ctx> {
unsafe {
let cstring_name = into_cstring(name);
let module_ref =
LLVMModuleCreateWithNameInContext(cstring_name.as_ptr(), context.context_ref);
Module {
context,
module_ref,
name: cstring_name,
}
}
}
pub fn add_function<ReturnType: BasicType, T: Into<String>>(
&self,
fn_type: FunctionType<'ctx, ReturnType>,
name: T,
) -> Function<'_, ReturnType> {
unsafe {
let name_cstring = into_cstring(name);
let function_ref =
LLVMAddFunction(self.module_ref, name_cstring.as_ptr(), fn_type.llvm_type());
Function {
module: self,
fn_type,
name: name_cstring,
fn_ref: function_ref,
}
}
}
pub fn print_to_string(&self) -> Result<String, String> {
unsafe {
LLVM_InitializeAllTargets();
LLVM_InitializeAllTargetInfos();
LLVM_InitializeAllTargetMCs();
LLVM_InitializeAllAsmParsers();
LLVM_InitializeAllAsmPrinters();
let triple = LLVMGetDefaultTargetTriple();
let mut target: _ = null_mut();
let mut err = ErrorMessageHolder::null();
LLVMGetTargetFromTriple(triple, &mut target, err.borrow_mut());
println!("{:?}, {:?}", from_cstring(triple), target);
err.into_result().unwrap();
let target_machine = LLVMCreateTargetMachine(
target,
triple,
c"generic".as_ptr(),
c"".as_ptr(),
llvm_sys::target_machine::LLVMCodeGenOptLevel::LLVMCodeGenLevelNone,
llvm_sys::target_machine::LLVMRelocMode::LLVMRelocDefault,
llvm_sys::target_machine::LLVMCodeModel::LLVMCodeModelDefault,
);
let data_layout = LLVMCreateTargetDataLayout(target_machine);
LLVMSetModuleDataLayout(self.module_ref, data_layout);
let mut err = ErrorMessageHolder::null();
LLVMVerifyModule(
self.module_ref,
llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction,
err.borrow_mut(),
);
err.into_result().unwrap();
let mut err = ErrorMessageHolder::null();
LLVMTargetMachineEmitToFile(
target_machine,
self.module_ref,
CString::new("hello.asm").unwrap().into_raw(),
LLVMCodeGenFileType::LLVMAssemblyFile,
err.borrow_mut(),
);
err.into_result().unwrap();
let mut err = ErrorMessageHolder::null();
LLVMTargetMachineEmitToFile(
target_machine,
self.module_ref,
CString::new("hello.o").unwrap().into_raw(),
LLVMCodeGenFileType::LLVMObjectFile,
err.borrow_mut(),
);
err.into_result().unwrap();
Ok(from_cstring(LLVMPrintModuleToString(self.module_ref)).expect("UTF8-err"))
}
}
}
impl<'a> Drop for Module<'a> {
fn drop(&mut self) {
// Clean up. Values created in the context mostly get cleaned up there.
unsafe {
LLVMDisposeModule(self.module_ref);
}
}
}
pub struct Function<'ctx, ReturnType: BasicType> {
module: &'ctx Module<'ctx>,
name: CString,
fn_type: FunctionType<'ctx, ReturnType>,
fn_ref: LLVMValueRef,
}
impl<'ctx, ReturnType: BasicType> Function<'ctx, ReturnType> {
pub fn block<T: Into<String>>(&'ctx self, name: T) -> BasicBlock<'ctx, ReturnType> {
BasicBlock::in_function(&self, name.into())
}
}
pub struct BasicBlock<'ctx, ReturnType: BasicType> {
function: &'ctx Function<'ctx, ReturnType>,
builder_ref: LLVMBuilderRef,
name: CString,
blockref: LLVMBasicBlockRef,
inserted: bool,
}
impl<'ctx, ReturnType: BasicType> BasicBlock<'ctx, ReturnType> {
fn in_function(
function: &'ctx Function<ReturnType>,
name: String,
) -> BasicBlock<'ctx, ReturnType> {
unsafe {
let block_name = into_cstring(name);
let block_ref = LLVMCreateBasicBlockInContext(
function.module.context.context_ref,
block_name.as_ptr(),
);
BasicBlock {
function: function,
builder_ref: function.module.context.builder_ref,
name: block_name,
blockref: block_ref,
inserted: false,
}
}
}
#[must_use]
pub fn integer_compare<T: Into<String>>(
&self,
lhs: &'ctx OpaqueValue<'ctx>,
rhs: &'ctx OpaqueValue<'ctx>,
comparison: &Comparison,
name: T,
) -> Result<OpaqueValue<'ctx>, ()> {
if lhs.basic_type != rhs.basic_type {
return Err(()); // TODO invalid amount of parameters
}
unsafe {
LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref);
let value = match comparison {
Comparison::LessThan => LLVMBuildICmp(
self.builder_ref,
llvm_sys::LLVMIntPredicate::LLVMIntSLT,
lhs.value_ref,
rhs.value_ref,
into_cstring(name.into()).as_ptr(),
),
};
Ok(OpaqueValue::new(lhs.basic_type, value))
}
}
#[must_use]
pub fn call<T: Into<String>>(
&self,
callee: &'ctx Function<'ctx, ReturnType>,
params: Vec<&'ctx OpaqueValue<'ctx>>,
name: T,
) -> Result<OpaqueValue<'ctx>, ()> {
if params.len() != callee.fn_type.param_types.len() {
return Err(()); // TODO invalid amount of parameters
}
for (t1, t2) in callee.fn_type.param_types.iter().zip(&params) {
if t1 != &t2.basic_type.llvm_type() {
return Err(()); // TODO wrong types in parameters
}
}
unsafe {
let mut param_list: Vec<LLVMValueRef> = params.iter().map(|p| p.value_ref).collect();
LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref);
let ret_val = LLVMBuildCall2(
self.builder_ref,
callee.fn_type.llvm_type(),
callee.fn_ref,
param_list.as_mut_ptr(),
param_list.len() as u32,
into_cstring(name.into()).as_ptr(),
);
Ok(OpaqueValue::new(callee.fn_type.return_type, ret_val))
}
}
#[must_use]
pub fn add<T: Into<String>>(
&self,
lhs: &OpaqueValue<'ctx>,
rhs: &OpaqueValue<'ctx>,
name: T,
) -> Result<OpaqueValue<'ctx>, ()> {
if lhs.basic_type != rhs.basic_type {
return Err(()); // TODO error
}
unsafe {
LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref);
let add_value_ref = LLVMBuildAdd(
self.builder_ref,
lhs.value_ref,
rhs.value_ref,
into_cstring(name.into()).as_ptr(),
);
Ok(OpaqueValue::new(lhs.basic_type, add_value_ref))
}
}
#[must_use]
pub fn br(self, into: BasicBlock<'ctx, ReturnType>) -> Result<(), ()> {
unsafe {
LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref);
LLVMBuildBr(self.builder_ref, into.blockref);
self.terminate();
Ok(())
}
}
#[must_use]
pub fn conditional_br<T: Into<String>, U: Into<String>>(
self,
condition: &OpaqueValue<'ctx>,
lhs_name: T,
rhs_name: U,
) -> Result<(BasicBlock<'ctx, ReturnType>, BasicBlock<'ctx, ReturnType>), ()> {
unsafe {
let lhs = BasicBlock::in_function(&self.function, lhs_name.into());
let rhs = BasicBlock::in_function(&self.function, rhs_name.into());
LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref);
LLVMBuildCondBr(
self.builder_ref,
condition.value_ref,
lhs.blockref,
rhs.blockref,
);
self.terminate();
Ok((lhs, rhs))
}
}
#[must_use]
pub fn ret(self, return_value: &OpaqueValue<'ctx>) -> Result<(), ()> {
if self.function.fn_type.return_type().llvm_type() != return_value.basic_type.llvm_type() {
return Err(());
}
unsafe {
LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref);
LLVMBuildRet(self.builder_ref, return_value.value_ref);
self.terminate();
Ok(())
}
}
unsafe fn terminate(mut self) {
unsafe {
LLVMAppendExistingBasicBlock(self.function.fn_ref, self.blockref);
self.inserted = true;
}
}
}
impl<'ctx, ReturnType: BasicType> Drop for BasicBlock<'ctx, ReturnType> {
fn drop(&mut self) {
if !self.inserted {
unsafe {
LLVMDeleteBasicBlock(self.blockref);
}
}
}
}

View File

@ -1,7 +1,6 @@
use std::ffi::{CStr, CString}; use std::ffi::CString;
use std::ptr::null_mut; use std::ptr::null_mut;
use context::Context;
use llvm_sys::analysis::LLVMVerifyModule; use llvm_sys::analysis::LLVMVerifyModule;
use llvm_sys::target::{ use llvm_sys::target::{
LLVM_InitializeAllAsmParsers, LLVM_InitializeAllAsmPrinters, LLVM_InitializeAllTargetInfos, LLVM_InitializeAllAsmParsers, LLVM_InitializeAllAsmPrinters, LLVM_InitializeAllTargetInfos,
@ -11,252 +10,347 @@ use llvm_sys::target_machine::{
LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine,
LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToFile, LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToFile,
}; };
use llvm_sys::{LLVMBasicBlock, LLVMModule, LLVMType, LLVMValue, core::*}; use llvm_sys::{LLVMBuilder, LLVMContext, core::*, prelude::*};
use types::BasicType; use types::{BasicType, FunctionType, IntegerType};
use util::{ErrorMessageHolder, from_cstring, into_cstring}; use util::{ErrorMessageHolder, from_cstring, into_cstring};
pub use types::OpaqueValue; pub use types::OpaqueValue;
pub mod context;
pub mod types; pub mod types;
mod util; mod util;
// pub struct IRModule<'a> { pub enum Comparison {
// context: &'a Context, LessThan,
// module: *mut LLVMModule, }
// }
// impl<'a> IRModule<'a> { pub struct Context {
// pub fn new(context: &'a Context, name: &String) -> IRModule<'a> { pub(crate) context_ref: *mut LLVMContext,
// unsafe { pub(crate) builder_ref: *mut LLVMBuilder,
// let module = }
// LLVMModuleCreateWithNameInContext(into_cstring(name).as_ptr(), context.context_ref);
// IRModule { context, module } impl Context {
// } pub fn new() -> Context {
// } unsafe {
// Set up a context, module and builder in that context.
let context = LLVMContextCreate();
let builder = LLVMCreateBuilderInContext(context);
// pub fn print_to_string(&self) -> Result<&str, String> { Context {
// unsafe { context_ref: context,
// LLVM_InitializeAllTargets(); builder_ref: builder,
// LLVM_InitializeAllTargetInfos(); }
// LLVM_InitializeAllTargetMCs(); }
// LLVM_InitializeAllAsmParsers(); }
// LLVM_InitializeAllAsmPrinters();
// let triple = LLVMGetDefaultTargetTriple(); pub fn integer_type<'a, const T: u32>(&'a self) -> IntegerType<'a, T> {
IntegerType::in_context(&self)
}
// let mut target: _ = null_mut(); pub fn module<T: Into<String>>(&self, name: T) -> Module {
// let mut err = ErrorMessageHolder::null(); Module::with_name(self, name.into())
// LLVMGetTargetFromTriple(triple, &mut target, err.borrow_mut()); }
// println!("{:?}, {:?}", from_cstring(triple), target); }
// err.into_result().unwrap();
// let target_machine = LLVMCreateTargetMachine( impl Drop for Context {
// target, fn drop(&mut self) {
// triple, // Clean up. Values created in the context mostly get cleaned up there.
// c"generic".as_ptr(), unsafe {
// c"".as_ptr(), LLVMDisposeBuilder(self.builder_ref);
// llvm_sys::target_machine::LLVMCodeGenOptLevel::LLVMCodeGenLevelNone, LLVMContextDispose(self.context_ref);
// llvm_sys::target_machine::LLVMRelocMode::LLVMRelocDefault, }
// llvm_sys::target_machine::LLVMCodeModel::LLVMCodeModelDefault, }
// ); }
// let data_layout = LLVMCreateTargetDataLayout(target_machine); pub struct Module<'ctx> {
// LLVMSetModuleDataLayout(self.module, data_layout); context: &'ctx Context,
module_ref: LLVMModuleRef,
name: CString,
}
// let mut err = ErrorMessageHolder::null(); impl<'ctx> Module<'ctx> {
// LLVMVerifyModule( fn with_name(context: &'ctx Context, name: String) -> Module<'ctx> {
// self.module, unsafe {
// llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction, let cstring_name = into_cstring(name);
// err.borrow_mut(), let module_ref =
// ); LLVMModuleCreateWithNameInContext(cstring_name.as_ptr(), context.context_ref);
// err.into_result().unwrap(); Module {
context,
module_ref,
name: cstring_name,
}
}
}
// let mut err = ErrorMessageHolder::null(); pub fn add_function<ReturnType: BasicType, T: Into<String>>(
// LLVMTargetMachineEmitToFile( &self,
// target_machine, fn_type: FunctionType<'ctx, ReturnType>,
// self.module, name: T,
// CString::new("hello.asm").unwrap().into_raw(), ) -> Function<'_, ReturnType> {
// LLVMCodeGenFileType::LLVMAssemblyFile, unsafe {
// err.borrow_mut(), let name_cstring = into_cstring(name);
// ); let function_ref =
// err.into_result().unwrap(); LLVMAddFunction(self.module_ref, name_cstring.as_ptr(), fn_type.llvm_type());
Function {
module: self,
fn_type,
name: name_cstring,
fn_ref: function_ref,
}
}
}
// let mut err = ErrorMessageHolder::null(); pub fn print_to_string(&self) -> Result<String, String> {
// LLVMTargetMachineEmitToFile( unsafe {
// target_machine, LLVM_InitializeAllTargets();
// self.module, LLVM_InitializeAllTargetInfos();
// CString::new("hello.o").unwrap().into_raw(), LLVM_InitializeAllTargetMCs();
// LLVMCodeGenFileType::LLVMObjectFile, LLVM_InitializeAllAsmParsers();
// err.borrow_mut(), LLVM_InitializeAllAsmPrinters();
// );
// err.into_result().unwrap();
// Ok(CStr::from_ptr(LLVMPrintModuleToString(self.module)) let triple = LLVMGetDefaultTargetTriple();
// .to_str()
// .expect("UTF8-err"))
// }
// }
// }
// impl<'a> Drop for IRModule<'a> { let mut target: _ = null_mut();
// fn drop(&mut self) { let mut err = ErrorMessageHolder::null();
// // Clean up. Values created in the context mostly get cleaned up there. LLVMGetTargetFromTriple(triple, &mut target, err.borrow_mut());
// unsafe { println!("{:?}, {:?}", from_cstring(triple), target);
// LLVMDisposeModule(self.module); err.into_result().unwrap();
// }
// }
// }
// pub struct IRFunction<'a> { let target_machine = LLVMCreateTargetMachine(
// pub name: String, target,
// pub module: &'a IRModule<'a>, triple,
// pub function_ref: *mut LLVMValue, c"generic".as_ptr(),
// pub function_type: *mut LLVMType, c"".as_ptr(),
// } llvm_sys::target_machine::LLVMCodeGenOptLevel::LLVMCodeGenLevelNone,
llvm_sys::target_machine::LLVMRelocMode::LLVMRelocDefault,
llvm_sys::target_machine::LLVMCodeModel::LLVMCodeModelDefault,
);
// impl<'a> IRFunction<'a> { let data_layout = LLVMCreateTargetDataLayout(target_machine);
// pub fn new(module: &'a IRModule<'a>, name: &String) -> IRFunction<'a> { LLVMSetModuleDataLayout(self.module_ref, data_layout);
// unsafe {
// // TODO, fix later!
// let return_type = LLVMInt128TypeInContext(module.context.context_ref);
// let mut argts = [];
// let func_type =
// LLVMFunctionType(return_type, argts.as_mut_ptr(), argts.len() as u32, 0);
// let function_ref = let mut err = ErrorMessageHolder::null();
// LLVMAddFunction(module.module, into_cstring(name).as_ptr(), func_type); LLVMVerifyModule(
self.module_ref,
llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction,
err.borrow_mut(),
);
err.into_result().unwrap();
// let function_type = let mut err = ErrorMessageHolder::null();
// LLVMFunctionType(return_type, argts.as_mut_ptr(), argts.len() as u32, 0); LLVMTargetMachineEmitToFile(
target_machine,
self.module_ref,
CString::new("hello.asm").unwrap().into_raw(),
LLVMCodeGenFileType::LLVMAssemblyFile,
err.borrow_mut(),
);
err.into_result().unwrap();
// IRFunction { let mut err = ErrorMessageHolder::null();
// name: name.clone(), LLVMTargetMachineEmitToFile(
// module, target_machine,
// function_ref, self.module_ref,
// function_type, CString::new("hello.o").unwrap().into_raw(),
// } LLVMCodeGenFileType::LLVMObjectFile,
// } err.borrow_mut(),
// } );
// } err.into_result().unwrap();
// pub struct IRBlock<'a> { Ok(from_cstring(LLVMPrintModuleToString(self.module_ref)).expect("UTF8-err"))
// context: &'a Context, }
// blockref: *mut LLVMBasicBlock, }
// inserted: bool, }
// }
// impl<'a> IRBlock<'a> { impl<'a> Drop for Module<'a> {
// pub fn new(context: &'a Context, name: &String) -> IRBlock<'a> { fn drop(&mut self) {
// unsafe { // Clean up. Values created in the context mostly get cleaned up there.
// let blockref = unsafe {
// LLVMCreateBasicBlockInContext(context.context_ref, into_cstring(name).as_ptr()); LLVMDisposeModule(self.module_ref);
}
}
}
// IRBlock { pub struct Function<'ctx, ReturnType: BasicType> {
// context, module: &'ctx Module<'ctx>,
// blockref, name: CString,
// inserted: false, fn_type: FunctionType<'ctx, ReturnType>,
// } fn_ref: LLVMValueRef,
// } }
// }
// pub fn call(&self, function: &IRFunction) -> OpaqueValue { impl<'ctx, ReturnType: BasicType> Function<'ctx, ReturnType> {
// unsafe { pub fn block<T: Into<String>>(&'ctx self, name: T) -> BasicBlock<'ctx, ReturnType> {
// let builder = self.context.builder_ref; BasicBlock::in_function(&self, name.into())
// LLVMPositionBuilderAtEnd(builder, self.blockref); }
}
// // Add way to check and use parameters pub struct BasicBlock<'ctx, ReturnType: BasicType> {
// let mut args = []; function: &'ctx Function<'ctx, ReturnType>,
builder_ref: LLVMBuilderRef,
name: CString,
blockref: LLVMBasicBlockRef,
inserted: bool,
}
// let value = LLVMBuildCall2( impl<'ctx, ReturnType: BasicType> BasicBlock<'ctx, ReturnType> {
// builder, fn in_function(
// function.function_type, function: &'ctx Function<ReturnType>,
// function.function_ref, name: String,
// args.as_mut_ptr(), ) -> BasicBlock<'ctx, ReturnType> {
// args.len() as u32, unsafe {
// into_cstring(&function.name).as_ptr(), let block_name = into_cstring(name);
// ); let block_ref = LLVMCreateBasicBlockInContext(
// OpaqueValue(i32::llvm_type(&self.context), value) function.module.context.context_ref,
// } block_name.as_ptr(),
// } );
BasicBlock {
function: function,
builder_ref: function.module.context.builder_ref,
name: block_name,
blockref: block_ref,
inserted: false,
}
}
}
// pub fn add(&self, lhs: OpaqueValue, rhs: OpaqueValue) -> Result<OpaqueValue, ()> { #[must_use]
// let OpaqueValue(t1, lhs) = lhs; pub fn integer_compare<T: Into<String>>(
// let OpaqueValue(t2, rhs) = rhs; &self,
// if t1 != t2 { lhs: &'ctx OpaqueValue<'ctx>,
// Err(()) rhs: &'ctx OpaqueValue<'ctx>,
// } else { comparison: &Comparison,
// unsafe { name: T,
// let builder = self.context.builder_ref; ) -> Result<OpaqueValue<'ctx>, ()> {
// LLVMPositionBuilderAtEnd(builder, self.blockref); if lhs.basic_type != rhs.basic_type {
// let value = LLVMBuildAdd(builder, lhs, rhs, c"add".as_ptr()); return Err(()); // TODO invalid amount of parameters
// Ok(OpaqueValue(t1, value)) }
// } unsafe {
// } LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref);
// } let value = match comparison {
Comparison::LessThan => LLVMBuildICmp(
self.builder_ref,
llvm_sys::LLVMIntPredicate::LLVMIntSLT,
lhs.value_ref,
rhs.value_ref,
into_cstring(name.into()).as_ptr(),
),
};
// pub fn less_than(&self, lhs: OpaqueValue, rhs: OpaqueValue) -> Result<IRValue<bool>, ()> { Ok(OpaqueValue::new(lhs.basic_type, value))
// let OpaqueValue(t1, lhs) = lhs; }
// let OpaqueValue(t2, rhs) = rhs; }
// if t1 != t2 { #[must_use]
// Err(()) pub fn call<T: Into<String>>(
// } else { &self,
// unsafe { callee: &'ctx Function<'ctx, ReturnType>,
// let builder = self.context.builder_ref; params: Vec<&'ctx OpaqueValue<'ctx>>,
// LLVMPositionBuilderAtEnd(builder, self.blockref); name: T,
// let value = LLVMBuildICmp( ) -> Result<OpaqueValue<'ctx>, ()> {
// builder, if params.len() != callee.fn_type.param_types.len() {
// llvm_sys::LLVMIntPredicate::LLVMIntSLT, return Err(()); // TODO invalid amount of parameters
// lhs, }
// rhs, for (t1, t2) in callee.fn_type.param_types.iter().zip(&params) {
// c"asd".as_ptr(), if t1 != &t2.basic_type.llvm_type() {
// ); return Err(()); // TODO wrong types in parameters
// Ok(IRValue::from_runtime(bool::llvm_type(&self.context), value)) }
// } }
// } unsafe {
// } let mut param_list: Vec<LLVMValueRef> = params.iter().map(|p| p.value_ref).collect();
LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref);
let ret_val = LLVMBuildCall2(
self.builder_ref,
callee.fn_type.llvm_type(),
callee.fn_ref,
param_list.as_mut_ptr(),
param_list.len() as u32,
into_cstring(name.into()).as_ptr(),
);
Ok(OpaqueValue::new(callee.fn_type.return_type, ret_val))
}
}
// pub fn cond_br( #[must_use]
// self, pub fn add<T: Into<String>>(
// function: &IRFunction, &self,
// value: IRValue<bool>, lhs: &OpaqueValue<'ctx>,
// ) -> (IRBlock<'a>, IRBlock<'a>) { rhs: &OpaqueValue<'ctx>,
// let lhs = IRBlock::new(self.context, &"lhs".to_owned()); name: T,
// let rhs = IRBlock::new(self.context, &"rhs".to_owned()); ) -> Result<OpaqueValue<'ctx>, ()> {
// unsafe { if lhs.basic_type != rhs.basic_type {
// let builder = self.context.builder_ref; return Err(()); // TODO error
// LLVMPositionBuilderAtEnd(builder, self.blockref); }
// LLVMBuildCondBr(builder, value.1.1, lhs.blockref, rhs.blockref); unsafe {
// self.append(function); LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref);
// (lhs, rhs) let add_value_ref = LLVMBuildAdd(
// } self.builder_ref,
// } lhs.value_ref,
rhs.value_ref,
into_cstring(name.into()).as_ptr(),
);
Ok(OpaqueValue::new(lhs.basic_type, add_value_ref))
}
}
// pub fn ret(self, function: &IRFunction, value: OpaqueValue) { #[must_use]
// unsafe { pub fn br(self, into: BasicBlock<'ctx, ReturnType>) -> Result<(), ()> {
// let builder = self.context.builder_ref; unsafe {
// LLVMPositionBuilderAtEnd(builder, self.blockref); LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref);
// LLVMBuildRet(builder, value.1); LLVMBuildBr(self.builder_ref, into.blockref);
// self.append(function); self.terminate();
// } Ok(())
// } }
}
// unsafe fn append(mut self, function: &IRFunction<'a>) { #[must_use]
// unsafe { pub fn conditional_br<T: Into<String>, U: Into<String>>(
// LLVMAppendExistingBasicBlock(function.function_ref, self.blockref); self,
// self.inserted = true; condition: &OpaqueValue<'ctx>,
// } lhs_name: T,
// } rhs_name: U,
// } ) -> Result<(BasicBlock<'ctx, ReturnType>, BasicBlock<'ctx, ReturnType>), ()> {
unsafe {
let lhs = BasicBlock::in_function(&self.function, lhs_name.into());
let rhs = BasicBlock::in_function(&self.function, rhs_name.into());
// impl<'a> Drop for IRBlock<'a> { LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref);
// fn drop(&mut self) { LLVMBuildCondBr(
// unsafe { self.builder_ref,
// if !self.inserted { condition.value_ref,
// LLVMDeleteBasicBlock(self.blockref); lhs.blockref,
// } rhs.blockref,
// } );
// } self.terminate();
// } Ok((lhs, rhs))
}
}
#[must_use]
pub fn ret(self, return_value: &OpaqueValue<'ctx>) -> Result<(), ()> {
if self.function.fn_type.return_type().llvm_type() != return_value.basic_type.llvm_type() {
return Err(());
}
unsafe {
LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref);
LLVMBuildRet(self.builder_ref, return_value.value_ref);
self.terminate();
Ok(())
}
}
unsafe fn terminate(mut self) {
unsafe {
LLVMAppendExistingBasicBlock(self.function.fn_ref, self.blockref);
self.inserted = true;
}
}
}
impl<'ctx, ReturnType: BasicType> Drop for BasicBlock<'ctx, ReturnType> {
fn drop(&mut self) {
if !self.inserted {
unsafe {
LLVMDeleteBasicBlock(self.blockref);
}
}
}
}

View File

@ -42,7 +42,7 @@ impl PartialEq for &dyn BasicType {
} }
} }
impl PartialEq<LLVMTypeRef> for dyn BasicType { impl PartialEq<LLVMTypeRef> for &dyn BasicType {
fn eq(&self, other: &LLVMTypeRef) -> bool { fn eq(&self, other: &LLVMTypeRef) -> bool {
self.llvm_type() == *other self.llvm_type() == *other
} }