#![allow(non_snake_case)]
use llvm_sys;
use libc;
use libc::{c_char, c_uint};
use std::ffi::{CStr, CString};
use std::fmt;
use self::llvm_sys::core::*;
use self::llvm_sys::prelude::*;
use self::llvm_sys::transforms::pass_manager_builder::LLVMPassManagerBuilderRef;
use self::llvm_sys::{LLVMAttributeFunctionIndex, LLVMAttributeReturnIndex};
use self::llvm_sys::target_machine::LLVMTargetMachineRef;
lazy_static! {
pub static ref PROCESS_TRIPLE: CString = unsafe {
let c_str = LLVMExtGetProcessTriple();
CStr::from_ptr(c_str).to_owned()
};
pub static ref HOST_CPU_NAME: CString = unsafe {
let c_str = LLVMExtGetHostCPUName();
CStr::from_ptr(c_str).to_owned()
};
pub static ref HOST_CPU_FEATURES: CString = unsafe {
let c_str = LLVMExtGetHostCPUFeatures();
CStr::from_ptr(c_str).to_owned()
};
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum LLVMExtAttribute {
AlwaysInline,
InlineHint,
NoAlias,
NoCapture,
NonNull,
NoReturn,
NoUnwind,
ReadOnly,
}
impl fmt::Display for LLVMExtAttribute {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use self::LLVMExtAttribute::*;
let string = match *self {
AlwaysInline => "alwaysinline",
InlineHint => "inlinehint",
NoAlias => "noalias",
NoCapture => "nocapture",
NonNull => "nonnull",
NoReturn => "noreturn",
NoUnwind => "nounwind",
ReadOnly => "readonly",
};
f.write_str(string)
}
}
unsafe fn add_attrs(
context: LLVMContextRef,
function: LLVMValueRef,
attrs: &[LLVMExtAttribute],
index: u32,
) {
for attr in attrs {
let name = CString::new(attr.to_string()).unwrap();
let kind = LLVMGetEnumAttributeKindForName(name.as_ptr(), name.as_bytes().len());
assert_ne!(kind, 0);
let attr = LLVMCreateEnumAttribute(context, kind, 0);
LLVMAddAttributeAtIndex(function, index, attr);
}
}
pub fn LLVMExtAddAttrsOnParameter(
context: LLVMContextRef,
function: LLVMValueRef,
attrs: &[LLVMExtAttribute],
index: u32,
) {
unsafe {
add_attrs(context, function, attrs, index + 1);
}
}
pub fn LLVMExtAddAttrsOnFunction(
context: LLVMContextRef,
function: LLVMValueRef,
attrs: &[LLVMExtAttribute],
) {
unsafe {
add_attrs(context, function, attrs, LLVMAttributeFunctionIndex);
}
}
pub fn LLVMExtAddAttrsOnReturn(
context: LLVMContextRef,
function: LLVMValueRef,
attrs: &[LLVMExtAttribute],
) {
unsafe {
add_attrs(context, function, attrs, LLVMAttributeReturnIndex);
}
}
pub fn LLVMExtAddDefaultAttrs(context: LLVMContextRef, function: LLVMValueRef) {
unsafe {
let cpu_name_attr = LLVMCreateStringAttribute(
context,
c_str!("target-cpu"),
10,
HOST_CPU_NAME.as_ptr(),
HOST_CPU_NAME.as_bytes().len() as u32,
);
let cpu_features_attr = LLVMCreateStringAttribute(
context,
c_str!("target-features"),
15,
HOST_CPU_FEATURES.as_ptr(),
HOST_CPU_FEATURES.as_bytes().len() as u32,
);
LLVMAddAttributeAtIndex(function, LLVMAttributeFunctionIndex, cpu_name_attr);
LLVMAddAttributeAtIndex(function, LLVMAttributeFunctionIndex, cpu_features_attr);
}
}
#[link(name = "llvmext", kind = "static")]
extern "C" {
#[no_mangle]
pub fn LLVMExtGetProcessTriple() -> *const c_char;
#[no_mangle]
pub fn LLVMExtGetHostCPUName() -> *const c_char;
#[no_mangle]
pub fn LLVMExtGetHostCPUFeatures() -> *const c_char;
#[no_mangle]
pub fn LLVMExtAddTargetLibraryInfo(manager: LLVMPassManagerRef);
#[no_mangle]
pub fn LLVMExtAddTargetPassConfig(target: LLVMTargetMachineRef, manager: LLVMPassManagerRef);
#[no_mangle]
pub fn LLVMExtPassManagerBuilderSetDisableVectorize(
builder: LLVMPassManagerBuilderRef,
disabled: c_uint,
);
}