#![allow(dead_code)]
extern crate llvm_sys;
use self::llvm_sys::core::*;
use self::llvm_sys::prelude::*;
use self::llvm_sys::analysis::{LLVMVerifyModule, LLVMVerifierFailureAction};
use cstring_manager::CStringManager;
use std::ffi::CString;
use std::os::raw::c_char;
use function;
use engine::Engine;
#[derive(Debug)]
pub struct Module {
llvm_module: LLVMModuleRef
}
impl Module {
pub fn new(name: &str) -> Module {
let mod_name_ptr = CStringManager::new_cstring_as_ptr(name);
let module = unsafe { LLVMModuleCreateWithName(mod_name_ptr) };
Module {
llvm_module: module
}
}
pub fn new_in_context(name: &str, context: LLVMContextRef) -> Module {
let mod_name_ptr = CStringManager::new_cstring_as_ptr(name);
let module = unsafe { LLVMModuleCreateWithNameInContext(mod_name_ptr, context) };
Module {
llvm_module: module
}
}
pub fn as_ref(&self) -> LLVMModuleRef {
self.llvm_module
}
pub fn add_function(&self, name: &str, function_type: LLVMTypeRef) -> function::Function {
function::Function::new(self.llvm_module, name, function_type)
}
#[inline]
pub fn named_function(&self, name: &str) -> function::Function {
let func_name_ptr = CStringManager::new_cstring_as_ptr(name);
let named_function = unsafe { LLVMGetNamedFunction(self.llvm_module, func_name_ptr) };
function::Function::from_ptr(named_function)
}
pub fn get_or_add_function(&self, name: &str, function_type: LLVMTypeRef) -> function::Function {
let func_name_ptr = CStringManager::new_cstring_as_ptr(name);
let named_function = unsafe { LLVMGetNamedFunction(self.llvm_module, func_name_ptr) };
if named_function.is_null() {
function::Function::new(self.llvm_module, name, function_type)
}else{
function::Function::from_ptr(named_function)
}
}
pub fn verify(&self) -> Result<(), String> {
let mut error: *mut c_char = 0 as *mut c_char;
let ok = unsafe {
let buf: *mut *mut c_char = &mut error;
LLVMVerifyModule(self.llvm_module, LLVMVerifierFailureAction::LLVMReturnStatusAction, buf)
};
if ok == 1 { let err_msg = unsafe { CString::from_raw(error).into_string().unwrap() };
Err(err_msg)
}else{ Ok(())
}
}
#[inline]
pub fn dump(&self){
unsafe { LLVMDumpModule(self.llvm_module) }
}
pub fn print_module_to_string(&self) -> String {
let ptr = unsafe { LLVMPrintModuleToString(self.llvm_module) };
let string = unsafe { CString::from_raw(ptr).into_string().unwrap() };
unsafe { LLVMDisposeMessage(ptr); }
string
}
pub fn print_module_to_file(&self, filename: &str) -> Result<(), String> {
let fname_ptr = CStringManager::new_cstring_as_ptr(filename);
let mut error: *mut c_char = 0 as *mut c_char;
let ok = unsafe {
let buf: *mut *mut c_char = &mut error;
LLVMPrintModuleToFile(self.llvm_module, fname_ptr, buf)
};
if ok == 1 { let err_msg = unsafe { CString::from_raw(error).into_string().unwrap() };
unsafe { LLVMDisposeMessage(error) }
Err(err_msg)
}else{ Ok(())
}
}
#[inline]
pub fn create_interpreter(&self) -> Result<Engine, String> {
Engine::create_interpreter(self.as_ref())
}
#[inline]
pub fn create_jit_engine(&self) -> Result<Engine, String> {
Engine::create_jit_engine(self.as_ref())
}
}
impl Drop for Module {
#[inline]
fn drop(&mut self) {
unsafe { LLVMDisposeModule(self.llvm_module) }
}
}