summaryrefslogtreecommitdiff
path: root/src/librustc_trans/trans/value.rs
blob: a33b7d62d2dcefd17efaa3263ff3cddc9ffeaa13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// 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 trans::basic_block::BasicBlock;
use trans::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())
    }
}