1 //===-- MipsTargetObjectFile.cpp - Mips Object Files ----------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "MipsTargetObjectFile.h" 11 #include "MipsSubtarget.h" 12 #include "llvm/IR/DataLayout.h" 13 #include "llvm/IR/DerivedTypes.h" 14 #include "llvm/IR/GlobalVariable.h" 15 #include "llvm/MC/MCContext.h" 16 #include "llvm/MC/MCSectionELF.h" 17 #include "llvm/Support/CommandLine.h" 18 #include "llvm/Support/ELF.h" 19 #include "llvm/Target/TargetMachine.h" 20 using namespace llvm; 21 22 static cl::opt<unsigned> 23 SSThreshold("mips-ssection-threshold", cl::Hidden, 24 cl::desc("Small data and bss section threshold size (default=8)"), 25 cl::init(8)); 26 27 static cl::opt<bool> 28 LocalSData("mlocal-sdata", cl::Hidden, 29 cl::desc("MIPS: Use gp_rel for object-local data."), 30 cl::init(true)); 31 32 static cl::opt<bool> 33 ExternSData("mextern-sdata", cl::Hidden, 34 cl::desc("MIPS: Use gp_rel for data that is not defined by the " 35 "current object."), 36 cl::init(true)); 37 38 void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ 39 TargetLoweringObjectFileELF::Initialize(Ctx, TM); 40 InitializeELF(TM.Options.UseInitArray); 41 42 SmallDataSection = 43 getContext().getELFSection(".sdata", ELF::SHT_PROGBITS, 44 ELF::SHF_WRITE |ELF::SHF_ALLOC, 45 SectionKind::getDataRel()); 46 47 SmallBSSSection = 48 getContext().getELFSection(".sbss", ELF::SHT_NOBITS, 49 ELF::SHF_WRITE |ELF::SHF_ALLOC, 50 SectionKind::getBSS()); 51 this->TM = &TM; 52 } 53 54 // A address must be loaded from a small section if its size is less than the 55 // small section size threshold. Data in this section must be addressed using 56 // gp_rel operator. 57 static bool IsInSmallSection(uint64_t Size) { 58 // gcc has traditionally not treated zero-sized objects as small data, so this 59 // is effectively part of the ABI. 60 return Size > 0 && Size <= SSThreshold; 61 } 62 63 /// Return true if this global address should be placed into small data/bss 64 /// section. 65 bool MipsTargetObjectFile:: 66 IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM) const { 67 // We first check the case where global is a declaration, because finding 68 // section kind using getKindForGlobal() is only allowed for global 69 // definitions. 70 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) 71 return IsGlobalInSmallSectionImpl(GV, TM); 72 73 return IsGlobalInSmallSection(GV, TM, getKindForGlobal(GV, TM)); 74 } 75 76 /// Return true if this global address should be placed into small data/bss 77 /// section. 78 bool MipsTargetObjectFile:: 79 IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, 80 SectionKind Kind) const { 81 return (IsGlobalInSmallSectionImpl(GV, TM) && 82 (Kind.isDataRel() || Kind.isBSS() || Kind.isCommon())); 83 } 84 85 /// Return true if this global address should be placed into small data/bss 86 /// section. This method does all the work, except for checking the section 87 /// kind. 88 bool MipsTargetObjectFile:: 89 IsGlobalInSmallSectionImpl(const GlobalValue *GV, 90 const TargetMachine &TM) const { 91 const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); 92 93 // Return if small section is not available. 94 if (!Subtarget.useSmallSection()) 95 return false; 96 97 // Only global variables, not functions. 98 const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GV); 99 if (!GVA) 100 return false; 101 102 // Enforce -mlocal-sdata. 103 if (!LocalSData && GV->hasLocalLinkage()) 104 return false; 105 106 // Enforce -mextern-sdata. 107 if (!ExternSData && ((GV->hasExternalLinkage() && GV->isDeclaration()) || 108 GV->hasCommonLinkage())) 109 return false; 110 111 Type *Ty = GV->getType()->getElementType(); 112 return IsInSmallSection( 113 TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize(Ty)); 114 } 115 116 const MCSection *MipsTargetObjectFile:: 117 SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, 118 Mangler &Mang, const TargetMachine &TM) const { 119 // TODO: Could also support "weak" symbols as well with ".gnu.linkonce.s.*" 120 // sections? 121 122 // Handle Small Section classification here. 123 if (Kind.isBSS() && IsGlobalInSmallSection(GV, TM, Kind)) 124 return SmallBSSSection; 125 if (Kind.isDataRel() && IsGlobalInSmallSection(GV, TM, Kind)) 126 return SmallDataSection; 127 128 // Otherwise, we work the same as ELF. 129 return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang,TM); 130 } 131 132 /// Return true if this constant should be placed into small data section. 133 bool MipsTargetObjectFile:: 134 IsConstantInSmallSection(const Constant *CN, const TargetMachine &TM) const { 135 return (TM.getSubtarget<MipsSubtarget>().useSmallSection() && 136 LocalSData && 137 IsInSmallSection(TM.getSubtargetImpl()->getDataLayout() 138 ->getTypeAllocSize(CN->getType()))); 139 } 140 141 const MCSection *MipsTargetObjectFile:: 142 getSectionForConstant(SectionKind Kind, const Constant *C) const { 143 if (IsConstantInSmallSection(C, *TM)) 144 return SmallDataSection; 145 146 // Otherwise, we work the same as ELF. 147 return TargetLoweringObjectFileELF::getSectionForConstant(Kind, C); 148 } 149