Path: blob/main/contrib/llvm-project/llvm/lib/Target/Lanai/LanaiTargetObjectFile.cpp
35271 views
//1// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.2// See https://llvm.org/LICENSE.txt for license information.3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception4//5//===----------------------------------------------------------------------===//67#include "LanaiTargetObjectFile.h"89#include "LanaiSubtarget.h"10#include "LanaiTargetMachine.h"11#include "llvm/BinaryFormat/ELF.h"12#include "llvm/IR/DataLayout.h"13#include "llvm/IR/DerivedTypes.h"14#include "llvm/IR/GlobalVariable.h"15#include "llvm/MC/MCContext.h"16#include "llvm/MC/MCSectionELF.h"17#include "llvm/Support/CommandLine.h"18#include "llvm/Target/TargetMachine.h"1920using namespace llvm;2122static cl::opt<unsigned> SSThreshold(23"lanai-ssection-threshold", cl::Hidden,24cl::desc("Small data and bss section threshold size (default=0)"),25cl::init(0));2627void LanaiTargetObjectFile::Initialize(MCContext &Ctx,28const TargetMachine &TM) {29TargetLoweringObjectFileELF::Initialize(Ctx, TM);3031SmallDataSection = getContext().getELFSection(32".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);33SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS,34ELF::SHF_WRITE | ELF::SHF_ALLOC);35}3637// A address must be loaded from a small section if its size is less than the38// small section size threshold. Data in this section must be addressed using39// gp_rel operator.40static bool isInSmallSection(uint64_t Size) {41// gcc has traditionally not treated zero-sized objects as small data, so this42// is effectively part of the ABI.43return Size > 0 && Size <= SSThreshold;44}4546// Return true if this global address should be placed into small data/bss47// section.48bool LanaiTargetObjectFile::isGlobalInSmallSection(49const GlobalObject *GO, const TargetMachine &TM) const {50if (GO == nullptr) return TM.getCodeModel() == CodeModel::Small;5152// We first check the case where global is a declaration, because finding53// section kind using getKindForGlobal() is only allowed for global54// definitions.55if (GO->isDeclaration() || GO->hasAvailableExternallyLinkage())56return isGlobalInSmallSectionImpl(GO, TM);5758return isGlobalInSmallSection(GO, TM, getKindForGlobal(GO, TM));59}6061// Return true if this global address should be placed into small data/bss62// section.63bool LanaiTargetObjectFile::isGlobalInSmallSection(const GlobalObject *GO,64const TargetMachine &TM,65SectionKind Kind) const {66return isGlobalInSmallSectionImpl(GO, TM);67}6869// Return true if this global address should be placed into small data/bss70// section. This method does all the work, except for checking the section71// kind.72bool LanaiTargetObjectFile::isGlobalInSmallSectionImpl(73const GlobalObject *GO, const TargetMachine &TM) const {74const auto *GVA = dyn_cast<GlobalVariable>(GO);7576// If not a GlobalVariable, only consider the code model.77if (!GVA) return TM.getCodeModel() == CodeModel::Small;7879// Global values placed in sections starting with .ldata do not fit in80// 21-bits, so always use large memory access for them. FIXME: This is a81// workaround for a tool limitation.82if (GVA->getSection().starts_with(".ldata"))83return false;8485if (TM.getCodeModel() == CodeModel::Small)86return true;8788if (GVA->hasLocalLinkage())89return false;9091if (((GVA->hasExternalLinkage() && GVA->isDeclaration()) ||92GVA->hasCommonLinkage()))93return false;9495Type *Ty = GVA->getValueType();96return isInSmallSection(97GVA->getDataLayout().getTypeAllocSize(Ty));98}99100MCSection *LanaiTargetObjectFile::SelectSectionForGlobal(101const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {102// Handle Small Section classification here.103if (Kind.isBSS() && isGlobalInSmallSection(GO, TM, Kind))104return SmallBSSSection;105if (Kind.isData() && isGlobalInSmallSection(GO, TM, Kind))106return SmallDataSection;107108// Otherwise, we work the same as ELF.109return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM);110}111112/// Return true if this constant should be placed into small data section.113bool LanaiTargetObjectFile::isConstantInSmallSection(const DataLayout &DL,114const Constant *CN) const {115return isInSmallSection(DL.getTypeAllocSize(CN->getType()));116}117118MCSection *LanaiTargetObjectFile::getSectionForConstant(119const DataLayout &DL, SectionKind Kind, const Constant *C,120Align &Alignment) const {121if (isConstantInSmallSection(DL, C))122return SmallDataSection;123124// Otherwise, we work the same as ELF.125return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C,126Alignment);127}128129130