// Copyright 2022 the Gigamono authors. All rights reserved. GPL-3.0 License. use llvm_sys::{ core::{ LLVMDoubleTypeInContext, LLVMFloatTypeInContext, LLVMFunctionType, LLVMInt32TypeInContext, LLVMInt64TypeInContext, }, prelude::LLVMTypeRef, }; use std::pin::Pin; use super::context::LLContext; pub(crate) enum LLTypeKind { I64, I32, F64, F32, } /// This is a wrapper for LLVM Type. /// /// # Safety /// Only a kind of each `LLVMTypeRef` is ever created. They are singletons and are never freed. /// /// - https://llvm.org/doxygen/classllvm_1_1Type.html#details pub(crate) struct LLType { type_ref: LLVMTypeRef, kind: LLTypeKind, } impl LLType { /// Creates a new LLVM type. /// /// # Safety /// LLContext does not own type here. pub(crate) fn new(context: &LLContext, kind: LLTypeKind) -> Self { use LLTypeKind::*; let context_ref = context.as_ptr(); let type_ref = unsafe { match kind { I64 => LLVMInt64TypeInContext(context_ref), I32 => LLVMInt32TypeInContext(context_ref), F64 => LLVMDoubleTypeInContext(context_ref), F32 => LLVMFloatTypeInContext(context_ref), } }; Self { type_ref, kind } } pub(crate) fn as_ptr(&self) -> LLVMTypeRef { self.type_ref } } /// This is a wrapper for LLVM Function Type. /// /// # Safety /// See [LLType](struct.LLType.html) for safety. pub(crate) struct LLFunctionType { pub(crate) params: Vec, pub(crate) result: LLVMTypeRef, pub(crate) type_ref: LLVMTypeRef, } impl LLFunctionType { /// # Safety /// TODO(appcypher): Investigate safety properly. /// Making sure that function copies param and result types. /// Also how dispose types. pub(crate) fn new(params: &[LLType], result: &LLType, is_varargs: bool) -> Pin> { let mut this = Self { params: params.iter().map(|p| p.as_ptr()).collect::>(), result: result.as_ptr(), type_ref: std::ptr::null_mut(), }; this.type_ref = unsafe { LLVMFunctionType( this.result, this.params.as_mut_ptr(), this.params.len() as u32, is_varargs as i32, ) }; Box::pin(this) } pub(crate) fn as_ptr(&self) -> LLVMTypeRef { self.type_ref } }