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 "MipsTargetMachine.h" 13 #include "llvm/IR/DataLayout.h" 14 #include "llvm/IR/DerivedTypes.h" 15 #include "llvm/IR/GlobalVariable.h" 16 #include "llvm/MC/MCContext.h" 17 #include "llvm/MC/MCSectionELF.h" 18 #include "llvm/Support/CommandLine.h" 19 #include "llvm/Support/ELF.h" 20 #include "llvm/Target/TargetMachine.h" 21 using namespace llvm; 22 23 static cl::opt<unsigned> 24 SSThreshold("mips-ssection-threshold", cl::Hidden, 25 cl::desc("Small data and bss section threshold size (default=8)"), 26 cl::init(8)); 27 28 static cl::opt<bool> 29 LocalSData("mlocal-sdata", cl::Hidden, 30 cl::desc("MIPS: Use gp_rel for object-local data."), 31 cl::init(true)); 32 33 static cl::opt<bool> 34 ExternSData("mextern-sdata", cl::Hidden, 35 cl::desc("MIPS: Use gp_rel for data that is not defined by the " 36 "current object."), 37 cl::init(true)); 38 39 void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ 40 TargetLoweringObjectFileELF::Initialize(Ctx, TM); 41 InitializeELF(TM.Options.UseInitArray); 42 43 SmallDataSection = getContext().getELFSection( 44 ".sdata", ELF::SHT_PROGBITS, 45 ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL); 46 47 SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS, 48 ELF::SHF_WRITE | ELF::SHF_ALLOC | 49 ELF::SHF_MIPS_GPREL); 50 this->TM = &static_cast<const MipsTargetMachine &>(TM); 51 } 52 53 // A address must be loaded from a small section if its size is less than the 54 // small section size threshold. Data in this section must be addressed using 55 // gp_rel operator. 56 static bool IsInSmallSection(uint64_t Size) { 57 // gcc has traditionally not treated zero-sized objects as small data, so this 58 // is effectively part of the ABI. 59 return Size > 0 && Size <= SSThreshold; 60 } 61 62 /// Return true if this global address should be placed into small data/bss 63 /// section. 64 bool MipsTargetObjectFile:: 65 IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM) const { 66 // We first check the case where global is a declaration, because finding 67 // section kind using getKindForGlobal() is only allowed for global 68 // definitions. 69 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) 70 return IsGlobalInSmallSectionImpl(GV, TM); 71 72 return IsGlobalInSmallSection(GV, TM, getKindForGlobal(GV, TM)); 73 } 74 75 /// Return true if this global address should be placed into small data/bss 76 /// section. 77 bool MipsTargetObjectFile:: 78 IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, 79 SectionKind Kind) const { 80 return (IsGlobalInSmallSectionImpl(GV, TM) && 81 (Kind.isData() || Kind.isBSS() || Kind.isCommon())); 82 } 83 84 /// Return true if this global address should be placed into small data/bss 85 /// section. This method does all the work, except for checking the section 86 /// kind. 87 bool MipsTargetObjectFile:: 88 IsGlobalInSmallSectionImpl(const GlobalValue *GV, 89 const TargetMachine &TM) const { 90 const MipsSubtarget &Subtarget = 91 *static_cast<const MipsTargetMachine &>(TM).getSubtargetImpl(); 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->getValueType(); 112 return IsInSmallSection( 113 GV->getParent()->getDataLayout().getTypeAllocSize(Ty)); 114 } 115 116 MCSection * 117 MipsTargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV, 118 SectionKind Kind, Mangler &Mang, 119 const TargetMachine &TM) const { 120 // TODO: Could also support "weak" symbols as well with ".gnu.linkonce.s.*" 121 // sections? 122 123 // Handle Small Section classification here. 124 if (Kind.isBSS() && IsGlobalInSmallSection(GV, TM, Kind)) 125 return SmallBSSSection; 126 if (Kind.isData() && IsGlobalInSmallSection(GV, TM, Kind)) 127 return SmallDataSection; 128 129 // Otherwise, we work the same as ELF. 130 return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang,TM); 131 } 132 133 /// Return true if this constant should be placed into small data section. 134 bool MipsTargetObjectFile::IsConstantInSmallSection( 135 const DataLayout &DL, const Constant *CN, const TargetMachine &TM) const { 136 return (static_cast<const MipsTargetMachine &>(TM) 137 .getSubtargetImpl() 138 ->useSmallSection() && 139 LocalSData && IsInSmallSection(DL.getTypeAllocSize(CN->getType()))); 140 } 141 142 /// Return true if this constant should be placed into small data section. 143 MCSection *MipsTargetObjectFile::getSectionForConstant(const DataLayout &DL, 144 SectionKind Kind, 145 const Constant *C, 146 unsigned &Align) const { 147 if (IsConstantInSmallSection(DL, C, *TM)) 148 return SmallDataSection; 149 150 // Otherwise, we work the same as ELF. 151 return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, Align); 152 } 153