LLVM  14.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"
19 #include "llvm/IR/Constants.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  to->setDSOLocal(from->isDSOLocal());
48  if (from->hasComdat()) {
49  to->setComdat(M.getOrInsertComdat(to->getName()));
50  to->getComdat()->setSelectionKind(from->getComdat()->getSelectionKind());
51  }
52  }
53 };
54 }
55 
56 char LowerEmuTLS::ID = 0;
57 
59  "Add __emutls_[vt]. variables for emultated TLS model", false,
60  false)
61 
62 ModulePass *llvm::createLowerEmuTLSPass() { return new LowerEmuTLS(); }
63 
64 bool LowerEmuTLS::runOnModule(Module &M) {
65  if (skipModule(M))
66  return false;
67 
68  auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
69  if (!TPC)
70  return false;
71 
72  auto &TM = TPC->getTM<TargetMachine>();
73  if (!TM.useEmulatedTLS())
74  return false;
75 
76  bool Changed = false;
78  for (const auto &G : M.globals()) {
79  if (G.isThreadLocal())
80  TlsVars.append({&G});
81  }
82  for (const auto G : TlsVars)
83  Changed |= addEmuTlsVar(M, G);
84  return Changed;
85 }
86 
87 bool LowerEmuTLS::addEmuTlsVar(Module &M, const GlobalVariable *GV) {
88  LLVMContext &C = M.getContext();
89  PointerType *VoidPtrType = Type::getInt8PtrTy(C);
90 
91  std::string EmuTlsVarName = ("__emutls_v." + GV->getName()).str();
92  GlobalVariable *EmuTlsVar = M.getNamedGlobal(EmuTlsVarName);
93  if (EmuTlsVar)
94  return false; // It has been added before.
95 
96  const DataLayout &DL = M.getDataLayout();
97  Constant *NullPtr = ConstantPointerNull::get(VoidPtrType);
98 
99  // Get non-zero initializer from GV's initializer.
100  const Constant *InitValue = nullptr;
101  if (GV->hasInitializer()) {
102  InitValue = GV->getInitializer();
103  const ConstantInt *InitIntValue = dyn_cast<ConstantInt>(InitValue);
104  // When GV's init value is all 0, omit the EmuTlsTmplVar and let
105  // the emutls library function to reset newly allocated TLS variables.
106  if (isa<ConstantAggregateZero>(InitValue) ||
107  (InitIntValue && InitIntValue->isZero()))
108  InitValue = nullptr;
109  }
110 
111  // Create the __emutls_v. symbol, whose type has 4 fields:
112  // word size; // size of GV in bytes
113  // word align; // alignment of GV
114  // void *ptr; // initialized to 0; set at run time per thread.
115  // void *templ; // 0 or point to __emutls_t.*
116  // sizeof(word) should be the same as sizeof(void*) on target.
117  IntegerType *WordType = DL.getIntPtrType(C);
118  PointerType *InitPtrType = InitValue ?
119  PointerType::getUnqual(InitValue->getType()) : VoidPtrType;
120  Type *ElementTypes[4] = {WordType, WordType, VoidPtrType, InitPtrType};
121  ArrayRef<Type*> ElementTypeArray(ElementTypes, 4);
122  StructType *EmuTlsVarType = StructType::create(ElementTypeArray);
123  EmuTlsVar = cast<GlobalVariable>(
124  M.getOrInsertGlobal(EmuTlsVarName, EmuTlsVarType));
125  copyLinkageVisibility(M, GV, EmuTlsVar);
126 
127  // Define "__emutls_t.*" and "__emutls_v.*" only if GV is defined.
128  if (!GV->hasInitializer())
129  return true;
130 
131  Type *GVType = GV->getValueType();
132  Align GVAlignment = DL.getValueOrABITypeAlignment(GV->getAlign(), GVType);
133 
134  // Define "__emutls_t.*" if there is InitValue
135  GlobalVariable *EmuTlsTmplVar = nullptr;
136  if (InitValue) {
137  std::string EmuTlsTmplName = ("__emutls_t." + GV->getName()).str();
138  EmuTlsTmplVar = dyn_cast_or_null<GlobalVariable>(
139  M.getOrInsertGlobal(EmuTlsTmplName, GVType));
140  assert(EmuTlsTmplVar && "Failed to create emualted TLS initializer");
141  EmuTlsTmplVar->setConstant(true);
142  EmuTlsTmplVar->setInitializer(const_cast<Constant*>(InitValue));
143  EmuTlsTmplVar->setAlignment(GVAlignment);
144  copyLinkageVisibility(M, GV, EmuTlsTmplVar);
145  }
146 
147  // Define "__emutls_v.*" with initializer and alignment.
148  Constant *ElementValues[4] = {
149  ConstantInt::get(WordType, DL.getTypeStoreSize(GVType)),
150  ConstantInt::get(WordType, GVAlignment.value()), NullPtr,
151  EmuTlsTmplVar ? EmuTlsTmplVar : NullPtr};
152  ArrayRef<Constant*> ElementValueArray(ElementValues, 4);
153  EmuTlsVar->setInitializer(
154  ConstantStruct::get(EmuTlsVarType, ElementValueArray));
155  Align MaxAlignment =
156  std::max(DL.getABITypeAlign(WordType), DL.getABITypeAlign(VoidPtrType));
157  EmuTlsVar->setAlignment(MaxAlignment);
158  return true;
159 }
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::DataLayout
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:113
llvm::ModulePass
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:238
llvm::GlobalVariable::setConstant
void setConstant(bool Val)
Definition: GlobalVariable.h:154
llvm::GlobalValue::getLinkage
LinkageTypes getLinkage() const
Definition: GlobalValue.h:467
Pass.h
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::GlobalObject::getAlign
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
Definition: GlobalObject.h:80
llvm::GlobalVariable
Definition: GlobalVariable.h:40
to
Should compile to
Definition: README.txt:449
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
Module.h
llvm::GlobalVariable::hasInitializer
bool hasInitializer() const
Definitions have initializers, declarations don't.
Definition: GlobalVariable.h:92
llvm::ConstantInt
This is the shared class of boolean and integer constants.
Definition: Constants.h:79
llvm::createLowerEmuTLSPass
ModulePass * createLowerEmuTLSPass()
LowerEmuTLS - This pass generates __emutls_[vt].xyz variables for all TLS variables for the emulated ...
TargetMachine.h
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:31
Constants.h
llvm::SmallVectorImpl::append
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:648
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::GlobalObject::getComdat
const Comdat * getComdat() const
Definition: GlobalObject.h:123
llvm::IntegerType
Class to represent integer types.
Definition: DerivedTypes.h:40
llvm::initializeLowerEmuTLSPass
void initializeLowerEmuTLSPass(PassRegistry &)
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
Passes.h
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
llvm::GlobalVariable::getInitializer
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
Definition: GlobalVariable.h:136
llvm::Constant
This is an important base class in LLVM.
Definition: Constant.h:41
llvm::GlobalValue::getVisibility
VisibilityTypes getVisibility() const
Definition: GlobalValue.h:229
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
llvm::PointerType
Class to represent pointers.
Definition: DerivedTypes.h:632
TargetPassConfig.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::TargetMachine
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:80
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::GlobalObject::hasComdat
bool hasComdat() const
Definition: GlobalObject.h:122
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::StructType
Class to represent struct types.
Definition: DerivedTypes.h:213
llvm::Value::getType
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
llvm::ConstantInt::isZero
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Definition: Constants.h:194
DEBUG_TYPE
#define DEBUG_TYPE
Definition: LowerEmuTLS.cpp:28
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
INITIALIZE_PASS
INITIALIZE_PASS(LowerEmuTLS, DEBUG_TYPE, "Add __emutls_[vt]. variables for emultated TLS model", false, false) ModulePass *llvm
Definition: LowerEmuTLS.cpp:58
llvm::Value::getName
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
get
Should compile to something r4 addze r3 instead we get
Definition: README.txt:24
llvm::Align::value
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition: Alignment.h:85
SmallVector.h
llvm::max
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:340
llvm::GlobalValue::getValueType
Type * getValueType() const
Definition: GlobalValue.h:273
TM
const char LLVMTargetMachineRef TM
Definition: PassBuilderBindings.cpp:47
LLVMContext.h
llvm::GlobalObject::setAlignment
void setAlignment(MaybeAlign Align)
Definition: Globals.cpp:117
llvm::Comdat::getSelectionKind
SelectionKind getSelectionKind() const
Definition: Comdat.h:44
llvm::GlobalValue::isDSOLocal
bool isDSOLocal() const
Definition: GlobalValue.h:282
InitializePasses.h
llvm::GlobalVariable::setInitializer
void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
Definition: Globals.cpp:419
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38