| use std::marker::PhantomData; |
| use std::fmt; |
| use std::ptr; |
| use std::mem; |
| use std::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitOr, BitXor, Shl, Shr}; |
| use context::Context; |
| use object::{ToObject, Object}; |
| use object; |
| use types::Type; |
| use types; |
| use field::Field; |
| use field; |
| use lvalue::LValue; |
| use lvalue; |
| use location::Location; |
| use location; |
| use block::BinaryOp; |
| |
| /// An RValue is a value that may or may not have a storage address in gccjit. |
| /// RValues can be dereferenced, used for field accesses, and are the parameters |
| /// given to a majority of the gccjit API calls. |
| #[derive(Copy, Clone, Eq, Hash, PartialEq)] |
| pub struct RValue<'ctx> { |
| marker: PhantomData<&'ctx Context<'ctx>>, |
| ptr: *mut gccjit_sys::gcc_jit_rvalue |
| } |
| |
| /// ToRValue is a trait implemented by types that can be converted to, or |
| /// treated as, an RValue. |
| pub trait ToRValue<'ctx> { |
| fn to_rvalue(&self) -> RValue<'ctx>; |
| } |
| |
| impl<'ctx> ToObject<'ctx> for RValue<'ctx> { |
| fn to_object(&self) -> Object<'ctx> { |
| unsafe { |
| object::from_ptr(gccjit_sys::gcc_jit_rvalue_as_object(self.ptr)) |
| } |
| } |
| } |
| |
| impl<'ctx> fmt::Debug for RValue<'ctx> { |
| fn fmt<'a>(&self, fmt: &mut fmt::Formatter<'a>) -> Result<(), fmt::Error> { |
| let obj = self.to_object(); |
| obj.fmt(fmt) |
| } |
| } |
| |
| impl<'ctx> ToRValue<'ctx> for RValue<'ctx> { |
| fn to_rvalue(&self) -> RValue<'ctx> { |
| unsafe { from_ptr(self.ptr) } |
| } |
| } |
| |
| macro_rules! binary_operator_for { |
| ($ty:ty, $name:ident, $op:expr) => { |
| impl<'ctx> $ty for RValue<'ctx> { |
| type Output = RValue<'ctx>; |
| |
| fn $name(self, rhs: RValue<'ctx>) -> RValue<'ctx> { |
| unsafe { |
| let rhs_rvalue = rhs.to_rvalue(); |
| let obj_ptr = object::get_ptr(&self.to_object()); |
| let ctx_ptr = gccjit_sys::gcc_jit_object_get_context(obj_ptr); |
| let ty = rhs.get_type(); |
| let ptr = gccjit_sys::gcc_jit_context_new_binary_op(ctx_ptr, |
| ptr::null_mut(), |
| mem::transmute::<BinaryOp, gccjit_sys::gcc_jit_binary_op>($op), |
| types::get_ptr(&ty), |
| self.ptr, |
| rhs_rvalue.ptr); |
| #[cfg(debug_assertions)] |
| if let Ok(Some(error)) = self.to_object().get_context().get_last_error() { |
| panic!("{}", error); |
| } |
| from_ptr(ptr) |
| } |
| } |
| } |
| } |
| } |
| |
| // Operator overloads for ease of manipulation of rvalues |
| binary_operator_for!(Add, add, BinaryOp::Plus); |
| binary_operator_for!(Sub, sub, BinaryOp::Minus); |
| binary_operator_for!(Mul, mul, BinaryOp::Mult); |
| binary_operator_for!(Div, div, BinaryOp::Divide); |
| binary_operator_for!(Rem, rem, BinaryOp::Modulo); |
| binary_operator_for!(BitAnd, bitand, BinaryOp::BitwiseAnd); |
| binary_operator_for!(BitOr, bitor, BinaryOp::BitwiseOr); |
| binary_operator_for!(BitXor, bitxor, BinaryOp::BitwiseXor); |
| binary_operator_for!(Shl<RValue<'ctx>>, shl, BinaryOp::LShift); |
| binary_operator_for!(Shr<RValue<'ctx>>, shr, BinaryOp::RShift); |
| |
| impl<'ctx> RValue<'ctx> { |
| /// Gets the type of this RValue. |
| pub fn get_type(&self) -> Type<'ctx> { |
| unsafe { |
| let ptr = gccjit_sys::gcc_jit_rvalue_get_type(self.ptr); |
| types::from_ptr(ptr) |
| } |
| } |
| |
| /// Sets the location of this RValue. |
| #[cfg(feature="master")] |
| pub fn set_location(&self, loc: Location) { |
| unsafe { |
| let loc_ptr = location::get_ptr(&loc); |
| gccjit_sys::gcc_jit_rvalue_set_location(self.ptr, loc_ptr); |
| } |
| } |
| |
| /// Change the type of this RValue. |
| #[cfg(feature="master")] |
| pub fn set_type(&self, typ: Type<'ctx>) { |
| unsafe { |
| let type_ptr = types::get_ptr(&typ); |
| gccjit_sys::gcc_jit_rvalue_set_type(self.ptr, type_ptr); |
| } |
| } |
| |
| /// Given an RValue x and a Field f, returns an RValue representing |
| /// C's x.f. |
| pub fn access_field(&self, |
| loc: Option<Location<'ctx>>, |
| field: Field<'ctx>) -> RValue<'ctx> { |
| let loc_ptr = match loc { |
| Some(loc) => unsafe { location::get_ptr(&loc) }, |
| None => ptr::null_mut() |
| }; |
| unsafe { |
| let ptr = gccjit_sys::gcc_jit_rvalue_access_field(self.ptr, |
| loc_ptr, |
| field::get_ptr(&field)); |
| from_ptr(ptr) |
| } |
| } |
| |
| /// Given an RValue x and a Field f, returns an LValue representing |
| /// C's x->f. |
| pub fn dereference_field(&self, |
| loc: Option<Location<'ctx>>, |
| field: Field<'ctx>) -> LValue<'ctx> { |
| let loc_ptr = match loc { |
| Some(loc) => unsafe { location::get_ptr(&loc) }, |
| None => ptr::null_mut() |
| }; |
| unsafe { |
| let ptr = gccjit_sys::gcc_jit_rvalue_dereference_field(self.ptr, |
| loc_ptr, |
| field::get_ptr(&field)); |
| #[cfg(debug_assertions)] |
| if let Ok(Some(error)) = self.to_object().get_context().get_last_error() { |
| panic!("{}", error); |
| } |
| lvalue::from_ptr(ptr) |
| } |
| } |
| |
| /// Given a RValue x, returns an RValue that represents *x. |
| pub fn dereference(&self, |
| loc: Option<Location<'ctx>>) -> LValue<'ctx> { |
| let loc_ptr = match loc { |
| Some(loc) => unsafe { location::get_ptr(&loc) }, |
| None => ptr::null_mut() |
| }; |
| unsafe { |
| let ptr = gccjit_sys::gcc_jit_rvalue_dereference(self.ptr, |
| loc_ptr); |
| |
| #[cfg(debug_assertions)] |
| if let Ok(Some(error)) = self.to_object().get_context().get_last_error() { |
| panic!("{}", error); |
| } |
| lvalue::from_ptr(ptr) |
| } |
| } |
| } |
| |
| pub unsafe fn from_ptr<'ctx>(ptr: *mut gccjit_sys::gcc_jit_rvalue) -> RValue<'ctx> { |
| RValue { |
| marker: PhantomData, |
| ptr |
| } |
| } |
| |
| pub unsafe fn get_ptr<'ctx>(rvalue: &RValue<'ctx>) -> *mut gccjit_sys::gcc_jit_rvalue { |
| rvalue.ptr |
| } |