1 //===-- RISCVTargetObjectFile.cpp - RISC-V Object Info --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "RISCVTargetObjectFile.h" 10 #include "MCTargetDesc/RISCVMCObjectFileInfo.h" 11 #include "RISCVTargetMachine.h" 12 #include "llvm/BinaryFormat/ELF.h" 13 #include "llvm/MC/MCContext.h" 14 #include "llvm/MC/MCSectionELF.h" 15 16 using namespace llvm; 17 18 unsigned RISCVELFTargetObjectFile::getTextSectionAlignment() const { 19 return RISCVMCObjectFileInfo::getTextSectionAlignment( 20 *getContext().getSubtargetInfo()); 21 } 22 23 void RISCVELFTargetObjectFile::Initialize(MCContext &Ctx, 24 const TargetMachine &TM) { 25 TargetLoweringObjectFileELF::Initialize(Ctx, TM); 26 27 PLTRelativeVariantKind = MCSymbolRefExpr::VK_PLT; 28 29 SmallDataSection = getContext().getELFSection( 30 ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); 31 SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS, 32 ELF::SHF_WRITE | ELF::SHF_ALLOC); 33 } 34 35 // A address must be loaded from a small section if its size is less than the 36 // small section size threshold. Data in this section could be addressed by 37 // using gp_rel operator. 38 bool RISCVELFTargetObjectFile::isInSmallSection(uint64_t Size) const { 39 // gcc has traditionally not treated zero-sized objects as small data, so this 40 // is effectively part of the ABI. 41 return Size > 0 && Size <= SSThreshold; 42 } 43 44 // Return true if this global address should be placed into small data/bss 45 // section. 46 bool RISCVELFTargetObjectFile::isGlobalInSmallSection( 47 const GlobalObject *GO, const TargetMachine &TM) const { 48 // Only global variables, not functions. 49 const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GO); 50 if (!GVA) 51 return false; 52 53 // If the variable has an explicit section, it is placed in that section. 54 if (GVA->hasSection()) { 55 StringRef Section = GVA->getSection(); 56 57 // Explicitly placing any variable in the small data section overrides 58 // the global -G value. 59 if (Section == ".sdata" || Section == ".sbss") 60 return true; 61 62 // Otherwise reject putting the variable to small section if it has an 63 // explicit section name. 64 return false; 65 } 66 67 if (((GVA->hasExternalLinkage() && GVA->isDeclaration()) || 68 GVA->hasCommonLinkage())) 69 return false; 70 71 Type *Ty = GVA->getValueType(); 72 // It is possible that the type of the global is unsized, i.e. a declaration 73 // of a extern struct. In this case don't presume it is in the small data 74 // section. This happens e.g. when building the FreeBSD kernel. 75 if (!Ty->isSized()) 76 return false; 77 78 return isInSmallSection( 79 GVA->getParent()->getDataLayout().getTypeAllocSize(Ty)); 80 } 81 82 MCSection *RISCVELFTargetObjectFile::SelectSectionForGlobal( 83 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { 84 // Handle Small Section classification here. 85 if (Kind.isBSS() && isGlobalInSmallSection(GO, TM)) 86 return SmallBSSSection; 87 if (Kind.isData() && isGlobalInSmallSection(GO, TM)) 88 return SmallDataSection; 89 90 // Otherwise, we work the same as ELF. 91 return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM); 92 } 93 94 void RISCVELFTargetObjectFile::getModuleMetadata(Module &M) { 95 TargetLoweringObjectFileELF::getModuleMetadata(M); 96 SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags; 97 M.getModuleFlagsMetadata(ModuleFlags); 98 99 for (const auto &MFE : ModuleFlags) { 100 StringRef Key = MFE.Key->getString(); 101 if (Key == "SmallDataLimit") { 102 SSThreshold = mdconst::extract<ConstantInt>(MFE.Val)->getZExtValue(); 103 break; 104 } 105 } 106 } 107 108 /// Return true if this constant should be placed into small data section. 109 bool RISCVELFTargetObjectFile::isConstantInSmallSection( 110 const DataLayout &DL, const Constant *CN) const { 111 return isInSmallSection(DL.getTypeAllocSize(CN->getType())); 112 } 113 114 MCSection *RISCVELFTargetObjectFile::getSectionForConstant( 115 const DataLayout &DL, SectionKind Kind, const Constant *C, 116 Align &Alignment) const { 117 if (isConstantInSmallSection(DL, C)) 118 return SmallDataSection; 119 120 // Otherwise, we work the same as ELF. 121 return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, 122 Alignment); 123 } 124