Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/CodeGen/LowerEmuTLS.cpp
Line
Count
Source (jump to first uncovered line)
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
class LowerEmuTLS : public ModulePass {
32
public:
33
  static char ID; // Pass identification, replacement for typeid
34
48
  LowerEmuTLS() : ModulePass(ID) {
35
48
    initializeLowerEmuTLSPass(*PassRegistry::getPassRegistry());
36
48
  }
37
38
  bool runOnModule(Module &M) override;
39
private:
40
  bool addEmuTlsVar(Module &M, const GlobalVariable *GV);
41
  static void copyLinkageVisibility(Module &M,
42
                                    const GlobalVariable *from,
43
238
                                    GlobalVariable *to) {
44
238
    to->setLinkage(from->getLinkage());
45
238
    to->setVisibility(from->getVisibility());
46
238
    if (
from->hasComdat()238
) {
47
3
      to->setComdat(M.getOrInsertComdat(to->getName()));
48
3
      to->getComdat()->setSelectionKind(from->getComdat()->getSelectionKind());
49
3
    }
50
238
  }
51
};
52
}
53
54
char LowerEmuTLS::ID = 0;
55
56
INITIALIZE_PASS(LowerEmuTLS, DEBUG_TYPE,
57
                "Add __emutls_[vt]. variables for emultated TLS model", false,
58
                false)
59
60
48
ModulePass *llvm::createLowerEmuTLSPass() { return new LowerEmuTLS(); }
61
62
48
bool LowerEmuTLS::runOnModule(Module &M) {
63
48
  if (skipModule(M))
64
0
    return false;
65
48
66
48
  auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
67
48
  if (!TPC)
68
0
    return false;
69
48
70
48
  auto &TM = TPC->getTM<TargetMachine>();
71
48
  if (!TM.Options.EmulatedTLS)
72
0
    return false;
73
48
74
48
  bool Changed = false;
75
48
  SmallVector<const GlobalVariable*, 8> TlsVars;
76
178
  for (const auto &G : M.globals()) {
77
178
    if (G.isThreadLocal())
78
152
      TlsVars.append({&G});
79
178
  }
80
48
  for (const auto G : TlsVars)
81
152
    Changed |= addEmuTlsVar(M, G);
82
48
  return Changed;
83
48
}
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
152
89
152
  std::string EmuTlsVarName = ("__emutls_v." + GV->getName()).str();
90
152
  GlobalVariable *EmuTlsVar = M.getNamedGlobal(EmuTlsVarName);
91
152
  if (EmuTlsVar)
92
0
    return false;  // It has been added before.
93
152
94
152
  const DataLayout &DL = M.getDataLayout();
95
152
  Constant *NullPtr = ConstantPointerNull::get(VoidPtrType);
96
152
97
152
  // Get non-zero initializer from GV's initializer.
98
152
  const Constant *InitValue = nullptr;
99
152
  if (
GV->hasInitializer()152
) {
100
104
    InitValue = GV->getInitializer();
101
104
    const ConstantInt *InitIntValue = dyn_cast<ConstantInt>(InitValue);
102
104
    // When GV's init value is all 0, omit the EmuTlsTmplVar and let
103
104
    // the emutls library function to reset newly allocated TLS variables.
104
104
    if (isa<ConstantAggregateZero>(InitValue) ||
105
103
        
(InitIntValue && 103
InitIntValue->isZero()102
))
106
18
      InitValue = nullptr;
107
104
  }
108
152
109
152
  // Create the __emutls_v. symbol, whose type has 4 fields:
110
152
  //     word size;   // size of GV in bytes
111
152
  //     word align;  // alignment of GV
112
152
  //     void *ptr;   // initialized to 0; set at run time per thread.
113
152
  //     void *templ; // 0 or point to __emutls_t.*
114
152
  // sizeof(word) should be the same as sizeof(void*) on target.
115
152
  IntegerType *WordType = DL.getIntPtrType(C);
116
152
  PointerType *InitPtrType = InitValue ?
117
152
      
PointerType::getUnqual(InitValue->getType())86
:
VoidPtrType66
;
118
152
  Type *ElementTypes[4] = {WordType, WordType, VoidPtrType, InitPtrType};
119
152
  ArrayRef<Type*> ElementTypeArray(ElementTypes, 4);
120
152
  StructType *EmuTlsVarType = StructType::create(ElementTypeArray);
121
152
  EmuTlsVar = cast<GlobalVariable>(
122
152
      M.getOrInsertGlobal(EmuTlsVarName, EmuTlsVarType));
123
152
  copyLinkageVisibility(M, GV, EmuTlsVar);
124
152
125
152
  // Define "__emutls_t.*" and "__emutls_v.*" only if GV is defined.
126
152
  if (!GV->hasInitializer())
127
48
    return true;
128
104
129
104
  Type *GVType = GV->getValueType();
130
104
  unsigned GVAlignment = GV->getAlignment();
131
104
  if (
!GVAlignment104
) {
132
64
    // When LLVM IL declares a variable without alignment, use
133
64
    // the ABI default alignment for the type.
134
64
    GVAlignment = DL.getABITypeAlignment(GVType);
135
64
  }
136
104
137
104
  // Define "__emutls_t.*" if there is InitValue
138
104
  GlobalVariable *EmuTlsTmplVar = nullptr;
139
104
  if (
InitValue104
) {
140
86
    std::string EmuTlsTmplName = ("__emutls_t." + GV->getName()).str();
141
86
    EmuTlsTmplVar = dyn_cast_or_null<GlobalVariable>(
142
86
        M.getOrInsertGlobal(EmuTlsTmplName, GVType));
143
86
    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
86
  }
149
104
150
104
  // Define "__emutls_v.*" with initializer and alignment.
151
104
  Constant *ElementValues[4] = {
152
104
      ConstantInt::get(WordType, DL.getTypeStoreSize(GVType)),
153
104
      ConstantInt::get(WordType, GVAlignment),
154
104
      NullPtr, EmuTlsTmplVar ? 
EmuTlsTmplVar86
:
NullPtr18
155
152
  };
156
152
  ArrayRef<Constant*> ElementValueArray(ElementValues, 4);
157
152
  EmuTlsVar->setInitializer(
158
152
      ConstantStruct::get(EmuTlsVarType, ElementValueArray));
159
152
  unsigned MaxAlignment = std::max(
160
152
      DL.getABITypeAlignment(WordType),
161
152
      DL.getABITypeAlignment(VoidPtrType));
162
152
  EmuTlsVar->setAlignment(MaxAlignment);
163
152
  return true;
164
152
}