| // Copyright 2013 The Rust Project Developers. See the COPYRIGHT |
| // file at the top-level directory of this distribution and at |
| // http://rust-lang.org/COPYRIGHT. |
| // |
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| // option. This file may not be copied, modified, or distributed |
| // except according to those terms. |
| |
| use llvm; |
| use llvm::{UseRef, ValueRef}; |
| use basic_block::BasicBlock; |
| use common::Block; |
| |
| use std::fmt; |
| |
| use libc::c_uint; |
| |
| #[derive(Copy, Clone, PartialEq)] |
| pub struct Value(pub ValueRef); |
| |
| impl fmt::Debug for Value { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| f.write_str(&llvm::build_string(|s| unsafe { |
| llvm::LLVMWriteValueToString(self.0, s); |
| }).expect("nun-UTF8 value description from LLVM")) |
| } |
| } |
| |
| macro_rules! opt_val { ($e:expr) => ( |
| unsafe { |
| match $e { |
| p if !p.is_null() => Some(Value(p)), |
| _ => None |
| } |
| } |
| ) } |
| |
| /// Wrapper for LLVM ValueRef |
| impl Value { |
| /// Returns the native ValueRef |
| pub fn get(&self) -> ValueRef { |
| let Value(v) = *self; v |
| } |
| |
| /// Returns the BasicBlock that contains this value |
| pub fn get_parent(self) -> Option<BasicBlock> { |
| unsafe { |
| match llvm::LLVMGetInstructionParent(self.get()) { |
| p if !p.is_null() => Some(BasicBlock(p)), |
| _ => None |
| } |
| } |
| } |
| |
| /// Removes this value from its containing BasicBlock |
| pub fn erase_from_parent(self) { |
| unsafe { |
| llvm::LLVMInstructionEraseFromParent(self.get()); |
| } |
| } |
| |
| /// Returns the single dominating store to this value, if any |
| /// This only performs a search for a trivially dominating store. The store |
| /// must be the only user of this value, and there must not be any conditional |
| /// branches between the store and the given block. |
| pub fn get_dominating_store(self, bcx: Block) -> Option<Value> { |
| match self.get_single_user().and_then(|user| user.as_store_inst()) { |
| Some(store) => { |
| store.get_parent().and_then(|store_bb| { |
| let mut bb = BasicBlock(bcx.llbb); |
| let mut ret = Some(store); |
| while bb.get() != store_bb.get() { |
| match bb.get_single_predecessor() { |
| Some(pred) => bb = pred, |
| None => { ret = None; break } |
| } |
| } |
| ret |
| }) |
| } |
| _ => None |
| } |
| } |
| |
| /// Returns the first use of this value, if any |
| pub fn get_first_use(self) -> Option<Use> { |
| unsafe { |
| match llvm::LLVMGetFirstUse(self.get()) { |
| u if !u.is_null() => Some(Use(u)), |
| _ => None |
| } |
| } |
| } |
| |
| /// Tests if there are no uses of this value |
| pub fn has_no_uses(self) -> bool { |
| self.get_first_use().is_none() |
| } |
| |
| /// Returns the single user of this value |
| /// If there are no users or multiple users, this returns None |
| pub fn get_single_user(self) -> Option<Value> { |
| let mut iter = self.user_iter(); |
| match (iter.next(), iter.next()) { |
| (Some(first), None) => Some(first), |
| _ => None |
| } |
| } |
| |
| /// Returns an iterator for the users of this value |
| pub fn user_iter(self) -> Users { |
| Users { |
| next: self.get_first_use() |
| } |
| } |
| |
| /// Returns the requested operand of this instruction |
| /// Returns None, if there's no operand at the given index |
| pub fn get_operand(self, i: usize) -> Option<Value> { |
| opt_val!(llvm::LLVMGetOperand(self.get(), i as c_uint)) |
| } |
| |
| /// Returns the Store represent by this value, if any |
| pub fn as_store_inst(self) -> Option<Value> { |
| opt_val!(llvm::LLVMIsAStoreInst(self.get())) |
| } |
| |
| /// Tests if this value is a terminator instruction |
| pub fn is_a_terminator_inst(self) -> bool { |
| unsafe { |
| !llvm::LLVMIsATerminatorInst(self.get()).is_null() |
| } |
| } |
| } |
| |
| /// Wrapper for LLVM UseRef |
| #[derive(Copy, Clone)] |
| pub struct Use(UseRef); |
| |
| impl Use { |
| pub fn get(&self) -> UseRef { |
| let Use(v) = *self; v |
| } |
| |
| pub fn get_user(self) -> Value { |
| unsafe { |
| Value(llvm::LLVMGetUser(self.get())) |
| } |
| } |
| |
| pub fn get_next_use(self) -> Option<Use> { |
| unsafe { |
| match llvm::LLVMGetNextUse(self.get()) { |
| u if !u.is_null() => Some(Use(u)), |
| _ => None |
| } |
| } |
| } |
| } |
| |
| /// Iterator for the users of a value |
| pub struct Users { |
| next: Option<Use> |
| } |
| |
| impl Iterator for Users { |
| type Item = Value; |
| |
| fn next(&mut self) -> Option<Value> { |
| let current = self.next; |
| |
| self.next = current.and_then(|u| u.get_next_use()); |
| |
| current.map(|u| u.get_user()) |
| } |
| } |