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