You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
4.4 KiB

use crate::{
types::ffi::{Bool, Nts, NtsMut},
use std::os::raw;
#[derive(thiserror::Error, Debug)]
#[error("{}", .0)]
pub(super) struct Err(String);
opaque_struct!(pub(super) BasicBlock);
opaque_struct!(pub(super) Builder);
opaque_struct!(pub(super) Context);
opaque_struct!(pub(super) Error);
opaque_struct!(pub(super) Jit);
opaque_struct!(pub(super) Module);
opaque_struct!(pub(super) Type);
opaque_struct!(pub(super) Value);
extern "C" {
// linking
pub(super) fn target_init();
// messages
#[link_name = "LLVMCreateMessage"]
pub(super) fn message_new(msg: Nts) -> NtsMut;
#[link_name = "LLVMDisposeMessage"]
pub(super) fn message_drop(msg: NtsMut);
// errors
#[link_name = "LLVMConsumeError"]
pub(super) fn error_drop(err: *mut Error);
#[link_name = "LLVMGetErrorMessage"]
pub(super) fn error_drop_get_message(err: *mut Error) -> NtsMut;
#[link_name = "LLVMDisposeErrorMessage"]
pub(super) fn error_message_drop(msg: NtsMut);
// contexts
#[link_name = "LLVMContextCreate"]
pub(super) fn context_new() -> *mut Context;
#[link_name = "LLVMContextDispose"]
pub(super) fn context_drop(contx: *mut Context);
#[link_name = "LLVMAppendBasicBlockInContext"]
pub(super) fn context_append_basic_block(
contx: *mut Context, func: *mut Value, name: Nts,
) -> *mut BasicBlock;
// modules
#[link_name = "LLVMModuleCreateWithNameInContext"]
pub(super) fn module_new_with_name_in_context(
module_id: Nts, contx: *mut Context,
) -> *mut Module;
#[link_name = "LLVMDisposeModule"]
pub(super) fn module_drop(modul: *mut Module);
#[link_name = "LLVMAddFunction"]
pub(super) fn module_add_function(
modul: *mut Module, name: Nts, func_ty: *mut Type,
) -> *mut Value;
#[link_name = "LLVMGetNamedFunction"]
pub(super) fn module_get_named_function(
modul: *mut Module, name: Nts,
) -> *mut Value;
// builders
#[link_name = "LLVMCreateBuilderInContext"]
pub(super) fn builder_new_in_context(contx: *mut Context) -> *mut Builder;
#[link_name = "LLVMDisposeBuilder"]
pub(super) fn builder_drop(build: *mut Builder);
#[link_name = "LLVMBuildCall2"]
pub(super) fn builder_call(
build: *mut Builder, ftyp: *mut Type, func: *mut Value,
args: *mut *mut Value, count: raw::c_uint, name: Nts,
) -> *mut Value;
#[link_name = "LLVMBuildRetVoid"]
pub(super) fn builder_ret_void(build: *mut Builder) -> *mut Value;
#[link_name = "LLVMBuildRet"]
pub(super) fn builder_ret(
build: *mut Builder, retn: *mut Value,
) -> *mut Value;
#[link_name = "LLVMPositionBuilderAtEnd"]
pub(super) fn builder_position_at_end(
build: *mut Builder, block: *mut BasicBlock,
// types
#[link_name = "LLVMPrintTypeToString"]
pub(super) fn type_print_to_string(handle: *mut Type) -> NtsMut;
#[link_name = "LLVMArrayType"]
pub(super) fn type_array(
element: *mut Type, count: raw::c_uint,
) -> *mut Type;
#[link_name = "LLVMFunctionType"]
pub(super) fn type_function(
retn: *mut Type, params: *mut *mut Type, count: raw::c_uint,
is_var_arg: Bool,
) -> *mut Type;
#[link_name = "LLVMVoidType"]
pub(super) fn type_void() -> *mut Type;
#[link_name = "LLVMInt1Type"]
pub(super) fn type_int1() -> *mut Type;
#[link_name = "LLVMInt8Type"]
pub(super) fn type_int8() -> *mut Type;
#[link_name = "LLVMInt16Type"]
pub(super) fn type_int16() -> *mut Type;
#[link_name = "LLVMInt32Type"]
pub(super) fn type_int32() -> *mut Type;
#[link_name = "LLVMInt64Type"]
pub(super) fn type_int64() -> *mut Type;
// values
#[link_name = "LLVMGetUndef"]
pub(super) fn value_undef(ty: *mut Type) -> *mut Value;
#[link_name = "LLVMConstInt"]
pub(super) fn value_const_int(
ty: *mut Type, num: raw::c_ulonglong, sign_extend: Bool,
) -> *mut Value;
#[link_name = "LLVMTypeOf"]
pub(super) fn value_type(value: *mut Value) -> *mut Type;
pub(super) fn value_verify_func(func: *mut Value) -> NtsMut;
// jit
pub(super) fn jit_new(jit: *mut *mut Jit) -> *mut Error;
pub(super) fn jit_drop(jit: *mut Jit);
impl Err {
pub(super) fn check(err: *mut Error) -> Result<(), Self> {
if err.is_null() {
} else {
Result::Err(Self(unsafe {
get_msg_and_drop(error_drop_get_message(err), error_message_drop)
pub(super) unsafe fn get_msg_and_drop(
msg: NtsMut, f: unsafe extern "C" fn(msg: NtsMut),
) -> String {
unsafe {
let res = std::ffi::CStr::from_ptr(msg).to_string_lossy().into_owned();
// EOF