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 (Kind.isBSS() && isGlobalInSmallSection(GO, TM)) 109 return SmallBSSSection; 110 if (Kind.isData() && isGlobalInSmallSection(GO, TM)) 111 return SmallDataSection; 112 113 // Otherwise, we work the same as ELF. 114 return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM); 115 } 116 117 void RISCVELFTargetObjectFile::getModuleMetadata(Module &M) { 118 TargetLoweringObjectFileELF::getModuleMetadata(M); 119 SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags; 120 M.getModuleFlagsMetadata(ModuleFlags); 121 122 for (const auto &MFE : ModuleFlags) { 123 StringRef Key = MFE.Key->getString(); 124 if (Key == "SmallDataLimit") { 125 SSThreshold = mdconst::extract<ConstantInt>(MFE.Val)->getZExtValue(); 126 break; 127 } 128 } 129 } 130 131 /// Return true if this constant should be placed into small data section. 132 bool RISCVELFTargetObjectFile::isConstantInSmallSection( 133 const DataLayout &DL, const Constant *CN) const { 134 return isInSmallSection(DL.getTypeAllocSize(CN->getType())); 135 } 136 137 MCSection *RISCVELFTargetObjectFile::getSectionForConstant( 138 const DataLayout &DL, SectionKind Kind, const Constant *C, 139 Align &Alignment) const { 140 if (isConstantInSmallSection(DL, C)) { 141 if (Kind.isMergeableConst4()) 142 return SmallROData4Section; 143 if (Kind.isMergeableConst8()) 144 return SmallROData8Section; 145 if (Kind.isMergeableConst16()) 146 return SmallROData16Section; 147 if (Kind.isMergeableConst32()) 148 return SmallROData32Section; 149 // LLVM only generate up to .rodata.cst32, and use .rodata section if more 150 // than 32 bytes, so just use .srodata here. 151 return SmallRODataSection; 152 } 153 154 // Otherwise, we work the same as ELF. 155 return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, 156 Alignment); 157 } 158