LCOV - code coverage report
Current view: top level - lib/CodeGen - LowerEmuTLS.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 70 70 100.0 %
Date: 2017-09-14 15:23:50 Functions: 7 8 87.5 %
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/TargetPassConfig.h"
      20             : #include "llvm/IR/LLVMContext.h"
      21             : #include "llvm/IR/Module.h"
      22             : #include "llvm/Pass.h"
      23             : #include "llvm/Target/TargetLowering.h"
      24             : 
      25             : using namespace llvm;
      26             : 
      27             : #define DEBUG_TYPE "loweremutls"
      28             : 
      29             : namespace {
      30             : 
      31          48 : class LowerEmuTLS : public ModulePass {
      32             : public:
      33             :   static char ID; // Pass identification, replacement for typeid
      34          96 :   LowerEmuTLS() : ModulePass(ID) {
      35          48 :     initializeLowerEmuTLSPass(*PassRegistry::getPassRegistry());
      36             :   }
      37             : 
      38             :   bool runOnModule(Module &M) override;
      39             : private:
      40             :   bool addEmuTlsVar(Module &M, const GlobalVariable *GV);
      41         238 :   static void copyLinkageVisibility(Module &M,
      42             :                                     const GlobalVariable *from,
      43             :                                     GlobalVariable *to) {
      44         714 :     to->setLinkage(from->getLinkage());
      45         714 :     to->setVisibility(from->getVisibility());
      46         476 :     if (from->hasComdat()) {
      47           6 :       to->setComdat(M.getOrInsertComdat(to->getName()));
      48           3 :       to->getComdat()->setSelectionKind(from->getComdat()->getSelectionKind());
      49             :     }
      50         238 :   }
      51             : };
      52             : }
      53             : 
      54             : char LowerEmuTLS::ID = 0;
      55             : 
      56         240 : INITIALIZE_PASS(LowerEmuTLS, DEBUG_TYPE,
      57             :                 "Add __emutls_[vt]. variables for emultated TLS model", false,
      58             :                 false)
      59             : 
      60          96 : ModulePass *llvm::createLowerEmuTLSPass() { return new LowerEmuTLS(); }
      61             : 
      62          48 : bool LowerEmuTLS::runOnModule(Module &M) {
      63          48 :   if (skipModule(M))
      64             :     return false;
      65             : 
      66          48 :   auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
      67          48 :   if (!TPC)
      68             :     return false;
      69             : 
      70          48 :   auto &TM = TPC->getTM<TargetMachine>();
      71          48 :   if (!TM.Options.EmulatedTLS)
      72             :     return false;
      73             : 
      74          48 :   bool Changed = false;
      75          48 :   SmallVector<const GlobalVariable*, 8> TlsVars;
      76         226 :   for (const auto &G : M.globals()) {
      77         356 :     if (G.isThreadLocal())
      78         304 :       TlsVars.append({&G});
      79             :   }
      80         296 :   for (const auto G : TlsVars)
      81         152 :     Changed |= addEmuTlsVar(M, G);
      82          48 :   return Changed;
      83             : }
      84             : 
      85         152 : bool LowerEmuTLS::addEmuTlsVar(Module &M, const GlobalVariable *GV) {
      86         152 :   LLVMContext &C = M.getContext();
      87         152 :   PointerType *VoidPtrType = Type::getInt8PtrTy(C);
      88             : 
      89         456 :   std::string EmuTlsVarName = ("__emutls_v." + GV->getName()).str();
      90         304 :   GlobalVariable *EmuTlsVar = M.getNamedGlobal(EmuTlsVarName);
      91         152 :   if (EmuTlsVar)
      92             :     return false;  // It has been added before.
      93             : 
      94         152 :   const DataLayout &DL = M.getDataLayout();
      95         152 :   Constant *NullPtr = ConstantPointerNull::get(VoidPtrType);
      96             : 
      97             :   // Get non-zero initializer from GV's initializer.
      98         152 :   const Constant *InitValue = nullptr;
      99         152 :   if (GV->hasInitializer()) {
     100         104 :     InitValue = GV->getInitializer();
     101         208 :     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         208 :     if (isa<ConstantAggregateZero>(InitValue) ||
     105         102 :         (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         152 :   IntegerType *WordType = DL.getIntPtrType(C);
     116         238 :   PointerType *InitPtrType = InitValue ?
     117         238 :       PointerType::getUnqual(InitValue->getType()) : VoidPtrType;
     118         152 :   Type *ElementTypes[4] = {WordType, WordType, VoidPtrType, InitPtrType};
     119         152 :   ArrayRef<Type*> ElementTypeArray(ElementTypes, 4);
     120         152 :   StructType *EmuTlsVarType = StructType::create(ElementTypeArray);
     121         304 :   EmuTlsVar = cast<GlobalVariable>(
     122             :       M.getOrInsertGlobal(EmuTlsVarName, EmuTlsVarType));
     123         152 :   copyLinkageVisibility(M, GV, EmuTlsVar);
     124             : 
     125             :   // Define "__emutls_t.*" and "__emutls_v.*" only if GV is defined.
     126         152 :   if (!GV->hasInitializer())
     127             :     return true;
     128             : 
     129         104 :   Type *GVType = GV->getValueType();
     130         208 :   unsigned GVAlignment = GV->getAlignment();
     131         104 :   if (!GVAlignment) {
     132             :     // When LLVM IL declares a variable without alignment, use
     133             :     // the ABI default alignment for the type.
     134          64 :     GVAlignment = DL.getABITypeAlignment(GVType);
     135             :   }
     136             : 
     137             :   // Define "__emutls_t.*" if there is InitValue
     138         104 :   GlobalVariable *EmuTlsTmplVar = nullptr;
     139         104 :   if (InitValue) {
     140         258 :     std::string EmuTlsTmplName = ("__emutls_t." + GV->getName()).str();
     141         172 :     EmuTlsTmplVar = dyn_cast_or_null<GlobalVariable>(
     142             :         M.getOrInsertGlobal(EmuTlsTmplName, GVType));
     143             :     assert(EmuTlsTmplVar && "Failed to create emualted TLS initializer");
     144          86 :     EmuTlsTmplVar->setConstant(true);
     145          86 :     EmuTlsTmplVar->setInitializer(const_cast<Constant*>(InitValue));
     146          86 :     EmuTlsTmplVar->setAlignment(GVAlignment);
     147          86 :     copyLinkageVisibility(M, GV, EmuTlsTmplVar);
     148             :   }
     149             : 
     150             :   // Define "__emutls_v.*" with initializer and alignment.
     151             :   Constant *ElementValues[4] = {
     152         104 :       ConstantInt::get(WordType, DL.getTypeStoreSize(GVType)),
     153         104 :       ConstantInt::get(WordType, GVAlignment),
     154         104 :       NullPtr, EmuTlsTmplVar ? EmuTlsTmplVar : NullPtr
     155         312 :   };
     156         104 :   ArrayRef<Constant*> ElementValueArray(ElementValues, 4);
     157         104 :   EmuTlsVar->setInitializer(
     158             :       ConstantStruct::get(EmuTlsVarType, ElementValueArray));
     159             :   unsigned MaxAlignment = std::max(
     160         208 :       DL.getABITypeAlignment(WordType),
     161         312 :       DL.getABITypeAlignment(VoidPtrType));
     162         104 :   EmuTlsVar->setAlignment(MaxAlignment);
     163             :   return true;
     164             : }

Generated by: LCOV version 1.13