LLVM  15.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/Module.h"
21 #include "llvm/InitializePasses.h"
22 #include "llvm/Pass.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  LowerEmuTLS() : ModulePass(ID) {
36  }
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  GlobalVariable *to) {
44  to->setLinkage(from->getLinkage());
45  to->setVisibility(from->getVisibility());
46  to->setDSOLocal(from->isDSOLocal());
47  if (from->hasComdat()) {
48  to->setComdat(M.getOrInsertComdat(to->getName()));
49  to->getComdat()->setSelectionKind(from->getComdat()->getSelectionKind());
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 }
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
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:248
llvm::GlobalVariable::setConstant
void setConstant(bool Val)
Definition: GlobalVariable.h:153
llvm::GlobalValue::getLinkage
LinkageTypes getLinkage() const
Definition: GlobalValue.h:466
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:1185
llvm::GlobalObject::getAlign
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
Definition: GlobalObject.h:79
llvm::GlobalVariable
Definition: GlobalVariable.h:39
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:91
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:667
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::GlobalObject::getComdat
const Comdat * getComdat() const
Definition: GlobalObject.h:122
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
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
Passes.h
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:200
llvm::GlobalVariable::getInitializer
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
Definition: GlobalVariable.h:135
llvm::Constant
This is an important base class in LLVM.
Definition: Constant.h:41
llvm::GlobalValue::getVisibility
VisibilityTypes getVisibility() const
Definition: GlobalValue.h:228
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:77
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
llvm::GlobalObject::hasComdat
bool hasComdat() const
Definition: GlobalObject.h:121
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:27
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:57
llvm::Value::getName
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:305
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:272
TM
const char LLVMTargetMachineRef TM
Definition: PassBuilderBindings.cpp:47
llvm::GlobalObject::setAlignment
void setAlignment(MaybeAlign Align)
Definition: Globals.cpp:122
llvm::Comdat::getSelectionKind
SelectionKind getSelectionKind() const
Definition: Comdat.h:46
llvm::GlobalValue::isDSOLocal
bool isDSOLocal() const
Definition: GlobalValue.h:281
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:432
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:37