LLVM  12.0.0git
LowerEmuTLS.cpp
Go to the documentation of this file.
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"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/InitializePasses.h"
23 #include "llvm/Pass.h"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "loweremutls"
29 
30 namespace {
31 
32 class LowerEmuTLS : public ModulePass {
33 public:
34  static char ID; // Pass identification, replacement for typeid
35  LowerEmuTLS() : ModulePass(ID) {
37  }
38 
39  bool runOnModule(Module &M) override;
40 private:
41  bool addEmuTlsVar(Module &M, const GlobalVariable *GV);
42  static void copyLinkageVisibility(Module &M,
43  const GlobalVariable *from,
44  GlobalVariable *to) {
45  to->setLinkage(from->getLinkage());
46  to->setVisibility(from->getVisibility());
47  if (from->hasComdat()) {
48  to->setComdat(M.getOrInsertComdat(to->getName()));
50  }
51  }
52 };
53 }
54 
55 char LowerEmuTLS::ID = 0;
56 
58  "Add __emutls_[vt]. variables for emultated TLS model", false,
59  false)
60 
61 ModulePass *llvm::createLowerEmuTLSPass() { return new LowerEmuTLS(); }
62 
63 bool LowerEmuTLS::runOnModule(Module &M) {
64  if (skipModule(M))
65  return false;
66 
67  auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
68  if (!TPC)
69  return false;
70 
71  auto &TM = TPC->getTM<TargetMachine>();
72  if (!TM.useEmulatedTLS())
73  return false;
74 
75  bool Changed = false;
77  for (const auto &G : M.globals()) {
78  if (G.isThreadLocal())
79  TlsVars.append({&G});
80  }
81  for (const auto G : TlsVars)
82  Changed |= addEmuTlsVar(M, G);
83  return Changed;
84 }
85 
86 bool LowerEmuTLS::addEmuTlsVar(Module &M, const GlobalVariable *GV) {
87  LLVMContext &C = M.getContext();
88  PointerType *VoidPtrType = Type::getInt8PtrTy(C);
89 
90  std::string EmuTlsVarName = ("__emutls_v." + GV->getName()).str();
91  GlobalVariable *EmuTlsVar = M.getNamedGlobal(EmuTlsVarName);
92  if (EmuTlsVar)
93  return false; // It has been added before.
94 
95  const DataLayout &DL = M.getDataLayout();
96  Constant *NullPtr = ConstantPointerNull::get(VoidPtrType);
97 
98  // Get non-zero initializer from GV's initializer.
99  const Constant *InitValue = nullptr;
100  if (GV->hasInitializer()) {
101  InitValue = GV->getInitializer();
102  const ConstantInt *InitIntValue = dyn_cast<ConstantInt>(InitValue);
103  // When GV's init value is all 0, omit the EmuTlsTmplVar and let
104  // the emutls library function to reset newly allocated TLS variables.
105  if (isa<ConstantAggregateZero>(InitValue) ||
106  (InitIntValue && InitIntValue->isZero()))
107  InitValue = nullptr;
108  }
109 
110  // Create the __emutls_v. symbol, whose type has 4 fields:
111  // word size; // size of GV in bytes
112  // word align; // alignment of GV
113  // void *ptr; // initialized to 0; set at run time per thread.
114  // void *templ; // 0 or point to __emutls_t.*
115  // sizeof(word) should be the same as sizeof(void*) on target.
116  IntegerType *WordType = DL.getIntPtrType(C);
117  PointerType *InitPtrType = InitValue ?
118  PointerType::getUnqual(InitValue->getType()) : VoidPtrType;
119  Type *ElementTypes[4] = {WordType, WordType, VoidPtrType, InitPtrType};
120  ArrayRef<Type*> ElementTypeArray(ElementTypes, 4);
121  StructType *EmuTlsVarType = StructType::create(ElementTypeArray);
122  EmuTlsVar = cast<GlobalVariable>(
123  M.getOrInsertGlobal(EmuTlsVarName, EmuTlsVarType));
124  copyLinkageVisibility(M, GV, EmuTlsVar);
125 
126  // Define "__emutls_t.*" and "__emutls_v.*" only if GV is defined.
127  if (!GV->hasInitializer())
128  return true;
129 
130  Type *GVType = GV->getValueType();
131  Align GVAlignment = DL.getValueOrABITypeAlignment(GV->getAlign(), GVType);
132 
133  // Define "__emutls_t.*" if there is InitValue
134  GlobalVariable *EmuTlsTmplVar = nullptr;
135  if (InitValue) {
136  std::string EmuTlsTmplName = ("__emutls_t." + GV->getName()).str();
137  EmuTlsTmplVar = dyn_cast_or_null<GlobalVariable>(
138  M.getOrInsertGlobal(EmuTlsTmplName, GVType));
139  assert(EmuTlsTmplVar && "Failed to create emualted TLS initializer");
140  EmuTlsTmplVar->setConstant(true);
141  EmuTlsTmplVar->setInitializer(const_cast<Constant*>(InitValue));
142  EmuTlsTmplVar->setAlignment(GVAlignment);
143  copyLinkageVisibility(M, GV, EmuTlsTmplVar);
144  }
145 
146  // Define "__emutls_v.*" with initializer and alignment.
147  Constant *ElementValues[4] = {
148  ConstantInt::get(WordType, DL.getTypeStoreSize(GVType)),
149  ConstantInt::get(WordType, GVAlignment.value()), NullPtr,
150  EmuTlsTmplVar ? EmuTlsTmplVar : NullPtr};
151  ArrayRef<Constant*> ElementValueArray(ElementValues, 4);
152  EmuTlsVar->setInitializer(
153  ConstantStruct::get(EmuTlsVarType, ElementValueArray));
154  Align MaxAlignment =
155  std::max(DL.getABITypeAlign(WordType), DL.getABITypeAlign(VoidPtrType));
156  EmuTlsVar->setAlignment(MaxAlignment);
157  return true;
158 }
void setVisibility(VisibilityTypes V)
Definition: GlobalValue.h:235
uint64_t CallInst * C
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:111
LLVM_NODISCARD std::enable_if_t< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
Definition: Casting.h:334
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:67
const GlobalVariable * getNamedGlobal(StringRef Name) const
Return the global variable in the module with the specified name, of arbitrary type.
Definition: Module.h:414
void initializeLowerEmuTLSPass(PassRegistry &)
Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
Definition: DataLayout.cpp:770
const DataLayout & getDataLayout() const
Get the data layout for the module&#39;s target platform.
Definition: Module.cpp:397
void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
Definition: Globals.cpp:384
Class to represent struct types.
Definition: DerivedTypes.h:218
LLVMContext & getContext() const
Get the global data context.
Definition: Module.h:253
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:244
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type...
Definition: DataLayout.h:458
void setComdat(Comdat *C)
Definition: GlobalObject.h:128
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:32
LinkageTypes getLinkage() const
Definition: GlobalValue.h:461
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition: Alignment.h:85
Align getValueOrABITypeAlignment(MaybeAlign Alignment, Type *Ty) const
Helper function to return Alignment if it&#39;s set or the result of getABITypeAlignment(Ty), in any case the result is a valid alignment.
Definition: DataLayout.h:516
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
Definition: GlobalObject.h:83
Class to represent pointers.
Definition: DerivedTypes.h:662
IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const
Returns an integer type with size at least as big as that of a pointer in the given address space...
Definition: DataLayout.cpp:789
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Definition: Constants.cpp:1651
VisibilityTypes getVisibility() const
Definition: GlobalValue.h:229
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
This is an important base class in LLVM.
Definition: Constant.h:41
static Constant * get(StructType *T, ArrayRef< Constant *> V)
Definition: Constants.cpp:1219
Class to represent integer types.
Definition: DerivedTypes.h:40
void setConstant(bool Val)
Comdat * getOrInsertComdat(StringRef Name)
Return the Comdat in the module with the specified name.
Definition: Module.cpp:526
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:234
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
ModulePass * createLowerEmuTLSPass()
LowerEmuTLS - This pass generates __emutls_[vt].xyz variables for all TLS variables for the emulated ...
INITIALIZE_PASS(LowerEmuTLS, DEBUG_TYPE, "Add __emutls_[vt]. variables for emultated TLS model", false, false) ModulePass *llvm
Definition: LowerEmuTLS.cpp:57
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the generic address space (address sp...
Definition: DerivedTypes.h:677
This is the shared class of boolean and integer constants.
Definition: Constants.h:77
void setSelectionKind(SelectionKind Val)
Definition: Comdat.h:45
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:350
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:883
Module.h This file contains the declarations for the Module class.
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:786
void setLinkage(LinkageTypes LT)
Definition: GlobalValue.h:454
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:433
bool hasComdat() const
Definition: GlobalObject.h:125
const Comdat * getComdat() const
Definition: GlobalObject.h:126
void setAlignment(MaybeAlign Align)
Definition: Globals.cpp:116
Constant * getOrInsertGlobal(StringRef Name, Type *Ty, function_ref< GlobalVariable *()> CreateGlobalCallback)
Look up the specified global in the module symbol table.
Definition: Module.cpp:204
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:270
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:224
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Definition: Constants.h:200
Type * getValueType() const
Definition: GlobalValue.h:273
#define DEBUG_TYPE
Definition: LowerEmuTLS.cpp:28
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool hasInitializer() const
Definitions have initializers, declarations don&#39;t.
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition: Type.cpp:451
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:65
iterator_range< global_iterator > globals()
Definition: Module.h:599
This file describes how to lower LLVM code to machine code.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
SelectionKind getSelectionKind() const
Definition: Comdat.h:44