Static Value-Flow Analysis
BreakConstantExpr.cpp
Go to the documentation of this file.
1 /* SVF - Static Value-Flow Analysis Framework
2 Copyright (C) 2015 Yulei Sui
3 Copyright (C) 2015 Jingling Xue
4 
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9 
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14 
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 
20 /*
21  * BreakConstantExpr.cpp
22  *
23  * Created on: Oct 8, 2013
24  * Author: Yulei Sui
25  */
26 
27 
28 
29 //===- BreakConstantGEPs.cpp - Change constant GEPs into GEP instructions - --//
30 //
31 // The SAFECode Compiler
32 //
33 // This file was developed by the LLVM research group and is distributed under
34 // the University of Illinois Open Source License. See LICENSE.TXT for details.
35 //
36 //===----------------------------------------------------------------------===//
37 //
38 // This pass changes all GEP constant expressions into GEP instructions. This
39 // permits the rest of SAFECode to put run-time checks on them if necessary.
40 //
41 //===----------------------------------------------------------------------===//
42 
43 
44 #include "llvm/ADT/Statistic.h"
45 #include "llvm/IR/Constants.h"
46 #include "llvm/IR/InstrTypes.h"
47 #include "llvm/IR/Instruction.h"
48 #include "llvm/IR/Instructions.h"
49 #include "llvm/IR/LLVMContext.h"
50 #include "llvm/IR/InstIterator.h"
51 
52 #include "SVF-LLVM/BasicTypes.h"
54 
55 #include <iostream>
56 #include <map>
57 #include <utility>
58 
59 using namespace SVF;
60 
61 // Identifier variable for the pass
62 char BreakConstantGEPs::ID = 0;
63 char MergeFunctionRets::ID = 0;
64 
65 #define DEBUG_TYPE "break-constgeps"
66 
67 // Statistics
68 STATISTIC (GEPChanges, "Number of Converted GEP Constant Expressions");
69 STATISTIC (TotalChanges, "Number of Converted Constant Expressions");
70 
71 //
72 // Function: hasConstantGEP()
73 //
74 // Description:
75 // This function determines whether the given value is a constant expression
76 // that has a constant GEP expression embedded within it.
77 //
78 // Inputs:
79 // V - The value to check.
80 //
81 // Return value:
82 // nullptr - This value is not a constant expression with a constant expression
83 // GEP within it.
84 // ~nullptr - A pointer to the value casted into a ConstantExpr is returned.
85 //
86 static ConstantExpr *
88 {
89  if (ConstantExpr * CE = SVFUtil::dyn_cast<ConstantExpr>(V))
90  {
91  if (CE->getOpcode() == Instruction::GetElementPtr)
92  {
93  return CE;
94  }
95  else
96  {
97  for (u32_t index = 0; index < CE->getNumOperands(); ++index)
98  {
99  if (hasConstantGEP (CE->getOperand(index)))
100  return CE;
101  }
102  }
103  }
104 
105  return nullptr;
106 }
107 
108 // Description:
109 // This function determines whether the given value is a constant expression
110 // that has a constant binary or unary operator expression embedded within it.
111 static ConstantExpr *
113 {
114  if (ConstantExpr * CE = SVFUtil::dyn_cast<ConstantExpr>(V))
115  {
116  if (Instruction::isBinaryOp(CE->getOpcode()) || Instruction::isUnaryOp(CE->getOpcode()))
117  {
118  return CE;
119  }
120  else
121  {
122  for (u32_t index = 0; index < CE->getNumOperands(); ++index)
123  {
124  if (hasConstantBinaryOrUnaryOp (CE->getOperand(index)))
125  return CE;
126  }
127  }
128  }
129 
130  return nullptr;
131 }
132 
133 // Description:
134 // Return true if this is a constant Gep or binaryOp or UnaryOp expression
135 static ConstantExpr *
137 {
138  if (ConstantExpr * gep = hasConstantGEP(V))
139  {
140  return gep;
141  }
142  else if (ConstantExpr * buop = hasConstantBinaryOrUnaryOp(V))
143  {
144  return buop;
145  }
146  else
147  {
148  return nullptr;
149  }
150 }
151 
152 
153 //
154 // Function: convertExpression()
155 //
156 // Description:
157 // Convert a constant expression into an instruction. This routine does *not*
158 // perform any recursion, so the resulting instruction may have constant
159 // expression operands.
160 //
161 static Instruction*
163 {
164  //
165  // Convert this constant expression into a regular instruction.
166  //
167  if (CE->getOpcode() == Instruction::GetElementPtr)
168  ++GEPChanges;
169  ++TotalChanges;
170  Instruction* Result = CE->getAsInstruction();
171  Result->insertBefore(InsertPt);
172  return Result;
173 }
174 
175 //
176 // Method: runOnFunction()
177 //
178 // Description:
179 // Entry point for this LLVM pass.
180 //
181 // Return value:
182 // true - The function was modified.
183 // false - The function was not modified.
184 //
185 bool
187 {
188  bool modified = false;
189  for (Module::iterator F = module.begin(), E = module.end(); F != E; ++F)
190  {
191  // Worklist of values to check for constant GEP expressions
192  std::vector<Instruction* > Worklist;
193 
194  //
195  // Initialize the worklist by finding all instructions that have one or more
196  // operands containing a constant GEP expression.
197  //
198  for (Function::iterator BB = (*F).begin(); BB != (*F).end(); ++BB)
199  {
200  for (BasicBlock::iterator i = BB->begin(); i != BB->end(); ++i)
201  {
202  //
203  // Scan through the operands of this instruction. If it is a constant
204  // expression GEP, insert an instruction GEP before the instruction.
205  //
206  Instruction* I = &(*i);
207  for (u32_t index = 0; index < I->getNumOperands(); ++index)
208  {
209  if (hasConstantExpr(I->getOperand(index)))
210  {
211  Worklist.push_back (I);
212  }
213  }
214  }
215  }
216 
217  //
218  // Determine whether we will modify anything.
219  //
220  if (Worklist.size()) modified = true;
221 
222  //
223  // While the worklist is not empty, take an item from it, convert the
224  // operands into instructions if necessary, and determine if the newly
225  // added instructions need to be processed as well.
226  //
227  while (Worklist.size())
228  {
229  Instruction* I = Worklist.back();
230  Worklist.pop_back();
231 
232  //
233  // Scan through the operands of this instruction and convert each into an
234  // instruction. Note that this works a little differently for phi
235  // instructions because the new instruction must be added to the
236  // appropriate predecessor block.
237  //
238  if (PHINode * PHI = SVFUtil::dyn_cast<PHINode>(I))
239  {
240  for (u32_t index = 0; index < PHI->getNumIncomingValues(); ++index)
241  {
242  //
243  // For PHI Nodes, if an operand is a constant expression with a GEP, we
244  // want to insert the new instructions in the predecessor basic block.
245  //
246  // Note: It seems that it's possible for a phi to have the same
247  // incoming basic block listed multiple times; this seems okay as long
248  // the same value is listed for the incoming block.
249  //
250  Instruction* InsertPt = PHI->getIncomingBlock(index)->getTerminator();
251  if (ConstantExpr * CE = hasConstantExpr(PHI->getIncomingValue(index)))
252  {
253  Instruction* NewInst = convertExpression (CE, InsertPt);
254  for (u32_t i2 = index; i2 < PHI->getNumIncomingValues(); ++i2)
255  {
256  if ((PHI->getIncomingBlock (i2)) == PHI->getIncomingBlock (index))
257  PHI->setIncomingValue (i2, NewInst);
258  }
259  Worklist.push_back (NewInst);
260  }
261  }
262  }
263  else
264  {
265  for (u32_t index = 0; index < I->getNumOperands(); ++index)
266  {
267  //
268  // For other instructions, we want to insert instructions replacing
269  // constant expressions immediately before the instruction using the
270  // constant expression.
271  //
272  if (ConstantExpr * CE = hasConstantExpr(I->getOperand(index)))
273  {
274  Instruction* NewInst = convertExpression (CE, I);
275  I->replaceUsesOfWith (CE, NewInst);
276  Worklist.push_back (NewInst);
277  }
278  }
279  }
280  }
281 
282  }
283  return modified;
284 }
285 
286 
287 
288 
static Instruction * convertExpression(ConstantExpr *CE, Instruction *InsertPt)
STATISTIC(GEPChanges, "Number of Converted GEP Constant Expressions")
static ConstantExpr * hasConstantExpr(Value *V)
static ConstantExpr * hasConstantBinaryOrUnaryOp(Value *V)
static ConstantExpr * hasConstantGEP(Value *V)
unsigned u32_t
Definition: CommandLine.h:18
#define F(f)
int index
Definition: cJSON.h:170
virtual bool runOnModule(Module &M)
for isBitcode
Definition: BasicTypes.h:68
llvm::Instruction Instruction
Definition: BasicTypes.h:87
llvm::Value Value
LLVM Basic classes.
Definition: BasicTypes.h:82
llvm::ConstantExpr ConstantExpr
Definition: BasicTypes.h:120
llvm::Module Module
Definition: BasicTypes.h:84
llvm::PHINode PHINode
Definition: BasicTypes.h:165
unsigned u32_t
Definition: GeneralType.h:46