Skip to content

Commit

Permalink
Merge pull request rust-lang#22 from 6A/master
Browse files Browse the repository at this point in the history
Made type and value enums clone- and copy-able.
  • Loading branch information
TheDan64 authored Oct 26, 2017
2 parents 322cf13 + db6f82c commit b75c231
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/types/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use types::traits::AsTypeRef;

macro_rules! enum_type_set {
($enum_name:ident: $($args:ident),*) => (
#[derive(Debug, EnumAsGetters, EnumIntoGetters, EnumIsA, PartialEq, Eq)]
#[derive(Debug, EnumAsGetters, EnumIntoGetters, EnumIsA, PartialEq, Eq, Clone, Copy)]
pub enum $enum_name {
$(
$args($args),
Expand Down
18 changes: 16 additions & 2 deletions src/types/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,27 @@ pub trait AsTypeRef {

macro_rules! trait_type_set {
($trait_name:ident: $($args:ident),*) => (
pub trait $trait_name: AsTypeRef + Debug {}

$(
impl $trait_name for $args {}
)*
);
}

/// Represents any LLVM type.
pub trait AnyType: AsTypeRef + Debug {
/// Returns an `AnyTypeEnum` that represents the current type.
fn as_any_type_enum(&self) -> AnyTypeEnum {
AnyTypeEnum::new(self.as_type_ref())
}
}

/// Represents a basic LLVM type, that may be used in functions and struct declarations.
pub trait BasicType: AnyType {
/// Returns a `BasicTypeEnum` that represents the current type.
fn as_basic_type_enum(&self) -> BasicTypeEnum {
BasicTypeEnum::new(self.as_type_ref())
}
}

trait_type_set! {AnyType: AnyTypeEnum, BasicTypeEnum, IntType, FunctionType, FloatType, PointerType, StructType, ArrayType, VoidType, VectorType}
trait_type_set! {BasicType: BasicTypeEnum, IntType, FloatType, PointerType, StructType, ArrayType, VectorType}
54 changes: 51 additions & 3 deletions src/values/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ use llvm_sys::core::{LLVMTypeOf, LLVMGetTypeKind};
use llvm_sys::LLVMTypeKind;
use llvm_sys::prelude::LLVMValueRef;

use types::BasicTypeEnum;
use types::{AnyTypeEnum, BasicTypeEnum};
use values::traits::AsValueRef;
use values::{IntValue, FunctionValue, PointerValue, VectorValue, ArrayValue, StructValue, FloatValue, PhiValue, InstructionValue, MetadataValue};

macro_rules! enum_value_set {
($enum_name:ident: $($args:ident),*) => (
#[derive(Debug, EnumAsGetters, EnumIntoGetters, EnumIsA)]
#[derive(Debug, EnumAsGetters, EnumIntoGetters, EnumIsA, Clone, Copy)]
pub enum $enum_name {
$(
$args($args),
Expand Down Expand Up @@ -43,6 +43,40 @@ enum_value_set! {AnyValueEnum: ArrayValue, IntValue, FloatValue, PhiValue, Funct
enum_value_set! {BasicValueEnum: ArrayValue, IntValue, FloatValue, PointerValue, StructValue, VectorValue}
enum_value_set! {BasicMetadataValueEnum: ArrayValue, IntValue, FloatValue, PointerValue, StructValue, VectorValue, MetadataValue}

impl AnyValueEnum {
pub(crate) fn new(value: LLVMValueRef) -> AnyValueEnum {
let type_kind = unsafe {
LLVMGetTypeKind(LLVMTypeOf(value))
};

match type_kind {
LLVMTypeKind::LLVMFloatTypeKind |
LLVMTypeKind::LLVMFP128TypeKind |
LLVMTypeKind::LLVMDoubleTypeKind |
LLVMTypeKind::LLVMHalfTypeKind |
LLVMTypeKind::LLVMX86_FP80TypeKind |
LLVMTypeKind::LLVMPPC_FP128TypeKind => AnyValueEnum::FloatValue(FloatValue::new(value)),
LLVMTypeKind::LLVMIntegerTypeKind => AnyValueEnum::IntValue(IntValue::new(value)),
LLVMTypeKind::LLVMStructTypeKind => AnyValueEnum::StructValue(StructValue::new(value)),
LLVMTypeKind::LLVMPointerTypeKind => AnyValueEnum::PointerValue(PointerValue::new(value)),
LLVMTypeKind::LLVMArrayTypeKind => AnyValueEnum::ArrayValue(ArrayValue::new(value)),
LLVMTypeKind::LLVMVectorTypeKind => AnyValueEnum::VectorValue(VectorValue::new(value)),
LLVMTypeKind::LLVMFunctionTypeKind => AnyValueEnum::FunctionValue(FunctionValue::new(value).unwrap()),
LLVMTypeKind::LLVMVoidTypeKind => panic!("Void values shouldn't exist."),
LLVMTypeKind::LLVMMetadataTypeKind => panic!("Metadata values are not supported as AnyValue's."),
_ => panic!("The given type is not supported.")
}
}

pub fn get_type(&self) -> AnyTypeEnum {
let type_ = unsafe {
LLVMTypeOf(self.as_value_ref())
};

AnyTypeEnum::new(type_)
}
}

impl BasicValueEnum {
pub(crate) fn new(value: LLVMValueRef) -> BasicValueEnum {
let type_kind = unsafe {
Expand All @@ -61,7 +95,7 @@ impl BasicValueEnum {
LLVMTypeKind::LLVMPointerTypeKind => BasicValueEnum::PointerValue(PointerValue::new(value)),
LLVMTypeKind::LLVMArrayTypeKind => BasicValueEnum::ArrayValue(ArrayValue::new(value)),
LLVMTypeKind::LLVMVectorTypeKind => BasicValueEnum::VectorValue(VectorValue::new(value)),
_ => unreachable!("Unsupported type"),
_ => unreachable!("The given type is not a basic type."),
}
}

Expand All @@ -85,6 +119,20 @@ impl BasicValueEnum {
}
}

impl AggregateValueEnum {
pub(crate) fn new(value: LLVMValueRef) -> AggregateValueEnum {
let type_kind = unsafe {
LLVMGetTypeKind(LLVMTypeOf(value))
};

match type_kind {
LLVMTypeKind::LLVMArrayTypeKind => AggregateValueEnum::ArrayValue(ArrayValue::new(value)),
LLVMTypeKind::LLVMStructTypeKind => AggregateValueEnum::StructValue(StructValue::new(value)),
_ => unreachable!("The given type is not an aggregate type."),
}
}
}

impl BasicMetadataValueEnum {
pub(crate) fn new(value: LLVMValueRef) -> BasicMetadataValueEnum {
let type_kind = unsafe {
Expand Down
28 changes: 26 additions & 2 deletions src/values/traits.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use llvm_sys::prelude::LLVMValueRef;

use std::fmt::Debug;

use values::{ArrayValue, AggregateValueEnum, StructValue, BasicValueEnum, AnyValueEnum, IntValue, FloatValue, PointerValue, PhiValue, VectorValue, FunctionValue, InstructionValue};

// This is an ugly privacy hack so that Type can stay private to this module
Expand All @@ -11,8 +13,6 @@ pub trait AsValueRef {

macro_rules! trait_value_set {
($trait_name:ident: $($args:ident),*) => (
pub trait $trait_name: AsValueRef {}

$(
impl $trait_name for $args {}
)*
Expand All @@ -22,6 +22,30 @@ macro_rules! trait_value_set {
);
}

/// Represents an aggregate value, built on top of other values.
pub trait AggregateValue: BasicValue {
/// Returns an enum containing a typed version of the `AggregateValue`.
fn as_aggregate_value_enum(&self) -> AggregateValueEnum {
AggregateValueEnum::new(self.as_value_ref())
}
}

/// Represents a basic value, which can be used both by itself, or in an `AggregateValue`.
pub trait BasicValue: AnyValue {
/// Returns an enum containing a typed version of the `BasicValue`.
fn as_basic_value_enum(&self) -> BasicValueEnum {
BasicValueEnum::new(self.as_value_ref())
}
}

/// Defines any struct wrapping an LLVM value.
pub trait AnyValue: AsValueRef + Debug {
/// Returns an enum containing a typed version of `AnyValue`.
fn as_any_value_enum(&self) -> AnyValueEnum {
AnyValueEnum::new(self.as_value_ref())
}
}

trait_value_set! {AggregateValue: ArrayValue, AggregateValueEnum, StructValue}
trait_value_set! {AnyValue: AnyValueEnum, BasicValueEnum, AggregateValueEnum, ArrayValue, IntValue, FloatValue, PhiValue, PointerValue, FunctionValue, StructValue, VectorValue, InstructionValue}
trait_value_set! {BasicValue: ArrayValue, BasicValueEnum, AggregateValueEnum, IntValue, FloatValue, StructValue, PointerValue, VectorValue}

0 comments on commit b75c231

Please sign in to comment.