// 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 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::LLVMRustWriteValueToString(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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 } impl Iterator for Users { type Item = Value; fn next(&mut self) -> Option { let current = self.next; self.next = current.and_then(|u| u.get_next_use()); current.map(|u| u.get_user()) } }