Coverage Report

Created: 2019-07-24 05:18

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