Remove the old files
This commit is contained in:
		
							parent
							
								
									35efa78a56
								
							
						
					
					
						commit
						48ae533f33
					
				| @ -1,455 +0,0 @@ | ||||
| use std::ffi::CString; | ||||
| use std::marker::PhantomData; | ||||
| use std::net::Incoming; | ||||
| use std::ptr::null_mut; | ||||
| 
 | ||||
| use llvm_sys::analysis::LLVMVerifyModule; | ||||
| use llvm_sys::target::{ | ||||
|     LLVM_InitializeAllAsmParsers, LLVM_InitializeAllAsmPrinters, LLVM_InitializeAllTargetInfos, | ||||
|     LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout, | ||||
| }; | ||||
| use llvm_sys::target_machine::{ | ||||
|     LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, | ||||
|     LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToFile, | ||||
| }; | ||||
| use llvm_sys::{LLVMBuilder, LLVMContext, LLVMIntPredicate, core::*, prelude::*}; | ||||
| use types::{BasicType, BasicValue, FunctionType, IntegerType, Value}; | ||||
| use util::{ErrorMessageHolder, from_cstring, into_cstring}; | ||||
| 
 | ||||
| pub mod test; | ||||
| pub mod types; | ||||
| mod util; | ||||
| 
 | ||||
| pub enum IntPredicate { | ||||
|     SLT, | ||||
|     SGT, | ||||
| 
 | ||||
|     ULT, | ||||
|     UGT, | ||||
| } | ||||
| 
 | ||||
| impl IntPredicate { | ||||
|     pub fn as_llvm(&self) -> LLVMIntPredicate { | ||||
|         match *self { | ||||
|             Self::SLT => LLVMIntPredicate::LLVMIntSLT, | ||||
|             Self::SGT => LLVMIntPredicate::LLVMIntSGT, | ||||
|             Self::ULT => LLVMIntPredicate::LLVMIntULT, | ||||
|             Self::UGT => LLVMIntPredicate::LLVMIntUGT, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 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 type_i1<'a>(&'a self) -> IntegerType<'a> { | ||||
|         IntegerType::in_context(&self, 1) | ||||
|     } | ||||
| 
 | ||||
|     pub fn type_i8<'a>(&'a self) -> IntegerType<'a> { | ||||
|         IntegerType::in_context(&self, 8) | ||||
|     } | ||||
| 
 | ||||
|     pub fn type_i16<'a>(&'a self) -> IntegerType<'a> { | ||||
|         IntegerType::in_context(&self, 16) | ||||
|     } | ||||
| 
 | ||||
|     pub fn type_i32<'a>(&'a self) -> IntegerType<'a> { | ||||
|         IntegerType::in_context(&self, 32) | ||||
|     } | ||||
| 
 | ||||
|     pub fn module(&self, name: &str) -> Module { | ||||
|         Module::with_name(self, name) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 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: &str) -> 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(&'ctx self, fn_type: FunctionType<'ctx>, name: &str) -> Function<'ctx> { | ||||
|         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); | ||||
|             LLVMSetTarget(self.module_ref, triple); | ||||
|             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(); | ||||
| 
 | ||||
|             from_cstring(LLVMPrintModuleToString(self.module_ref)).ok_or("UTF-8 error".to_owned()) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct Function<'ctx> { | ||||
|     module: &'ctx Module<'ctx>, | ||||
|     name: CString, | ||||
|     fn_type: FunctionType<'ctx>, | ||||
|     fn_ref: LLVMValueRef, | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> Function<'ctx> { | ||||
|     pub fn block<T: Into<String>>(&'ctx self, name: T) -> BasicBlock<'ctx> { | ||||
|         BasicBlock::in_function(&self, name.into()) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_param<T: BasicValue<'ctx>>( | ||||
|         &'ctx self, | ||||
|         nth: usize, | ||||
|         param_type: T::BaseType, | ||||
|     ) -> Result<T, String> { | ||||
|         if let Some(actual_type) = self.fn_type.param_types.iter().nth(nth) { | ||||
|             if param_type.llvm_type() != *actual_type { | ||||
|                 return Err(String::from("Wrong type")); | ||||
|             } | ||||
|         } else { | ||||
|             return Err(String::from("nth too large")); | ||||
|         } | ||||
|         unsafe { Ok(T::from_llvm(LLVMGetParam(self.fn_ref, nth as u32))) } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct BasicBlock<'ctx> { | ||||
|     function: &'ctx Function<'ctx>, | ||||
|     builder_ref: LLVMBuilderRef, | ||||
|     name: String, | ||||
|     blockref: LLVMBasicBlockRef, | ||||
|     inserted: bool, | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> BasicBlock<'ctx> { | ||||
|     fn in_function(function: &'ctx Function<'ctx>, name: String) -> BasicBlock<'ctx> { | ||||
|         unsafe { | ||||
|             let block_name = into_cstring(name.clone()); | ||||
|             let block_ref = LLVMCreateBasicBlockInContext( | ||||
|                 function.module.context.context_ref, | ||||
|                 block_name.as_ptr(), | ||||
|             ); | ||||
|             LLVMAppendExistingBasicBlock(function.fn_ref, block_ref); | ||||
|             BasicBlock { | ||||
|                 function: function, | ||||
|                 builder_ref: function.module.context.builder_ref, | ||||
|                 name, | ||||
|                 blockref: block_ref, | ||||
|                 inserted: false, | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[must_use] | ||||
|     pub fn integer_compare<T: BasicValue<'ctx>>( | ||||
|         &self, | ||||
|         lhs: &T, | ||||
|         rhs: &T, | ||||
|         comparison: &IntPredicate, | ||||
|         name: &str, | ||||
|     ) -> Result<T, ()> { | ||||
|         unsafe { | ||||
|             LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref); | ||||
|             let value = LLVMBuildICmp( | ||||
|                 self.builder_ref, | ||||
|                 comparison.as_llvm(), | ||||
|                 lhs.llvm_value(), | ||||
|                 rhs.llvm_value(), | ||||
|                 into_cstring(name).as_ptr(), | ||||
|             ); | ||||
| 
 | ||||
|             Ok(T::from_llvm(value)) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[must_use] | ||||
|     pub fn call<T: BasicValue<'ctx>>( | ||||
|         &self, | ||||
|         callee: &Function<'ctx>, | ||||
|         params: Vec<Value<'ctx>>, | ||||
|         name: &str, | ||||
|     ) -> Result<T, ()> { | ||||
|         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(¶ms) { | ||||
|             if t1 != &t2.llvm_type() { | ||||
|                 return Err(()); // TODO wrong types in parameters
 | ||||
|             } | ||||
|         } | ||||
|         if !T::BaseType::is_type(callee.fn_type.return_type) { | ||||
|             return Err(()); // TODO wrong return type
 | ||||
|         } | ||||
|         unsafe { | ||||
|             let mut param_list: Vec<LLVMValueRef> = params.iter().map(|p| p.llvm_value()).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).as_ptr(), | ||||
|             ); | ||||
|             Ok(T::from_llvm(ret_val)) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[must_use] | ||||
|     pub fn add<T: BasicValue<'ctx>>(&self, lhs: &T, rhs: &T, name: &str) -> Result<T, ()> { | ||||
|         if lhs.llvm_type() != rhs.llvm_type() { | ||||
|             return Err(()); // TODO error
 | ||||
|         } | ||||
|         unsafe { | ||||
|             LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref); | ||||
|             let add_value_ref = LLVMBuildAdd( | ||||
|                 self.builder_ref, | ||||
|                 lhs.llvm_value(), | ||||
|                 rhs.llvm_value(), | ||||
|                 into_cstring(name).as_ptr(), | ||||
|             ); | ||||
|             Ok(T::from_llvm(add_value_ref)) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[must_use] | ||||
|     pub fn sub<T: BasicValue<'ctx>>(&self, lhs: &T, rhs: &T, name: &str) -> Result<T, ()> { | ||||
|         dbg!(lhs, rhs); | ||||
|         dbg!(lhs.llvm_type(), rhs.llvm_type()); | ||||
|         if lhs.llvm_type() != rhs.llvm_type() { | ||||
|             return Err(()); // TODO error
 | ||||
|         } | ||||
|         unsafe { | ||||
|             LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref); | ||||
|             let add_value_ref = LLVMBuildSub( | ||||
|                 self.builder_ref, | ||||
|                 lhs.llvm_value(), | ||||
|                 rhs.llvm_value(), | ||||
|                 into_cstring(name).as_ptr(), | ||||
|             ); | ||||
|             Ok(T::from_llvm(add_value_ref)) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[must_use] | ||||
|     pub fn phi<PhiValue: BasicValue<'ctx>>( | ||||
|         &self, | ||||
|         phi_type: &PhiValue::BaseType, | ||||
|         name: &str, | ||||
|     ) -> Result<PhiBuilder<'ctx, PhiValue>, ()> { | ||||
|         unsafe { | ||||
|             LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref); | ||||
|             let phi_node = LLVMBuildPhi( | ||||
|                 self.builder_ref, | ||||
|                 phi_type.llvm_type(), | ||||
|                 into_cstring(name).as_ptr(), | ||||
|             ); | ||||
|             Ok(PhiBuilder::new(phi_node)) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[must_use] | ||||
|     pub fn br(&mut self, into: &BasicBlock<'ctx>) -> Result<(), ()> { | ||||
|         self.try_insert()?; | ||||
|         unsafe { | ||||
|             LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref); | ||||
|             LLVMBuildBr(self.builder_ref, into.blockref); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[must_use] | ||||
|     pub fn conditional_br<T: BasicValue<'ctx>>( | ||||
|         &mut self, | ||||
|         condition: &T, | ||||
|         lhs: &BasicBlock<'ctx>, | ||||
|         rhs: &BasicBlock<'ctx>, | ||||
|     ) -> Result<(), ()> { | ||||
|         self.try_insert()?; | ||||
|         unsafe { | ||||
|             LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref); | ||||
|             LLVMBuildCondBr( | ||||
|                 self.builder_ref, | ||||
|                 condition.llvm_value(), | ||||
|                 lhs.blockref, | ||||
|                 rhs.blockref, | ||||
|             ); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[must_use] | ||||
|     pub fn ret<T: BasicValue<'ctx>>(&mut self, return_value: &T) -> Result<(), ()> { | ||||
|         if self.function.fn_type.return_type != return_value.llvm_type() { | ||||
|             return Err(()); | ||||
|         } | ||||
|         self.try_insert()?; | ||||
| 
 | ||||
|         unsafe { | ||||
|             LLVMPositionBuilderAtEnd(self.builder_ref, self.blockref); | ||||
|             LLVMBuildRet(self.builder_ref, return_value.llvm_value()); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn try_insert(&mut self) -> Result<(), ()> { | ||||
|         if self.inserted { | ||||
|             return Err(()); | ||||
|         } | ||||
|         self.inserted = true; | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> Drop for BasicBlock<'ctx> { | ||||
|     fn drop(&mut self) { | ||||
|         if !self.inserted { | ||||
|             unsafe { | ||||
|                 LLVMDeleteBasicBlock(self.blockref); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct PhiBuilder<'ctx, PhiValue: BasicValue<'ctx>> { | ||||
|     phi_node: LLVMValueRef, | ||||
|     phantom: PhantomData<&'ctx PhiValue>, | ||||
| } | ||||
| 
 | ||||
| impl<'ctx, PhiValue: BasicValue<'ctx>> PhiBuilder<'ctx, PhiValue> { | ||||
|     fn new(phi_node: LLVMValueRef) -> PhiBuilder<'ctx, PhiValue> { | ||||
|         PhiBuilder { | ||||
|             phi_node, | ||||
|             phantom: PhantomData, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn add_incoming(&self, value: &PhiValue, block: &BasicBlock<'ctx>) -> &Self { | ||||
|         let mut values = vec![value.llvm_value()]; | ||||
|         let mut blocks = vec![block.blockref]; | ||||
|         unsafe { | ||||
|             LLVMAddIncoming( | ||||
|                 self.phi_node, | ||||
|                 values.as_mut_ptr(), | ||||
|                 blocks.as_mut_ptr(), | ||||
|                 values.len() as u32, | ||||
|             ); | ||||
|             self | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn build(&self) -> PhiValue { | ||||
|         unsafe { PhiValue::from_llvm(self.phi_node) } | ||||
|     } | ||||
| } | ||||
| @ -1,336 +0,0 @@ | ||||
| use std::{any::Any, marker::PhantomData, ptr::null_mut}; | ||||
| 
 | ||||
| use llvm_sys::{ | ||||
|     LLVMTypeKind, | ||||
|     core::*, | ||||
|     prelude::{LLVMTypeRef, LLVMValueRef}, | ||||
| }; | ||||
| 
 | ||||
| use crate::{BasicBlock, Context, PhiBuilder}; | ||||
| 
 | ||||
| pub trait BasicType<'ctx> { | ||||
|     fn llvm_type(&self) -> LLVMTypeRef; | ||||
| 
 | ||||
|     fn is_type(llvm_type: LLVMTypeRef) -> bool | ||||
|     where | ||||
|         Self: Sized; | ||||
| 
 | ||||
|     unsafe fn from_llvm(context: &'ctx Context, llvm_type: LLVMTypeRef) -> Self | ||||
|     where | ||||
|         Self: Sized; | ||||
| 
 | ||||
|     fn function_type(&self, params: Vec<TypeEnum>) -> FunctionType<'ctx> { | ||||
|         unsafe { | ||||
|             let mut typerefs: Vec<LLVMTypeRef> = params.iter().map(|b| b.llvm_type()).collect(); | ||||
|             let param_ptr = typerefs.as_mut_ptr(); | ||||
|             let param_len = typerefs.len(); | ||||
|             FunctionType { | ||||
|                 phantom: PhantomData, | ||||
|                 return_type: self.llvm_type(), | ||||
|                 param_types: typerefs, | ||||
|                 type_ref: LLVMFunctionType(self.llvm_type(), param_ptr, param_len as u32, 0), | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn array_type(&'ctx self, length: u32) -> ArrayType<'ctx> | ||||
|     where | ||||
|         Self: Sized, | ||||
|     { | ||||
|         ArrayType { | ||||
|             phantom: PhantomData, | ||||
|             element_type: self.llvm_type(), | ||||
|             length, | ||||
|             type_ref: unsafe { LLVMArrayType(self.llvm_type(), length) }, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> PartialEq for &dyn BasicType<'ctx> { | ||||
|     fn eq(&self, other: &Self) -> bool { | ||||
|         self.llvm_type() == other.llvm_type() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> PartialEq<LLVMTypeRef> for &dyn BasicType<'ctx> { | ||||
|     fn eq(&self, other: &LLVMTypeRef) -> bool { | ||||
|         self.llvm_type() == *other | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Copy)] | ||||
| pub struct IntegerType<'ctx> { | ||||
|     context: &'ctx Context, | ||||
|     type_ref: LLVMTypeRef, | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> BasicType<'ctx> for IntegerType<'ctx> { | ||||
|     fn llvm_type(&self) -> LLVMTypeRef { | ||||
|         self.type_ref | ||||
|     } | ||||
| 
 | ||||
|     unsafe fn from_llvm(context: &'ctx Context, llvm_type: LLVMTypeRef) -> Self | ||||
|     where | ||||
|         Self: Sized, | ||||
|     { | ||||
|         IntegerType { | ||||
|             context, | ||||
|             type_ref: llvm_type, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn is_type(llvm_type: LLVMTypeRef) -> bool { | ||||
|         unsafe { LLVMGetTypeKind(llvm_type) == LLVMTypeKind::LLVMIntegerTypeKind } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> IntegerType<'ctx> { | ||||
|     pub(crate) fn in_context(context: &Context, width: u32) -> IntegerType { | ||||
|         let type_ref = unsafe { | ||||
|             match width { | ||||
|                 128 => LLVMInt128TypeInContext(context.context_ref), | ||||
|                 64 => LLVMInt64TypeInContext(context.context_ref), | ||||
|                 32 => LLVMInt32TypeInContext(context.context_ref), | ||||
|                 16 => LLVMInt16TypeInContext(context.context_ref), | ||||
|                 8 => LLVMInt8TypeInContext(context.context_ref), | ||||
|                 1 => LLVMInt1TypeInContext(context.context_ref), | ||||
|                 _ => LLVMIntTypeInContext(context.context_ref, width), | ||||
|             } | ||||
|         }; | ||||
|         IntegerType { context, type_ref } | ||||
|     } | ||||
| 
 | ||||
|     pub fn from_signed(&self, value: i64) -> IntegerValue<'ctx> { | ||||
|         self.from_const(value as u64, true) | ||||
|     } | ||||
| 
 | ||||
|     pub fn from_unsigned(&self, value: i64) -> IntegerValue<'ctx> { | ||||
|         self.from_const(value as u64, false) | ||||
|     } | ||||
| 
 | ||||
|     fn from_const(&self, value: u64, sign: bool) -> IntegerValue<'ctx> { | ||||
|         unsafe { | ||||
|             IntegerValue::from_llvm(LLVMConstInt( | ||||
|                 self.type_ref, | ||||
|                 value, | ||||
|                 match sign { | ||||
|                     true => 1, | ||||
|                     false => 0, | ||||
|                 }, | ||||
|             )) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct FunctionType<'ctx> { | ||||
|     phantom: PhantomData<&'ctx ()>, | ||||
|     pub(crate) return_type: LLVMTypeRef, | ||||
|     pub(crate) param_types: Vec<LLVMTypeRef>, | ||||
|     type_ref: LLVMTypeRef, | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> BasicType<'ctx> for FunctionType<'ctx> { | ||||
|     fn llvm_type(&self) -> LLVMTypeRef { | ||||
|         self.type_ref | ||||
|     } | ||||
| 
 | ||||
|     unsafe fn from_llvm(_context: &'ctx Context, fn_type: LLVMTypeRef) -> Self | ||||
|     where | ||||
|         Self: Sized, | ||||
|     { | ||||
|         unsafe { | ||||
|             let param_count = LLVMCountParamTypes(fn_type); | ||||
|             let param_types_ptr: *mut LLVMTypeRef = null_mut(); | ||||
|             LLVMGetParamTypes(fn_type, param_types_ptr); | ||||
|             let param_types: Vec<LLVMTypeRef> = | ||||
|                 std::slice::from_raw_parts(param_types_ptr, param_count as usize) | ||||
|                     .iter() | ||||
|                     .map(|t| *t) | ||||
|                     .collect(); | ||||
|             FunctionType { | ||||
|                 phantom: PhantomData, | ||||
|                 return_type: LLVMGetReturnType(fn_type), | ||||
|                 param_types, | ||||
|                 type_ref: fn_type, | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn is_type(llvm_type: LLVMTypeRef) -> bool { | ||||
|         unsafe { LLVMGetTypeKind(llvm_type) == LLVMTypeKind::LLVMFunctionTypeKind } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Copy)] | ||||
| pub struct ArrayType<'ctx> { | ||||
|     phantom: PhantomData<&'ctx ()>, | ||||
|     element_type: LLVMTypeRef, | ||||
|     length: u32, | ||||
|     type_ref: LLVMTypeRef, | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> BasicType<'ctx> for ArrayType<'ctx> { | ||||
|     fn llvm_type(&self) -> LLVMTypeRef { | ||||
|         self.type_ref | ||||
|     } | ||||
| 
 | ||||
|     unsafe fn from_llvm(context: &'ctx Context, llvm_type: LLVMTypeRef) -> Self | ||||
|     where | ||||
|         Self: Sized, | ||||
|     { | ||||
|         unsafe { | ||||
|             let length = LLVMGetArrayLength(llvm_type); | ||||
|             todo!() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn is_type(llvm_type: LLVMTypeRef) -> bool { | ||||
|         unsafe { LLVMGetTypeKind(llvm_type) == LLVMTypeKind::LLVMArrayTypeKind } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub enum TypeEnum<'ctx> { | ||||
|     Integer(IntegerType<'ctx>), | ||||
|     Array(ArrayType<'ctx>), | ||||
|     Function(FunctionType<'ctx>), | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> From<IntegerType<'ctx>> for TypeEnum<'ctx> { | ||||
|     fn from(int: IntegerType<'ctx>) -> Self { | ||||
|         TypeEnum::Integer(int) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> From<ArrayType<'ctx>> for TypeEnum<'ctx> { | ||||
|     fn from(arr: ArrayType<'ctx>) -> Self { | ||||
|         TypeEnum::Array(arr) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> From<FunctionType<'ctx>> for TypeEnum<'ctx> { | ||||
|     fn from(func: FunctionType<'ctx>) -> Self { | ||||
|         TypeEnum::Function(func) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> TypeEnum<'ctx> { | ||||
|     fn inner_basic(&'ctx self) -> &'ctx dyn BasicType<'ctx> { | ||||
|         match self { | ||||
|             TypeEnum::Integer(integer_type) => integer_type, | ||||
|             TypeEnum::Array(array_type) => array_type, | ||||
|             TypeEnum::Function(function_type) => function_type, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> BasicType<'ctx> for TypeEnum<'ctx> { | ||||
|     fn llvm_type(&self) -> LLVMTypeRef { | ||||
|         self.inner_basic().llvm_type() | ||||
|     } | ||||
| 
 | ||||
|     fn is_type(llvm_type: LLVMTypeRef) -> bool | ||||
|     where | ||||
|         Self: Sized, | ||||
|     { | ||||
|         true | ||||
|     } | ||||
| 
 | ||||
|     unsafe fn from_llvm(context: &'ctx Context, llvm_type: LLVMTypeRef) -> Self | ||||
|     where | ||||
|         Self: Sized, | ||||
|     { | ||||
|         unsafe { | ||||
|             match LLVMGetTypeKind(llvm_type) { | ||||
|                 LLVMTypeKind::LLVMIntegerTypeKind => { | ||||
|                     TypeEnum::Integer(IntegerType::from_llvm(context, llvm_type)) | ||||
|                 } | ||||
|                 LLVMTypeKind::LLVMArrayTypeKind => { | ||||
|                     TypeEnum::Array(ArrayType::from_llvm(context, llvm_type)) | ||||
|                 } | ||||
|                 LLVMTypeKind::LLVMFunctionTypeKind => { | ||||
|                     TypeEnum::Function(FunctionType::from_llvm(context, llvm_type)) | ||||
|                 } | ||||
|                 _ => todo!(), | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub trait BasicValue<'ctx>: std::fmt::Debug { | ||||
|     type BaseType: BasicType<'ctx>; | ||||
|     unsafe fn from_llvm(value: LLVMValueRef) -> Self | ||||
|     where | ||||
|         Self: Sized; | ||||
|     fn llvm_value(&self) -> LLVMValueRef; | ||||
|     fn llvm_type(&self) -> LLVMTypeRef; | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct IntegerValue<'ctx> { | ||||
|     phantom: PhantomData<&'ctx ()>, | ||||
|     pub(crate) value_ref: LLVMValueRef, | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> BasicValue<'ctx> for IntegerValue<'ctx> { | ||||
|     type BaseType = IntegerType<'ctx>; | ||||
| 
 | ||||
|     unsafe fn from_llvm(value: LLVMValueRef) -> Self { | ||||
|         IntegerValue { | ||||
|             phantom: PhantomData, | ||||
|             value_ref: value, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn llvm_value(&self) -> LLVMValueRef { | ||||
|         self.value_ref | ||||
|     } | ||||
| 
 | ||||
|     fn llvm_type(&self) -> LLVMTypeRef { | ||||
|         unsafe { LLVMTypeOf(self.value_ref) } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub enum Value<'ctx> { | ||||
|     Integer(IntegerValue<'ctx>), | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> BasicValue<'ctx> for Value<'ctx> { | ||||
|     type BaseType = TypeEnum<'ctx>; | ||||
| 
 | ||||
|     unsafe fn from_llvm(value: LLVMValueRef) -> Self | ||||
|     where | ||||
|         Self: Sized, | ||||
|     { | ||||
|         unsafe { | ||||
|             use LLVMTypeKind::*; | ||||
| 
 | ||||
|             let llvm_type = LLVMTypeOf(value); | ||||
|             let type_kind = LLVMGetTypeKind(llvm_type); | ||||
|             match type_kind { | ||||
|                 LLVMIntegerTypeKind => Value::Integer(IntegerValue::from_llvm(value)), | ||||
|                 _ => panic!("asd"), | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn llvm_value(&self) -> LLVMValueRef { | ||||
|         match self { | ||||
|             Self::Integer(i) => i.llvm_value(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn llvm_type(&self) -> LLVMTypeRef { | ||||
|         match self { | ||||
|             Self::Integer(i) => i.llvm_type(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'ctx> From<IntegerValue<'ctx>> for Value<'ctx> { | ||||
|     fn from(value: IntegerValue<'ctx>) -> Self { | ||||
|         Value::Integer(value) | ||||
|     } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user