use llvm_sys::core::*;
use llvm_sys::prelude::LLVMValueRef;
use llvm_sys::LLVMValueKind;
use std::marker::PhantomData;
use crate::utils::string_of_value;
use crate::values::*;
use crate::*;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Global<'ctx> {
Variable(GlobalVariable<'ctx>),
Alias(GlobalAlias<'ctx>),
}
pub trait GlobalValueTrait<'ctx>: ValueRef {
fn name(&self) -> String {
string_of_value(self.value_ref())
}
fn as_global(&self) -> Global<'ctx>;
}
impl<'ctx> GetType<'ctx> for Global<'ctx> {}
impl<'ctx> GlobalValueTrait<'ctx> for Global<'ctx> {
fn as_global(&self) -> Self { self.clone() }
}
impl<'ctx> Global<'ctx> {
pub fn is_alias(&self) -> bool {
match self {
Self::Variable(_) => false,
_ => true,
}
}
pub fn aliasee(&self) -> Option<Constant<'ctx>> {
match self {
Self::Alias(a) => Some(a.aliasee()),
_ => None,
}
}
}
impl<'ctx> FromLLVMValue for Global<'ctx> {
fn from_llvm(ptr: LLVMValueRef) -> Self {
use LLVMValueKind::*;
match unsafe { LLVMGetValueKind(ptr) } {
LLVMGlobalVariableValueKind => Self::Variable(GlobalVariable::from_llvm(ptr)),
LLVMGlobalAliasValueKind => Self::Alias(GlobalAlias::from_llvm(ptr)),
x => panic!("Not global variable kind {:?}", x),
}
}
}
impl<'ctx> ValueRef for Global<'ctx> {
fn value_ref(&self) -> LLVMValueRef {
match self {
Self::Variable(v) => v.value_ref(),
Self::Alias(a) => a.value_ref(),
}
}
}
impl<'ctx> AsConstant<'ctx> for Global<'ctx> {
fn as_constant(&self) -> Constant<'ctx> {
Constant::Global(self.clone())
}
}
impl_as_operand_for_constant!(Global);
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct GlobalVariable<'ctx>(LLVMValueRef, PhantomData<&'ctx ()>);
impl<'ctx> std::fmt::Debug for GlobalVariable<'ctx> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_tuple("GlobalVariable").field(&self.name()).finish()
}
}
impl_send_sync!(GlobalVariable);
impl<'ctx> GetType<'ctx> for GlobalVariable<'ctx> {}
impl<'ctx> GlobalValueTrait<'ctx> for GlobalVariable<'ctx> {
fn as_global(&self) -> Global<'ctx> {
Global::Variable(self.clone())
}
}
impl_positional_value_ref!(GlobalVariable, 0);
impl_positional_from_llvm_value!(GlobalVariable);
impl<'ctx> AsConstant<'ctx> for GlobalVariable<'ctx> {
fn as_constant(&self) -> Constant<'ctx> {
Constant::Global(Global::Variable(self.clone()))
}
}
impl_as_operand_for_constant!(GlobalVariable);
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct GlobalAlias<'ctx>(LLVMValueRef, PhantomData<&'ctx ()>);
impl<'ctx> std::fmt::Debug for GlobalAlias<'ctx> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_tuple("GlobalAlias").field(&self.name()).finish()
}
}
impl_send_sync!(GlobalAlias);
impl<'ctx> GetType<'ctx> for GlobalAlias<'ctx> {}
impl<'ctx> GlobalValueTrait<'ctx> for GlobalAlias<'ctx> {
fn as_global(&self) -> Global<'ctx> {
Global::Alias(self.clone())
}
}
impl<'ctx> GlobalAlias<'ctx> {
pub fn aliasee(&self) -> Constant<'ctx> {
Constant::from_llvm(unsafe { LLVMAliasGetAliasee(self.0) })
}
}
impl_positional_value_ref!(GlobalAlias, 0);
impl_positional_from_llvm_value!(GlobalAlias);
impl<'ctx> AsConstant<'ctx> for GlobalAlias<'ctx> {
fn as_constant(&self) -> Constant<'ctx> {
Constant::Global(Global::Alias(self.clone()))
}
}
impl_as_operand_for_constant!(GlobalAlias);