1234285Sdim//===-- ModuleUtils.cpp - Functions to manipulate Modules -----------------===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim// 10234285Sdim// This family of functions perform manipulations on Modules. 11234285Sdim// 12234285Sdim//===----------------------------------------------------------------------===// 13234285Sdim 14234285Sdim#include "llvm/Transforms/Utils/ModuleUtils.h" 15263509Sdim#include "llvm/ADT/SmallPtrSet.h" 16252723Sdim#include "llvm/IR/DerivedTypes.h" 17252723Sdim#include "llvm/IR/Function.h" 18252723Sdim#include "llvm/IR/IRBuilder.h" 19252723Sdim#include "llvm/IR/Module.h" 20234285Sdim 21234285Sdimusing namespace llvm; 22234285Sdim 23234285Sdimstatic void appendToGlobalArray(const char *Array, 24234285Sdim Module &M, Function *F, int Priority) { 25234285Sdim IRBuilder<> IRB(M.getContext()); 26234285Sdim FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false); 27234285Sdim StructType *Ty = StructType::get( 28234285Sdim IRB.getInt32Ty(), PointerType::getUnqual(FnTy), NULL); 29234285Sdim 30234285Sdim Constant *RuntimeCtorInit = ConstantStruct::get( 31234285Sdim Ty, IRB.getInt32(Priority), F, NULL); 32234285Sdim 33234285Sdim // Get the current set of static global constructors and add the new ctor 34234285Sdim // to the list. 35234285Sdim SmallVector<Constant *, 16> CurrentCtors; 36234285Sdim if (GlobalVariable * GVCtor = M.getNamedGlobal(Array)) { 37234285Sdim if (Constant *Init = GVCtor->getInitializer()) { 38234285Sdim unsigned n = Init->getNumOperands(); 39234285Sdim CurrentCtors.reserve(n + 1); 40234285Sdim for (unsigned i = 0; i != n; ++i) 41234285Sdim CurrentCtors.push_back(cast<Constant>(Init->getOperand(i))); 42234285Sdim } 43234285Sdim GVCtor->eraseFromParent(); 44234285Sdim } 45234285Sdim 46234285Sdim CurrentCtors.push_back(RuntimeCtorInit); 47234285Sdim 48234285Sdim // Create a new initializer. 49234285Sdim ArrayType *AT = ArrayType::get(RuntimeCtorInit->getType(), 50234285Sdim CurrentCtors.size()); 51234285Sdim Constant *NewInit = ConstantArray::get(AT, CurrentCtors); 52234285Sdim 53234285Sdim // Create the new global variable and replace all uses of 54234285Sdim // the old global variable with the new one. 55234285Sdim (void)new GlobalVariable(M, NewInit->getType(), false, 56234285Sdim GlobalValue::AppendingLinkage, NewInit, Array); 57234285Sdim} 58234285Sdim 59234285Sdimvoid llvm::appendToGlobalCtors(Module &M, Function *F, int Priority) { 60234285Sdim appendToGlobalArray("llvm.global_ctors", M, F, Priority); 61234285Sdim} 62234285Sdim 63234285Sdimvoid llvm::appendToGlobalDtors(Module &M, Function *F, int Priority) { 64234285Sdim appendToGlobalArray("llvm.global_dtors", M, F, Priority); 65234285Sdim} 66263509Sdim 67263509SdimGlobalVariable * 68263509Sdimllvm::collectUsedGlobalVariables(Module &M, SmallPtrSet<GlobalValue *, 8> &Set, 69263509Sdim bool CompilerUsed) { 70263509Sdim const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used"; 71263509Sdim GlobalVariable *GV = M.getGlobalVariable(Name); 72263509Sdim if (!GV || !GV->hasInitializer()) 73263509Sdim return GV; 74263509Sdim 75263509Sdim const ConstantArray *Init = cast<ConstantArray>(GV->getInitializer()); 76263509Sdim for (unsigned I = 0, E = Init->getNumOperands(); I != E; ++I) { 77263509Sdim Value *Op = Init->getOperand(I); 78263509Sdim GlobalValue *G = cast<GlobalValue>(Op->stripPointerCastsNoFollowAliases()); 79263509Sdim Set.insert(G); 80263509Sdim } 81263509Sdim return GV; 82263509Sdim} 83