-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathInstruction.h
134 lines (103 loc) · 3.18 KB
/
Instruction.h
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
#pragma once
#include <cassert>
#include <iostream>
#include <memory>
#include <ostream>
#include <string>
#include <llvm-c/Core.h>
class BasicBlock;
class Instruction {
LLVMValueRef inst_ = nullptr;
public:
Instruction() {}
Instruction(LLVMValueRef &&inst):inst_(inst)
{ assert(LLVMIsAInstruction(inst_)); }
Instruction(LLVMValueRef &inst):inst_(inst)
{ assert(LLVMIsAInstruction(inst_)); }
LLVMValueRef getMetadata(unsigned kind) const
{ return LLVMGetMetadata(inst_, kind); }
LLVMValueRef getCalledValue() const {
assert(getOpcode() == LLVMCall ||
getOpcode() == LLVMInvoke);
return LLVMGetCalledValue(inst_);
}
::std::string getName() const;
LLVMValueRef value() const
{ return inst_; }
BasicBlock getParent() const;
LLVMOpcode getOpcode() const
{ return LLVMGetInstructionOpcode(inst_); }
int getNumOperands() const
{ return LLVMGetNumOperands(inst_); }
Instruction getOperandInstruction(int idx) const
{ return Instruction(LLVMGetOperand(inst_, idx)); }
class op_iterator {
Instruction &inst_;
int op_index_;
::std::unique_ptr<Instruction> instance_ = nullptr;
public:
op_iterator(Instruction &i, int idx): inst_(i), op_index_(idx) {}
bool operator != (const op_iterator &i)
{ return &inst_ != &i.inst_ || op_index_ != i.op_index_; }
Instruction& operator *()
{ return *get_instance_(); }
Instruction* operator -> ()
{ return get_instance_(); }
bool isInstruction()
{ return !!get_instance_(); }
const op_iterator & operator++()
{ ++op_index_; instance_ = nullptr; return *this; }
LLVMValueRef value() const
{ return LLVMGetOperand(inst_.inst_, op_index_); }
private:
Instruction * get_instance_() {
if (!instance_) {
LLVMValueRef v = value();
if (LLVMIsAInstruction(v))
instance_.reset(new Instruction(v));
}
return instance_.get();
}
};
op_iterator op_begin()
{ return op_iterator(*this, 0); }
op_iterator op_end()
{ return op_iterator(*this, getNumOperands()); }
class use_iterator {
const Instruction &inst_;
LLVMUseRef use_ = nullptr;
::std::unique_ptr<Instruction> instance_ = nullptr;
public:
use_iterator(const Instruction &i, LLVMUseRef &&u): inst_(i), use_(u) {}
bool operator != (const use_iterator &i)
{ return &inst_ != &i.inst_ || use_ != i.use_; }
Instruction& operator *()
{ return *get_instance_(); }
Instruction* operator -> ()
{ return get_instance_(); }
bool isInstruction()
{ return !!get_instance_(); }
const use_iterator & operator++()
{ use_ = LLVMGetNextUse(use_); instance_ = nullptr; return *this; }
LLVMValueRef value() const
{ return LLVMGetUser(use_); }
private:
Instruction * get_instance_() {
if (!instance_) {
LLVMValueRef v = value();
if (LLVMIsAInstruction(v))
instance_.reset(new Instruction(v));
}
return instance_.get();
}
};
use_iterator use_begin() const
{ return use_iterator(*this, LLVMGetFirstUse(inst_)); }
use_iterator use_end() const
{ return use_iterator(*this, nullptr); }
friend class BasicBlock;
friend class op_iterator;
friend class use_iterator;
friend ::std::ostream & operator << (::std::ostream &, const Instruction &);
};
::std::ostream & operator << (::std::ostream &, const Instruction &);