109467b48Spatrick //
209467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
309467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
409467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
509467b48Spatrick //
609467b48Spatrick //===----------------------------------------------------------------------===//
709467b48Spatrick
809467b48Spatrick #include "LanaiTargetObjectFile.h"
909467b48Spatrick
1009467b48Spatrick #include "LanaiSubtarget.h"
1109467b48Spatrick #include "LanaiTargetMachine.h"
1209467b48Spatrick #include "llvm/BinaryFormat/ELF.h"
1309467b48Spatrick #include "llvm/IR/DataLayout.h"
1409467b48Spatrick #include "llvm/IR/DerivedTypes.h"
1509467b48Spatrick #include "llvm/IR/GlobalVariable.h"
1609467b48Spatrick #include "llvm/MC/MCContext.h"
1709467b48Spatrick #include "llvm/MC/MCSectionELF.h"
1809467b48Spatrick #include "llvm/Support/CommandLine.h"
1909467b48Spatrick #include "llvm/Target/TargetMachine.h"
2009467b48Spatrick
2109467b48Spatrick using namespace llvm;
2209467b48Spatrick
2309467b48Spatrick static cl::opt<unsigned> SSThreshold(
2409467b48Spatrick "lanai-ssection-threshold", cl::Hidden,
2509467b48Spatrick cl::desc("Small data and bss section threshold size (default=0)"),
2609467b48Spatrick cl::init(0));
2709467b48Spatrick
Initialize(MCContext & Ctx,const TargetMachine & TM)2809467b48Spatrick void LanaiTargetObjectFile::Initialize(MCContext &Ctx,
2909467b48Spatrick const TargetMachine &TM) {
3009467b48Spatrick TargetLoweringObjectFileELF::Initialize(Ctx, TM);
3109467b48Spatrick
3209467b48Spatrick SmallDataSection = getContext().getELFSection(
3309467b48Spatrick ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
3409467b48Spatrick SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS,
3509467b48Spatrick ELF::SHF_WRITE | ELF::SHF_ALLOC);
3609467b48Spatrick }
3709467b48Spatrick
3809467b48Spatrick // A address must be loaded from a small section if its size is less than the
3909467b48Spatrick // small section size threshold. Data in this section must be addressed using
4009467b48Spatrick // gp_rel operator.
isInSmallSection(uint64_t Size)4109467b48Spatrick static bool isInSmallSection(uint64_t Size) {
4209467b48Spatrick // gcc has traditionally not treated zero-sized objects as small data, so this
4309467b48Spatrick // is effectively part of the ABI.
4409467b48Spatrick return Size > 0 && Size <= SSThreshold;
4509467b48Spatrick }
4609467b48Spatrick
4709467b48Spatrick // Return true if this global address should be placed into small data/bss
4809467b48Spatrick // section.
isGlobalInSmallSection(const GlobalObject * GO,const TargetMachine & TM) const4909467b48Spatrick bool LanaiTargetObjectFile::isGlobalInSmallSection(
5009467b48Spatrick const GlobalObject *GO, const TargetMachine &TM) const {
5109467b48Spatrick if (GO == nullptr) return TM.getCodeModel() == CodeModel::Small;
5209467b48Spatrick
5309467b48Spatrick // We first check the case where global is a declaration, because finding
5409467b48Spatrick // section kind using getKindForGlobal() is only allowed for global
5509467b48Spatrick // definitions.
5609467b48Spatrick if (GO->isDeclaration() || GO->hasAvailableExternallyLinkage())
5709467b48Spatrick return isGlobalInSmallSectionImpl(GO, TM);
5809467b48Spatrick
5909467b48Spatrick return isGlobalInSmallSection(GO, TM, getKindForGlobal(GO, TM));
6009467b48Spatrick }
6109467b48Spatrick
6209467b48Spatrick // Return true if this global address should be placed into small data/bss
6309467b48Spatrick // section.
isGlobalInSmallSection(const GlobalObject * GO,const TargetMachine & TM,SectionKind Kind) const6409467b48Spatrick bool LanaiTargetObjectFile::isGlobalInSmallSection(const GlobalObject *GO,
6509467b48Spatrick const TargetMachine &TM,
6609467b48Spatrick SectionKind Kind) const {
6709467b48Spatrick return isGlobalInSmallSectionImpl(GO, TM);
6809467b48Spatrick }
6909467b48Spatrick
7009467b48Spatrick // Return true if this global address should be placed into small data/bss
7109467b48Spatrick // section. This method does all the work, except for checking the section
7209467b48Spatrick // kind.
isGlobalInSmallSectionImpl(const GlobalObject * GO,const TargetMachine & TM) const7309467b48Spatrick bool LanaiTargetObjectFile::isGlobalInSmallSectionImpl(
7409467b48Spatrick const GlobalObject *GO, const TargetMachine &TM) const {
7509467b48Spatrick const auto *GVA = dyn_cast<GlobalVariable>(GO);
7609467b48Spatrick
7709467b48Spatrick // If not a GlobalVariable, only consider the code model.
7809467b48Spatrick if (!GVA) return TM.getCodeModel() == CodeModel::Small;
7909467b48Spatrick
8009467b48Spatrick // Global values placed in sections starting with .ldata do not fit in
8109467b48Spatrick // 21-bits, so always use large memory access for them. FIXME: This is a
8209467b48Spatrick // workaround for a tool limitation.
8309467b48Spatrick if (GVA->getSection().startswith(".ldata"))
8409467b48Spatrick return false;
8509467b48Spatrick
8609467b48Spatrick if (TM.getCodeModel() == CodeModel::Small)
8709467b48Spatrick return true;
8809467b48Spatrick
8909467b48Spatrick if (GVA->hasLocalLinkage())
9009467b48Spatrick return false;
9109467b48Spatrick
9209467b48Spatrick if (((GVA->hasExternalLinkage() && GVA->isDeclaration()) ||
9309467b48Spatrick GVA->hasCommonLinkage()))
9409467b48Spatrick return false;
9509467b48Spatrick
9609467b48Spatrick Type *Ty = GVA->getValueType();
9709467b48Spatrick return isInSmallSection(
9809467b48Spatrick GVA->getParent()->getDataLayout().getTypeAllocSize(Ty));
9909467b48Spatrick }
10009467b48Spatrick
SelectSectionForGlobal(const GlobalObject * GO,SectionKind Kind,const TargetMachine & TM) const10109467b48Spatrick MCSection *LanaiTargetObjectFile::SelectSectionForGlobal(
10209467b48Spatrick const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
10309467b48Spatrick // Handle Small Section classification here.
10409467b48Spatrick if (Kind.isBSS() && isGlobalInSmallSection(GO, TM, Kind))
10509467b48Spatrick return SmallBSSSection;
10609467b48Spatrick if (Kind.isData() && isGlobalInSmallSection(GO, TM, Kind))
10709467b48Spatrick return SmallDataSection;
10809467b48Spatrick
10909467b48Spatrick // Otherwise, we work the same as ELF.
11009467b48Spatrick return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM);
11109467b48Spatrick }
11209467b48Spatrick
11309467b48Spatrick /// Return true if this constant should be placed into small data section.
isConstantInSmallSection(const DataLayout & DL,const Constant * CN) const11409467b48Spatrick bool LanaiTargetObjectFile::isConstantInSmallSection(const DataLayout &DL,
11509467b48Spatrick const Constant *CN) const {
11609467b48Spatrick return isInSmallSection(DL.getTypeAllocSize(CN->getType()));
11709467b48Spatrick }
11809467b48Spatrick
getSectionForConstant(const DataLayout & DL,SectionKind Kind,const Constant * C,Align & Alignment) const119*097a140dSpatrick MCSection *LanaiTargetObjectFile::getSectionForConstant(
120*097a140dSpatrick const DataLayout &DL, SectionKind Kind, const Constant *C,
121*097a140dSpatrick Align &Alignment) const {
12209467b48Spatrick if (isConstantInSmallSection(DL, C))
12309467b48Spatrick return SmallDataSection;
12409467b48Spatrick
12509467b48Spatrick // Otherwise, we work the same as ELF.
126*097a140dSpatrick return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C,
127*097a140dSpatrick Alignment);
12809467b48Spatrick }
129