1dff0c46cSDimitry Andric //===-- ModuleUtils.cpp - Functions to manipulate Modules -----------------===//
2dff0c46cSDimitry Andric //
3dff0c46cSDimitry Andric //                     The LLVM Compiler Infrastructure
4dff0c46cSDimitry Andric //
5dff0c46cSDimitry Andric // This file is distributed under the University of Illinois Open Source
6dff0c46cSDimitry Andric // License. See LICENSE.TXT for details.
7dff0c46cSDimitry Andric //
8dff0c46cSDimitry Andric //===----------------------------------------------------------------------===//
9dff0c46cSDimitry Andric //
10dff0c46cSDimitry Andric // This family of functions perform manipulations on Modules.
11dff0c46cSDimitry Andric //
12dff0c46cSDimitry Andric //===----------------------------------------------------------------------===//
13dff0c46cSDimitry Andric 
14dff0c46cSDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
15f785676fSDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
16139f7f9bSDimitry Andric #include "llvm/IR/DerivedTypes.h"
17139f7f9bSDimitry Andric #include "llvm/IR/Function.h"
18139f7f9bSDimitry Andric #include "llvm/IR/IRBuilder.h"
19139f7f9bSDimitry Andric #include "llvm/IR/Module.h"
20dff0c46cSDimitry Andric 
21dff0c46cSDimitry Andric using namespace llvm;
22dff0c46cSDimitry Andric 
23dff0c46cSDimitry Andric static void appendToGlobalArray(const char *Array,
24dff0c46cSDimitry Andric                                 Module &M, Function *F, int Priority) {
25dff0c46cSDimitry Andric   IRBuilder<> IRB(M.getContext());
26dff0c46cSDimitry Andric   FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false);
27dff0c46cSDimitry Andric 
28dff0c46cSDimitry Andric   // Get the current set of static global constructors and add the new ctor
29dff0c46cSDimitry Andric   // to the list.
30dff0c46cSDimitry Andric   SmallVector<Constant *, 16> CurrentCtors;
3191bc56edSDimitry Andric   StructType *EltTy;
32dff0c46cSDimitry Andric   if (GlobalVariable *GVCtor = M.getNamedGlobal(Array)) {
3391bc56edSDimitry Andric     // If there is a global_ctors array, use the existing struct type, which can
3491bc56edSDimitry Andric     // have 2 or 3 fields.
3591bc56edSDimitry Andric     ArrayType *ATy = cast<ArrayType>(GVCtor->getType()->getElementType());
3691bc56edSDimitry Andric     EltTy = cast<StructType>(ATy->getElementType());
37dff0c46cSDimitry Andric     if (Constant *Init = GVCtor->getInitializer()) {
38dff0c46cSDimitry Andric       unsigned n = Init->getNumOperands();
39dff0c46cSDimitry Andric       CurrentCtors.reserve(n + 1);
40dff0c46cSDimitry Andric       for (unsigned i = 0; i != n; ++i)
41dff0c46cSDimitry Andric         CurrentCtors.push_back(cast<Constant>(Init->getOperand(i)));
42dff0c46cSDimitry Andric     }
43dff0c46cSDimitry Andric     GVCtor->eraseFromParent();
4491bc56edSDimitry Andric   } else {
4591bc56edSDimitry Andric     // Use a simple two-field struct if there isn't one already.
4691bc56edSDimitry Andric     EltTy = StructType::get(IRB.getInt32Ty(), PointerType::getUnqual(FnTy),
4791bc56edSDimitry Andric                             nullptr);
48dff0c46cSDimitry Andric   }
49dff0c46cSDimitry Andric 
5091bc56edSDimitry Andric   // Build a 2 or 3 field global_ctor entry.  We don't take a comdat key.
5191bc56edSDimitry Andric   Constant *CSVals[3];
5291bc56edSDimitry Andric   CSVals[0] = IRB.getInt32(Priority);
5391bc56edSDimitry Andric   CSVals[1] = F;
5491bc56edSDimitry Andric   // FIXME: Drop support for the two element form in LLVM 4.0.
5591bc56edSDimitry Andric   if (EltTy->getNumElements() >= 3)
5691bc56edSDimitry Andric     CSVals[2] = llvm::Constant::getNullValue(IRB.getInt8PtrTy());
5791bc56edSDimitry Andric   Constant *RuntimeCtorInit =
5891bc56edSDimitry Andric       ConstantStruct::get(EltTy, makeArrayRef(CSVals, EltTy->getNumElements()));
5991bc56edSDimitry Andric 
60dff0c46cSDimitry Andric   CurrentCtors.push_back(RuntimeCtorInit);
61dff0c46cSDimitry Andric 
62dff0c46cSDimitry Andric   // Create a new initializer.
6391bc56edSDimitry Andric   ArrayType *AT = ArrayType::get(EltTy, CurrentCtors.size());
64dff0c46cSDimitry Andric   Constant *NewInit = ConstantArray::get(AT, CurrentCtors);
65dff0c46cSDimitry Andric 
66dff0c46cSDimitry Andric   // Create the new global variable and replace all uses of
67dff0c46cSDimitry Andric   // the old global variable with the new one.
68dff0c46cSDimitry Andric   (void)new GlobalVariable(M, NewInit->getType(), false,
69dff0c46cSDimitry Andric                            GlobalValue::AppendingLinkage, NewInit, Array);
70dff0c46cSDimitry Andric }
71dff0c46cSDimitry Andric 
72dff0c46cSDimitry Andric void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority) {
73dff0c46cSDimitry Andric   appendToGlobalArray("llvm.global_ctors", M, F, Priority);
74dff0c46cSDimitry Andric }
75dff0c46cSDimitry Andric 
76dff0c46cSDimitry Andric void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority) {
77dff0c46cSDimitry Andric   appendToGlobalArray("llvm.global_dtors", M, F, Priority);
78dff0c46cSDimitry Andric }
79f785676fSDimitry Andric 
80f785676fSDimitry Andric GlobalVariable *
81f785676fSDimitry Andric llvm::collectUsedGlobalVariables(Module &M, SmallPtrSet<GlobalValue *, 8> &Set,
82f785676fSDimitry Andric                                  bool CompilerUsed) {
83f785676fSDimitry Andric   const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used";
84f785676fSDimitry Andric   GlobalVariable *GV = M.getGlobalVariable(Name);
85f785676fSDimitry Andric   if (!GV || !GV->hasInitializer())
86f785676fSDimitry Andric     return GV;
87f785676fSDimitry Andric 
88f785676fSDimitry Andric   const ConstantArray *Init = cast<ConstantArray>(GV->getInitializer());
89f785676fSDimitry Andric   for (unsigned I = 0, E = Init->getNumOperands(); I != E; ++I) {
90f785676fSDimitry Andric     Value *Op = Init->getOperand(I);
91f785676fSDimitry Andric     GlobalValue *G = cast<GlobalValue>(Op->stripPointerCastsNoFollowAliases());
92f785676fSDimitry Andric     Set.insert(G);
93f785676fSDimitry Andric   }
94f785676fSDimitry Andric   return GV;
95f785676fSDimitry Andric }
96