xref: /openbsd-src/gnu/llvm/llvm/lib/Target/Lanai/LanaiTargetObjectFile.cpp (revision 097a140d792de8b2bbe59ad827d39eabf9b4280a)
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