xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
10b57cec5SDimitry Andric //===-- HexagonTargetObjectFile.cpp ---------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains the declarations of the HexagonTargetAsmInfo properties.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "HexagonTargetObjectFile.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
150b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
160b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
170b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
180b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
190b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
200b57cec5SDimitry Andric #include "llvm/IR/GlobalObject.h"
210b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
220b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
235ffd83dbSDimitry Andric #include "llvm/IR/Module.h"
240b57cec5SDimitry Andric #include "llvm/IR/Type.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
260b57cec5SDimitry Andric #include "llvm/MC/SectionKind.h"
270b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
280b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
290b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
300b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
310b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
320b57cec5SDimitry Andric 
33fe6060f1SDimitry Andric #define DEBUG_TYPE "hexagon-sdata"
34fe6060f1SDimitry Andric 
350b57cec5SDimitry Andric using namespace llvm;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric static cl::opt<unsigned> SmallDataThreshold("hexagon-small-data-threshold",
380b57cec5SDimitry Andric   cl::init(8), cl::Hidden,
390b57cec5SDimitry Andric   cl::desc("The maximum size of an object in the sdata section"));
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric static cl::opt<bool> NoSmallDataSorting("mno-sort-sda", cl::init(false),
420b57cec5SDimitry Andric   cl::Hidden, cl::desc("Disable small data sections sorting"));
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric static cl::opt<bool> StaticsInSData("hexagon-statics-in-small-data",
450b57cec5SDimitry Andric   cl::init(false), cl::Hidden, cl::ZeroOrMore,
460b57cec5SDimitry Andric   cl::desc("Allow static variables in .sdata"));
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric static cl::opt<bool> TraceGVPlacement("trace-gv-placement",
490b57cec5SDimitry Andric   cl::Hidden, cl::init(false),
500b57cec5SDimitry Andric   cl::desc("Trace global value placement"));
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric static cl::opt<bool>
530b57cec5SDimitry Andric     EmitJtInText("hexagon-emit-jt-text", cl::Hidden, cl::init(false),
540b57cec5SDimitry Andric                  cl::desc("Emit hexagon jump tables in function section"));
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric static cl::opt<bool>
570b57cec5SDimitry Andric     EmitLutInText("hexagon-emit-lut-text", cl::Hidden, cl::init(false),
580b57cec5SDimitry Andric                  cl::desc("Emit hexagon lookup tables in function section"));
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric // TraceGVPlacement controls messages for all builds. For builds with assertions
610b57cec5SDimitry Andric // (debug or release), messages are also controlled by the usual debug flags
620b57cec5SDimitry Andric // (e.g. -debug and -debug-only=globallayout)
630b57cec5SDimitry Andric #define TRACE_TO(s, X) s << X
640b57cec5SDimitry Andric #ifdef NDEBUG
650b57cec5SDimitry Andric #define TRACE(X)                                                               \
660b57cec5SDimitry Andric   do {                                                                         \
670b57cec5SDimitry Andric     if (TraceGVPlacement) {                                                    \
680b57cec5SDimitry Andric       TRACE_TO(errs(), X);                                                     \
690b57cec5SDimitry Andric     }                                                                          \
700b57cec5SDimitry Andric   } while (false)
710b57cec5SDimitry Andric #else
720b57cec5SDimitry Andric #define TRACE(X)                                                               \
730b57cec5SDimitry Andric   do {                                                                         \
740b57cec5SDimitry Andric     if (TraceGVPlacement) {                                                    \
750b57cec5SDimitry Andric       TRACE_TO(errs(), X);                                                     \
760b57cec5SDimitry Andric     } else {                                                                   \
770b57cec5SDimitry Andric       LLVM_DEBUG(TRACE_TO(dbgs(), X));                                         \
780b57cec5SDimitry Andric     }                                                                          \
790b57cec5SDimitry Andric   } while (false)
800b57cec5SDimitry Andric #endif
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric // Returns true if the section name is such that the symbol will be put
830b57cec5SDimitry Andric // in a small data section.
840b57cec5SDimitry Andric // For instance, global variables with section attributes such as ".sdata"
850b57cec5SDimitry Andric // ".sdata.*", ".sbss", and ".sbss.*" will go into small data.
860b57cec5SDimitry Andric static bool isSmallDataSection(StringRef Sec) {
870b57cec5SDimitry Andric   // sectionName is either ".sdata" or ".sbss". Looking for an exact match
880b57cec5SDimitry Andric   // obviates the need for checks for section names such as ".sdatafoo".
890b57cec5SDimitry Andric   if (Sec.equals(".sdata") || Sec.equals(".sbss") || Sec.equals(".scommon"))
900b57cec5SDimitry Andric     return true;
910b57cec5SDimitry Andric   // If either ".sdata." or ".sbss." is a substring of the section name
920b57cec5SDimitry Andric   // then put the symbol in small data.
93*349cc55cSDimitry Andric   return Sec.contains(".sdata.") || Sec.contains(".sbss.") ||
94*349cc55cSDimitry Andric          Sec.contains(".scommon.");
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric static const char *getSectionSuffixForSize(unsigned Size) {
980b57cec5SDimitry Andric   switch (Size) {
990b57cec5SDimitry Andric   default:
1000b57cec5SDimitry Andric     return "";
1010b57cec5SDimitry Andric   case 1:
1020b57cec5SDimitry Andric     return ".1";
1030b57cec5SDimitry Andric   case 2:
1040b57cec5SDimitry Andric     return ".2";
1050b57cec5SDimitry Andric   case 4:
1060b57cec5SDimitry Andric     return ".4";
1070b57cec5SDimitry Andric   case 8:
1080b57cec5SDimitry Andric     return ".8";
1090b57cec5SDimitry Andric   }
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric void HexagonTargetObjectFile::Initialize(MCContext &Ctx,
1130b57cec5SDimitry Andric       const TargetMachine &TM) {
1140b57cec5SDimitry Andric   TargetLoweringObjectFileELF::Initialize(Ctx, TM);
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   SmallDataSection =
1170b57cec5SDimitry Andric     getContext().getELFSection(".sdata", ELF::SHT_PROGBITS,
1180b57cec5SDimitry Andric                                ELF::SHF_WRITE | ELF::SHF_ALLOC |
1190b57cec5SDimitry Andric                                ELF::SHF_HEX_GPREL);
1200b57cec5SDimitry Andric   SmallBSSSection =
1210b57cec5SDimitry Andric     getContext().getELFSection(".sbss", ELF::SHT_NOBITS,
1220b57cec5SDimitry Andric                                ELF::SHF_WRITE | ELF::SHF_ALLOC |
1230b57cec5SDimitry Andric                                ELF::SHF_HEX_GPREL);
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric MCSection *HexagonTargetObjectFile::SelectSectionForGlobal(
1270b57cec5SDimitry Andric     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
1280b57cec5SDimitry Andric   TRACE("[SelectSectionForGlobal] GO(" << GO->getName() << ") ");
1290b57cec5SDimitry Andric   TRACE("input section(" << GO->getSection() << ") ");
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   TRACE((GO->hasPrivateLinkage() ? "private_linkage " : "")
1320b57cec5SDimitry Andric          << (GO->hasLocalLinkage() ? "local_linkage " : "")
1330b57cec5SDimitry Andric          << (GO->hasInternalLinkage() ? "internal " : "")
1340b57cec5SDimitry Andric          << (GO->hasExternalLinkage() ? "external " : "")
1350b57cec5SDimitry Andric          << (GO->hasCommonLinkage() ? "common_linkage " : "")
1360b57cec5SDimitry Andric          << (GO->hasCommonLinkage() ? "common " : "" )
1370b57cec5SDimitry Andric          << (Kind.isCommon() ? "kind_common " : "" )
1380b57cec5SDimitry Andric          << (Kind.isBSS() ? "kind_bss " : "" )
1390b57cec5SDimitry Andric          << (Kind.isBSSLocal() ? "kind_bss_local " : "" ));
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   // If the lookup table is used by more than one function, do not place
1420b57cec5SDimitry Andric   // it in text section.
1430b57cec5SDimitry Andric   if (EmitLutInText && GO->getName().startswith("switch.table")) {
1440b57cec5SDimitry Andric     if (const Function *Fn = getLutUsedFunction(GO))
1450b57cec5SDimitry Andric       return selectSectionForLookupTable(GO, TM, Fn);
1460b57cec5SDimitry Andric   }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   if (isGlobalInSmallSection(GO, TM))
1490b57cec5SDimitry Andric     return selectSmallSectionForGlobal(GO, Kind, TM);
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   if (Kind.isCommon()) {
1520b57cec5SDimitry Andric     // This is purely for LTO+Linker Script because commons don't really have a
1530b57cec5SDimitry Andric     // section. However, the BitcodeSectionWriter pass will query for the
1540b57cec5SDimitry Andric     // sections of commons (and the linker expects us to know their section) so
1550b57cec5SDimitry Andric     // we'll return one here.
1560b57cec5SDimitry Andric     return BSSSection;
1570b57cec5SDimitry Andric   }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   TRACE("default_ELF_section\n");
1600b57cec5SDimitry Andric   // Otherwise, we work the same as ELF.
1610b57cec5SDimitry Andric   return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM);
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric MCSection *HexagonTargetObjectFile::getExplicitSectionGlobal(
1650b57cec5SDimitry Andric     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
1660b57cec5SDimitry Andric   TRACE("[getExplicitSectionGlobal] GO(" << GO->getName() << ") from("
1670b57cec5SDimitry Andric         << GO->getSection() << ") ");
1680b57cec5SDimitry Andric   TRACE((GO->hasPrivateLinkage() ? "private_linkage " : "")
1690b57cec5SDimitry Andric          << (GO->hasLocalLinkage() ? "local_linkage " : "")
1700b57cec5SDimitry Andric          << (GO->hasInternalLinkage() ? "internal " : "")
1710b57cec5SDimitry Andric          << (GO->hasExternalLinkage() ? "external " : "")
1720b57cec5SDimitry Andric          << (GO->hasCommonLinkage() ? "common_linkage " : "")
1730b57cec5SDimitry Andric          << (GO->hasCommonLinkage() ? "common " : "" )
1740b57cec5SDimitry Andric          << (Kind.isCommon() ? "kind_common " : "" )
1750b57cec5SDimitry Andric          << (Kind.isBSS() ? "kind_bss " : "" )
1760b57cec5SDimitry Andric          << (Kind.isBSSLocal() ? "kind_bss_local " : "" ));
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   if (GO->hasSection()) {
1790b57cec5SDimitry Andric     StringRef Section = GO->getSection();
180*349cc55cSDimitry Andric     if (Section.contains(".access.text.group"))
1810b57cec5SDimitry Andric       return getContext().getELFSection(GO->getSection(), ELF::SHT_PROGBITS,
1820b57cec5SDimitry Andric                                         ELF::SHF_ALLOC | ELF::SHF_EXECINSTR);
183*349cc55cSDimitry Andric     if (Section.contains(".access.data.group"))
1840b57cec5SDimitry Andric       return getContext().getELFSection(GO->getSection(), ELF::SHT_PROGBITS,
1850b57cec5SDimitry Andric                                         ELF::SHF_WRITE | ELF::SHF_ALLOC);
1860b57cec5SDimitry Andric   }
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   if (isGlobalInSmallSection(GO, TM))
1890b57cec5SDimitry Andric     return selectSmallSectionForGlobal(GO, Kind, TM);
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   // Otherwise, we work the same as ELF.
1920b57cec5SDimitry Andric   TRACE("default_ELF_section\n");
1930b57cec5SDimitry Andric   return TargetLoweringObjectFileELF::getExplicitSectionGlobal(GO, Kind, TM);
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric /// Return true if this global value should be placed into small data/bss
1970b57cec5SDimitry Andric /// section.
1980b57cec5SDimitry Andric bool HexagonTargetObjectFile::isGlobalInSmallSection(const GlobalObject *GO,
1990b57cec5SDimitry Andric       const TargetMachine &TM) const {
2000b57cec5SDimitry Andric   bool HaveSData = isSmallDataEnabled(TM);
2010b57cec5SDimitry Andric   if (!HaveSData)
2020b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Small-data allocation is disabled, but symbols "
2030b57cec5SDimitry Andric                          "may have explicit section assignments...\n");
2040b57cec5SDimitry Andric   // Only global variables, not functions.
2050b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Checking if value is in small-data, -G"
2060b57cec5SDimitry Andric                     << SmallDataThreshold << ": \"" << GO->getName() << "\": ");
2070b57cec5SDimitry Andric   const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO);
2080b57cec5SDimitry Andric   if (!GVar) {
2090b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "no, not a global variable\n");
2100b57cec5SDimitry Andric     return false;
2110b57cec5SDimitry Andric   }
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   // Globals with external linkage that have an original section set must be
2140b57cec5SDimitry Andric   // emitted to that section, regardless of whether we would put them into
2150b57cec5SDimitry Andric   // small data or not. This is how we can support mixing -G0/-G8 in LTO.
2160b57cec5SDimitry Andric   if (GVar->hasSection()) {
2170b57cec5SDimitry Andric     bool IsSmall = isSmallDataSection(GVar->getSection());
2180b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << (IsSmall ? "yes" : "no")
2190b57cec5SDimitry Andric                       << ", has section: " << GVar->getSection() << '\n');
2200b57cec5SDimitry Andric     return IsSmall;
2210b57cec5SDimitry Andric   }
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   // If sdata is disabled, stop the checks here.
2240b57cec5SDimitry Andric   if (!HaveSData) {
2250b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "no, small-data allocation is disabled\n");
2260b57cec5SDimitry Andric     return false;
2270b57cec5SDimitry Andric   }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   if (GVar->isConstant()) {
2300b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "no, is a constant\n");
2310b57cec5SDimitry Andric     return false;
2320b57cec5SDimitry Andric   }
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   bool IsLocal = GVar->hasLocalLinkage();
2350b57cec5SDimitry Andric   if (!StaticsInSData && IsLocal) {
2360b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "no, is static\n");
2370b57cec5SDimitry Andric     return false;
2380b57cec5SDimitry Andric   }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   Type *GType = GVar->getValueType();
2410b57cec5SDimitry Andric   if (isa<ArrayType>(GType)) {
2420b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "no, is an array\n");
2430b57cec5SDimitry Andric     return false;
2440b57cec5SDimitry Andric   }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   // If the type is a struct with no body provided, treat is conservatively.
2470b57cec5SDimitry Andric   // There cannot be actual definitions of object of such a type in this CU
2480b57cec5SDimitry Andric   // (only references), so assuming that they are not in sdata is safe. If
2490b57cec5SDimitry Andric   // these objects end up in the sdata, the references will still be valid.
2500b57cec5SDimitry Andric   if (StructType *ST = dyn_cast<StructType>(GType)) {
2510b57cec5SDimitry Andric     if (ST->isOpaque()) {
2520b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "no, has opaque type\n");
2530b57cec5SDimitry Andric       return false;
2540b57cec5SDimitry Andric     }
2550b57cec5SDimitry Andric   }
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   unsigned Size = GVar->getParent()->getDataLayout().getTypeAllocSize(GType);
2580b57cec5SDimitry Andric   if (Size == 0) {
2590b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "no, has size 0\n");
2600b57cec5SDimitry Andric     return false;
2610b57cec5SDimitry Andric   }
2620b57cec5SDimitry Andric   if (Size > SmallDataThreshold) {
2630b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "no, size exceeds sdata threshold: " << Size << '\n');
2640b57cec5SDimitry Andric     return false;
2650b57cec5SDimitry Andric   }
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "yes\n");
2680b57cec5SDimitry Andric   return true;
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric bool HexagonTargetObjectFile::isSmallDataEnabled(const TargetMachine &TM)
2720b57cec5SDimitry Andric     const {
2730b57cec5SDimitry Andric   return SmallDataThreshold > 0 && !TM.isPositionIndependent();
2740b57cec5SDimitry Andric }
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric unsigned HexagonTargetObjectFile::getSmallDataSize() const {
2770b57cec5SDimitry Andric   return SmallDataThreshold;
2780b57cec5SDimitry Andric }
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric bool HexagonTargetObjectFile::shouldPutJumpTableInFunctionSection(
2810b57cec5SDimitry Andric     bool UsesLabelDifference, const Function &F) const {
2820b57cec5SDimitry Andric   return EmitJtInText;
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric /// Descends any type down to "elementary" components,
2860b57cec5SDimitry Andric /// discovering the smallest addressable one.
2870b57cec5SDimitry Andric /// If zero is returned, declaration will not be modified.
2880b57cec5SDimitry Andric unsigned HexagonTargetObjectFile::getSmallestAddressableSize(const Type *Ty,
2890b57cec5SDimitry Andric       const GlobalValue *GV, const TargetMachine &TM) const {
2900b57cec5SDimitry Andric   // Assign the smallest element access size to the highest
2910b57cec5SDimitry Andric   // value which assembler can handle.
2920b57cec5SDimitry Andric   unsigned SmallestElement = 8;
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric   if (!Ty)
2950b57cec5SDimitry Andric     return 0;
2960b57cec5SDimitry Andric   switch (Ty->getTypeID()) {
2970b57cec5SDimitry Andric   case Type::StructTyID: {
2980b57cec5SDimitry Andric     const StructType *STy = cast<const StructType>(Ty);
2990b57cec5SDimitry Andric     for (auto &E : STy->elements()) {
3000b57cec5SDimitry Andric       unsigned AtomicSize = getSmallestAddressableSize(E, GV, TM);
3010b57cec5SDimitry Andric       if (AtomicSize < SmallestElement)
3020b57cec5SDimitry Andric         SmallestElement = AtomicSize;
3030b57cec5SDimitry Andric     }
3040b57cec5SDimitry Andric     return (STy->getNumElements() == 0) ? 0 : SmallestElement;
3050b57cec5SDimitry Andric   }
3060b57cec5SDimitry Andric   case Type::ArrayTyID: {
3070b57cec5SDimitry Andric     const ArrayType *ATy = cast<const ArrayType>(Ty);
3080b57cec5SDimitry Andric     return getSmallestAddressableSize(ATy->getElementType(), GV, TM);
3090b57cec5SDimitry Andric   }
3105ffd83dbSDimitry Andric   case Type::FixedVectorTyID:
3115ffd83dbSDimitry Andric   case Type::ScalableVectorTyID: {
3120b57cec5SDimitry Andric     const VectorType *PTy = cast<const VectorType>(Ty);
3130b57cec5SDimitry Andric     return getSmallestAddressableSize(PTy->getElementType(), GV, TM);
3140b57cec5SDimitry Andric   }
3150b57cec5SDimitry Andric   case Type::PointerTyID:
3160b57cec5SDimitry Andric   case Type::HalfTyID:
3170b57cec5SDimitry Andric   case Type::FloatTyID:
3180b57cec5SDimitry Andric   case Type::DoubleTyID:
3190b57cec5SDimitry Andric   case Type::IntegerTyID: {
3200b57cec5SDimitry Andric     const DataLayout &DL = GV->getParent()->getDataLayout();
3210b57cec5SDimitry Andric     // It is unfortunate that DL's function take non-const Type*.
3220b57cec5SDimitry Andric     return DL.getTypeAllocSize(const_cast<Type*>(Ty));
3230b57cec5SDimitry Andric   }
3240b57cec5SDimitry Andric   case Type::FunctionTyID:
3250b57cec5SDimitry Andric   case Type::VoidTyID:
3265ffd83dbSDimitry Andric   case Type::BFloatTyID:
3270b57cec5SDimitry Andric   case Type::X86_FP80TyID:
3280b57cec5SDimitry Andric   case Type::FP128TyID:
3290b57cec5SDimitry Andric   case Type::PPC_FP128TyID:
3300b57cec5SDimitry Andric   case Type::LabelTyID:
3310b57cec5SDimitry Andric   case Type::MetadataTyID:
3320b57cec5SDimitry Andric   case Type::X86_MMXTyID:
333e8d8bef9SDimitry Andric   case Type::X86_AMXTyID:
3340b57cec5SDimitry Andric   case Type::TokenTyID:
3350b57cec5SDimitry Andric     return 0;
3360b57cec5SDimitry Andric   }
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   return 0;
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric MCSection *HexagonTargetObjectFile::selectSmallSectionForGlobal(
3420b57cec5SDimitry Andric     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
3430b57cec5SDimitry Andric   const Type *GTy = GO->getValueType();
3440b57cec5SDimitry Andric   unsigned Size = getSmallestAddressableSize(GTy, GO, TM);
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   // If we have -ffunction-section or -fdata-section then we should emit the
3470b57cec5SDimitry Andric   // global value to a unique section specifically for it... even for sdata.
3480b57cec5SDimitry Andric   bool EmitUniquedSection = TM.getDataSections();
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   TRACE("Small data. Size(" << Size << ")");
3510b57cec5SDimitry Andric   // Handle Small Section classification here.
3520b57cec5SDimitry Andric   if (Kind.isBSS() || Kind.isBSSLocal()) {
3530b57cec5SDimitry Andric     // If -mno-sort-sda is not set, find out smallest accessible entity in
3540b57cec5SDimitry Andric     // declaration and add it to the section name string.
3550b57cec5SDimitry Andric     // Note. It does not track the actual usage of the value, only its de-
3560b57cec5SDimitry Andric     // claration. Also, compiler adds explicit pad fields to some struct
3570b57cec5SDimitry Andric     // declarations - they are currently counted towards smallest addres-
3580b57cec5SDimitry Andric     // sable entity.
3590b57cec5SDimitry Andric     if (NoSmallDataSorting) {
3600b57cec5SDimitry Andric       TRACE(" default sbss\n");
3610b57cec5SDimitry Andric       return SmallBSSSection;
3620b57cec5SDimitry Andric     }
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric     StringRef Prefix(".sbss");
3650b57cec5SDimitry Andric     SmallString<128> Name(Prefix);
3660b57cec5SDimitry Andric     Name.append(getSectionSuffixForSize(Size));
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric     if (EmitUniquedSection) {
3690b57cec5SDimitry Andric       Name.append(".");
3700b57cec5SDimitry Andric       Name.append(GO->getName());
3710b57cec5SDimitry Andric     }
3720b57cec5SDimitry Andric     TRACE(" unique sbss(" << Name << ")\n");
3730b57cec5SDimitry Andric     return getContext().getELFSection(Name.str(), ELF::SHT_NOBITS,
3740b57cec5SDimitry Andric                 ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_HEX_GPREL);
3750b57cec5SDimitry Andric   }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   if (Kind.isCommon()) {
3780b57cec5SDimitry Andric     // This is purely for LTO+Linker Script because commons don't really have a
3790b57cec5SDimitry Andric     // section. However, the BitcodeSectionWriter pass will query for the
3800b57cec5SDimitry Andric     // sections of commons (and the linker expects us to know their section) so
3810b57cec5SDimitry Andric     // we'll return one here.
3820b57cec5SDimitry Andric     if (NoSmallDataSorting)
3830b57cec5SDimitry Andric       return BSSSection;
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric     Twine Name = Twine(".scommon") + getSectionSuffixForSize(Size);
3860b57cec5SDimitry Andric     TRACE(" small COMMON (" << Name << ")\n");
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric     return getContext().getELFSection(Name.str(), ELF::SHT_NOBITS,
3890b57cec5SDimitry Andric                                       ELF::SHF_WRITE | ELF::SHF_ALLOC |
3900b57cec5SDimitry Andric                                       ELF::SHF_HEX_GPREL);
3910b57cec5SDimitry Andric   }
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   // We could have changed sdata object to a constant... in this
3940b57cec5SDimitry Andric   // case the Kind could be wrong for it.
3950b57cec5SDimitry Andric   if (Kind.isMergeableConst()) {
3960b57cec5SDimitry Andric     TRACE(" const_object_as_data ");
3970b57cec5SDimitry Andric     const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO);
3980b57cec5SDimitry Andric     if (GVar->hasSection() && isSmallDataSection(GVar->getSection()))
3990b57cec5SDimitry Andric       Kind = SectionKind::getData();
4000b57cec5SDimitry Andric   }
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric   if (Kind.isData()) {
4030b57cec5SDimitry Andric     if (NoSmallDataSorting) {
4040b57cec5SDimitry Andric       TRACE(" default sdata\n");
4050b57cec5SDimitry Andric       return SmallDataSection;
4060b57cec5SDimitry Andric     }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric     StringRef Prefix(".sdata");
4090b57cec5SDimitry Andric     SmallString<128> Name(Prefix);
4100b57cec5SDimitry Andric     Name.append(getSectionSuffixForSize(Size));
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric     if (EmitUniquedSection) {
4130b57cec5SDimitry Andric       Name.append(".");
4140b57cec5SDimitry Andric       Name.append(GO->getName());
4150b57cec5SDimitry Andric     }
4160b57cec5SDimitry Andric     TRACE(" unique sdata(" << Name << ")\n");
4170b57cec5SDimitry Andric     return getContext().getELFSection(Name.str(), ELF::SHT_PROGBITS,
4180b57cec5SDimitry Andric                 ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_HEX_GPREL);
4190b57cec5SDimitry Andric   }
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric   TRACE("default ELF section\n");
4220b57cec5SDimitry Andric   // Otherwise, we work the same as ELF.
4230b57cec5SDimitry Andric   return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM);
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric // Return the function that uses the lookup table. If there are more
4270b57cec5SDimitry Andric // than one live function that uses this look table, bail out and place
4280b57cec5SDimitry Andric // the lookup table in default section.
4290b57cec5SDimitry Andric const Function *
4300b57cec5SDimitry Andric HexagonTargetObjectFile::getLutUsedFunction(const GlobalObject *GO) const {
4310b57cec5SDimitry Andric   const Function *ReturnFn = nullptr;
4320b57cec5SDimitry Andric   for (auto U : GO->users()) {
4330b57cec5SDimitry Andric     // validate each instance of user to be a live function.
4340b57cec5SDimitry Andric     auto *I = dyn_cast<Instruction>(U);
4350b57cec5SDimitry Andric     if (!I)
4360b57cec5SDimitry Andric       continue;
4370b57cec5SDimitry Andric     auto *Bb = I->getParent();
4380b57cec5SDimitry Andric     if (!Bb)
4390b57cec5SDimitry Andric       continue;
4400b57cec5SDimitry Andric     auto *UserFn = Bb->getParent();
4410b57cec5SDimitry Andric     if (!ReturnFn)
4420b57cec5SDimitry Andric       ReturnFn = UserFn;
4430b57cec5SDimitry Andric     else if (ReturnFn != UserFn)
4440b57cec5SDimitry Andric       return nullptr;
4450b57cec5SDimitry Andric   }
4460b57cec5SDimitry Andric   return ReturnFn;
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric MCSection *HexagonTargetObjectFile::selectSectionForLookupTable(
4500b57cec5SDimitry Andric     const GlobalObject *GO, const TargetMachine &TM, const Function *Fn) const {
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric   SectionKind Kind = SectionKind::getText();
4530b57cec5SDimitry Andric   // If the function has explicit section, place the lookup table in this
4540b57cec5SDimitry Andric   // explicit section.
4550b57cec5SDimitry Andric   if (Fn->hasSection())
4560b57cec5SDimitry Andric     return getExplicitSectionGlobal(Fn, Kind, TM);
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   const auto *FuncObj = dyn_cast<GlobalObject>(Fn);
4590b57cec5SDimitry Andric   return SelectSectionForGlobal(FuncObj, Kind, TM);
4600b57cec5SDimitry Andric }
461