1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use raw::*;
use function::Func;
use types::Ty;
use util::{from_ptr, from_ptr_opt};
use value::Val;
use std::{ffi, fmt, mem, str};
use std::marker::PhantomData;

/// Represents a single LibJIT instruction
#[derive(Clone, Copy)]
pub struct Instruction<'a> {
    _insn: jit_insn_t,
    marker: PhantomData<&'a ()>
}
native_ref!(contra Instruction, _insn: jit_insn_t);

impl<'a> Instruction<'a> {
	/// Get the opcode of the instruction
	pub fn get_opcode(self) -> i32 {
		unsafe {
			jit_insn_get_opcode(self._insn)
		}
	}
	/// Get the destination value
	pub fn get_dest(self) -> Option<&'a Val> {
		unsafe {
			from_ptr_opt(jit_insn_get_dest(self._insn))
		}
	}
	/// Get if the destination value is a value
	pub fn dest_is_value(self) -> bool {
		unsafe {
			jit_insn_dest_is_value(self._insn) != 0
		}
	}
	/// Get the left value
	pub fn get_value1(self) -> Option<&'a Val> {
		unsafe {
			from_ptr_opt(jit_insn_get_value1(self._insn))
		}
	}
	/// Get the right value
	pub fn get_value2(self) -> Option<&'a Val> {
		unsafe {
			from_ptr_opt(jit_insn_get_value2(self._insn))
		}
	}
	/// Get the function containing this value
	pub fn get_function(self) -> Option<&'a Func> {
		unsafe {
			from_ptr_opt(jit_insn_get_function(self._insn))
		}
	}
	/// Get the signature of this value
	pub fn get_signature(self) -> Option<&'a Ty> {
		unsafe {
			from_ptr_opt(jit_insn_get_signature(self._insn))
		}
	}
	/// Get the name of the instruction
	pub fn get_name(self) -> &'a str {
		unsafe {
			let c_name = jit_insn_get_name(self._insn);
            let c_name = ffi::CStr::from_ptr(c_name);
			str::from_utf8(c_name.to_bytes()).unwrap()
		}
	}
}
impl<'a> fmt::Display for Instruction<'a> {
	fn fmt(&self, fmt:&mut fmt::Formatter) -> fmt::Result {
		write!(fmt, "{}", self.get_name())
	}
}

pub struct InstructionIter<'a> {
	_iter: jit_insn_iter_t,
	marker: PhantomData<&'a ()>,
}
impl<'a> Iterator for InstructionIter<'a> {
	type Item = Instruction<'a>;
	fn next(&mut self) -> Option<Instruction<'a>> {
		unsafe {
			let ptr = jit_insn_iter_next(&mut self._iter);
            if ptr.is_null() {
                None
            } else {
                Some(from_ptr(ptr))
            }
		}
	}
}

/// Represents a single LibJIT block
#[derive(Clone, Copy)]
pub struct Block<'a> {
    _block: jit_block_t,
    marker: PhantomData<&'a ()>
}
native_ref!(contra Block, _block: jit_block_t);
impl<'a> Block<'a> {
	/// Get the function containing this block
	pub fn get_function(self) -> &'a Func {
		unsafe {
			from_ptr(jit_block_get_function(self._block))
		}
	}
	/// Check if the block is reachable
	pub fn is_reachable(self) -> bool {
		unsafe {
			jit_block_is_reachable(self._block) != 0
		}
	}
	/// Check if the block ends in dead code
	pub fn ends_in_dead(self) -> bool {
		unsafe {
			jit_block_ends_in_dead(self._block) != 0
		}
	}
	/// Iterate through the instructions
	pub fn iter(self) -> InstructionIter<'a> {
		unsafe {
			let mut iter = mem::zeroed();
			jit_insn_iter_init(&mut iter, self._block);
			assert!(iter.block == self._block);
			assert!(iter.posn == 0);
			InstructionIter {
				_iter: iter,
				marker: PhantomData
			}
		}
	}
}