LCOV - code coverage report
Current view: top level - lib/CodeGen - LowerEmuTLS.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 20 58 34.5 %
Date: 2018-10-20 13:21:21 Functions: 5 6 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- LowerEmuTLS.cpp - Add __emutls_[vt].* variables --------------------===//
       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 transformation is required for targets depending on libgcc style
      11             : // emulated thread local storage variables. For every defined TLS variable xyz,
      12             : // an __emutls_v.xyz is generated. If there is non-zero initialized value
      13             : // an __emutls_t.xyz is also generated.
      14             : //
      15             : //===----------------------------------------------------------------------===//
      16             : 
      17             : #include "llvm/ADT/SmallVector.h"
      18             : #include "llvm/CodeGen/Passes.h"
      19             : #include "llvm/CodeGen/TargetLowering.h"
      20             : #include "llvm/CodeGen/TargetPassConfig.h"
      21             : #include "llvm/IR/LLVMContext.h"
      22             : #include "llvm/IR/Module.h"
      23             : #include "llvm/Pass.h"
      24             : 
      25             : using namespace llvm;
      26             : 
      27             : #define DEBUG_TYPE "loweremutls"
      28             : 
      29             : namespace {
      30             : 
      31             : class LowerEmuTLS : public ModulePass {
      32             : public:
      33             :   static char ID; // Pass identification, replacement for typeid
      34         433 :   LowerEmuTLS() : ModulePass(ID) {
      35         433 :     initializeLowerEmuTLSPass(*PassRegistry::getPassRegistry());
      36             :   }
      37             : 
      38             :   bool runOnModule(Module &M) override;
      39             : private:
      40             :   bool addEmuTlsVar(Module &M, const GlobalVariable *GV);
      41         405 :   static void copyLinkageVisibility(Module &M,
      42             :                                     const GlobalVariable *from,
      43             :                                     GlobalVariable *to) {
      44             :     to->setLinkage(from->getLinkage());
      45             :     to->setVisibility(from->getVisibility());
      46         405 :     if (from->hasComdat()) {
      47           6 :       to->setComdat(M.getOrInsertComdat(to->getName()));
      48           6 :       to->getComdat()->setSelectionKind(from->getComdat()->getSelectionKind());
      49             :     }
      50         405 :   }
      51             : };
      52             : }
      53             : 
      54             : char LowerEmuTLS::ID = 0;
      55             : 
      56         811 : INITIALIZE_PASS(LowerEmuTLS, DEBUG_TYPE,
      57             :                 "Add __emutls_[vt]. variables for emultated TLS model", false,
      58             :                 false)
      59             : 
      60         433 : ModulePass *llvm::createLowerEmuTLSPass() { return new LowerEmuTLS(); }
      61             : 
      62         433 : bool LowerEmuTLS::runOnModule(Module &M) {
      63         433 :   if (skipModule(M))
      64             :     return false;
      65             : 
      66         433 :   auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
      67         433 :   if (!TPC)
      68             :     return false;
      69             : 
      70         433 :   auto &TM = TPC->getTM<TargetMachine>();
      71         433 :   if (!TM.useEmulatedTLS())
      72             :     return false;
      73             : 
      74             :   bool Changed = false;
      75             :   SmallVector<const GlobalVariable*, 8> TlsVars;
      76         951 :   for (const auto &G : M.globals()) {
      77         518 :     if (G.isThreadLocal())
      78         256 :       TlsVars.append({&G});
      79             :   }
      80         689 :   for (const auto G : TlsVars)
      81         256 :     Changed |= addEmuTlsVar(M, G);
      82             :   return Changed;
      83             : }
      84             : 
      85           0 : bool LowerEmuTLS::addEmuTlsVar(Module &M, const GlobalVariable *GV) {
      86           0 :   LLVMContext &C = M.getContext();
      87           0 :   PointerType *VoidPtrType = Type::getInt8PtrTy(C);
      88             : 
      89           0 :   std::string EmuTlsVarName = ("__emutls_v." + GV->getName()).str();
      90             :   GlobalVariable *EmuTlsVar = M.getNamedGlobal(EmuTlsVarName);
      91           0 :   if (EmuTlsVar)
      92           0 :     return false;  // It has been added before.
      93             : 
      94           0 :   const DataLayout &DL = M.getDataLayout();
      95           0 :   Constant *NullPtr = ConstantPointerNull::get(VoidPtrType);
      96             : 
      97             :   // Get non-zero initializer from GV's initializer.
      98             :   const Constant *InitValue = nullptr;
      99           0 :   if (GV->hasInitializer()) {
     100             :     InitValue = GV->getInitializer();
     101             :     const ConstantInt *InitIntValue = dyn_cast<ConstantInt>(InitValue);
     102             :     // When GV's init value is all 0, omit the EmuTlsTmplVar and let
     103             :     // the emutls library function to reset newly allocated TLS variables.
     104           0 :     if (isa<ConstantAggregateZero>(InitValue) ||
     105           0 :         (InitIntValue && InitIntValue->isZero()))
     106             :       InitValue = nullptr;
     107             :   }
     108             : 
     109             :   // Create the __emutls_v. symbol, whose type has 4 fields:
     110             :   //     word size;   // size of GV in bytes
     111             :   //     word align;  // alignment of GV
     112             :   //     void *ptr;   // initialized to 0; set at run time per thread.
     113             :   //     void *templ; // 0 or point to __emutls_t.*
     114             :   // sizeof(word) should be the same as sizeof(void*) on target.
     115           0 :   IntegerType *WordType = DL.getIntPtrType(C);
     116           0 :   PointerType *InitPtrType = InitValue ?
     117           0 :       PointerType::getUnqual(InitValue->getType()) : VoidPtrType;
     118           0 :   Type *ElementTypes[4] = {WordType, WordType, VoidPtrType, InitPtrType};
     119             :   ArrayRef<Type*> ElementTypeArray(ElementTypes, 4);
     120           0 :   StructType *EmuTlsVarType = StructType::create(ElementTypeArray);
     121           0 :   EmuTlsVar = cast<GlobalVariable>(
     122             :       M.getOrInsertGlobal(EmuTlsVarName, EmuTlsVarType));
     123           0 :   copyLinkageVisibility(M, GV, EmuTlsVar);
     124             : 
     125             :   // Define "__emutls_t.*" and "__emutls_v.*" only if GV is defined.
     126           0 :   if (!GV->hasInitializer())
     127           0 :     return true;
     128             : 
     129           0 :   Type *GVType = GV->getValueType();
     130             :   unsigned GVAlignment = GV->getAlignment();
     131           0 :   if (!GVAlignment) {
     132             :     // When LLVM IL declares a variable without alignment, use
     133             :     // the ABI default alignment for the type.
     134           0 :     GVAlignment = DL.getABITypeAlignment(GVType);
     135             :   }
     136             : 
     137             :   // Define "__emutls_t.*" if there is InitValue
     138             :   GlobalVariable *EmuTlsTmplVar = nullptr;
     139           0 :   if (InitValue) {
     140           0 :     std::string EmuTlsTmplName = ("__emutls_t." + GV->getName()).str();
     141           0 :     EmuTlsTmplVar = dyn_cast_or_null<GlobalVariable>(
     142             :         M.getOrInsertGlobal(EmuTlsTmplName, GVType));
     143             :     assert(EmuTlsTmplVar && "Failed to create emualted TLS initializer");
     144             :     EmuTlsTmplVar->setConstant(true);
     145           0 :     EmuTlsTmplVar->setInitializer(const_cast<Constant*>(InitValue));
     146           0 :     EmuTlsTmplVar->setAlignment(GVAlignment);
     147           0 :     copyLinkageVisibility(M, GV, EmuTlsTmplVar);
     148             :   }
     149             : 
     150             :   // Define "__emutls_v.*" with initializer and alignment.
     151             :   Constant *ElementValues[4] = {
     152           0 :       ConstantInt::get(WordType, DL.getTypeStoreSize(GVType)),
     153           0 :       ConstantInt::get(WordType, GVAlignment),
     154           0 :       NullPtr, EmuTlsTmplVar ? EmuTlsTmplVar : NullPtr
     155           0 :   };
     156             :   ArrayRef<Constant*> ElementValueArray(ElementValues, 4);
     157           0 :   EmuTlsVar->setInitializer(
     158             :       ConstantStruct::get(EmuTlsVarType, ElementValueArray));
     159             :   unsigned MaxAlignment = std::max(
     160           0 :       DL.getABITypeAlignment(WordType),
     161           0 :       DL.getABITypeAlignment(VoidPtrType));
     162           0 :   EmuTlsVar->setAlignment(MaxAlignment);
     163           0 :   return true;
     164             : }

Generated by: LCOV version 1.13