462 lines · cpp
1//===-- HexagonTargetObjectFile.cpp ---------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the declarations of the HexagonTargetAsmInfo properties.10//11//===----------------------------------------------------------------------===//12 13#include "HexagonTargetObjectFile.h"14#include "llvm/ADT/SmallString.h"15#include "llvm/ADT/StringRef.h"16#include "llvm/ADT/Twine.h"17#include "llvm/BinaryFormat/ELF.h"18#include "llvm/IR/DataLayout.h"19#include "llvm/IR/DerivedTypes.h"20#include "llvm/IR/GlobalObject.h"21#include "llvm/IR/GlobalValue.h"22#include "llvm/IR/GlobalVariable.h"23#include "llvm/IR/Module.h"24#include "llvm/IR/Type.h"25#include "llvm/MC/MCContext.h"26#include "llvm/MC/SectionKind.h"27#include "llvm/Support/Casting.h"28#include "llvm/Support/CommandLine.h"29#include "llvm/Support/Debug.h"30#include "llvm/Support/raw_ostream.h"31#include "llvm/Target/TargetMachine.h"32 33#define DEBUG_TYPE "hexagon-sdata"34 35using namespace llvm;36 37static cl::opt<unsigned> SmallDataThreshold("hexagon-small-data-threshold",38 cl::init(8), cl::Hidden,39 cl::desc("The maximum size of an object in the sdata section"));40 41static cl::opt<bool> NoSmallDataSorting("mno-sort-sda", cl::init(false),42 cl::Hidden, cl::desc("Disable small data sections sorting"));43 44static cl::opt<bool>45 StaticsInSData("hexagon-statics-in-small-data", cl::Hidden,46 cl::desc("Allow static variables in .sdata"));47 48static cl::opt<bool> TraceGVPlacement("trace-gv-placement",49 cl::Hidden, cl::init(false),50 cl::desc("Trace global value placement"));51 52static cl::opt<bool>53 EmitJtInText("hexagon-emit-jt-text", cl::Hidden, cl::init(false),54 cl::desc("Emit hexagon jump tables in function section"));55 56static cl::opt<bool>57 EmitLutInText("hexagon-emit-lut-text", cl::Hidden, cl::init(false),58 cl::desc("Emit hexagon lookup tables in function section"));59 60// TraceGVPlacement controls messages for all builds. For builds with assertions61// (debug or release), messages are also controlled by the usual debug flags62// (e.g. -debug and -debug-only=globallayout)63#define TRACE_TO(s, X) s << X64#ifdef NDEBUG65#define TRACE(X) \66 do { \67 if (TraceGVPlacement) { \68 TRACE_TO(errs(), X); \69 } \70 } while (false)71#else72#define TRACE(X) \73 do { \74 if (TraceGVPlacement) { \75 TRACE_TO(errs(), X); \76 } else { \77 LLVM_DEBUG(TRACE_TO(dbgs(), X)); \78 } \79 } while (false)80#endif81 82// Returns true if the section name is such that the symbol will be put83// in a small data section.84// For instance, global variables with section attributes such as ".sdata"85// ".sdata.*", ".sbss", and ".sbss.*" will go into small data.86static bool isSmallDataSection(StringRef Sec) {87 // sectionName is either ".sdata" or ".sbss". Looking for an exact match88 // obviates the need for checks for section names such as ".sdatafoo".89 if (Sec == ".sdata" || Sec == ".sbss" || Sec == ".scommon")90 return true;91 // If either ".sdata." or ".sbss." is a substring of the section name92 // then put the symbol in small data.93 return Sec.contains(".sdata.") || Sec.contains(".sbss.") ||94 Sec.contains(".scommon.");95}96 97static const char *getSectionSuffixForSize(unsigned Size) {98 switch (Size) {99 default:100 return "";101 case 1:102 return ".1";103 case 2:104 return ".2";105 case 4:106 return ".4";107 case 8:108 return ".8";109 }110}111 112void HexagonTargetObjectFile::Initialize(MCContext &Ctx,113 const TargetMachine &TM) {114 TargetLoweringObjectFileELF::Initialize(Ctx, TM);115 116 SmallDataSection =117 getContext().getELFSection(".sdata", ELF::SHT_PROGBITS,118 ELF::SHF_WRITE | ELF::SHF_ALLOC |119 ELF::SHF_HEX_GPREL);120 SmallBSSSection =121 getContext().getELFSection(".sbss", ELF::SHT_NOBITS,122 ELF::SHF_WRITE | ELF::SHF_ALLOC |123 ELF::SHF_HEX_GPREL);124}125 126MCSection *HexagonTargetObjectFile::SelectSectionForGlobal(127 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {128 TRACE("[SelectSectionForGlobal] GO(" << GO->getName() << ") ");129 TRACE("input section(" << GO->getSection() << ") ");130 131 TRACE((GO->hasPrivateLinkage() ? "private_linkage " : "")132 << (GO->hasLocalLinkage() ? "local_linkage " : "")133 << (GO->hasInternalLinkage() ? "internal " : "")134 << (GO->hasExternalLinkage() ? "external " : "")135 << (GO->hasCommonLinkage() ? "common_linkage " : "")136 << (GO->hasCommonLinkage() ? "common " : "" )137 << (Kind.isCommon() ? "kind_common " : "" )138 << (Kind.isBSS() ? "kind_bss " : "" )139 << (Kind.isBSSLocal() ? "kind_bss_local " : "" ));140 141 // If the lookup table is used by more than one function, do not place142 // it in text section.143 if (EmitLutInText && GO->getName().starts_with("switch.table")) {144 if (const Function *Fn = getLutUsedFunction(GO))145 return selectSectionForLookupTable(GO, TM, Fn);146 }147 148 if (isGlobalInSmallSection(GO, TM))149 return selectSmallSectionForGlobal(GO, Kind, TM);150 151 if (Kind.isCommon()) {152 // This is purely for LTO+Linker Script because commons don't really have a153 // section. However, the BitcodeSectionWriter pass will query for the154 // sections of commons (and the linker expects us to know their section) so155 // we'll return one here.156 return BSSSection;157 }158 159 TRACE("default_ELF_section\n");160 // Otherwise, we work the same as ELF.161 return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM);162}163 164MCSection *HexagonTargetObjectFile::getExplicitSectionGlobal(165 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {166 TRACE("[getExplicitSectionGlobal] GO(" << GO->getName() << ") from("167 << GO->getSection() << ") ");168 TRACE((GO->hasPrivateLinkage() ? "private_linkage " : "")169 << (GO->hasLocalLinkage() ? "local_linkage " : "")170 << (GO->hasInternalLinkage() ? "internal " : "")171 << (GO->hasExternalLinkage() ? "external " : "")172 << (GO->hasCommonLinkage() ? "common_linkage " : "")173 << (GO->hasCommonLinkage() ? "common " : "" )174 << (Kind.isCommon() ? "kind_common " : "" )175 << (Kind.isBSS() ? "kind_bss " : "" )176 << (Kind.isBSSLocal() ? "kind_bss_local " : "" ));177 178 if (GO->hasSection()) {179 StringRef Section = GO->getSection();180 if (Section.contains(".access.text.group"))181 return getContext().getELFSection(GO->getSection(), ELF::SHT_PROGBITS,182 ELF::SHF_ALLOC | ELF::SHF_EXECINSTR);183 if (Section.contains(".access.data.group"))184 return getContext().getELFSection(GO->getSection(), ELF::SHT_PROGBITS,185 ELF::SHF_WRITE | ELF::SHF_ALLOC);186 }187 188 if (isGlobalInSmallSection(GO, TM))189 return selectSmallSectionForGlobal(GO, Kind, TM);190 191 // Otherwise, we work the same as ELF.192 TRACE("default_ELF_section\n");193 return TargetLoweringObjectFileELF::getExplicitSectionGlobal(GO, Kind, TM);194}195 196/// Return true if this global value should be placed into small data/bss197/// section.198bool HexagonTargetObjectFile::isGlobalInSmallSection(const GlobalObject *GO,199 const TargetMachine &TM) const {200 bool HaveSData = isSmallDataEnabled(TM);201 if (!HaveSData)202 LLVM_DEBUG(dbgs() << "Small-data allocation is disabled, but symbols "203 "may have explicit section assignments...\n");204 // Only global variables, not functions.205 LLVM_DEBUG(dbgs() << "Checking if value is in small-data, -G"206 << SmallDataThreshold << ": \"" << GO->getName() << "\": ");207 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO);208 if (!GVar) {209 LLVM_DEBUG(dbgs() << "no, not a global variable\n");210 return false;211 }212 213 // Globals with external linkage that have an original section set must be214 // emitted to that section, regardless of whether we would put them into215 // small data or not. This is how we can support mixing -G0/-G8 in LTO.216 if (GVar->hasSection()) {217 bool IsSmall = isSmallDataSection(GVar->getSection());218 LLVM_DEBUG(dbgs() << (IsSmall ? "yes" : "no")219 << ", has section: " << GVar->getSection() << '\n');220 return IsSmall;221 }222 223 // If sdata is disabled, stop the checks here.224 if (!HaveSData) {225 LLVM_DEBUG(dbgs() << "no, small-data allocation is disabled\n");226 return false;227 }228 229 if (GVar->isConstant()) {230 LLVM_DEBUG(dbgs() << "no, is a constant\n");231 return false;232 }233 234 bool IsLocal = GVar->hasLocalLinkage();235 if (!StaticsInSData && IsLocal) {236 LLVM_DEBUG(dbgs() << "no, is static\n");237 return false;238 }239 240 Type *GType = GVar->getValueType();241 if (isa<ArrayType>(GType)) {242 LLVM_DEBUG(dbgs() << "no, is an array\n");243 return false;244 }245 246 // If the type is a struct with no body provided, treat is conservatively.247 // There cannot be actual definitions of object of such a type in this CU248 // (only references), so assuming that they are not in sdata is safe. If249 // these objects end up in the sdata, the references will still be valid.250 if (StructType *ST = dyn_cast<StructType>(GType)) {251 if (ST->isOpaque()) {252 LLVM_DEBUG(dbgs() << "no, has opaque type\n");253 return false;254 }255 }256 257 unsigned Size = GVar->getDataLayout().getTypeAllocSize(GType);258 if (Size == 0) {259 LLVM_DEBUG(dbgs() << "no, has size 0\n");260 return false;261 }262 if (Size > SmallDataThreshold) {263 LLVM_DEBUG(dbgs() << "no, size exceeds sdata threshold: " << Size << '\n');264 return false;265 }266 267 LLVM_DEBUG(dbgs() << "yes\n");268 return true;269}270 271bool HexagonTargetObjectFile::isSmallDataEnabled(const TargetMachine &TM)272 const {273 return SmallDataThreshold > 0 && !TM.isPositionIndependent();274}275 276unsigned HexagonTargetObjectFile::getSmallDataSize() const {277 return SmallDataThreshold;278}279 280bool HexagonTargetObjectFile::shouldPutJumpTableInFunctionSection(281 bool UsesLabelDifference, const Function &F) const {282 return EmitJtInText;283}284 285/// Descends any type down to "elementary" components,286/// discovering the smallest addressable one.287/// If zero is returned, declaration will not be modified.288unsigned HexagonTargetObjectFile::getSmallestAddressableSize(const Type *Ty,289 const GlobalValue *GV, const TargetMachine &TM) const {290 // Assign the smallest element access size to the highest291 // value which assembler can handle.292 unsigned SmallestElement = 8;293 294 if (!Ty)295 return 0;296 switch (Ty->getTypeID()) {297 case Type::StructTyID: {298 const StructType *STy = cast<const StructType>(Ty);299 for (auto &E : STy->elements()) {300 unsigned AtomicSize = getSmallestAddressableSize(E, GV, TM);301 if (AtomicSize < SmallestElement)302 SmallestElement = AtomicSize;303 }304 return (STy->getNumElements() == 0) ? 0 : SmallestElement;305 }306 case Type::ArrayTyID: {307 const ArrayType *ATy = cast<const ArrayType>(Ty);308 return getSmallestAddressableSize(ATy->getElementType(), GV, TM);309 }310 case Type::FixedVectorTyID:311 case Type::ScalableVectorTyID: {312 const VectorType *PTy = cast<const VectorType>(Ty);313 return getSmallestAddressableSize(PTy->getElementType(), GV, TM);314 }315 case Type::PointerTyID:316 case Type::HalfTyID:317 case Type::FloatTyID:318 case Type::DoubleTyID:319 case Type::IntegerTyID: {320 const DataLayout &DL = GV->getDataLayout();321 // It is unfortunate that DL's function take non-const Type*.322 return DL.getTypeAllocSize(const_cast<Type*>(Ty));323 }324 case Type::FunctionTyID:325 case Type::VoidTyID:326 case Type::BFloatTyID:327 case Type::X86_FP80TyID:328 case Type::FP128TyID:329 case Type::PPC_FP128TyID:330 case Type::LabelTyID:331 case Type::MetadataTyID:332 case Type::X86_AMXTyID:333 case Type::TokenTyID:334 case Type::TypedPointerTyID:335 case Type::TargetExtTyID:336 return 0;337 }338 339 return 0;340}341 342MCSection *HexagonTargetObjectFile::selectSmallSectionForGlobal(343 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {344 const Type *GTy = GO->getValueType();345 unsigned Size = getSmallestAddressableSize(GTy, GO, TM);346 347 // If we have -ffunction-section or -fdata-section then we should emit the348 // global value to a unique section specifically for it... even for sdata.349 bool EmitUniquedSection = TM.getDataSections();350 351 TRACE("Small data. Size(" << Size << ")");352 // Handle Small Section classification here.353 if (Kind.isBSS() || Kind.isBSSLocal()) {354 // If -mno-sort-sda is not set, find out smallest accessible entity in355 // declaration and add it to the section name string.356 // Note. It does not track the actual usage of the value, only its de-357 // claration. Also, compiler adds explicit pad fields to some struct358 // declarations - they are currently counted towards smallest addres-359 // sable entity.360 if (NoSmallDataSorting) {361 TRACE(" default sbss\n");362 return SmallBSSSection;363 }364 365 StringRef Prefix(".sbss");366 SmallString<128> Name(Prefix);367 Name.append(getSectionSuffixForSize(Size));368 369 if (EmitUniquedSection) {370 Name.append(".");371 Name.append(GO->getName());372 }373 TRACE(" unique sbss(" << Name << ")\n");374 return getContext().getELFSection(Name.str(), ELF::SHT_NOBITS,375 ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_HEX_GPREL);376 }377 378 if (Kind.isCommon()) {379 // This is purely for LTO+Linker Script because commons don't really have a380 // section. However, the BitcodeSectionWriter pass will query for the381 // sections of commons (and the linker expects us to know their section) so382 // we'll return one here.383 if (NoSmallDataSorting)384 return BSSSection;385 386 Twine Name = Twine(".scommon") + getSectionSuffixForSize(Size);387 TRACE(" small COMMON (" << Name << ")\n");388 389 return getContext().getELFSection(Name.str(), ELF::SHT_NOBITS,390 ELF::SHF_WRITE | ELF::SHF_ALLOC |391 ELF::SHF_HEX_GPREL);392 }393 394 // We could have changed sdata object to a constant... in this395 // case the Kind could be wrong for it.396 if (Kind.isMergeableConst()) {397 TRACE(" const_object_as_data ");398 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO);399 if (GVar->hasSection() && isSmallDataSection(GVar->getSection()))400 Kind = SectionKind::getData();401 }402 403 if (Kind.isData()) {404 if (NoSmallDataSorting) {405 TRACE(" default sdata\n");406 return SmallDataSection;407 }408 409 StringRef Prefix(".sdata");410 SmallString<128> Name(Prefix);411 Name.append(getSectionSuffixForSize(Size));412 413 if (EmitUniquedSection) {414 Name.append(".");415 Name.append(GO->getName());416 }417 TRACE(" unique sdata(" << Name << ")\n");418 return getContext().getELFSection(Name.str(), ELF::SHT_PROGBITS,419 ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_HEX_GPREL);420 }421 422 TRACE("default ELF section\n");423 // Otherwise, we work the same as ELF.424 return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM);425}426 427// Return the function that uses the lookup table. If there are more428// than one live function that uses this look table, bail out and place429// the lookup table in default section.430const Function *431HexagonTargetObjectFile::getLutUsedFunction(const GlobalObject *GO) const {432 const Function *ReturnFn = nullptr;433 for (const auto *U : GO->users()) {434 // validate each instance of user to be a live function.435 auto *I = dyn_cast<Instruction>(U);436 if (!I)437 continue;438 auto *Bb = I->getParent();439 if (!Bb)440 continue;441 auto *UserFn = Bb->getParent();442 if (!ReturnFn)443 ReturnFn = UserFn;444 else if (ReturnFn != UserFn)445 return nullptr;446 }447 return ReturnFn;448}449 450MCSection *HexagonTargetObjectFile::selectSectionForLookupTable(451 const GlobalObject *GO, const TargetMachine &TM, const Function *Fn) const {452 453 SectionKind Kind = SectionKind::getText();454 // If the function has explicit section, place the lookup table in this455 // explicit section.456 if (Fn->hasSection())457 return getExplicitSectionGlobal(Fn, Kind, TM);458 459 const auto *FuncObj = dyn_cast<GlobalObject>(Fn);460 return SelectSectionForGlobal(FuncObj, Kind, TM);461}462