| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   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  Loading... | 
|  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 } | 
| OLD | NEW |