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/ADT/SmallVector.h" 18de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/CodeGen/Passes.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) { 66de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (skipModule(M)) 67de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return false; 68de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 69f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!TM || !TM->Options.EmulatedTLS) 70f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return false; 71f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 72f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar bool Changed = false; 73f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar SmallVector<const GlobalVariable*, 8> TlsVars; 74f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar for (const auto &G : M.globals()) { 75f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (G.isThreadLocal()) 76f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar TlsVars.append({&G}); 77f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 78f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar for (const auto G : TlsVars) 79f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Changed |= addEmuTlsVar(M, G); 80f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Changed; 81f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 82f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 83f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarbool LowerEmuTLS::addEmuTlsVar(Module &M, const GlobalVariable *GV) { 84f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar LLVMContext &C = M.getContext(); 85f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar PointerType *VoidPtrType = Type::getInt8PtrTy(C); 86f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 87f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::string EmuTlsVarName = ("__emutls_v." + GV->getName()).str(); 88f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar GlobalVariable *EmuTlsVar = M.getNamedGlobal(EmuTlsVarName); 89f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (EmuTlsVar) 90f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return false; // It has been added before. 91f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 92f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const DataLayout &DL = M.getDataLayout(); 93f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Constant *NullPtr = ConstantPointerNull::get(VoidPtrType); 94f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 95f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Get non-zero initializer from GV's initializer. 96f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const Constant *InitValue = nullptr; 97f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (GV->hasInitializer()) { 98f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar InitValue = GV->getInitializer(); 99f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const ConstantInt *InitIntValue = dyn_cast<ConstantInt>(InitValue); 100f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // When GV's init value is all 0, omit the EmuTlsTmplVar and let 101f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // the emutls library function to reset newly allocated TLS variables. 102f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (isa<ConstantAggregateZero>(InitValue) || 103f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar (InitIntValue && InitIntValue->isZero())) 104f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar InitValue = nullptr; 105f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 106f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 107f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Create the __emutls_v. symbol, whose type has 4 fields: 108f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // word size; // size of GV in bytes 109f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // word align; // alignment of GV 110f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // void *ptr; // initialized to 0; set at run time per thread. 111f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // void *templ; // 0 or point to __emutls_t.* 112f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // sizeof(word) should be the same as sizeof(void*) on target. 113f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar IntegerType *WordType = DL.getIntPtrType(C); 114f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar PointerType *InitPtrType = InitValue ? 115f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar PointerType::getUnqual(InitValue->getType()) : VoidPtrType; 116f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Type *ElementTypes[4] = {WordType, WordType, VoidPtrType, InitPtrType}; 117f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ArrayRef<Type*> ElementTypeArray(ElementTypes, 4); 118f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar StructType *EmuTlsVarType = StructType::create(ElementTypeArray); 119f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsVar = cast<GlobalVariable>( 120f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar M.getOrInsertGlobal(EmuTlsVarName, EmuTlsVarType)); 121f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar copyLinkageVisibility(M, GV, EmuTlsVar); 122f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 123f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Define "__emutls_t.*" and "__emutls_v.*" only if GV is defined. 124f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!GV->hasInitializer()) 125f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return true; 126f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 127f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Type *GVType = GV->getValueType(); 128f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar unsigned GVAlignment = GV->getAlignment(); 129f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!GVAlignment) { 130f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // When LLVM IL declares a variable without alignment, use 131f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // the ABI default alignment for the type. 132f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar GVAlignment = DL.getABITypeAlignment(GVType); 133f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 134f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 135f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Define "__emutls_t.*" if there is InitValue 136f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar GlobalVariable *EmuTlsTmplVar = nullptr; 137f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (InitValue) { 138f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::string EmuTlsTmplName = ("__emutls_t." + GV->getName()).str(); 139f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsTmplVar = dyn_cast_or_null<GlobalVariable>( 140f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar M.getOrInsertGlobal(EmuTlsTmplName, GVType)); 141f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar assert(EmuTlsTmplVar && "Failed to create emualted TLS initializer"); 142f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsTmplVar->setConstant(true); 143f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsTmplVar->setInitializer(const_cast<Constant*>(InitValue)); 144f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsTmplVar->setAlignment(GVAlignment); 145f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar copyLinkageVisibility(M, GV, EmuTlsTmplVar); 146f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 147f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 148f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Define "__emutls_v.*" with initializer and alignment. 149f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Constant *ElementValues[4] = { 150f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ConstantInt::get(WordType, DL.getTypeStoreSize(GVType)), 151f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ConstantInt::get(WordType, GVAlignment), 152f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar NullPtr, EmuTlsTmplVar ? EmuTlsTmplVar : NullPtr 153f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar }; 154f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ArrayRef<Constant*> ElementValueArray(ElementValues, 4); 155f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsVar->setInitializer( 156f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar ConstantStruct::get(EmuTlsVarType, ElementValueArray)); 157f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar unsigned MaxAlignment = std::max( 158f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DL.getABITypeAlignment(WordType), 159f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DL.getABITypeAlignment(VoidPtrType)); 160f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EmuTlsVar->setAlignment(MaxAlignment); 161f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return true; 162f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 163