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 21using namespace llvm; 22 23static 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 59void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority) { 60 appendToGlobalArray("llvm.global_ctors", M, F, Priority); 61} 62 63void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority) { 64 appendToGlobalArray("llvm.global_dtors", M, F, Priority); 65} 66 67GlobalVariable * 68llvm::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