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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 unsigned Alignment = State->DL.getPreferredAlignment(TlsVar); | 109 unsigned Alignment = State->DL.getPreferredAlignment(TlsVar); |
110 padToAlignment(State, FieldTypes, FieldValues, Alignment); | 110 padToAlignment(State, FieldTypes, FieldValues, Alignment); |
111 | 111 |
112 FieldTypes->push_back(TlsVar->getType()->getElementType()); | 112 FieldTypes->push_back(TlsVar->getType()->getElementType()); |
113 if (FieldValues) | 113 if (FieldValues) |
114 FieldValues->push_back(TlsVar->getInitializer()); | 114 FieldValues->push_back(TlsVar->getInitializer()); |
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 PointerType *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 (Module::global_iterator GV = M.global_begin(); |
126 GV != M.global_end(); | 126 GV != M.global_end(); |
127 ++GV) { | 127 ++GV) { |
128 if (GV->isThreadLocal()) { | 128 if (GV->isThreadLocal()) { |
129 if (!GV->hasInitializer()) { | 129 if (!GV->hasInitializer()) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 const char *StartSymbol = "__tls_template_start"; | 196 const char *StartSymbol = "__tls_template_start"; |
197 Constant *TemplateData = ConstantStruct::get(InitTemplateType, | 197 Constant *TemplateData = ConstantStruct::get(InitTemplateType, |
198 FieldInitValues); | 198 FieldInitValues); |
199 GlobalVariable *TemplateDataVar = | 199 GlobalVariable *TemplateDataVar = |
200 new GlobalVariable(M, InitTemplateType, /*isConstant=*/true, | 200 new GlobalVariable(M, InitTemplateType, /*isConstant=*/true, |
201 GlobalValue::InternalLinkage, TemplateData); | 201 GlobalValue::InternalLinkage, TemplateData); |
202 setGlobalVariableValue(M, StartSymbol, TemplateDataVar); | 202 setGlobalVariableValue(M, StartSymbol, TemplateDataVar); |
203 TemplateDataVar->setName(StartSymbol); | 203 TemplateDataVar->setName(StartSymbol); |
204 | 204 |
205 Constant *TdataEnd = ConstantExpr::getGetElementPtr( | 205 Constant *TdataEnd = ConstantExpr::getGetElementPtr( |
| 206 InitTemplateType, |
206 TemplateDataVar, | 207 TemplateDataVar, |
207 ConstantInt::get(M.getContext(), APInt(32, 1))); | 208 ConstantInt::get(M.getContext(), APInt(32, 1))); |
208 setGlobalVariableValue(M, "__tls_template_tdata_end", TdataEnd); | 209 setGlobalVariableValue(M, "__tls_template_tdata_end", TdataEnd); |
209 | 210 |
210 Constant *TotalEnd = ConstantExpr::getGetElementPtr( | 211 Constant *TotalEnd = ConstantExpr::getGetElementPtr( |
| 212 TemplateType, |
211 ConstantExpr::getBitCast(TemplateDataVar, TemplatePtrType), | 213 ConstantExpr::getBitCast(TemplateDataVar, TemplatePtrType), |
212 ConstantInt::get(M.getContext(), APInt(32, 1))); | 214 ConstantInt::get(M.getContext(), APInt(32, 1))); |
213 setGlobalVariableValue(M, "__tls_template_end", TotalEnd); | 215 setGlobalVariableValue(M, "__tls_template_end", TotalEnd); |
214 | 216 |
215 const char *AlignmentSymbol = "__tls_template_alignment"; | 217 const char *AlignmentSymbol = "__tls_template_alignment"; |
216 Type *i32 = Type::getInt32Ty(M.getContext()); | 218 Type *i32 = Type::getInt32Ty(M.getContext()); |
217 GlobalVariable *AlignmentVar = new GlobalVariable( | 219 GlobalVariable *AlignmentVar = new GlobalVariable( |
218 M, i32, /*isConstant=*/true, | 220 M, i32, /*isConstant=*/true, |
219 GlobalValue::InternalLinkage, | 221 GlobalValue::InternalLinkage, |
220 ConstantInt::get(M.getContext(), APInt(32, State.Alignment))); | 222 ConstantInt::get(M.getContext(), APInt(32, State.Alignment))); |
221 setGlobalVariableValue(M, AlignmentSymbol, AlignmentVar); | 223 setGlobalVariableValue(M, AlignmentSymbol, AlignmentVar); |
222 AlignmentVar->setName(AlignmentSymbol); | 224 AlignmentVar->setName(AlignmentSymbol); |
223 | 225 |
224 return TemplatePtrType; | 226 return TemplateType; |
225 } | 227 } |
226 | 228 |
227 static void rewriteTlsVars(Module &M, std::vector<VarInfo> *TlsVars, | 229 static void rewriteTlsVars(Module &M, std::vector<VarInfo> *TlsVars, |
228 PointerType *TemplatePtrType) { | 230 StructType *TemplateType) { |
229 // Set up the intrinsic that reads the thread pointer. | 231 // Set up the intrinsic that reads the thread pointer. |
230 Function *ReadTpFunc = Intrinsic::getDeclaration(&M, Intrinsic::nacl_read_tp); | 232 Function *ReadTpFunc = Intrinsic::getDeclaration(&M, Intrinsic::nacl_read_tp); |
231 | 233 |
232 for (std::vector<VarInfo>::iterator VarInfo = TlsVars->begin(); | 234 for (std::vector<VarInfo>::iterator VarInfo = TlsVars->begin(); |
233 VarInfo != TlsVars->end(); | 235 VarInfo != TlsVars->end(); |
234 ++VarInfo) { | 236 ++VarInfo) { |
235 GlobalVariable *Var = VarInfo->TlsVar; | 237 GlobalVariable *Var = VarInfo->TlsVar; |
236 while (Var->hasNUsesOrMore(1)) { | 238 while (Var->hasNUsesOrMore(1)) { |
237 Use *U = &*Var->use_begin(); | 239 Use *U = &*Var->use_begin(); |
238 Instruction *InsertPt = PhiSafeInsertPt(U); | 240 Instruction *InsertPt = PhiSafeInsertPt(U); |
239 Value *RawThreadPtr = CallInst::Create(ReadTpFunc, "tls_raw", InsertPt); | 241 Value *RawThreadPtr = CallInst::Create(ReadTpFunc, "tls_raw", InsertPt); |
240 Value *TypedThreadPtr = new BitCastInst(RawThreadPtr, TemplatePtrType, | 242 Value *TypedThreadPtr = new BitCastInst( |
241 "tls_struct", InsertPt); | 243 RawThreadPtr, TemplateType->getPointerTo(), "tls_struct", InsertPt); |
242 SmallVector<Value*, 3> Indexes; | 244 SmallVector<Value*, 3> Indexes; |
243 // We use -1 because we use the x86-style TLS layout in which | 245 // We use -1 because we use the x86-style TLS layout in which |
244 // the TLS data is stored at addresses below the thread pointer. | 246 // the TLS data is stored at addresses below the thread pointer. |
245 // This is largely because a check in nacl_irt_thread_create() | 247 // This is largely because a check in nacl_irt_thread_create() |
246 // in irt/irt_thread.c requires the thread pointer to be a | 248 // in irt/irt_thread.c requires the thread pointer to be a |
247 // self-pointer on x86-32. | 249 // self-pointer on x86-32. |
248 // TODO(mseaborn): I intend to remove that check because it is | 250 // TODO(mseaborn): I intend to remove that check because it is |
249 // non-portable. In the mean time, we want PNaCl pexes to work | 251 // non-portable. In the mean time, we want PNaCl pexes to work |
250 // in older Chromium releases when translated to nexes. | 252 // in older Chromium releases when translated to nexes. |
251 Indexes.push_back(ConstantInt::get( | 253 Indexes.push_back(ConstantInt::get( |
252 M.getContext(), APInt(32, -1))); | 254 M.getContext(), APInt(32, -1))); |
253 Indexes.push_back(ConstantInt::get( | 255 Indexes.push_back(ConstantInt::get( |
254 M.getContext(), APInt(32, VarInfo->IsBss ? 1 : 0))); | 256 M.getContext(), APInt(32, VarInfo->IsBss ? 1 : 0))); |
255 Indexes.push_back(ConstantInt::get( | 257 Indexes.push_back(ConstantInt::get( |
256 M.getContext(), APInt(32, VarInfo->TemplateIndex))); | 258 M.getContext(), APInt(32, VarInfo->TemplateIndex))); |
257 Value *TlsField = GetElementPtrInst::Create(TypedThreadPtr, Indexes, | 259 Value *TlsField = GetElementPtrInst::Create( |
258 "field", InsertPt); | 260 TemplateType, TypedThreadPtr, Indexes, "field", InsertPt); |
259 PhiSafeReplaceUses(U, TlsField); | 261 PhiSafeReplaceUses(U, TlsField); |
260 } | 262 } |
261 VarInfo->TlsVar->eraseFromParent(); | 263 VarInfo->TlsVar->eraseFromParent(); |
262 } | 264 } |
263 } | 265 } |
264 | 266 |
265 static void replaceFunction(Module &M, const char *Name, Value *NewFunc) { | 267 static void replaceFunction(Module &M, const char *Name, Value *NewFunc) { |
266 if (Function *Func = M.getFunction(Name)) { | 268 if (Function *Func = M.getFunction(Name)) { |
267 if (Func->hasLocalLinkage()) | 269 if (Func->hasLocalLinkage()) |
268 return; | 270 return; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 ReturnInst::Create(M.getContext(), Result, BB); | 316 ReturnInst::Create(M.getContext(), Result, BB); |
315 replaceFunction(M, "__nacl_tp_tls_offset", NewFunc); | 317 replaceFunction(M, "__nacl_tp_tls_offset", NewFunc); |
316 } | 318 } |
317 | 319 |
318 bool ExpandTls::runOnModule(Module &M) { | 320 bool ExpandTls::runOnModule(Module &M) { |
319 ModulePass *Pass = createExpandTlsConstantExprPass(); | 321 ModulePass *Pass = createExpandTlsConstantExprPass(); |
320 Pass->runOnModule(M); | 322 Pass->runOnModule(M); |
321 delete Pass; | 323 delete Pass; |
322 | 324 |
323 std::vector<VarInfo> TlsVars; | 325 std::vector<VarInfo> TlsVars; |
324 PointerType *TemplatePtrType = buildTlsTemplate(M, &TlsVars); | 326 StructType *TemplateType = buildTlsTemplate(M, &TlsVars); |
325 rewriteTlsVars(M, &TlsVars, TemplatePtrType); | 327 rewriteTlsVars(M, &TlsVars, TemplateType); |
326 | 328 |
327 defineTlsLayoutFunctions(M); | 329 defineTlsLayoutFunctions(M); |
328 | 330 |
329 return true; | 331 return true; |
330 } | 332 } |
331 | 333 |
332 ModulePass *llvm::createExpandTlsPass() { | 334 ModulePass *llvm::createExpandTlsPass() { |
333 return new ExpandTls(); | 335 return new ExpandTls(); |
334 } | 336 } |
OLD | NEW |