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 = getContext().getELFSection( 43 ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); 44 45 SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS, 46 ELF::SHF_WRITE | ELF::SHF_ALLOC); 47 this->TM = &TM; 48 } 49 50 // A address must be loaded from a small section if its size is less than the 51 // small section size threshold. Data in this section must be addressed using 52 // gp_rel operator. 53 static bool IsInSmallSection(uint64_t Size) { 54 // gcc has traditionally not treated zero-sized objects as small data, so this 55 // is effectively part of the ABI. 56 return Size > 0 && Size <= SSThreshold; 57 } 58 59 /// Return true if this global address should be placed into small data/bss 60 /// section. 61 bool MipsTargetObjectFile:: 62 IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM) const { 63 // We first check the case where global is a declaration, because finding 64 // section kind using getKindForGlobal() is only allowed for global 65 // definitions. 66 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) 67 return IsGlobalInSmallSectionImpl(GV, TM); 68 69 return IsGlobalInSmallSection(GV, TM, getKindForGlobal(GV, TM)); 70 } 71 72 /// Return true if this global address should be placed into small data/bss 73 /// section. 74 bool MipsTargetObjectFile:: 75 IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, 76 SectionKind Kind) const { 77 return (IsGlobalInSmallSectionImpl(GV, TM) && 78 (Kind.isDataRel() || Kind.isBSS() || Kind.isCommon())); 79 } 80 81 /// Return true if this global address should be placed into small data/bss 82 /// section. This method does all the work, except for checking the section 83 /// kind. 84 bool MipsTargetObjectFile:: 85 IsGlobalInSmallSectionImpl(const GlobalValue *GV, 86 const TargetMachine &TM) const { 87 const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); 88 89 // Return if small section is not available. 90 if (!Subtarget.useSmallSection()) 91 return false; 92 93 // Only global variables, not functions. 94 const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GV); 95 if (!GVA) 96 return false; 97 98 // Enforce -mlocal-sdata. 99 if (!LocalSData && GV->hasLocalLinkage()) 100 return false; 101 102 // Enforce -mextern-sdata. 103 if (!ExternSData && ((GV->hasExternalLinkage() && GV->isDeclaration()) || 104 GV->hasCommonLinkage())) 105 return false; 106 107 Type *Ty = GV->getType()->getElementType(); 108 return IsInSmallSection(TM.getDataLayout()->getTypeAllocSize(Ty)); 109 } 110 111 const MCSection *MipsTargetObjectFile:: 112 SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, 113 Mangler &Mang, const TargetMachine &TM) const { 114 // TODO: Could also support "weak" symbols as well with ".gnu.linkonce.s.*" 115 // sections? 116 117 // Handle Small Section classification here. 118 if (Kind.isBSS() && IsGlobalInSmallSection(GV, TM, Kind)) 119 return SmallBSSSection; 120 if (Kind.isDataRel() && IsGlobalInSmallSection(GV, TM, Kind)) 121 return SmallDataSection; 122 123 // Otherwise, we work the same as ELF. 124 return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang,TM); 125 } 126 127 /// Return true if this constant should be placed into small data section. 128 bool MipsTargetObjectFile:: 129 IsConstantInSmallSection(const Constant *CN, const TargetMachine &TM) const { 130 return ( 131 TM.getSubtarget<MipsSubtarget>().useSmallSection() && LocalSData && 132 IsInSmallSection(TM.getDataLayout()->getTypeAllocSize(CN->getType()))); 133 } 134 135 const MCSection *MipsTargetObjectFile:: 136 getSectionForConstant(SectionKind Kind, const Constant *C) const { 137 if (IsConstantInSmallSection(C, *TM)) 138 return SmallDataSection; 139 140 // Otherwise, we work the same as ELF. 141 return TargetLoweringObjectFileELF::getSectionForConstant(Kind, C); 142 } 143