Skip to content

Commit 2669dc6

Browse files
committed
Use new Sub instead of CastFrom, and use this to simplify casting code.
1 parent 3a7017c commit 2669dc6

File tree

5 files changed

+63
-101
lines changed

5 files changed

+63
-101
lines changed

src/engine.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ use ffi::target_machine::LLVMCodeModel;
66
use cbox::{CBox, CSemiBox, DisposeRef};
77
use std::marker::PhantomData;
88
use std::{mem, ptr};
9-
use std::ops::*;
109
use compile::Compile;
1110
use context::{Context, GetContext};
1211
use module::Module;
1312
use ty::{StructType, Type};
14-
use util::{self, CastFrom};
13+
use util::{self, Sub};
1514
use value::{Function, Value};
1615

1716
/// An abstract interface for implementation execution of LLVM modules.
@@ -108,7 +107,7 @@ impl<'a> JitEngine {
108107
let sig = function.get_signature();
109108
assert_eq!(Type::get::<R>(ctx), sig.get_return());
110109
let arg = Type::get::<A>(ctx);
111-
assert_eq!(sig.get_params(), if let Some(args) = StructType::cast(arg) {
110+
assert_eq!(sig.get_params(), if let Some(args) = StructType::from_super(arg) {
112111
args.get_elements()
113112
} else {
114113
vec![arg]

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@ pub use object::{ObjectFile, Symbol, Symbols};
3434
pub use target::{TargetData, Target};
3535
pub use ty::{FunctionType, StructType, Type};
3636
pub use value::{Alias, Arg, Attribute, Value, Function, GlobalValue, GlobalVariable, Linkage, Predicate};
37-
pub use util::CastFrom;
37+
pub use util::Sub;

src/ty.rs

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use libc::{c_int, c_uint};
44
use compile::Compile;
55
use context::{Context, GetContext};
66
use target::TargetData;
7-
use util::{self, CastFrom};
7+
use util::{self, Sub};
88
use std::{fmt, mem};
99
use std::marker::PhantomData;
1010
use std::iter::Iterator;
@@ -115,16 +115,11 @@ impl StructType {
115115
}
116116
}
117117
}
118-
impl CastFrom for StructType {
119-
type From = Type;
120-
fn cast(ty: &Type) -> Option<&StructType> {
118+
unsafe impl Sub<Type> for StructType {
119+
fn is(ty: &Type) -> bool {
121120
unsafe {
122121
let kind = core::LLVMGetTypeKind(ty.into());
123-
if kind as c_uint == LLVMTypeKind::LLVMStructTypeKind as c_uint {
124-
mem::transmute(ty)
125-
} else {
126-
None
127-
}
122+
kind as c_uint == LLVMTypeKind::LLVMStructTypeKind as c_uint
128123
}
129124
}
130125
}
@@ -136,20 +131,14 @@ to_str!(StructType, LLVMPrintTypeToString);
136131
pub struct FunctionType;
137132
native_ref!(&FunctionType = LLVMTypeRef);
138133
deref!(FunctionType, Type);
139-
impl CastFrom for FunctionType {
140-
type From = Type;
141-
fn cast(mut ty: &Type) -> Option<&FunctionType> {
134+
unsafe impl Sub<Type> for FunctionType {
135+
fn is(mut ty: &Type) -> bool {
142136
unsafe {
143-
use libc::c_uint;
144137
while let Some(elem) = ty.get_element() {
145138
ty = elem;
146139
}
147140
let kind = core::LLVMGetTypeKind(ty.into());
148-
if kind as c_uint == LLVMTypeKind::LLVMFunctionTypeKind as c_uint {
149-
mem::transmute(ty)
150-
} else {
151-
None
152-
}
141+
kind as c_uint == LLVMTypeKind::LLVMFunctionTypeKind as c_uint
153142
}
154143
}
155144
}

src/util.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
use libc::c_char;
22
use std::ffi::{CStr, CString};
3+
use std::mem;
34
use std::str;
4-
5-
/// Cast from one type into another
6-
pub trait CastFrom {
7-
/// The type that can be casted from.
8-
type From;
9-
/// Cast it
10-
fn cast<'a>(ty: &'a Self::From) -> Option<&'a Self>;
5+
/// Indicates that this structure is a substructure of another.
6+
pub unsafe trait Sub<T>: Sized {
7+
/// Check if the given super value is an instance of this type.
8+
fn is(c: &T) -> bool;
9+
/// Attempt to cast the given super value into an instance of this type.
10+
fn from_super(c: &T) -> Option<&Self> {
11+
if Self::is(c) {
12+
Some(unsafe { mem::transmute(c) })
13+
} else {
14+
None
15+
}
16+
}
17+
/// Cast this value to a super value.
18+
fn to_super(&self) -> &T {
19+
unsafe { mem::transmute(self) }
20+
}
1121
}
12-
1322
#[inline(always)]
1423
pub fn with_cstr<C, R>(text: &str, cb: C) -> R where C:FnOnce(*const c_char) -> R {
1524
let c_text = CString::new(text).unwrap();

src/value.rs

Lines changed: 36 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,31 @@ use std::ops::{Deref, Index};
88
use block::BasicBlock;
99
use context::{Context, GetContext};
1010
use ty::{FunctionType, Type};
11-
use util::{self, CastFrom};
11+
use util::{self, Sub};
12+
13+
macro_rules! sub {
14+
($this:ty, $name:ident) => (
15+
sub!{$this, $name, ::Value}
16+
);
17+
($this:ty, $name:ident, $sup:ty) => (
18+
unsafe impl Sub<$sup> for $this {
19+
fn is(value: &$sup) -> bool {
20+
unsafe {
21+
!core::$name(value.into()).is_null()
22+
}
23+
}
24+
fn from_super(value: &$sup) -> Option<&$this> {
25+
unsafe { mem::transmute(core::$name(value.into())) }
26+
}
27+
}
28+
impl Deref for $this {
29+
type Target = $sup;
30+
fn deref(&self) -> &$sup {
31+
self.to_super()
32+
}
33+
}
34+
)
35+
}
1236

1337
/// A typed value that can be used as an operand in instructions.
1438
pub struct Value;
@@ -66,12 +90,7 @@ pub enum Predicate {
6690
/// An argument that is passed to a function.
6791
pub struct Arg;
6892
native_ref!(&Arg = LLVMValueRef);
69-
impl Deref for Arg {
70-
type Target = Value;
71-
fn deref(&self) -> &Value {
72-
unsafe { mem::transmute(self) }
73-
}
74-
}
93+
sub!{Arg, LLVMIsAArgument}
7594
impl Arg {
7695
/// Add the attribute given to this argument.
7796
pub fn add_attribute(&self, attr: Attribute) {
@@ -114,21 +133,7 @@ impl Arg {
114133
/// A value with global scope (eg: Function, Alias, Global variable)
115134
pub struct GlobalValue;
116135
native_ref!(&GlobalValue = LLVMValueRef);
117-
impl Deref for GlobalValue {
118-
type Target = Value;
119-
fn deref(&self) -> &Value {
120-
unsafe { mem::transmute(self) }
121-
}
122-
}
123-
impl CastFrom for GlobalValue {
124-
type From = Value;
125-
fn cast<'a>(val: &'a Value) -> Option<&'a GlobalValue> {
126-
unsafe {
127-
let global = mem::transmute(core::LLVMIsAGlobalValue(val.into()));
128-
util::ptr_to_null(global)
129-
}
130-
}
131-
}
136+
sub!{GlobalValue, LLVMIsAGlobalValue}
132137
impl GlobalValue {
133138
/// Set the linkage type for this global
134139
pub fn set_linkage(&self, linkage: Linkage) {
@@ -154,21 +159,7 @@ impl GlobalValue {
154159
/// A global variable
155160
pub struct GlobalVariable;
156161
native_ref!(&GlobalVariable = LLVMValueRef);
157-
impl Deref for GlobalVariable {
158-
type Target = GlobalValue;
159-
fn deref(&self) -> &GlobalValue {
160-
unsafe { mem::transmute(self) }
161-
}
162-
}
163-
impl CastFrom for GlobalVariable {
164-
type From = Value;
165-
fn cast<'a>(val: &'a Value) -> Option<&'a GlobalVariable> {
166-
unsafe {
167-
let global = mem::transmute(core::LLVMIsAGlobalVariable(val.into()));
168-
util::ptr_to_null(global)
169-
}
170-
}
171-
}
162+
sub!{GlobalVariable, LLVMIsAGlobalVariable, GlobalValue}
172163
impl GlobalVariable {
173164
/// Set the initial value of the global
174165
pub fn set_initializer(&self, val: &Value) {
@@ -200,34 +191,14 @@ impl GlobalVariable {
200191
/// An alias to another global value.
201192
pub struct Alias;
202193
native_ref!(&Alias = LLVMValueRef);
203-
impl Deref for Alias {
204-
type Target = GlobalValue;
205-
fn deref(&self) -> &GlobalValue {
206-
unsafe { mem::transmute(self) }
207-
}
208-
}
209-
impl CastFrom for Alias {
210-
type From = Value;
211-
fn cast<'a>(val: &'a Value) -> Option<&'a Alias> {
212-
unsafe {
213-
let alias = mem::transmute(core::LLVMIsAGlobalAlias(val.into()));
214-
util::ptr_to_null(alias)
215-
}
216-
}
217-
}
218-
194+
sub!{Alias, LLVMIsAGlobalAlias, GlobalValue}
219195
/// A function is a kind of value that can be called and contains blocks of code.
220196
///
221197
/// To get the value of each argument to a function, you can use the index operator.
222198
/// For example, `&func[0]` is the value that represents the first argument to the function.
223199
pub struct Function;
224200
native_ref!(&Function = LLVMValueRef);
225-
impl Deref for Function {
226-
type Target = GlobalValue;
227-
fn deref(&self) -> &GlobalValue {
228-
unsafe { mem::transmute(self) }
229-
}
230-
}
201+
sub!{Function, LLVMIsAFunction, GlobalValue}
231202
impl Index<usize> for Function {
232203
type Output = Arg;
233204
fn index(&self, index: usize) -> &Arg {
@@ -240,19 +211,13 @@ impl Index<usize> for Function {
240211
}
241212
}
242213
}
243-
impl CastFrom for Function {
244-
type From = Value;
245-
fn cast<'a>(val: &'a Value) -> Option<&'a Function> {
246-
let ty = val.get_type();
247-
let mut is_func = ty.is_function();
248-
if let Some(elem) = ty.get_element() {
249-
is_func = is_func || elem.is_function()
250-
}
251-
if is_func {
252-
Some(unsafe { mem::transmute(val) })
253-
} else {
254-
None
214+
unsafe impl Sub<Value> for Function {
215+
fn is(value: &Value) -> bool {
216+
let mut ty = value.get_type();
217+
while let Some(elem) = ty.get_element() {
218+
ty = elem;
255219
}
220+
ty.is_function()
256221
}
257222
}
258223
impl Function {

0 commit comments

Comments
 (0)