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
|
//===-- Value.cpp - Implement the Value class -----------------------------===//
//
// This file implements the Value, User, and SymTabValue classes.
//
//===----------------------------------------------------------------------===//
#include "llvm/InstrTypes.h"
#include "llvm/SymbolTable.h"
#include "llvm/SymTabValue.h"
#include "llvm/DerivedTypes.h"
#include <algorithm>
//===----------------------------------------------------------------------===//
// Value Class
//===----------------------------------------------------------------------===//
static inline const Type *checkType(const Type *Ty) {
assert(Ty && "Value defined with a null type: Error!");
return Ty;
}
Value::Value(const Type *ty, ValueTy vty, const std::string &name = "")
: Name(name), Ty(checkType(ty), this) {
VTy = vty;
}
Value::~Value() {
#ifndef NDEBUG // Only in -g mode...
// Check to make sure that there are no uses of this value that are still
// around when the value is destroyed. If there are, then we have a dangling
// reference and something is wrong. This code is here to print out what is
// still being referenced. The value in question should be printed as
// a <badref>
//
if (Uses.begin() != Uses.end()) {
std::cerr << "While deleting: ";
dump();
for (use_const_iterator I = Uses.begin(); I != Uses.end(); ++I) {
std::cerr << "Use still stuck around after Def is destroyed:";
(*I)->dump();
std::cerr << "\n";
}
}
#endif
assert(Uses.begin() == Uses.end());
}
void Value::replaceAllUsesWith(Value *D) {
assert(D && "Value::replaceAllUsesWith(<null>) is invalid!");
assert(D != this && "V->replaceAllUsesWith(V) is NOT valid!");
assert(D->getType() == getType() &&
"replaceAllUses of value with new value of different type!");
while (!Uses.empty()) {
User *Use = Uses.back();
#ifndef NDEBUG
unsigned NumUses = Uses.size();
#endif
Use->replaceUsesOfWith(this, D);
#ifndef NDEBUG // only in -g mode...
if (Uses.size() == NumUses) {
std::cerr << "Use: ";
Use->dump();
std::cerr << "replace with: ";
D->dump();
}
#endif
assert(Uses.size() != NumUses && "Didn't remove definition!");
}
}
// refineAbstractType - This function is implemented because we use
// potentially abstract types, and these types may be resolved to more
// concrete types after we are constructed. For the value class, we simply
// change Ty to point to the right type. :)
//
void Value::refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
assert(Ty.get() == OldTy &&"Can't refine anything but my type!");
if (OldTy == NewTy && !OldTy->isAbstract())
Ty.removeUserFromConcrete();
Ty = NewTy;
}
void Value::killUse(User *i) {
if (i == 0) return;
use_iterator I = find(Uses.begin(), Uses.end(), i);
assert(I != Uses.end() && "Use not in uses list!!");
Uses.erase(I);
}
User *Value::use_remove(use_iterator &I) {
assert(I != Uses.end() && "Trying to remove the end of the use list!!!");
User *i = *I;
I = Uses.erase(I);
return i;
}
//===----------------------------------------------------------------------===//
// User Class
//===----------------------------------------------------------------------===//
User::User(const Type *Ty, ValueTy vty, const std::string &name)
: Value(Ty, vty, name) {
}
// replaceUsesOfWith - Replaces all references to the "From" definition with
// references to the "To" definition.
//
void User::replaceUsesOfWith(Value *From, Value *To) {
if (From == To) return; // Duh what?
for (unsigned i = 0, E = getNumOperands(); i != E; ++i)
if (getOperand(i) == From) { // Is This operand is pointing to oldval?
// The side effects of this setOperand call include linking to
// "To", adding "this" to the uses list of To, and
// most importantly, removing "this" from the use list of "From".
setOperand(i, To); // Fix it now...
}
}
//===----------------------------------------------------------------------===//
// SymTabValue Class
//===----------------------------------------------------------------------===//
SymTabValue::SymTabValue(Value *p) : ValueParent(p) {
assert(ValueParent && "SymTavValue without parent!?!");
ParentSymTab = SymTab = 0;
}
SymTabValue::~SymTabValue() {
delete SymTab;
}
void SymTabValue::setParentSymTab(SymbolTable *ST) {
ParentSymTab = ST;
if (SymTab)
SymTab->setParentSymTab(ST);
}
SymbolTable *SymTabValue::getSymbolTableSure() {
if (!SymTab) SymTab = new SymbolTable(ParentSymTab);
return SymTab;
}
// hasSymbolTable() - Returns true if there is a symbol table allocated to
// this object AND if there is at least one name in it!
//
bool SymTabValue::hasSymbolTable() const {
if (!SymTab) return false;
for (SymbolTable::const_iterator I = SymTab->begin();
I != SymTab->end(); ++I) {
if (I->second.begin() != I->second.end())
return true; // Found nonempty type plane!
}
return false;
}
|