1 //===-- ModuleUtils.cpp - Functions to manipulate Modules -----------------===// 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 family of functions perform manipulations on Modules. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Transforms/Utils/ModuleUtils.h" 15 #include "llvm/ADT/SmallPtrSet.h" 16 #include "llvm/IR/DerivedTypes.h" 17 #include "llvm/IR/Function.h" 18 #include "llvm/IR/IRBuilder.h" 19 #include "llvm/IR/Module.h" 20 21 using namespace llvm; 22 23 static void appendToGlobalArray(const char *Array, 24 Module &M, Function *F, int Priority) { 25 IRBuilder<> IRB(M.getContext()); 26 FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false); 27 StructType *Ty = StructType::get( 28 IRB.getInt32Ty(), PointerType::getUnqual(FnTy), NULL); 29 30 Constant *RuntimeCtorInit = ConstantStruct::get( 31 Ty, IRB.getInt32(Priority), F, NULL); 32 33 // Get the current set of static global constructors and add the new ctor 34 // to the list. 35 SmallVector<Constant *, 16> CurrentCtors; 36 if (GlobalVariable * GVCtor = M.getNamedGlobal(Array)) { 37 if (Constant *Init = GVCtor->getInitializer()) { 38 unsigned n = Init->getNumOperands(); 39 CurrentCtors.reserve(n + 1); 40 for (unsigned i = 0; i != n; ++i) 41 CurrentCtors.push_back(cast<Constant>(Init->getOperand(i))); 42 } 43 GVCtor->eraseFromParent(); 44 } 45 46 CurrentCtors.push_back(RuntimeCtorInit); 47 48 // Create a new initializer. 49 ArrayType *AT = ArrayType::get(RuntimeCtorInit->getType(), 50 CurrentCtors.size()); 51 Constant *NewInit = ConstantArray::get(AT, CurrentCtors); 52 53 // Create the new global variable and replace all uses of 54 // the old global variable with the new one. 55 (void)new GlobalVariable(M, NewInit->getType(), false, 56 GlobalValue::AppendingLinkage, NewInit, Array); 57 } 58 59 void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority) { 60 appendToGlobalArray("llvm.global_ctors", M, F, Priority); 61 } 62 63 void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority) { 64 appendToGlobalArray("llvm.global_dtors", M, F, Priority); 65 } 66 67 GlobalVariable * 68 llvm::collectUsedGlobalVariables(Module &M, SmallPtrSet<GlobalValue *, 8> &Set, 69 bool CompilerUsed) { 70 const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used"; 71 GlobalVariable *GV = M.getGlobalVariable(Name); 72 if (!GV || !GV->hasInitializer()) 73 return GV; 74 75 const ConstantArray *Init = cast<ConstantArray>(GV->getInitializer()); 76 for (unsigned I = 0, E = Init->getNumOperands(); I != E; ++I) { 77 Value *Op = Init->getOperand(I); 78 GlobalValue *G = cast<GlobalValue>(Op->stripPointerCastsNoFollowAliases()); 79 Set.insert(G); 80 } 81 return GV; 82 } 83