| 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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 |