OLD | NEW |
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 104 matching lines...) Loading... |
115 State->Offset += | 115 State->Offset += |
116 State->DL.getTypeAllocSize(TlsVar->getType()->getElementType()); | 116 State->DL.getTypeAllocSize(TlsVar->getType()->getElementType()); |
117 } | 117 } |
118 | 118 |
119 static StructType *buildTlsTemplate(Module &M, std::vector<VarInfo> *TlsVars) { | 119 static StructType *buildTlsTemplate(Module &M, std::vector<VarInfo> *TlsVars) { |
120 std::vector<Type*> FieldBssTypes; | 120 std::vector<Type*> FieldBssTypes; |
121 std::vector<Type*> FieldInitTypes; | 121 std::vector<Type*> FieldInitTypes; |
122 std::vector<Constant*> FieldInitValues; | 122 std::vector<Constant*> FieldInitValues; |
123 PassState State(&M); | 123 PassState State(&M); |
124 | 124 |
125 for (Module::global_iterator GV = M.global_begin(); | 125 for (GlobalVariable &GV : M.globals()) { |
126 GV != M.global_end(); | 126 if (GV.isThreadLocal()) { |
127 ++GV) { | 127 if (!GV.hasInitializer()) { |
128 if (GV->isThreadLocal()) { | |
129 if (!GV->hasInitializer()) { | |
130 // Since this is a whole-program transformation, "extern" TLS | 128 // Since this is a whole-program transformation, "extern" TLS |
131 // variables are not allowed at this point. | 129 // variables are not allowed at this point. |
132 report_fatal_error(std::string("TLS variable without an initializer: ") | 130 report_fatal_error(std::string("TLS variable without an initializer: ") |
133 + GV->getName()); | 131 + GV.getName()); |
134 } | 132 } |
135 if (!GV->getInitializer()->isNullValue()) { | 133 if (!GV.getInitializer()->isNullValue()) { |
136 addVarToTlsTemplate(&State, &FieldInitTypes, | 134 addVarToTlsTemplate(&State, &FieldInitTypes, &FieldInitValues, &GV); |
137 &FieldInitValues, GV); | |
138 VarInfo Info; | 135 VarInfo Info; |
139 Info.TlsVar = GV; | 136 Info.TlsVar = &GV; |
140 Info.IsBss = false; | 137 Info.IsBss = false; |
141 Info.TemplateIndex = FieldInitTypes.size() - 1; | 138 Info.TemplateIndex = FieldInitTypes.size() - 1; |
142 TlsVars->push_back(Info); | 139 TlsVars->push_back(Info); |
143 } | 140 } |
144 } | 141 } |
145 } | 142 } |
146 // Handle zero-initialized TLS variables in a second pass, because | 143 // Handle zero-initialized TLS variables in a second pass, because |
147 // these should follow non-zero-initialized TLS variables. | 144 // these should follow non-zero-initialized TLS variables. |
148 for (Module::global_iterator GV = M.global_begin(); | 145 for (GlobalVariable &GV : M.globals()) { |
149 GV != M.global_end(); | 146 if (GV.isThreadLocal() && GV.getInitializer()->isNullValue()) { |
150 ++GV) { | 147 addVarToTlsTemplate(&State, &FieldBssTypes, NULL, &GV); |
151 if (GV->isThreadLocal() && GV->getInitializer()->isNullValue()) { | |
152 addVarToTlsTemplate(&State, &FieldBssTypes, NULL, GV); | |
153 VarInfo Info; | 148 VarInfo Info; |
154 Info.TlsVar = GV; | 149 Info.TlsVar = &GV; |
155 Info.IsBss = true; | 150 Info.IsBss = true; |
156 Info.TemplateIndex = FieldBssTypes.size() - 1; | 151 Info.TemplateIndex = FieldBssTypes.size() - 1; |
157 TlsVars->push_back(Info); | 152 TlsVars->push_back(Info); |
158 } | 153 } |
159 } | 154 } |
160 // Add final alignment padding so that | 155 // Add final alignment padding so that |
161 // (struct tls_struct *) __nacl_read_tp() - 1 | 156 // (struct tls_struct *) __nacl_read_tp() - 1 |
162 // gives the correct, aligned start of the TLS variables given the | 157 // gives the correct, aligned start of the TLS variables given the |
163 // x86-style layout we are using. This requires some more bytes to | 158 // x86-style layout we are using. This requires some more bytes to |
164 // be memset() to zero at runtime. This wastage doesn't seem | 159 // be memset() to zero at runtime. This wastage doesn't seem |
(...skipping 59 matching lines...) Loading... |
224 AlignmentVar->setName(AlignmentSymbol); | 219 AlignmentVar->setName(AlignmentSymbol); |
225 | 220 |
226 return TemplateType; | 221 return TemplateType; |
227 } | 222 } |
228 | 223 |
229 static void rewriteTlsVars(Module &M, std::vector<VarInfo> *TlsVars, | 224 static void rewriteTlsVars(Module &M, std::vector<VarInfo> *TlsVars, |
230 StructType *TemplateType) { | 225 StructType *TemplateType) { |
231 // Set up the intrinsic that reads the thread pointer. | 226 // Set up the intrinsic that reads the thread pointer. |
232 Function *ReadTpFunc = Intrinsic::getDeclaration(&M, Intrinsic::nacl_read_tp); | 227 Function *ReadTpFunc = Intrinsic::getDeclaration(&M, Intrinsic::nacl_read_tp); |
233 | 228 |
234 for (std::vector<VarInfo>::iterator VarInfo = TlsVars->begin(); | 229 for (VarInfo &VarInfo : *TlsVars) { |
235 VarInfo != TlsVars->end(); | 230 GlobalVariable *Var = VarInfo.TlsVar; |
236 ++VarInfo) { | 231 while (!Var->use_empty()) { |
237 GlobalVariable *Var = VarInfo->TlsVar; | |
238 while (Var->hasNUsesOrMore(1)) { | |
239 Use *U = &*Var->use_begin(); | 232 Use *U = &*Var->use_begin(); |
240 Instruction *InsertPt = PhiSafeInsertPt(U); | 233 Instruction *InsertPt = PhiSafeInsertPt(U); |
241 Value *RawThreadPtr = CallInst::Create(ReadTpFunc, "tls_raw", InsertPt); | 234 Value *RawThreadPtr = CallInst::Create(ReadTpFunc, "tls_raw", InsertPt); |
242 Value *TypedThreadPtr = new BitCastInst( | 235 Value *TypedThreadPtr = new BitCastInst( |
243 RawThreadPtr, TemplateType->getPointerTo(), "tls_struct", InsertPt); | 236 RawThreadPtr, TemplateType->getPointerTo(), "tls_struct", InsertPt); |
244 SmallVector<Value*, 3> Indexes; | 237 SmallVector<Value*, 3> Indexes; |
245 // We use -1 because we use the x86-style TLS layout in which | 238 // We use -1 because we use the x86-style TLS layout in which |
246 // the TLS data is stored at addresses below the thread pointer. | 239 // the TLS data is stored at addresses below the thread pointer. |
247 // This is largely because a check in nacl_irt_thread_create() | 240 // This is largely because a check in nacl_irt_thread_create() |
248 // in irt/irt_thread.c requires the thread pointer to be a | 241 // in irt/irt_thread.c requires the thread pointer to be a |
249 // self-pointer on x86-32. | 242 // self-pointer on x86-32. |
250 // TODO(mseaborn): I intend to remove that check because it is | 243 // TODO(mseaborn): I intend to remove that check because it is |
251 // non-portable. In the mean time, we want PNaCl pexes to work | 244 // non-portable. In the mean time, we want PNaCl pexes to work |
252 // in older Chromium releases when translated to nexes. | 245 // in older Chromium releases when translated to nexes. |
253 Indexes.push_back(ConstantInt::get( | 246 Indexes.push_back(ConstantInt::get( |
254 M.getContext(), APInt(32, -1))); | 247 M.getContext(), APInt(32, -1))); |
255 Indexes.push_back(ConstantInt::get( | 248 Indexes.push_back(ConstantInt::get( |
256 M.getContext(), APInt(32, VarInfo->IsBss ? 1 : 0))); | 249 M.getContext(), APInt(32, VarInfo.IsBss ? 1 : 0))); |
257 Indexes.push_back(ConstantInt::get( | 250 Indexes.push_back(ConstantInt::get( |
258 M.getContext(), APInt(32, VarInfo->TemplateIndex))); | 251 M.getContext(), APInt(32, VarInfo.TemplateIndex))); |
259 Value *TlsField = GetElementPtrInst::Create( | 252 Value *TlsField = GetElementPtrInst::Create( |
260 TemplateType, TypedThreadPtr, Indexes, "field", InsertPt); | 253 TemplateType, TypedThreadPtr, Indexes, "field", InsertPt); |
261 PhiSafeReplaceUses(U, TlsField); | 254 PhiSafeReplaceUses(U, TlsField); |
262 } | 255 } |
263 VarInfo->TlsVar->eraseFromParent(); | 256 Var->eraseFromParent(); |
264 } | 257 } |
265 } | 258 } |
266 | 259 |
267 static void replaceFunction(Module &M, const char *Name, Value *NewFunc) { | 260 static void replaceFunction(Module &M, const char *Name, Value *NewFunc) { |
268 if (Function *Func = M.getFunction(Name)) { | 261 if (Function *Func = M.getFunction(Name)) { |
269 if (Func->hasLocalLinkage()) | 262 if (Func->hasLocalLinkage()) |
270 return; | 263 return; |
271 if (!Func->isDeclaration()) | 264 if (!Func->isDeclaration()) |
272 report_fatal_error(std::string("Function already defined: ") + Name); | 265 report_fatal_error(std::string("Function already defined: ") + Name); |
273 Func->replaceAllUsesWith(NewFunc); | 266 Func->replaceAllUsesWith(NewFunc); |
(...skipping 53 matching lines...) Loading... |
327 rewriteTlsVars(M, &TlsVars, TemplateType); | 320 rewriteTlsVars(M, &TlsVars, TemplateType); |
328 | 321 |
329 defineTlsLayoutFunctions(M); | 322 defineTlsLayoutFunctions(M); |
330 | 323 |
331 return true; | 324 return true; |
332 } | 325 } |
333 | 326 |
334 ModulePass *llvm::createExpandTlsPass() { | 327 ModulePass *llvm::createExpandTlsPass() { |
335 return new ExpandTls(); | 328 return new ExpandTls(); |
336 } | 329 } |
OLD | NEW |