]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/trans/value.rs
doc: remove incomplete sentence
[rust.git] / src / librustc_trans / trans / value.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use llvm;
12 use llvm::{UseRef, ValueRef};
13 use trans::basic_block::BasicBlock;
14 use trans::common::Block;
15 use libc::c_uint;
16
17 #[deriving(Copy)]
18 pub struct Value(pub ValueRef);
19
20 macro_rules! opt_val { ($e:expr) => (
21     unsafe {
22         match $e {
23             p if !p.is_null() => Some(Value(p)),
24             _ => None
25         }
26     }
27 ) }
28
29 /// Wrapper for LLVM ValueRef
30 impl Value {
31     /// Returns the native ValueRef
32     pub fn get(&self) -> ValueRef {
33         let Value(v) = *self; v
34     }
35
36     /// Returns the BasicBlock that contains this value
37     pub fn get_parent(self) -> Option<BasicBlock> {
38         unsafe {
39             match llvm::LLVMGetInstructionParent(self.get()) {
40                 p if !p.is_null() => Some(BasicBlock(p)),
41                 _ => None
42             }
43         }
44     }
45
46     /// Removes this value from its containing BasicBlock
47     pub fn erase_from_parent(self) {
48         unsafe {
49             llvm::LLVMInstructionEraseFromParent(self.get());
50         }
51     }
52
53     /// Returns the single dominating store to this value, if any
54     /// This only performs a search for a trivially dominating store. The store
55     /// must be the only user of this value, and there must not be any conditional
56     /// branches between the store and the given block.
57     pub fn get_dominating_store(self, bcx: Block) -> Option<Value> {
58         match self.get_single_user().and_then(|user| user.as_store_inst()) {
59             Some(store) => {
60                 store.get_parent().and_then(|store_bb| {
61                     let mut bb = BasicBlock(bcx.llbb);
62                     let mut ret = Some(store);
63                     while bb.get() != store_bb.get() {
64                         match bb.get_single_predecessor() {
65                             Some(pred) => bb = pred,
66                             None => { ret = None; break }
67                         }
68                     }
69                     ret
70                 })
71             }
72             _ => None
73         }
74     }
75
76     /// Returns the first use of this value, if any
77     pub fn get_first_use(self) -> Option<Use> {
78         unsafe {
79             match llvm::LLVMGetFirstUse(self.get()) {
80                 u if !u.is_null() => Some(Use(u)),
81                 _ => None
82             }
83         }
84     }
85
86     /// Tests if there are no uses of this value
87     pub fn has_no_uses(self) -> bool {
88         self.get_first_use().is_none()
89     }
90
91     /// Returns the single user of this value
92     /// If there are no users or multiple users, this returns None
93     pub fn get_single_user(self) -> Option<Value> {
94         let mut iter = self.user_iter();
95         match (iter.next(), iter.next()) {
96             (Some(first), None) => Some(first),
97             _ => None
98         }
99     }
100
101     /// Returns an iterator for the users of this value
102     pub fn user_iter(self) -> Users {
103         Users {
104             next: self.get_first_use()
105         }
106     }
107
108     /// Returns the requested operand of this instruction
109     /// Returns None, if there's no operand at the given index
110     pub fn get_operand(self, i: uint) -> Option<Value> {
111         opt_val!(llvm::LLVMGetOperand(self.get(), i as c_uint))
112     }
113
114     /// Returns the Store represent by this value, if any
115     pub fn as_store_inst(self) -> Option<Value> {
116         opt_val!(llvm::LLVMIsAStoreInst(self.get()))
117     }
118
119     /// Tests if this value is a terminator instruction
120     pub fn is_a_terminator_inst(self) -> bool {
121         unsafe {
122             !llvm::LLVMIsATerminatorInst(self.get()).is_null()
123         }
124     }
125 }
126
127 /// Wrapper for LLVM UseRef
128 #[deriving(Copy)]
129 pub struct Use(UseRef);
130
131 impl Use {
132     pub fn get(&self) -> UseRef {
133         let Use(v) = *self; v
134     }
135
136     pub fn get_user(self) -> Value {
137         unsafe {
138             Value(llvm::LLVMGetUser(self.get()))
139         }
140     }
141
142     pub fn get_next_use(self) -> Option<Use> {
143         unsafe {
144             match llvm::LLVMGetNextUse(self.get()) {
145                 u if !u.is_null() => Some(Use(u)),
146                 _ => None
147             }
148         }
149     }
150 }
151
152 /// Iterator for the users of a value
153 #[allow(missing_copy_implementations)]
154 pub struct Users {
155     next: Option<Use>
156 }
157
158 impl Iterator for Users {
159     type Item = Value;
160
161     fn next(&mut self) -> Option<Value> {
162         let current = self.next;
163
164         self.next = current.and_then(|u| u.get_next_use());
165
166         current.map(|u| u.get_user())
167     }
168 }