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/IR/Module.h" 14 #include "llvm/MC/MCContext.h" 15 #include "llvm/MC/MCSectionELF.h" 16 #include "llvm/MC/MCValue.h" 17 18 using namespace llvm; 19 20 unsigned RISCVELFTargetObjectFile::getTextSectionAlignment() const { 21 return RISCVMCObjectFileInfo::getTextSectionAlignment( 22 *getContext().getSubtargetInfo()); 23 } 24 25 void RISCVELFTargetObjectFile::Initialize(MCContext &Ctx, 26 const TargetMachine &TM) { 27 TargetLoweringObjectFileELF::Initialize(Ctx, TM); 28 29 PLTRelativeVariantKind = MCSymbolRefExpr::VK_PLT; 30 SupportIndirectSymViaGOTPCRel = true; 31 32 SmallDataSection = getContext().getELFSection( 33 ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); 34 SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS, 35 ELF::SHF_WRITE | ELF::SHF_ALLOC); 36 SmallRODataSection = 37 getContext().getELFSection(".srodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC); 38 SmallROData4Section = getContext().getELFSection( 39 ".srodata.cst4", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_MERGE, 4); 40 SmallROData8Section = getContext().getELFSection( 41 ".srodata.cst8", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_MERGE, 8); 42 SmallROData16Section = getContext().getELFSection( 43 ".srodata.cst16", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_MERGE, 16); 44 SmallROData32Section = getContext().getELFSection( 45 ".srodata.cst32", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_MERGE, 32); 46 } 47 48 const MCExpr *RISCVELFTargetObjectFile::getIndirectSymViaGOTPCRel( 49 const GlobalValue *GV, const MCSymbol *Sym, const MCValue &MV, 50 int64_t Offset, MachineModuleInfo *MMI, MCStreamer &Streamer) const { 51 int64_t FinalOffset = Offset + MV.getConstant(); 52 const MCExpr *Res = 53 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTPCREL, getContext()); 54 const MCExpr *Off = MCConstantExpr::create(FinalOffset, getContext()); 55 return MCBinaryExpr::createAdd(Res, Off, getContext()); 56 } 57 58 // A address must be loaded from a small section if its size is less than the 59 // small section size threshold. Data in this section could be addressed by 60 // using gp_rel operator. 61 bool RISCVELFTargetObjectFile::isInSmallSection(uint64_t Size) const { 62 // gcc has traditionally not treated zero-sized objects as small data, so this 63 // is effectively part of the ABI. 64 return Size > 0 && Size <= SSThreshold; 65 } 66 67 // Return true if this global address should be placed into small data/bss 68 // section. 69 bool RISCVELFTargetObjectFile::isGlobalInSmallSection( 70 const GlobalObject *GO, const TargetMachine &TM) const { 71 // Only global variables, not functions. 72 const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GO); 73 if (!GVA) 74 return false; 75 76 // If the variable has an explicit section, it is placed in that section. 77 if (GVA->hasSection()) { 78 StringRef Section = GVA->getSection(); 79 80 // Explicitly placing any variable in the small data section overrides 81 // the global -G value. 82 if (Section == ".sdata" || Section == ".sbss") 83 return true; 84 85 // Otherwise reject putting the variable to small section if it has an 86 // explicit section name. 87 return false; 88 } 89 90 if (((GVA->hasExternalLinkage() && GVA->isDeclaration()) || 91 GVA->hasCommonLinkage())) 92 return false; 93 94 Type *Ty = GVA->getValueType(); 95 // It is possible that the type of the global is unsized, i.e. a declaration 96 // of a extern struct. In this case don't presume it is in the small data 97 // section. This happens e.g. when building the FreeBSD kernel. 98 if (!Ty->isSized()) 99 return false; 100 101 return isInSmallSection( 102 GVA->getDataLayout().getTypeAllocSize(Ty)); 103 } 104 105 MCSection *RISCVELFTargetObjectFile::SelectSectionForGlobal( 106 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { 107 // Handle Small Section classification here. 108 if (isGlobalInSmallSection(GO, TM)) { 109 // Emit to an unique sdata/sbss section when -fdata-section is set. 110 // However, if a symbol has an explicit sdata/sbss section, place it in that 111 // section. 112 bool EmitUniquedSection = TM.getDataSections() && !GO->hasSection(); 113 114 if (Kind.isBSS()) { 115 if (EmitUniquedSection) { 116 SmallString<128> Name(".sbss."); 117 Name.append(GO->getName()); 118 return getContext().getELFSection(Name.str(), ELF::SHT_NOBITS, 119 ELF::SHF_WRITE | ELF::SHF_ALLOC); 120 } 121 122 return SmallBSSSection; 123 } 124 125 if (Kind.isData()) { 126 if (EmitUniquedSection) { 127 SmallString<128> Name(".sdata."); 128 Name.append(GO->getName()); 129 return getContext().getELFSection(Name.str(), ELF::SHT_PROGBITS, 130 ELF::SHF_WRITE | ELF::SHF_ALLOC); 131 } 132 133 return SmallDataSection; 134 } 135 } 136 137 // Otherwise, we work the same as ELF. 138 return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM); 139 } 140 141 void RISCVELFTargetObjectFile::getModuleMetadata(Module &M) { 142 TargetLoweringObjectFileELF::getModuleMetadata(M); 143 SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags; 144 M.getModuleFlagsMetadata(ModuleFlags); 145 146 for (const auto &MFE : ModuleFlags) { 147 StringRef Key = MFE.Key->getString(); 148 if (Key == "SmallDataLimit") { 149 SSThreshold = mdconst::extract<ConstantInt>(MFE.Val)->getZExtValue(); 150 break; 151 } 152 } 153 } 154 155 /// Return true if this constant should be placed into small data section. 156 bool RISCVELFTargetObjectFile::isConstantInSmallSection( 157 const DataLayout &DL, const Constant *CN) const { 158 return isInSmallSection(DL.getTypeAllocSize(CN->getType())); 159 } 160 161 MCSection *RISCVELFTargetObjectFile::getSectionForConstant( 162 const DataLayout &DL, SectionKind Kind, const Constant *C, 163 Align &Alignment) const { 164 if (C && isConstantInSmallSection(DL, C)) { 165 if (Kind.isMergeableConst4()) 166 return SmallROData4Section; 167 if (Kind.isMergeableConst8()) 168 return SmallROData8Section; 169 if (Kind.isMergeableConst16()) 170 return SmallROData16Section; 171 if (Kind.isMergeableConst32()) 172 return SmallROData32Section; 173 // LLVM only generate up to .rodata.cst32, and use .rodata section if more 174 // than 32 bytes, so just use .srodata here. 175 return SmallRODataSection; 176 } 177 178 // Otherwise, we work the same as ELF. 179 return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, 180 Alignment); 181 } 182