OLD | NEW |
(Empty) | |
| 1 //===- FlattenGlobals.cpp - Flatten global variable initializers-----------===// |
| 2 // |
| 3 // The LLVM Compiler Infrastructure |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 // |
| 10 // This pass converts initializers for global variables into a |
| 11 // flattened normal form which removes nested struct types and |
| 12 // simplifies ConstantExprs. |
| 13 // |
| 14 // In this normal form, an initializer is either a SimpleElement or a |
| 15 // CompoundElement. |
| 16 // |
| 17 // A SimpleElement is one of the following: |
| 18 // |
| 19 // 1) An i8 array literal or zeroinitializer: |
| 20 // |
| 21 // [SIZE x i8] c"DATA" |
| 22 // [SIZE x i8] zeroinitializer |
| 23 // |
| 24 // 2) A reference to a GlobalValue (a function or global variable) |
| 25 // with an optional 32-bit byte offset added to it (the addend): |
| 26 // |
| 27 // ptrtoint (TYPE* @GLOBAL to i32) |
| 28 // add (i32 ptrtoint (TYPE* @GLOBAL to i32), i32 ADDEND) |
| 29 // |
| 30 // We use ptrtoint+add rather than bitcast+getelementptr because |
| 31 // the constructor for getelementptr ConstantExprs performs |
| 32 // constant folding which introduces more complex getelementptrs, |
| 33 // and it is hard to check that they follow a normal form. |
| 34 // |
| 35 // For completeness, the pass also allows a BlockAddress as well as |
| 36 // a GlobalValue here, although BlockAddresses are currently not |
| 37 // allowed in the PNaCl ABI, so this should not be considered part |
| 38 // of the normal form. |
| 39 // |
| 40 // A CompoundElement is a unnamed, packed struct containing only |
| 41 // SimpleElements. |
| 42 // |
| 43 // Limitations: |
| 44 // |
| 45 // LLVM IR allows ConstantExprs that calculate the difference between |
| 46 // two globals' addresses. FlattenGlobals rejects these because Clang |
| 47 // does not generate these and because ELF does not support such |
| 48 // relocations in general. |
| 49 // |
| 50 //===----------------------------------------------------------------------===// |
| 51 |
| 52 #include "llvm/ADT/DenseMap.h" |
| 53 #include "llvm/ADT/SmallVector.h" |
| 54 #include "llvm/ADT/STLExtras.h" |
| 55 #include "llvm/IR/Constants.h" |
| 56 #include "llvm/IR/DataLayout.h" |
| 57 #include "llvm/IR/DerivedTypes.h" |
| 58 #include "llvm/IR/Instructions.h" |
| 59 #include "llvm/IR/Module.h" |
| 60 #include "llvm/Pass.h" |
| 61 #include "llvm/Support/raw_ostream.h" |
| 62 #include "llvm/Transforms/NaCl.h" |
| 63 |
| 64 using namespace llvm; |
| 65 |
| 66 namespace { |
| 67 |
| 68 // Defines a (non-constant) handle that records a use of a |
| 69 // constant. Used to make sure a relocation, within flattened global |
| 70 // variable initializers, does not get destroyed when method |
| 71 // removeDeadConstantUsers gets called. For simplicity, rather than |
| 72 // defining a new (non-constant) construct, we use a return |
| 73 // instruction as the handle. |
| 74 typedef ReturnInst RelocUserType; |
| 75 |
| 76 // Define map from a relocation, appearing in the flattened global variable |
| 77 // initializers, to it's corresponding use handle. |
| 78 typedef DenseMap<Constant*, RelocUserType*> RelocMapType; |
| 79 |
| 80 // Define the list to hold the list of global variables being flattened. |
| 81 struct FlattenedGlobal; |
| 82 typedef std::vector<FlattenedGlobal*> FlattenedGlobalsVectorType; |
| 83 |
| 84 // Returns the corresponding relocation, for the given user handle. |
| 85 Constant *getRelocUseConstant(RelocUserType *RelocUser) { |
| 86 return cast<Constant>(RelocUser->getReturnValue()); |
| 87 } |
| 88 |
| 89 // The state associated with flattening globals of a module. |
| 90 struct FlattenGlobalsState { |
| 91 /// The module being flattened. |
| 92 Module &M; |
| 93 /// The data layout to be used. |
| 94 DataLayout DL; |
| 95 /// The relocations (within the original global variable initializers) |
| 96 /// that must be kept. |
| 97 RelocMapType RelocMap; |
| 98 /// The list of global variables that are being flattened. |
| 99 FlattenedGlobalsVectorType FlattenedGlobalsVector; |
| 100 /// True if the module was modified during the "flatten globals" pass. |
| 101 bool Modified; |
| 102 /// The type model of a byte. |
| 103 Type *ByteType; |
| 104 /// The type model of the integer pointer type. |
| 105 Type *IntPtrType; |
| 106 /// The size of the pointer type. |
| 107 unsigned PtrSize; |
| 108 |
| 109 explicit FlattenGlobalsState(Module &M) |
| 110 : M(M), DL(&M), RelocMap(), |
| 111 Modified(false), |
| 112 ByteType(Type::getInt8Ty(M.getContext())), |
| 113 IntPtrType(DL.getIntPtrType(M.getContext())), |
| 114 PtrSize(DL.getPointerSize()) |
| 115 {} |
| 116 |
| 117 ~FlattenGlobalsState() { |
| 118 // Remove added user handles. |
| 119 for (RelocMapType::iterator |
| 120 I = RelocMap.begin(), E = RelocMap.end(); I != E; ++I) { |
| 121 delete I->second; |
| 122 } |
| 123 // Remove flatteners for global varaibles. |
| 124 DeleteContainerPointers(FlattenedGlobalsVector); |
| 125 } |
| 126 |
| 127 /// Collect Global variables whose initializers should be |
| 128 /// flattened. Creates corresponding flattened initializers (if |
| 129 /// applicable), and creates uninitialized replacement global |
| 130 /// variables. |
| 131 void flattenGlobalsWithInitializers(); |
| 132 |
| 133 /// Remove initializers from original global variables, and |
| 134 /// then remove the portions of the initializers that are |
| 135 /// no longer used. |
| 136 void removeDeadInitializerConstants(); |
| 137 |
| 138 // Replace the original global variables with their flattened |
| 139 // global variable counterparts. |
| 140 void replaceGlobalsWithFlattenedGlobals(); |
| 141 |
| 142 // Builds and installs initializers for flattened global |
| 143 // variables, based on the flattened initializers of the |
| 144 // corresponding original global variables. |
| 145 void installFlattenedGlobalInitializers(); |
| 146 |
| 147 // Returns the user handle associated with the reloc, so that it |
| 148 // won't be deleted during the flattening process. |
| 149 RelocUserType *getRelocUserHandle(Constant *Reloc) { |
| 150 RelocUserType *RelocUser = RelocMap[Reloc]; |
| 151 if (RelocUser == NULL) { |
| 152 RelocUser = ReturnInst::Create(M.getContext(), Reloc); |
| 153 RelocMap[Reloc] = RelocUser; |
| 154 } |
| 155 return RelocUser; |
| 156 } |
| 157 }; |
| 158 |
| 159 // A FlattenedConstant represents a global variable initializer that |
| 160 // has been flattened and may be converted into the normal form. |
| 161 class FlattenedConstant { |
| 162 FlattenGlobalsState &State; |
| 163 |
| 164 // A flattened global variable initializer is represented as: |
| 165 // 1) an array of bytes; |
| 166 unsigned BufSize; |
| 167 uint8_t *Buf; |
| 168 uint8_t *BufEnd; |
| 169 |
| 170 // 2) an array of relocations. |
| 171 class Reloc { |
| 172 private: |
| 173 unsigned RelOffset; // Offset at which the relocation is to be applied. |
| 174 RelocUserType *RelocUser; |
| 175 public: |
| 176 |
| 177 unsigned getRelOffset() const { return RelOffset; } |
| 178 Constant *getRelocUse() const { return getRelocUseConstant(RelocUser); } |
| 179 Reloc(FlattenGlobalsState &State, unsigned RelOffset, Constant *NewVal) |
| 180 : RelOffset(RelOffset), RelocUser(State.getRelocUserHandle(NewVal)) {} |
| 181 |
| 182 explicit Reloc(const Reloc &R) |
| 183 : RelOffset(R.RelOffset), RelocUser(R.RelocUser) {} |
| 184 |
| 185 void operator=(const Reloc &R) { |
| 186 RelOffset = R.RelOffset; |
| 187 RelocUser = R.RelocUser; |
| 188 } |
| 189 }; |
| 190 typedef SmallVector<Reloc, 10> RelocArray; |
| 191 RelocArray Relocs; |
| 192 |
| 193 const DataLayout &getDataLayout() const { return State.DL; } |
| 194 |
| 195 Module &getModule() const { return State.M; } |
| 196 |
| 197 Type *getIntPtrType() const { return State.IntPtrType; } |
| 198 |
| 199 Type *getByteType() const { return State.ByteType; } |
| 200 |
| 201 unsigned getPtrSize() const { return State.PtrSize; } |
| 202 |
| 203 void putAtDest(Constant *Value, uint8_t *Dest); |
| 204 |
| 205 Constant *dataSlice(unsigned StartPos, unsigned EndPos) const { |
| 206 return ConstantDataArray::get( |
| 207 getModule().getContext(), |
| 208 ArrayRef<uint8_t>(Buf + StartPos, Buf + EndPos)); |
| 209 } |
| 210 |
| 211 Type *dataSliceType(unsigned StartPos, unsigned EndPos) const { |
| 212 return ArrayType::get(getByteType(), EndPos - StartPos); |
| 213 } |
| 214 |
| 215 public: |
| 216 FlattenedConstant(FlattenGlobalsState &State, Constant *Value): |
| 217 State(State), |
| 218 BufSize(getDataLayout().getTypeAllocSize(Value->getType())), |
| 219 Buf(new uint8_t[BufSize]), |
| 220 BufEnd(Buf + BufSize) { |
| 221 memset(Buf, 0, BufSize); |
| 222 putAtDest(Value, Buf); |
| 223 } |
| 224 |
| 225 ~FlattenedConstant() { |
| 226 delete[] Buf; |
| 227 } |
| 228 |
| 229 // Returns the corresponding flattened initializer. |
| 230 Constant *getAsNormalFormConstant() const; |
| 231 |
| 232 // Returns the type of the corresponding flattened initializer; |
| 233 Type *getAsNormalFormType() const; |
| 234 |
| 235 }; |
| 236 |
| 237 // Structure used to flatten a global variable. |
| 238 struct FlattenedGlobal { |
| 239 // The state of the flatten globals pass. |
| 240 FlattenGlobalsState &State; |
| 241 // The global variable to flatten. |
| 242 GlobalVariable *Global; |
| 243 // The replacement global variable, if known. |
| 244 GlobalVariable *NewGlobal; |
| 245 // True if Global has an initializer. |
| 246 bool HasInitializer; |
| 247 // The flattened initializer, if the initializer would not just be |
| 248 // filled with zeroes. |
| 249 FlattenedConstant *FlatConst; |
| 250 // The type of GlobalType, when used in an initializer. |
| 251 Type *GlobalType; |
| 252 // The size of the initializer. |
| 253 uint64_t Size; |
| 254 public: |
| 255 FlattenedGlobal(FlattenGlobalsState &State, GlobalVariable *Global) |
| 256 : State(State), |
| 257 Global(Global), |
| 258 NewGlobal(NULL), |
| 259 HasInitializer(Global->hasInitializer()), |
| 260 FlatConst(NULL), |
| 261 GlobalType(Global->getType()->getPointerElementType()), |
| 262 Size(GlobalType->isSized() |
| 263 ? getDataLayout().getTypeAllocSize(GlobalType) : 0) { |
| 264 Type *NewType = NULL; |
| 265 if (HasInitializer) { |
| 266 if (Global->getInitializer()->isNullValue()) { |
| 267 // Special case of NullValue. As an optimization, for large |
| 268 // BSS variables, avoid allocating a buffer that would only be filled |
| 269 // with zeros. |
| 270 NewType = ArrayType::get(getByteType(), Size); |
| 271 } else { |
| 272 FlatConst = new FlattenedConstant(State, Global->getInitializer()); |
| 273 NewType = FlatConst->getAsNormalFormType(); |
| 274 } |
| 275 } else { |
| 276 NewType = ArrayType::get(getByteType(), Size); |
| 277 } |
| 278 NewGlobal = new GlobalVariable(getModule(), NewType, |
| 279 Global->isConstant(), |
| 280 Global->getLinkage(), |
| 281 NULL, "", Global, |
| 282 Global->getThreadLocalMode()); |
| 283 NewGlobal->copyAttributesFrom(Global); |
| 284 if (NewGlobal->getAlignment() == 0 && GlobalType->isSized()) |
| 285 NewGlobal->setAlignment(getDataLayout(). |
| 286 getPrefTypeAlignment(GlobalType)); |
| 287 NewGlobal->setExternallyInitialized(Global->isExternallyInitialized()); |
| 288 NewGlobal->takeName(Global); |
| 289 } |
| 290 |
| 291 ~FlattenedGlobal() { |
| 292 delete FlatConst; |
| 293 } |
| 294 |
| 295 const DataLayout &getDataLayout() const { return State.DL; } |
| 296 |
| 297 Module &getModule() const { return State.M; } |
| 298 |
| 299 Type *getByteType() const { return State.ByteType; } |
| 300 |
| 301 // Removes the original initializer from the global variable to be |
| 302 // flattened, if applicable. |
| 303 void removeOriginalInitializer() { |
| 304 if (HasInitializer) Global->setInitializer(NULL); |
| 305 } |
| 306 |
| 307 // Replaces the original global variable with the corresponding |
| 308 // flattened global variable. |
| 309 void replaceGlobalWithFlattenedGlobal() { |
| 310 Global->replaceAllUsesWith( |
| 311 ConstantExpr::getBitCast(NewGlobal, Global->getType())); |
| 312 Global->eraseFromParent(); |
| 313 } |
| 314 |
| 315 // Installs flattened initializers to the corresponding flattened |
| 316 // global variable. |
| 317 void installFlattenedInitializer() { |
| 318 if (HasInitializer) { |
| 319 Constant *NewInit = NULL; |
| 320 if (FlatConst == NULL) { |
| 321 // Special case of NullValue. |
| 322 NewInit = ConstantAggregateZero::get(ArrayType::get(getByteType(), |
| 323 Size)); |
| 324 } else { |
| 325 NewInit = FlatConst->getAsNormalFormConstant(); |
| 326 } |
| 327 NewGlobal->setInitializer(NewInit); |
| 328 } |
| 329 } |
| 330 }; |
| 331 |
| 332 class FlattenGlobals : public ModulePass { |
| 333 public: |
| 334 static char ID; // Pass identification, replacement for typeid |
| 335 FlattenGlobals() : ModulePass(ID) { |
| 336 initializeFlattenGlobalsPass(*PassRegistry::getPassRegistry()); |
| 337 } |
| 338 |
| 339 virtual bool runOnModule(Module &M); |
| 340 }; |
| 341 } |
| 342 |
| 343 static void ExpandConstant(const DataLayout *DL, Constant *Val, |
| 344 Constant **ResultGlobal, uint64_t *ResultOffset) { |
| 345 if (isa<GlobalValue>(Val) || isa<BlockAddress>(Val)) { |
| 346 *ResultGlobal = Val; |
| 347 *ResultOffset = 0; |
| 348 } else if (isa<ConstantPointerNull>(Val)) { |
| 349 *ResultGlobal = NULL; |
| 350 *ResultOffset = 0; |
| 351 } else if (ConstantInt *CI = dyn_cast<ConstantInt>(Val)) { |
| 352 *ResultGlobal = NULL; |
| 353 *ResultOffset = CI->getZExtValue(); |
| 354 } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Val)) { |
| 355 ExpandConstant(DL, CE->getOperand(0), ResultGlobal, ResultOffset); |
| 356 if (CE->getOpcode() == Instruction::GetElementPtr) { |
| 357 SmallVector<Value *, 8> Indexes(CE->op_begin() + 1, CE->op_end()); |
| 358 *ResultOffset += DL->getIndexedOffset(CE->getOperand(0)->getType(), |
| 359 Indexes); |
| 360 } else if (CE->getOpcode() == Instruction::BitCast || |
| 361 CE->getOpcode() == Instruction::IntToPtr) { |
| 362 // Nothing more to do. |
| 363 } else if (CE->getOpcode() == Instruction::PtrToInt) { |
| 364 if (Val->getType()->getIntegerBitWidth() < DL->getPointerSizeInBits()) { |
| 365 errs() << "Not handled: " << *CE << "\n"; |
| 366 report_fatal_error("FlattenGlobals: a ptrtoint that truncates " |
| 367 "a pointer is not allowed"); |
| 368 } |
| 369 } else { |
| 370 errs() << "Not handled: " << *CE << "\n"; |
| 371 report_fatal_error( |
| 372 std::string("FlattenGlobals: ConstantExpr opcode not handled: ") |
| 373 + CE->getOpcodeName()); |
| 374 } |
| 375 } else { |
| 376 errs() << "Not handled: " << *Val << "\n"; |
| 377 report_fatal_error("FlattenGlobals: Constant type not handled for reloc"); |
| 378 } |
| 379 } |
| 380 |
| 381 void FlattenedConstant::putAtDest(Constant *Val, uint8_t *Dest) { |
| 382 uint64_t ValSize = getDataLayout().getTypeAllocSize(Val->getType()); |
| 383 assert(Dest + ValSize <= BufEnd); |
| 384 if (isa<ConstantAggregateZero>(Val) || |
| 385 isa<UndefValue>(Val) || |
| 386 isa<ConstantPointerNull>(Val)) { |
| 387 // The buffer is already zero-initialized. |
| 388 } else if (ConstantInt *CI = dyn_cast<ConstantInt>(Val)) { |
| 389 memcpy(Dest, CI->getValue().getRawData(), ValSize); |
| 390 } else if (ConstantFP *CF = dyn_cast<ConstantFP>(Val)) { |
| 391 APInt Data = CF->getValueAPF().bitcastToAPInt(); |
| 392 assert((Data.getBitWidth() + 7) / 8 == ValSize); |
| 393 assert(Data.getBitWidth() % 8 == 0); |
| 394 memcpy(Dest, Data.getRawData(), ValSize); |
| 395 } else if (ConstantDataSequential *CD = |
| 396 dyn_cast<ConstantDataSequential>(Val)) { |
| 397 // Note that getRawDataValues() assumes the host endianness is the same. |
| 398 StringRef Data = CD->getRawDataValues(); |
| 399 assert(Data.size() == ValSize); |
| 400 memcpy(Dest, Data.data(), Data.size()); |
| 401 } else if (isa<ConstantArray>(Val) || isa<ConstantDataVector>(Val) || |
| 402 isa<ConstantVector>(Val)) { |
| 403 uint64_t ElementSize = getDataLayout().getTypeAllocSize( |
| 404 Val->getType()->getSequentialElementType()); |
| 405 for (unsigned I = 0; I < Val->getNumOperands(); ++I) { |
| 406 putAtDest(cast<Constant>(Val->getOperand(I)), Dest + ElementSize * I); |
| 407 } |
| 408 } else if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Val)) { |
| 409 const StructLayout *Layout = getDataLayout().getStructLayout(CS->getType()); |
| 410 for (unsigned I = 0; I < CS->getNumOperands(); ++I) { |
| 411 putAtDest(CS->getOperand(I), Dest + Layout->getElementOffset(I)); |
| 412 } |
| 413 } else { |
| 414 Constant *GV; |
| 415 uint64_t Offset; |
| 416 ExpandConstant(&getDataLayout(), Val, &GV, &Offset); |
| 417 if (GV) { |
| 418 Constant *NewVal = ConstantExpr::getPtrToInt(GV, getIntPtrType()); |
| 419 if (Offset) { |
| 420 // For simplicity, require addends to be 32-bit. |
| 421 if ((int64_t) Offset != (int32_t) (uint32_t) Offset) { |
| 422 errs() << "Not handled: " << *Val << "\n"; |
| 423 report_fatal_error( |
| 424 "FlattenGlobals: Offset does not fit into 32 bits"); |
| 425 } |
| 426 NewVal = ConstantExpr::getAdd( |
| 427 NewVal, ConstantInt::get(getIntPtrType(), Offset, |
| 428 /* isSigned= */ true)); |
| 429 } |
| 430 Reloc NewRel(State, Dest - Buf, NewVal); |
| 431 Relocs.push_back(NewRel); |
| 432 } else { |
| 433 memcpy(Dest, &Offset, ValSize); |
| 434 } |
| 435 } |
| 436 } |
| 437 |
| 438 Constant *FlattenedConstant::getAsNormalFormConstant() const { |
| 439 // Return a single SimpleElement. |
| 440 if (Relocs.size() == 0) |
| 441 return dataSlice(0, BufSize); |
| 442 if (Relocs.size() == 1 && BufSize == getPtrSize()) { |
| 443 assert(Relocs[0].getRelOffset() == 0); |
| 444 return Relocs[0].getRelocUse(); |
| 445 } |
| 446 |
| 447 // Return a CompoundElement. |
| 448 SmallVector<Constant *, 10> Elements; |
| 449 unsigned PrevPos = 0; |
| 450 for (RelocArray::const_iterator Rel = Relocs.begin(), E = Relocs.end(); |
| 451 Rel != E; ++Rel) { |
| 452 if (Rel->getRelOffset() > PrevPos) |
| 453 Elements.push_back(dataSlice(PrevPos, Rel->getRelOffset())); |
| 454 Elements.push_back(Rel->getRelocUse()); |
| 455 PrevPos = Rel->getRelOffset() + getPtrSize(); |
| 456 } |
| 457 if (PrevPos < BufSize) |
| 458 Elements.push_back(dataSlice(PrevPos, BufSize)); |
| 459 return ConstantStruct::getAnon(getModule().getContext(), Elements, true); |
| 460 } |
| 461 |
| 462 Type *FlattenedConstant::getAsNormalFormType() const { |
| 463 // Return a single element type. |
| 464 if (Relocs.size() == 0) |
| 465 return dataSliceType(0, BufSize); |
| 466 if (Relocs.size() == 1 && BufSize == getPtrSize()) { |
| 467 assert(Relocs[0].getRelOffset() == 0); |
| 468 return Relocs[0].getRelocUse()->getType(); |
| 469 } |
| 470 |
| 471 // Return a compound type. |
| 472 SmallVector<Type *, 10> Elements; |
| 473 unsigned PrevPos = 0; |
| 474 for (RelocArray::const_iterator Rel = Relocs.begin(), E = Relocs.end(); |
| 475 Rel != E; ++Rel) { |
| 476 if (Rel->getRelOffset() > PrevPos) |
| 477 Elements.push_back(dataSliceType(PrevPos, Rel->getRelOffset())); |
| 478 Elements.push_back(Rel->getRelocUse()->getType()); |
| 479 PrevPos = Rel->getRelOffset() + getPtrSize(); |
| 480 } |
| 481 if (PrevPos < BufSize) |
| 482 Elements.push_back(dataSliceType(PrevPos, BufSize)); |
| 483 return StructType::get(getModule().getContext(), Elements, true); |
| 484 } |
| 485 |
| 486 char FlattenGlobals::ID = 0; |
| 487 INITIALIZE_PASS(FlattenGlobals, "flatten-globals", |
| 488 "Flatten global variable initializers into byte arrays", |
| 489 false, false) |
| 490 |
| 491 void FlattenGlobalsState::flattenGlobalsWithInitializers() { |
| 492 for (Module::global_iterator I = M.global_begin(), E = M.global_end(); |
| 493 I != E;) { |
| 494 GlobalVariable *Global = I++; |
| 495 // Variables with "appending" linkage must always be arrays and so |
| 496 // cannot be normalized, so leave them alone. |
| 497 if (Global->hasAppendingLinkage()) |
| 498 continue; |
| 499 Modified = true; |
| 500 FlattenedGlobalsVector.push_back(new FlattenedGlobal(*this, Global)); |
| 501 } |
| 502 } |
| 503 |
| 504 void FlattenGlobalsState::removeDeadInitializerConstants() { |
| 505 // Detach original initializers. |
| 506 for (FlattenedGlobalsVectorType::iterator |
| 507 I = FlattenedGlobalsVector.begin(), E = FlattenedGlobalsVector.end(); |
| 508 I != E; ++I) { |
| 509 (*I)->removeOriginalInitializer(); |
| 510 } |
| 511 // Do cleanup of old initializers. |
| 512 for (RelocMapType::iterator I = RelocMap.begin(), E = RelocMap.end(); |
| 513 I != E; ++I) { |
| 514 getRelocUseConstant(I->second)->removeDeadConstantUsers(); |
| 515 } |
| 516 |
| 517 } |
| 518 |
| 519 void FlattenGlobalsState::replaceGlobalsWithFlattenedGlobals() { |
| 520 for (FlattenedGlobalsVectorType::iterator |
| 521 I = FlattenedGlobalsVector.begin(), E = FlattenedGlobalsVector.end(); |
| 522 I != E; ++I) { |
| 523 (*I)->replaceGlobalWithFlattenedGlobal(); |
| 524 } |
| 525 } |
| 526 |
| 527 void FlattenGlobalsState::installFlattenedGlobalInitializers() { |
| 528 for (FlattenedGlobalsVectorType::iterator |
| 529 I = FlattenedGlobalsVector.begin(), E = FlattenedGlobalsVector.end(); |
| 530 I != E; ++I) { |
| 531 (*I)->installFlattenedInitializer(); |
| 532 } |
| 533 } |
| 534 |
| 535 bool FlattenGlobals::runOnModule(Module &M) { |
| 536 FlattenGlobalsState State(M); |
| 537 State.flattenGlobalsWithInitializers(); |
| 538 State.removeDeadInitializerConstants(); |
| 539 State.replaceGlobalsWithFlattenedGlobals(); |
| 540 State.installFlattenedGlobalInitializers(); |
| 541 return State.Modified; |
| 542 } |
| 543 |
| 544 ModulePass *llvm::createFlattenGlobalsPass() { |
| 545 return new FlattenGlobals(); |
| 546 } |
OLD | NEW |