12ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel//===-- ModuleUtils.cpp - Functions to manipulate Modules -----------------===//
22ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel//
32ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel//                     The LLVM Compiler Infrastructure
42ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel//
52ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel// This file is distributed under the University of Illinois Open Source
62ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel// License. See LICENSE.TXT for details.
72ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel//
82ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel//===----------------------------------------------------------------------===//
92ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel//
102ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel// This family of functions perform manipulations on Modules.
112ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel//
122ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel//===----------------------------------------------------------------------===//
132ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel
142ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel#include "llvm/Transforms/Utils/ModuleUtils.h"
154ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola#include "llvm/ADT/SmallPtrSet.h"
160b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DerivedTypes.h"
170b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Function.h"
180b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/IRBuilder.h"
190b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Module.h"
20a2a2d1fddd0c2de82fb90be8fb1e0ec2ed6c44acKostya Serebryany
212ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patelusing namespace llvm;
222ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel
237bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryanystatic void appendToGlobalArray(const char *Array,
247bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany                                Module &M, Function *F, int Priority) {
252ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  IRBuilder<> IRB(M.getContext());
262ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false);
272ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  StructType *Ty = StructType::get(
282ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel      IRB.getInt32Ty(), PointerType::getUnqual(FnTy), NULL);
292ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel
302ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  Constant *RuntimeCtorInit = ConstantStruct::get(
312ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel      Ty, IRB.getInt32(Priority), F, NULL);
322ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel
332ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  // Get the current set of static global constructors and add the new ctor
342ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  // to the list.
352ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  SmallVector<Constant *, 16> CurrentCtors;
367bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany  if (GlobalVariable * GVCtor = M.getNamedGlobal(Array)) {
372ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel    if (Constant *Init = GVCtor->getInitializer()) {
382ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel      unsigned n = Init->getNumOperands();
392ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel      CurrentCtors.reserve(n + 1);
402ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel      for (unsigned i = 0; i != n; ++i)
412ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel        CurrentCtors.push_back(cast<Constant>(Init->getOperand(i)));
422ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel    }
432ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel    GVCtor->eraseFromParent();
442ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  }
452ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel
462ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  CurrentCtors.push_back(RuntimeCtorInit);
472ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel
482ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  // Create a new initializer.
492ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  ArrayType *AT = ArrayType::get(RuntimeCtorInit->getType(),
502ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel                                 CurrentCtors.size());
512ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  Constant *NewInit = ConstantArray::get(AT, CurrentCtors);
522ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel
532ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  // Create the new global variable and replace all uses of
542ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  // the old global variable with the new one.
552ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel  (void)new GlobalVariable(M, NewInit->getType(), false,
567bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany                           GlobalValue::AppendingLinkage, NewInit, Array);
577bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany}
587bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany
597bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryanyvoid llvm::appendToGlobalCtors(Module &M, Function *F, int Priority) {
607bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany  appendToGlobalArray("llvm.global_ctors", M, F, Priority);
617bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany}
627bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany
637bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryanyvoid llvm::appendToGlobalDtors(Module &M, Function *F, int Priority) {
647bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany  appendToGlobalArray("llvm.global_dtors", M, F, Priority);
652ad3f93b5f1d6e22f682efd6fd10f7f3ed9fa992Devang Patel}
664ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola
674ef7eafa3f823443d1b8921f6020d946612281dbRafael EspindolaGlobalVariable *
684ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindolallvm::collectUsedGlobalVariables(Module &M, SmallPtrSet<GlobalValue *, 8> &Set,
694ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola                                 bool CompilerUsed) {
704ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used";
714ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  GlobalVariable *GV = M.getGlobalVariable(Name);
724ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  if (!GV || !GV->hasInitializer())
734ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola    return GV;
744ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola
754ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  const ConstantArray *Init = cast<ConstantArray>(GV->getInitializer());
764ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  for (unsigned I = 0, E = Init->getNumOperands(); I != E; ++I) {
774ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola    Value *Op = Init->getOperand(I);
784ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola    GlobalValue *G = cast<GlobalValue>(Op->stripPointerCastsNoFollowAliases());
794ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola    Set.insert(G);
804ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  }
814ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola  return GV;
824ef7eafa3f823443d1b8921f6020d946612281dbRafael Espindola}
83