// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use lib::llvm::{llvm, UseRef, ValueRef}; use middle::trans::basic_block::BasicBlock; use middle::trans::common::Block; use std::libc::c_uint; pub struct Value(ValueRef); macro_rules! opt_val ( ($e:expr) => ( unsafe { match $e { p if p.is_not_null() => Some(Value(p)), _ => None } } )) /** * Wrapper for LLVM ValueRef */ impl Value { /// Returns the BasicBlock that contains this value pub fn get_parent(self) -> Option { unsafe { match llvm::LLVMGetInstructionParent(*self) { p if p.is_not_null() => Some(BasicBlock(p)), _ => None } } } /// Removes this value from its containing BasicBlock pub fn erase_from_parent(self) { unsafe { llvm::LLVMInstructionEraseFromParent(*self); } } /// 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: @mut Block) -> Option { match self.get_single_user().chain(|user| user.as_store_inst()) { Some(store) => { do store.get_parent().chain |store_bb| { let mut bb = BasicBlock(bcx.llbb); let mut ret = Some(store); while *bb != *store_bb { 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 { unsafe { match llvm::LLVMGetFirstUse(*self) { u if u.is_not_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 { 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) -> UserIterator { UserIterator { 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: uint) -> Option { opt_val!(llvm::LLVMGetOperand(*self, i as c_uint)) } /// Returns the Store represent by this value, if any pub fn as_store_inst(self) -> Option { opt_val!(llvm::LLVMIsAStoreInst(*self)) } /// Tests if this value is a terminator instruction pub fn is_a_terminator_inst(self) -> bool { unsafe { llvm::LLVMIsATerminatorInst(*self).is_not_null() } } } pub struct Use(UseRef); /** * Wrapper for LLVM UseRef */ impl Use { pub fn get_user(self) -> Value { unsafe { Value(llvm::LLVMGetUser(*self)) } } pub fn get_next_use(self) -> Option { unsafe { match llvm::LLVMGetNextUse(*self) { u if u.is_not_null() => Some(Use(u)), _ => None } } } } /// Iterator for the users of a value pub struct UserIterator { priv next: Option } impl Iterator for UserIterator { fn next(&mut self) -> Option { let current = self.next; self.next = do current.chain |u| { u.get_next_use() }; do current.map |u| { u.get_user() } } }