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
4481ad6265SDimitry Andric static cl::opt<bool>
4581ad6265SDimitry Andric StaticsInSData("hexagon-statics-in-small-data", cl::Hidden,
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.
isSmallDataSection(StringRef Sec)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".
89*0fca6ea1SDimitry Andric if (Sec == ".sdata" || Sec == ".sbss" || Sec == ".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.
93349cc55cSDimitry Andric return Sec.contains(".sdata.") || Sec.contains(".sbss.") ||
94349cc55cSDimitry Andric Sec.contains(".scommon.");
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric
getSectionSuffixForSize(unsigned Size)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
Initialize(MCContext & Ctx,const TargetMachine & TM)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
SelectSectionForGlobal(const GlobalObject * GO,SectionKind Kind,const TargetMachine & TM) const1260b57cec5SDimitry 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.
1435f757f3fSDimitry Andric if (EmitLutInText && GO->getName().starts_with("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
getExplicitSectionGlobal(const GlobalObject * GO,SectionKind Kind,const TargetMachine & TM) const1640b57cec5SDimitry 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();
180349cc55cSDimitry 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);
183349cc55cSDimitry 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.
isGlobalInSmallSection(const GlobalObject * GO,const TargetMachine & TM) const1980b57cec5SDimitry 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
257*0fca6ea1SDimitry Andric unsigned Size = GVar->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
isSmallDataEnabled(const TargetMachine & TM) const2710b57cec5SDimitry Andric bool HexagonTargetObjectFile::isSmallDataEnabled(const TargetMachine &TM)
2720b57cec5SDimitry Andric const {
2730b57cec5SDimitry Andric return SmallDataThreshold > 0 && !TM.isPositionIndependent();
2740b57cec5SDimitry Andric }
2750b57cec5SDimitry Andric
getSmallDataSize() const2760b57cec5SDimitry Andric unsigned HexagonTargetObjectFile::getSmallDataSize() const {
2770b57cec5SDimitry Andric return SmallDataThreshold;
2780b57cec5SDimitry Andric }
2790b57cec5SDimitry Andric
shouldPutJumpTableInFunctionSection(bool UsesLabelDifference,const Function & F) const2800b57cec5SDimitry 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.
getSmallestAddressableSize(const Type * Ty,const GlobalValue * GV,const TargetMachine & TM) const2880b57cec5SDimitry 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: {
320*0fca6ea1SDimitry Andric const DataLayout &DL = GV->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:
335bdd1243dSDimitry Andric case Type::TypedPointerTyID:
336bdd1243dSDimitry Andric case Type::TargetExtTyID:
3370b57cec5SDimitry Andric return 0;
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric
3400b57cec5SDimitry Andric return 0;
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric
selectSmallSectionForGlobal(const GlobalObject * GO,SectionKind Kind,const TargetMachine & TM) const3430b57cec5SDimitry Andric MCSection *HexagonTargetObjectFile::selectSmallSectionForGlobal(
3440b57cec5SDimitry Andric const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
3450b57cec5SDimitry Andric const Type *GTy = GO->getValueType();
3460b57cec5SDimitry Andric unsigned Size = getSmallestAddressableSize(GTy, GO, TM);
3470b57cec5SDimitry Andric
3480b57cec5SDimitry Andric // If we have -ffunction-section or -fdata-section then we should emit the
3490b57cec5SDimitry Andric // global value to a unique section specifically for it... even for sdata.
3500b57cec5SDimitry Andric bool EmitUniquedSection = TM.getDataSections();
3510b57cec5SDimitry Andric
3520b57cec5SDimitry Andric TRACE("Small data. Size(" << Size << ")");
3530b57cec5SDimitry Andric // Handle Small Section classification here.
3540b57cec5SDimitry Andric if (Kind.isBSS() || Kind.isBSSLocal()) {
3550b57cec5SDimitry Andric // If -mno-sort-sda is not set, find out smallest accessible entity in
3560b57cec5SDimitry Andric // declaration and add it to the section name string.
3570b57cec5SDimitry Andric // Note. It does not track the actual usage of the value, only its de-
3580b57cec5SDimitry Andric // claration. Also, compiler adds explicit pad fields to some struct
3590b57cec5SDimitry Andric // declarations - they are currently counted towards smallest addres-
3600b57cec5SDimitry Andric // sable entity.
3610b57cec5SDimitry Andric if (NoSmallDataSorting) {
3620b57cec5SDimitry Andric TRACE(" default sbss\n");
3630b57cec5SDimitry Andric return SmallBSSSection;
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andric StringRef Prefix(".sbss");
3670b57cec5SDimitry Andric SmallString<128> Name(Prefix);
3680b57cec5SDimitry Andric Name.append(getSectionSuffixForSize(Size));
3690b57cec5SDimitry Andric
3700b57cec5SDimitry Andric if (EmitUniquedSection) {
3710b57cec5SDimitry Andric Name.append(".");
3720b57cec5SDimitry Andric Name.append(GO->getName());
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric TRACE(" unique sbss(" << Name << ")\n");
3750b57cec5SDimitry Andric return getContext().getELFSection(Name.str(), ELF::SHT_NOBITS,
3760b57cec5SDimitry Andric ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_HEX_GPREL);
3770b57cec5SDimitry Andric }
3780b57cec5SDimitry Andric
3790b57cec5SDimitry Andric if (Kind.isCommon()) {
3800b57cec5SDimitry Andric // This is purely for LTO+Linker Script because commons don't really have a
3810b57cec5SDimitry Andric // section. However, the BitcodeSectionWriter pass will query for the
3820b57cec5SDimitry Andric // sections of commons (and the linker expects us to know their section) so
3830b57cec5SDimitry Andric // we'll return one here.
3840b57cec5SDimitry Andric if (NoSmallDataSorting)
3850b57cec5SDimitry Andric return BSSSection;
3860b57cec5SDimitry Andric
3870b57cec5SDimitry Andric Twine Name = Twine(".scommon") + getSectionSuffixForSize(Size);
3880b57cec5SDimitry Andric TRACE(" small COMMON (" << Name << ")\n");
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andric return getContext().getELFSection(Name.str(), ELF::SHT_NOBITS,
3910b57cec5SDimitry Andric ELF::SHF_WRITE | ELF::SHF_ALLOC |
3920b57cec5SDimitry Andric ELF::SHF_HEX_GPREL);
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric
3950b57cec5SDimitry Andric // We could have changed sdata object to a constant... in this
3960b57cec5SDimitry Andric // case the Kind could be wrong for it.
3970b57cec5SDimitry Andric if (Kind.isMergeableConst()) {
3980b57cec5SDimitry Andric TRACE(" const_object_as_data ");
3990b57cec5SDimitry Andric const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO);
4000b57cec5SDimitry Andric if (GVar->hasSection() && isSmallDataSection(GVar->getSection()))
4010b57cec5SDimitry Andric Kind = SectionKind::getData();
4020b57cec5SDimitry Andric }
4030b57cec5SDimitry Andric
4040b57cec5SDimitry Andric if (Kind.isData()) {
4050b57cec5SDimitry Andric if (NoSmallDataSorting) {
4060b57cec5SDimitry Andric TRACE(" default sdata\n");
4070b57cec5SDimitry Andric return SmallDataSection;
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric
4100b57cec5SDimitry Andric StringRef Prefix(".sdata");
4110b57cec5SDimitry Andric SmallString<128> Name(Prefix);
4120b57cec5SDimitry Andric Name.append(getSectionSuffixForSize(Size));
4130b57cec5SDimitry Andric
4140b57cec5SDimitry Andric if (EmitUniquedSection) {
4150b57cec5SDimitry Andric Name.append(".");
4160b57cec5SDimitry Andric Name.append(GO->getName());
4170b57cec5SDimitry Andric }
4180b57cec5SDimitry Andric TRACE(" unique sdata(" << Name << ")\n");
4190b57cec5SDimitry Andric return getContext().getELFSection(Name.str(), ELF::SHT_PROGBITS,
4200b57cec5SDimitry Andric ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_HEX_GPREL);
4210b57cec5SDimitry Andric }
4220b57cec5SDimitry Andric
4230b57cec5SDimitry Andric TRACE("default ELF section\n");
4240b57cec5SDimitry Andric // Otherwise, we work the same as ELF.
4250b57cec5SDimitry Andric return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM);
4260b57cec5SDimitry Andric }
4270b57cec5SDimitry Andric
4280b57cec5SDimitry Andric // Return the function that uses the lookup table. If there are more
4290b57cec5SDimitry Andric // than one live function that uses this look table, bail out and place
4300b57cec5SDimitry Andric // the lookup table in default section.
4310b57cec5SDimitry Andric const Function *
getLutUsedFunction(const GlobalObject * GO) const4320b57cec5SDimitry Andric HexagonTargetObjectFile::getLutUsedFunction(const GlobalObject *GO) const {
4330b57cec5SDimitry Andric const Function *ReturnFn = nullptr;
434bdd1243dSDimitry Andric for (const auto *U : GO->users()) {
4350b57cec5SDimitry Andric // validate each instance of user to be a live function.
4360b57cec5SDimitry Andric auto *I = dyn_cast<Instruction>(U);
4370b57cec5SDimitry Andric if (!I)
4380b57cec5SDimitry Andric continue;
4390b57cec5SDimitry Andric auto *Bb = I->getParent();
4400b57cec5SDimitry Andric if (!Bb)
4410b57cec5SDimitry Andric continue;
4420b57cec5SDimitry Andric auto *UserFn = Bb->getParent();
4430b57cec5SDimitry Andric if (!ReturnFn)
4440b57cec5SDimitry Andric ReturnFn = UserFn;
4450b57cec5SDimitry Andric else if (ReturnFn != UserFn)
4460b57cec5SDimitry Andric return nullptr;
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric return ReturnFn;
4490b57cec5SDimitry Andric }
4500b57cec5SDimitry Andric
selectSectionForLookupTable(const GlobalObject * GO,const TargetMachine & TM,const Function * Fn) const4510b57cec5SDimitry Andric MCSection *HexagonTargetObjectFile::selectSectionForLookupTable(
4520b57cec5SDimitry Andric const GlobalObject *GO, const TargetMachine &TM, const Function *Fn) const {
4530b57cec5SDimitry Andric
4540b57cec5SDimitry Andric SectionKind Kind = SectionKind::getText();
4550b57cec5SDimitry Andric // If the function has explicit section, place the lookup table in this
4560b57cec5SDimitry Andric // explicit section.
4570b57cec5SDimitry Andric if (Fn->hasSection())
4580b57cec5SDimitry Andric return getExplicitSectionGlobal(Fn, Kind, TM);
4590b57cec5SDimitry Andric
4600b57cec5SDimitry Andric const auto *FuncObj = dyn_cast<GlobalObject>(Fn);
4610b57cec5SDimitry Andric return SelectSectionForGlobal(FuncObj, Kind, TM);
4620b57cec5SDimitry Andric }
463