LowerEmuTLS.cpp revision f3ef5332fa3f4d5ec72c178a2b19dac363a19383
1f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar//===- LowerEmuTLS.cpp - Add __emutls_[vt].* variables --------------------===// 2f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// 3f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// The LLVM Compiler Infrastructure 4f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// 5f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source 6f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// License. See LICENSE.TXT for details. 7f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// 8f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar//===----------------------------------------------------------------------===// 9f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// 10f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// This transformation is required for targets depending on libgcc style 11f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// emulated thread local storage variables. For every defined TLS variable xyz, 12f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// an __emutls_v.xyz is generated. If there is non-zero initialized value 13f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// an __emutls_t.xyz is also generated. 14f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar// 15f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar//===----------------------------------------------------------------------===// 16f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 17f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Transforms/Scalar.h" 18f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/ADT/SmallVector.h" 19f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/IR/LLVMContext.h" 20f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/IR/Module.h" 21f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Pass.h" 22f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Target/TargetLowering.h" 23f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 24f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarusing namespace llvm; 25f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 26f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#define DEBUG_TYPE "loweremutls" 27f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 28f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarnamespace { 29f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 30f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarclass LowerEmuTLS : public ModulePass { 31f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const TargetMachine *TM; 32f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarpublic: 33f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar static char ID; // Pass identification, replacement for typeid 34f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar explicit LowerEmuTLS() : ModulePass(ID), TM(nullptr) { } 35f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar explicit LowerEmuTLS(const TargetMachine *TM) 36f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar : ModulePass(ID), TM(TM) { 37f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar initializeLowerEmuTLSPass(*PassRegistry::getPassRegistry()); 38f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 39f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar bool runOnModule(Module &M) override; 40f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarprivate: 41f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar bool addEmuTlsVar(Module &M, const GlobalVariable *GV); 42f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar static void copyLinkageVisibility(Module &M, 43f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const GlobalVariable *from, 44f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar GlobalVariable *to) { 45f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar to->setLinkage(from->getLinkage()); 46f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar to->setVisibility(from->getVisibility()); 47f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (from->hasComdat()) { 48f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar to->setComdat(M.getOrInsertComdat(to->getName())); 49f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar to->getComdat()->setSelectionKind(from->getComdat()->getSelectionKind()); 50f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 51f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 52f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar}; 53f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 54f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 55f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarchar LowerEmuTLS::ID = 0; 56f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 57f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga NainarINITIALIZE_PASS(LowerEmuTLS, "loweremutls", 58f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar "Add __emutls_[vt]. variables for emultated TLS model", 59f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar false, false) 60f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 61f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga NainarModulePass *llvm::createLowerEmuTLSPass(const TargetMachine *TM) { 62f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return new LowerEmuTLS(TM); 63f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 64f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 65f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarbool LowerEmuTLS::runOnModule(Module &M) { 66f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!TM || !TM->Options.EmulatedTLS) 67f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return false; 68f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 69f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar bool Changed = false; 70f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar SmallVector<const GlobalVariable*, 8> TlsVars; 71f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar for (const auto &G : M.globals()) { 72f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (G.isThreadLocal()) 73f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar TlsVars.append({&G}); 74f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 75f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar for (const auto G : TlsVars) 76f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Changed |= addEmuTlsVar(M, G); 77f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Changed; 78f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 79f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 80f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarbool LowerEmuTLS::addEmuTlsVar(Module &M, const GlobalVariable *GV) { 81f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar LLVMContext &C = M.getContext(); 82f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar PointerType *VoidPtrType = Type::getInt8PtrTy(C); 83f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 84f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::string EmuTlsVarName = ("__emutls_v." + GV->getName()).str(); 85f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar GlobalVariable *EmuTlsVar = M.getNamedGlobal(EmuTlsVarName); 86f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (EmuTlsVar) 87f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return false; // It has been added before. 88f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 89f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const DataLayout &DL = M.getDataLayout(); 90f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Constant *NullPtr = ConstantPointerNull::get(VoidPtrType); 91f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 92f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Get non-zero initializer from GV's initializer. 93f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const Constant *InitValue = nullptr; 94f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (GV->hasInitializer()) { 95f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar InitValue = GV->getInitializer(); 96f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const ConstantInt *InitIntValue = dyn_cast<ConstantInt>(InitValue); 97f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // When GV's init value is all 0, omit the EmuTlsTmplVar and let 98f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // the emutls library function to reset newly allocated TLS variables. 99f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (isa<ConstantAggregateZero>(InitValue) || 100f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar (InitIntValue && InitIntValue->isZero())) 101f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar InitValue = nullptr; 102f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 103f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 104f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Create the __emutls_v. symbol, whose type has 4 fields: 105f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // word size; // size of GV in bytes 106f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // word align; // alignment of GV 107f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // void *ptr; // initialized to 0; set at run time per thread. 108f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // void *templ; // 0 or point to __emutls_t.* 109f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // sizeof(word) should be the same as sizeof(void*) on target. 110f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar IntegerType *WordType = DL.getIntPtrType(C); 111f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar PointerType *InitPtrType = InitValue ? 112f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar PointerType::getUnqual(InitValue->getType()) : VoidPtrType; 113f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Type *ElementTypes[4] = {WordType, WordType, VoidPtrType, InitPtrType}; 114f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ArrayRef<Type*> ElementTypeArray(ElementTypes, 4); 115f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar StructType *EmuTlsVarType = StructType::create(ElementTypeArray); 116f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsVar = cast<GlobalVariable>( 117f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar M.getOrInsertGlobal(EmuTlsVarName, EmuTlsVarType)); 118f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar copyLinkageVisibility(M, GV, EmuTlsVar); 119f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 120f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Define "__emutls_t.*" and "__emutls_v.*" only if GV is defined. 121f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!GV->hasInitializer()) 122f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return true; 123f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 124f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Type *GVType = GV->getValueType(); 125f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar unsigned GVAlignment = GV->getAlignment(); 126f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!GVAlignment) { 127f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // When LLVM IL declares a variable without alignment, use 128f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // the ABI default alignment for the type. 129f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar GVAlignment = DL.getABITypeAlignment(GVType); 130f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 131f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 132f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Define "__emutls_t.*" if there is InitValue 133f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar GlobalVariable *EmuTlsTmplVar = nullptr; 134f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (InitValue) { 135f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::string EmuTlsTmplName = ("__emutls_t." + GV->getName()).str(); 136f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsTmplVar = dyn_cast_or_null<GlobalVariable>( 137f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar M.getOrInsertGlobal(EmuTlsTmplName, GVType)); 138f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar assert(EmuTlsTmplVar && "Failed to create emualted TLS initializer"); 139f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsTmplVar->setConstant(true); 140f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsTmplVar->setInitializer(const_cast<Constant*>(InitValue)); 141f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsTmplVar->setAlignment(GVAlignment); 142f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar copyLinkageVisibility(M, GV, EmuTlsTmplVar); 143f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 144f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 145f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Define "__emutls_v.*" with initializer and alignment. 146f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Constant *ElementValues[4] = { 147f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ConstantInt::get(WordType, DL.getTypeStoreSize(GVType)), 148f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ConstantInt::get(WordType, GVAlignment), 149f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar NullPtr, EmuTlsTmplVar ? EmuTlsTmplVar : NullPtr 150f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar }; 151f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ArrayRef<Constant*> ElementValueArray(ElementValues, 4); 152f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsVar->setInitializer( 153f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ConstantStruct::get(EmuTlsVarType, ElementValueArray)); 154f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar unsigned MaxAlignment = std::max( 155f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DL.getABITypeAlignment(WordType), 156f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DL.getABITypeAlignment(VoidPtrType)); 157f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsVar->setAlignment(MaxAlignment); 158f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return true; 159f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 160