use libc::{c_char, c_uint, c_int};
use ffi::prelude::LLVMValueRef;
use ffi::{core, LLVMAttribute};
use std::ffi::CString;
use std::{fmt, mem};
use std::ops::{Deref, Index};
use block::BasicBlock;
use context::{Context, GetContext};
use ty::{FunctionType, Type};
use util::{self, CastFrom};
pub struct Value;
native_ref!(&Value = LLVMValueRef);
impl Value {
pub fn new_struct<'a>(context: &'a Context, vals: &[&'a Value], packed: bool) -> &'a Value {
unsafe { core::LLVMConstStructInContext(context.into(), vals.as_ptr() as *mut LLVMValueRef, vals.len() as c_uint, packed as c_int) }.into()
}
pub fn new_string<'a>(context: &'a Context, text: &str, rust_style: bool) -> &'a Value {
unsafe {
let ptr = text.as_ptr() as *const c_char;
let len = text.len() as c_uint;
core::LLVMConstStringInContext(context.into(), ptr, len, rust_style as c_int).into()
}
}
pub fn get_name(&self) -> Option<&str> {
unsafe {
let c_name = core::LLVMGetValueName(self.into());
util::to_null_str(c_name as *mut i8)
}
}
pub fn set_name(&self, name: &str) {
let c_name = CString::new(name).unwrap();
unsafe {
core::LLVMSetValueName(self.into(), c_name.as_ptr())
}
}
pub fn get_type(&self) -> &Type {
unsafe { core::LLVMTypeOf(self.into()) }.into()
}
}
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Predicate {
Equal,
NotEqual,
GreaterThan,
GreaterThanOrEqual,
LessThan,
LessThanOrEqual
}
pub struct Arg;
native_ref!(&Arg = LLVMValueRef);
impl Deref for Arg {
type Target = Value;
fn deref(&self) -> &Value {
unsafe { mem::transmute(self) }
}
}
impl Arg {
pub fn add_attribute(&self, attr: Attribute) {
unsafe { core::LLVMAddAttribute(self.into(), attr.into()) }
}
pub fn add_attributes(&self, attrs: &[Attribute]) {
let mut sum = LLVMAttribute::empty();
for attr in attrs {
let attr:LLVMAttribute = (*attr).into();
sum = sum | attr;
}
unsafe { core::LLVMAddAttribute(self.into(), sum.into()) }
}
pub fn has_attribute(&self, attr: Attribute) -> bool {
unsafe {
let other = core::LLVMGetAttribute(self.into());
other.contains(attr.into())
}
}
pub fn has_attributes(&self, attrs: &[Attribute]) -> bool {
unsafe {
let other = core::LLVMGetAttribute(self.into());
for &attr in attrs {
if !other.contains(attr.into()) {
return false;
}
}
return true;
}
}
pub fn remove_attribute(&self, attr: Attribute) {
unsafe { core::LLVMRemoveAttribute(self.into(), attr.into()) }
}
}
pub struct Function;
native_ref!(&Function = LLVMValueRef);
impl Deref for Function {
type Target = Value;
fn deref(&self) -> &Value {
unsafe { mem::transmute(self) }
}
}
impl Index<usize> for Function {
type Output = Arg;
fn index(&self, index: usize) -> &Arg {
unsafe {
if index < core::LLVMCountParams(self.into()) as usize {
core::LLVMGetParam(self.into(), index as c_uint).into()
} else {
panic!("no such index {} on {:?}", index, self.get_type())
}
}
}
}
impl CastFrom for Function {
type From = Value;
fn cast<'a>(val: &'a Value) -> Option<&'a Function> {
let ty = val.get_type();
let mut is_func = ty.is_function();
if let Some(elem) = ty.get_element() {
is_func = is_func || elem.is_function()
}
if is_func {
Some(unsafe { mem::transmute(val) })
} else {
None
}
}
}
impl Function {
pub fn append<'a>(&'a self, name: &str) -> &'a BasicBlock {
util::with_cstr(name, |ptr| unsafe {
core::LLVMAppendBasicBlockInContext(self.get_context().into(), self.into(), ptr).into()
})
}
pub fn get_entry(&self) -> Option<&BasicBlock> {
unsafe { mem::transmute(core::LLVMGetEntryBasicBlock(self.into())) }
}
pub fn get_name(&self) -> &str {
unsafe {
let c_name = core::LLVMGetValueName(self.into());
util::to_str(c_name as *mut i8)
}
}
pub fn get_signature(&self) -> &FunctionType {
unsafe {
let ty = core::LLVMTypeOf(self.into());
core::LLVMGetElementType(ty).into()
}
}
pub fn add_attribute(&self, attr: Attribute) {
unsafe { core::LLVMAddFunctionAttr(self.into(), attr.into()) }
}
pub fn add_attributes(&self, attrs: &[Attribute]) {
let mut sum = LLVMAttribute::empty();
for attr in attrs {
let attr:LLVMAttribute = (*attr).into();
sum = sum | attr;
}
unsafe { core::LLVMAddFunctionAttr(self.into(), sum.into()) }
}
pub fn has_attribute(&self, attr: Attribute) -> bool {
unsafe {
let other = core::LLVMGetFunctionAttr(self.into());
other.contains(attr.into())
}
}
pub fn has_attributes(&self, attrs: &[Attribute]) -> bool {
unsafe {
let other = core::LLVMGetFunctionAttr(self.into());
for &attr in attrs {
if !other.contains(attr.into()) {
return false;
}
}
return true;
}
}
pub fn remove_attribute(&self, attr: Attribute) {
unsafe { core::LLVMRemoveFunctionAttr(self.into(), attr.into()) }
}
}
impl GetContext for Function {
fn get_context(&self) -> &Context {
self.get_type().get_context()
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(C)]
pub enum Attribute {
ZExt = 0b1,
SExt = 0b10,
NoReturn = 0b100,
InReg = 0b1000,
StructRet = 0b10000,
NoUnwind = 0b100000,
NoAlias = 0b1000000,
ByVal = 0b10000000,
Nest = 0b100000000,
ReadNone = 0b1000000000,
ReadOnly = 0b10000000000,
NoInline = 0b100000000000,
AlwaysInline = 0b1000000000000,
OptimizeForSize = 0b10000000000000,
StackProtect = 0b100000000000000,
StackProtectReq = 0b1000000000000000,
Alignment = 0b10000000000000000,
NoCapture = 0b100000000000000000,
NoRedZone = 0b1000000000000000000,
NoImplicitFloat = 0b10000000000000000000,
Naked = 0b100000000000000000000,
InlineHint = 0b1000000000000000000000,
StackAlignment = 0b11100000000000000000000000000,
ReturnsTwice = 0b100000000000000000000000000000,
UWTable = 0b1000000000000000000000000000000,
NonLazyBind = 0b10000000000000000000000000000000
}
impl From<LLVMAttribute> for Attribute {
fn from(attr: LLVMAttribute) -> Attribute {
unsafe { mem::transmute(attr) }
}
}
impl From<Attribute> for LLVMAttribute {
fn from(attr: Attribute) -> LLVMAttribute {
unsafe { mem::transmute(attr) }
}
}
impl GetContext for Value {
fn get_context(&self) -> &Context {
self.get_type().get_context()
}
}
to_str!(Value, LLVMPrintValueToString);