@@ -15,6 +15,7 @@ using namespace llvm;
15
15
16
16
namespace
17
17
{
18
+
18
19
struct Hpps : public FunctionPass
19
20
{
20
21
static char ID;
@@ -23,15 +24,19 @@ namespace
23
24
// Run over a single function
24
25
bool runOnFunction (Function &Func) override
25
26
{
27
+ // Null Value reference
28
+ LLVMContext &context = Func.getContext ();
29
+ Value *nullValue = ConstantInt::get (Type::getInt32Ty (context), -1 );
30
+
26
31
// Keep reference of value still left to find the ranges
27
32
// 'from' is unknown, it depends on 'to', 'toValue', and 'toOps' ('+' or '-')
28
33
// from = to toOps toValue (a = b + 1)
29
34
// from = toValue toOps to (a = 1 + b)
30
35
// from = to toOps to2 (a = b + c)
31
36
std::vector<Value *> from;
32
37
std::vector<Value *> to;
33
- std::vector<int > toValue;
34
38
std::vector<Value *> to2;
39
+ std::vector<int > toValue;
35
40
std::vector<unsigned > toOps;
36
41
37
42
// Reference of variabiles for which range has been found
@@ -58,30 +63,31 @@ namespace
58
63
{
59
64
Value *v = U.get ();
60
65
loadRef.push_back (v);
61
- errs () << " -Load:" << v->getName () << " \n " ;
66
+ errs () << " -Load: " << v->getName () << " \n " ;
62
67
}
63
68
}
64
69
65
- // When instruction is Add or Sub
70
+ // When instruction is Add or Sub (a = a + c or a = b + 1 or a = 1 + b)
66
71
// Save operand0 (reference/constant) and operand1 (reference/constant)
67
72
if (auto *operInst = dyn_cast<BinaryOperator>(&I))
68
73
{
69
74
Value *oper0 = operInst->getOperand (0 );
70
75
Value *oper1 = operInst->getOperand (1 );
71
76
72
77
// Store reference of variable still to find range
73
- from.push_back (operInst);
78
+ from.push_back (operInst); // left-hand side of the operation
74
79
toOps.push_back (operInst->getOpcode ()); // '+' ot '-'
75
80
76
81
// Store constants/references
77
- errs () << " -Stored: " << operInst->getName () << " \n " ;
82
+ errs () << " -Operation: " << operInst->getName () << " \n " ;
78
83
79
84
// a = b + 1 (variable + constant)
80
85
// Get reference from previous load instruction
81
86
if (ConstantInt *CI = dyn_cast<ConstantInt>(oper1))
82
87
{
83
88
toValue.push_back (CI->getZExtValue ());
84
89
to.push_back (loadRef.at (0 ));
90
+ to2.push_back (nullValue);
85
91
loadRef.pop_back ();
86
92
}
87
93
@@ -90,25 +96,35 @@ namespace
90
96
else if (ConstantInt *CI = dyn_cast<ConstantInt>(oper0))
91
97
{
92
98
toValue.push_back (CI->getZExtValue ());
93
- to.push_back (loadRef.at (0 ));
99
+ to.push_back (nullValue);
100
+ to2.push_back (loadRef.at (0 ));
94
101
loadRef.pop_back ();
95
102
}
96
103
97
104
// a = b + c (variable + variable)
98
105
// Get reference from two previous load instructions
99
106
else
100
107
{
101
- // TODO: It may be that there are x2 'to', create a struct to handle them both
108
+ // It may be that there are x2 'to'
109
+ toValue.push_back (0 );
102
110
to.push_back (loadRef.at (0 ));
103
- to.push_back (loadRef.at (1 ));
111
+
112
+ // TODO: When a = a + b + 3, the IR creates two loads for a and b, then
113
+ // it does the 'add' = a + b, and then uses 'add1' = 'add' + 3. The problem
114
+ // is that 'add' is not in loadRef, so there is an error!
115
+ //
116
+ // Same with a = a + b + c, 'add' = a + b, then load of c and 'add1' = 'add' + c,
117
+ // but since those are both variables, and loadRef contains only c, calling
118
+ // loadRef.at(1) gives error!
119
+ to2.push_back (loadRef.at (1 ));
104
120
105
121
// Remove previous used load instruction value
106
122
loadRef.pop_back ();
107
123
loadRef.pop_back ();
108
124
}
109
125
}
110
126
111
- // When instruction is store
127
+ // When instruction is store (a = b or a = 1)
112
128
if (auto *strInst = dyn_cast<StoreInst>(&I))
113
129
{
114
130
// Get operand0 (value) and operand1 (assigned)
@@ -120,10 +136,11 @@ namespace
120
136
// a = b
121
137
if (oper0->hasName ())
122
138
{
123
- errs () << " -Ref:" << oper0->getName () << " \n " ;
139
+ errs () << " -Ref: " << oper0->getName () << " \n " ;
124
140
from.push_back (oper1); // a
125
141
to.push_back (oper0); // b
126
142
143
+ to2.push_back (nullValue); // Placeholder
127
144
toValue.push_back (0 ); // Placeholder
128
145
toOps.push_back (Instruction::Add); // Placeholder
129
146
}
@@ -134,7 +151,7 @@ namespace
134
151
{
135
152
if (ConstantInt *CI = dyn_cast<ConstantInt>(oper0))
136
153
{
137
- errs () << " -Const: " << CI->getZExtValue () << " \n " ;
154
+ errs () << " -Range found: " << CI->getZExtValue () << " \n " ;
138
155
ranged.push_back (oper1);
139
156
minRange.push_back (CI->getZExtValue ());
140
157
maxRange.push_back (CI->getZExtValue ());
@@ -147,39 +164,85 @@ namespace
147
164
}
148
165
149
166
// Resolve references
150
- errs () << " \n REFERENCES: \n " ;
167
+ errs () << " \n --- REFERENCES --- \n " ;
151
168
for (unsigned i = 0 ; i < from.size (); ++i)
152
169
{
153
- errs () << to.at (i)->getName () << " +" << toValue.at (i) << " <-" << from.at (i)->getName () << " \n " ;
170
+ // Print all dependencies
171
+ errs () << from.at (i)->getName () << " (" ;
172
+ if (to.at (i) == nullValue)
173
+ {
174
+ errs () << toValue.at (i) << " , " ;
175
+ }
176
+ else
177
+ {
178
+ errs () << to.at (i)->getName () << " , " ;
179
+ }
180
+ if (to2.at (i) == nullValue)
181
+ {
182
+ errs () << toValue.at (i) << " )\n " ;
183
+ }
184
+ else
185
+ {
186
+ errs () << to2.at (i)->getName () << " )\n " ;
187
+ }
188
+
189
+ // Get value from ranged ranges
190
+ int refValue1 = -1 ;
191
+ int refValue2 = -1 ;
192
+
193
+ if (to.at (i) == nullValue)
194
+ {
195
+ refValue1 = toValue.at (i);
196
+ // errs() << "- F(const):" << refValue1 << "\n";
197
+ }
198
+
199
+ if (to2.at (i) == nullValue)
200
+ {
201
+ refValue2 = toValue.at (i);
202
+ // errs() << "- F(const):" << refValue2 << "\n";
203
+ }
154
204
155
205
// Search variable reference inside already found ranges
156
206
for (unsigned v = 0 ; v < ranged.size (); ++v)
157
207
{
158
- // When range found, add a new found range
208
+ // When found value of 'to' in 'ranged'
159
209
if (to.at (i) == ranged.at (v))
160
210
{
161
- errs () << " -FOUND:" << ranged.at (v)->getName () << " \n " ;
162
- if (toOps.at (i) == Instruction::Add)
163
- {
164
- minRange.push_back (minRange.at (v) + toValue.at (i));
165
- maxRange.push_back (minRange.at (v) + toValue.at (i));
166
- }
167
- else if (toOps.at (i) == Instruction::Sub)
168
- {
169
- minRange.push_back (minRange.at (v) - toValue.at (i));
170
- maxRange.push_back (minRange.at (v) - toValue.at (i));
171
- }
211
+ // When range found, add a new found range
212
+ refValue1 = minRange.at (v);
213
+ // errs() << "- F(to):" << ranged.at(v)->getName() << " (" << refValue1 << "\n\n";
214
+ }
172
215
173
- ranged.push_back (from.at (i));
216
+ // When found value of 'to2' in 'ranged'
217
+ if (to2.at (i) == ranged.at (v))
218
+ {
219
+ // When range found, add a new found range
220
+ refValue2 = minRange.at (v);
221
+ // errs() << "- F(to2):" << ranged.at(v)->getName() << " (" << refValue2 << "\n\n";
174
222
}
175
223
}
224
+
225
+ if (toOps.at (i) == Instruction::Add)
226
+ {
227
+ minRange.push_back (refValue1 + refValue2);
228
+ maxRange.push_back (refValue1 + refValue2);
229
+ ranged.push_back (from.at (i));
230
+ errs () << " " << from.at (i)->getName () << " = " << refValue1 << " + " << refValue2 << " = " << (refValue1 + refValue2) << " \n\n " ;
231
+ }
232
+ else if (toOps.at (i) == Instruction::Sub)
233
+ {
234
+ minRange.push_back (refValue1 - refValue2);
235
+ maxRange.push_back (refValue1 - refValue2);
236
+ ranged.push_back (from.at (i));
237
+ errs () << " " << from.at (i)->getName () << " = " << refValue1 << " - " << refValue2 << " = " << (refValue1 - refValue2) << " \n\n " ;
238
+ }
176
239
}
177
240
178
241
// Print value range computed
179
- errs () << " \n VALUE RANGES\n " ;
242
+ errs () << " \n --- VALUE RANGES --- \n " ;
180
243
for (unsigned i = 0 ; i < minRange.size (); ++i)
181
244
{
182
- errs () << ranged.at (i)->getName () << " (" << minRange.at (i) << " , " << maxRange.at (i) << " )\n " ;
245
+ errs () << " " << ranged.at (i)->getName () << " (" << minRange.at (i) << " , " << maxRange.at (i) << " )\n " ;
183
246
}
184
247
185
248
return false ;
0 commit comments