Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: lib/Transforms/NaCl/ExpandTls.cpp

Issue 1780463004: PNaCl: ExpandTls: Simplify by using a C++11 lambda function (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm@master
Patch Set: Rebase Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- ExpandTls.cpp - Convert TLS variables to a concrete layout----------===// 1 //===- ExpandTls.cpp - Convert TLS variables to a concrete layout----------===//
2 // 2 //
3 // The LLVM Compiler Infrastructure 3 // The LLVM Compiler Infrastructure
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This pass expands out uses of thread-local (TLS) variables into 10 // This pass expands out uses of thread-local (TLS) variables into
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 #include "llvm/IR/DataLayout.h" 52 #include "llvm/IR/DataLayout.h"
53 #include "llvm/IR/DerivedTypes.h" 53 #include "llvm/IR/DerivedTypes.h"
54 #include "llvm/IR/Instructions.h" 54 #include "llvm/IR/Instructions.h"
55 #include "llvm/IR/Intrinsics.h" 55 #include "llvm/IR/Intrinsics.h"
56 #include "llvm/IR/Module.h" 56 #include "llvm/IR/Module.h"
57 #include "llvm/Transforms/NaCl.h" 57 #include "llvm/Transforms/NaCl.h"
58 58
59 using namespace llvm; 59 using namespace llvm;
60 60
61 namespace { 61 namespace {
62 class PassState {
63 public:
64 PassState(Module *M): M(M), DL(M), Offset(0), Alignment(1) {}
65
66 Module *M;
67 DataLayout DL;
68 uint32_t Offset;
69 // 'Alignment' is the maximum variable alignment seen so far, in
70 // bytes. After visiting all TLS variables, this is the overall
71 // alignment required for the TLS template.
72 uint32_t Alignment;
73 };
74
75 class ExpandTls : public ModulePass { 62 class ExpandTls : public ModulePass {
76 public: 63 public:
77 static char ID; // Pass identification, replacement for typeid 64 static char ID; // Pass identification, replacement for typeid
78 ExpandTls() : ModulePass(ID) { 65 ExpandTls() : ModulePass(ID) {
79 initializeExpandTlsPass(*PassRegistry::getPassRegistry()); 66 initializeExpandTlsPass(*PassRegistry::getPassRegistry());
80 } 67 }
81 68
82 virtual bool runOnModule(Module &M); 69 virtual bool runOnModule(Module &M);
83 }; 70 };
84 } 71 }
85 72
86 char ExpandTls::ID = 0; 73 char ExpandTls::ID = 0;
87 INITIALIZE_PASS(ExpandTls, "nacl-expand-tls", 74 INITIALIZE_PASS(ExpandTls, "nacl-expand-tls",
88 "Expand out TLS variables and fix TLS variable layout", 75 "Expand out TLS variables and fix TLS variable layout",
89 false, false) 76 false, false)
90 77
91 static void setGlobalVariableValue(Module &M, const char *Name, 78 static void setGlobalVariableValue(Module &M, const char *Name,
92 Constant *Value) { 79 Constant *Value) {
93 if (GlobalVariable *Var = M.getNamedGlobal(Name)) { 80 if (GlobalVariable *Var = M.getNamedGlobal(Name)) {
94 if (Var->hasInitializer()) { 81 if (Var->hasInitializer()) {
95 report_fatal_error(std::string("Variable ") + Name + 82 report_fatal_error(std::string("Variable ") + Name +
96 " already has an initializer"); 83 " already has an initializer");
97 } 84 }
98 Var->replaceAllUsesWith(ConstantExpr::getBitCast(Value, Var->getType())); 85 Var->replaceAllUsesWith(ConstantExpr::getBitCast(Value, Var->getType()));
99 Var->eraseFromParent(); 86 Var->eraseFromParent();
100 } 87 }
101 } 88 }
102 89
103 // Insert alignment padding into the TLS template.
104 static void padToAlignment(PassState *State,
105 std::vector<Constant*> *FieldValues,
106 unsigned Alignment) {
107 if ((State->Offset & (Alignment - 1)) != 0) {
108 unsigned PadSize = Alignment - (State->Offset & (Alignment - 1));
109 Type *i8 = Type::getInt8Ty(State->M->getContext());
110 Type *PadType = ArrayType::get(i8, PadSize);
111 if (FieldValues)
112 FieldValues->push_back(Constant::getNullValue(PadType));
113 State->Offset += PadSize;
114 }
115 if (State->Alignment < Alignment) {
116 State->Alignment = Alignment;
117 }
118 }
119
120 static uint32_t addVarToTlsTemplate(PassState *State,
121 std::vector<Constant*> *FieldValues,
122 GlobalVariable *TlsVar) {
123 unsigned Alignment = State->DL.getPreferredAlignment(TlsVar);
124 padToAlignment(State, FieldValues, Alignment);
125
126 if (FieldValues)
127 FieldValues->push_back(TlsVar->getInitializer());
128 uint32_t Offset = State->Offset;
129 State->Offset +=
130 State->DL.getTypeAllocSize(TlsVar->getType()->getElementType());
131 return Offset;
132 }
133
134 // This is similar to ConstantStruct::getAnon(), but we give a name to the 90 // This is similar to ConstantStruct::getAnon(), but we give a name to the
135 // struct type to make the IR output more readable. 91 // struct type to make the IR output more readable.
136 static Constant *makeInitStruct(Module &M, ArrayRef<Constant *> Elements) { 92 static Constant *makeInitStruct(Module &M, ArrayRef<Constant *> Elements) {
137 SmallVector<Type *, 32> FieldTypes; 93 SmallVector<Type *, 32> FieldTypes;
138 FieldTypes.reserve(Elements.size()); 94 FieldTypes.reserve(Elements.size());
139 for (Constant *Val : Elements) 95 for (Constant *Val : Elements)
140 FieldTypes.push_back(Val->getType()); 96 FieldTypes.push_back(Val->getType());
141 97
142 // We create the TLS template struct as "packed" because we insert 98 // We create the TLS template struct as "packed" because we insert
143 // alignment padding ourselves. 99 // alignment padding ourselves.
144 StructType *Ty = StructType::create(M.getContext(), FieldTypes, 100 StructType *Ty = StructType::create(M.getContext(), FieldTypes,
145 "tls_init_template", /*isPacked=*/ true); 101 "tls_init_template", /*isPacked=*/ true);
146 return ConstantStruct::get(Ty, Elements); 102 return ConstantStruct::get(Ty, Elements);
147 } 103 }
148 104
149 void llvm::buildTlsTemplate(Module &M, TlsTemplate *Result) { 105 void llvm::buildTlsTemplate(Module &M, TlsTemplate *Result) {
150 std::vector<Constant*> FieldInitValues; 106 std::vector<Constant*> FieldInitValues;
151 PassState State(&M); 107 DataLayout DL(&M);
108 uint32_t CurrentOffset = 0;
109 uint32_t OverallAlignment = 1;
110
111 auto addVarToTlsTemplate = [&](GlobalVariable *TlsVar, bool IsBss) {
112 // Add alignment padding if necessary.
113 uint32_t VarAlignment = DL.getPreferredAlignment(TlsVar);
114 if ((CurrentOffset & (VarAlignment - 1)) != 0) {
115 uint32_t PadSize = VarAlignment - (CurrentOffset & (VarAlignment - 1));
116 CurrentOffset += PadSize;
117 if (!IsBss) {
118 Type *I8 = Type::getInt8Ty(M.getContext());
119 Type *PadType = ArrayType::get(I8, PadSize);
120 FieldInitValues.push_back(Constant::getNullValue(PadType));
121 }
122 }
123 if (OverallAlignment < VarAlignment)
124 OverallAlignment = VarAlignment;
125
126 TlsVarInfo Info;
127 Info.TlsVar = TlsVar;
128 Info.Offset = CurrentOffset;
129 Result->TlsVars.push_back(Info);
130
131 CurrentOffset += DL.getTypeAllocSize(TlsVar->getType()->getElementType());
132 if (!IsBss)
133 FieldInitValues.push_back(TlsVar->getInitializer());
134 };
152 135
153 for (GlobalVariable &GV : M.globals()) { 136 for (GlobalVariable &GV : M.globals()) {
154 if (GV.isThreadLocal()) { 137 if (GV.isThreadLocal()) {
155 if (!GV.hasInitializer()) { 138 if (!GV.hasInitializer()) {
156 // Since this is a whole-program transformation, "extern" TLS 139 // Since this is a whole-program transformation, "extern" TLS
157 // variables are not allowed at this point. 140 // variables are not allowed at this point.
158 report_fatal_error(std::string("TLS variable without an initializer: ") 141 report_fatal_error(std::string("TLS variable without an initializer: ")
159 + GV.getName()); 142 + GV.getName());
160 } 143 }
161 if (!GV.getInitializer()->isNullValue()) { 144 if (!GV.getInitializer()->isNullValue())
162 TlsVarInfo Info; 145 addVarToTlsTemplate(&GV, /*IsBss=*/ false);
163 Info.TlsVar = &GV;
164 Info.Offset = addVarToTlsTemplate(&State, &FieldInitValues, &GV);
165 Result->TlsVars.push_back(Info);
166 }
167 } 146 }
168 } 147 }
169 Result->DataSize = State.Offset; 148 Result->DataSize = CurrentOffset;
170 // Handle zero-initialized TLS variables in a second pass, because 149 // Handle zero-initialized TLS variables in a second pass, because
171 // these should follow non-zero-initialized TLS variables. 150 // these should follow non-zero-initialized TLS variables.
172 for (GlobalVariable &GV : M.globals()) { 151 for (GlobalVariable &GV : M.globals()) {
173 if (GV.isThreadLocal() && GV.getInitializer()->isNullValue()) { 152 if (GV.isThreadLocal() && GV.getInitializer()->isNullValue())
174 TlsVarInfo Info; 153 addVarToTlsTemplate(&GV, /*IsBss=*/ true);
175 Info.TlsVar = &GV;
176 Info.Offset = addVarToTlsTemplate(&State, NULL, &GV);
177 Result->TlsVars.push_back(Info);
178 }
179 } 154 }
180 Result->TotalSize = State.Offset; 155 Result->TotalSize = CurrentOffset;
181 Result->Alignment = State.Alignment; 156 Result->Alignment = OverallAlignment;
182 Result->Data = makeInitStruct(M, FieldInitValues); 157 Result->Data = makeInitStruct(M, FieldInitValues);
183 } 158 }
184 159
185 static void adjustToX86StyleLayout(TlsTemplate *Templ) { 160 static void adjustToX86StyleLayout(TlsTemplate *Templ) {
186 // Add final alignment padding so that 161 // Add final alignment padding so that
187 // (struct tls_struct *) __nacl_read_tp() - 1 162 // (struct tls_struct *) __nacl_read_tp() - 1
188 // gives the correct, aligned start of the TLS variables given the 163 // gives the correct, aligned start of the TLS variables given the
189 // x86-style layout we are using. This requires some more bytes to 164 // x86-style layout we are using. This requires some more bytes to
190 // be memset() to zero at runtime. This wastage doesn't seem 165 // be memset() to zero at runtime. This wastage doesn't seem
191 // important gives that we're not trying to optimize packing by 166 // important gives that we're not trying to optimize packing by
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 rewriteTlsVars(M, &Templ.TlsVars); 301 rewriteTlsVars(M, &Templ.TlsVars);
327 302
328 defineTlsLayoutFunctions(M); 303 defineTlsLayoutFunctions(M);
329 304
330 return true; 305 return true;
331 } 306 }
332 307
333 ModulePass *llvm::createExpandTlsPass() { 308 ModulePass *llvm::createExpandTlsPass() {
334 return new ExpandTls(); 309 return new ExpandTls();
335 } 310 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698