]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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 | ||
c34b1796 | 17 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
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 | |
c34b1796 | 110 | pub fn get_operand(self, i: usize) -> Option<Value> { |
1a4d82fc JJ |
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 | |
c34b1796 | 128 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
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 | |
1a4d82fc JJ |
153 | pub struct Users { |
154 | next: Option<Use> | |
155 | } | |
156 | ||
157 | impl Iterator for Users { | |
158 | type Item = Value; | |
159 | ||
160 | fn next(&mut self) -> Option<Value> { | |
161 | let current = self.next; | |
162 | ||
163 | self.next = current.and_then(|u| u.get_next_use()); | |
164 | ||
165 | current.map(|u| u.get_user()) | |
166 | } | |
167 | } |