126 lines · cpp
1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7 8#include "LanaiTargetObjectFile.h"9 10#include "llvm/BinaryFormat/ELF.h"11#include "llvm/IR/DataLayout.h"12#include "llvm/IR/GlobalVariable.h"13#include "llvm/MC/MCContext.h"14#include "llvm/MC/MCSectionELF.h"15#include "llvm/Support/CommandLine.h"16#include "llvm/Target/TargetMachine.h"17 18using namespace llvm;19 20static cl::opt<unsigned> SSThreshold(21 "lanai-ssection-threshold", cl::Hidden,22 cl::desc("Small data and bss section threshold size (default=0)"),23 cl::init(0));24 25void LanaiTargetObjectFile::Initialize(MCContext &Ctx,26 const TargetMachine &TM) {27 TargetLoweringObjectFileELF::Initialize(Ctx, TM);28 29 SmallDataSection = getContext().getELFSection(30 ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);31 SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS,32 ELF::SHF_WRITE | ELF::SHF_ALLOC);33}34 35// A address must be loaded from a small section if its size is less than the36// small section size threshold. Data in this section must be addressed using37// gp_rel operator.38static bool isInSmallSection(uint64_t Size) {39 // gcc has traditionally not treated zero-sized objects as small data, so this40 // is effectively part of the ABI.41 return Size > 0 && Size <= SSThreshold;42}43 44// Return true if this global address should be placed into small data/bss45// section.46bool LanaiTargetObjectFile::isGlobalInSmallSection(47 const GlobalObject *GO, const TargetMachine &TM) const {48 if (GO == nullptr) return TM.getCodeModel() == CodeModel::Small;49 50 // We first check the case where global is a declaration, because finding51 // section kind using getKindForGlobal() is only allowed for global52 // definitions.53 if (GO->isDeclaration() || GO->hasAvailableExternallyLinkage())54 return isGlobalInSmallSectionImpl(GO, TM);55 56 return isGlobalInSmallSection(GO, TM, getKindForGlobal(GO, TM));57}58 59// Return true if this global address should be placed into small data/bss60// section.61bool LanaiTargetObjectFile::isGlobalInSmallSection(const GlobalObject *GO,62 const TargetMachine &TM,63 SectionKind Kind) const {64 return isGlobalInSmallSectionImpl(GO, TM);65}66 67// Return true if this global address should be placed into small data/bss68// section. This method does all the work, except for checking the section69// kind.70bool LanaiTargetObjectFile::isGlobalInSmallSectionImpl(71 const GlobalObject *GO, const TargetMachine &TM) const {72 const auto *GVA = dyn_cast<GlobalVariable>(GO);73 74 // If not a GlobalVariable, only consider the code model.75 if (!GVA) return TM.getCodeModel() == CodeModel::Small;76 77 // Global values placed in sections starting with .ldata do not fit in78 // 21-bits, so always use large memory access for them. FIXME: This is a79 // workaround for a tool limitation.80 if (GVA->getSection().starts_with(".ldata"))81 return false;82 83 if (TM.getCodeModel() == CodeModel::Small)84 return true;85 86 if (GVA->hasLocalLinkage())87 return false;88 89 if (((GVA->hasExternalLinkage() && GVA->isDeclaration()) ||90 GVA->hasCommonLinkage()))91 return false;92 93 Type *Ty = GVA->getValueType();94 return isInSmallSection(95 GVA->getDataLayout().getTypeAllocSize(Ty));96}97 98MCSection *LanaiTargetObjectFile::SelectSectionForGlobal(99 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {100 // Handle Small Section classification here.101 if (Kind.isBSS() && isGlobalInSmallSection(GO, TM, Kind))102 return SmallBSSSection;103 if (Kind.isData() && isGlobalInSmallSection(GO, TM, Kind))104 return SmallDataSection;105 106 // Otherwise, we work the same as ELF.107 return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM);108}109 110/// Return true if this constant should be placed into small data section.111bool LanaiTargetObjectFile::isConstantInSmallSection(const DataLayout &DL,112 const Constant *CN) const {113 return isInSmallSection(DL.getTypeAllocSize(CN->getType()));114}115 116MCSection *LanaiTargetObjectFile::getSectionForConstant(117 const DataLayout &DL, SectionKind Kind, const Constant *C,118 Align &Alignment) const {119 if (isConstantInSmallSection(DL, C))120 return SmallDataSection;121 122 // Otherwise, we work the same as ELF.123 return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C,124 Alignment);125}126