Path: blob/main/contrib/llvm-project/llvm/lib/Target/TargetLoweringObjectFile.cpp
35232 views
//===-- llvm/Target/TargetLoweringObjectFile.cpp - Object File Info -------===//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// This file implements classes used to handle lowerings specific to common9// object file formats.10//11//===----------------------------------------------------------------------===//1213#include "llvm/Target/TargetLoweringObjectFile.h"14#include "llvm/BinaryFormat/Dwarf.h"15#include "llvm/IR/Constants.h"16#include "llvm/IR/DataLayout.h"17#include "llvm/IR/DerivedTypes.h"18#include "llvm/IR/Function.h"19#include "llvm/IR/GlobalVariable.h"20#include "llvm/IR/Mangler.h"21#include "llvm/IR/Module.h"22#include "llvm/MC/MCAsmInfo.h"23#include "llvm/MC/MCContext.h"24#include "llvm/MC/MCExpr.h"25#include "llvm/MC/MCStreamer.h"26#include "llvm/MC/SectionKind.h"27#include "llvm/Support/ErrorHandling.h"28#include "llvm/Target/TargetMachine.h"29#include "llvm/Target/TargetOptions.h"30using namespace llvm;3132//===----------------------------------------------------------------------===//33// Generic Code34//===----------------------------------------------------------------------===//3536/// Initialize - this method must be called before any actual lowering is37/// done. This specifies the current context for codegen, and gives the38/// lowering implementations a chance to set up their default sections.39void TargetLoweringObjectFile::Initialize(MCContext &ctx,40const TargetMachine &TM) {41// `Initialize` can be called more than once.42delete Mang;43Mang = new Mangler();44initMCObjectFileInfo(ctx, TM.isPositionIndependent(),45TM.getCodeModel() == CodeModel::Large);4647// Reset various EH DWARF encodings.48PersonalityEncoding = LSDAEncoding = TTypeEncoding = dwarf::DW_EH_PE_absptr;49CallSiteEncoding = dwarf::DW_EH_PE_uleb128;5051this->TM = &TM;52}5354TargetLoweringObjectFile::~TargetLoweringObjectFile() {55delete Mang;56}5758unsigned TargetLoweringObjectFile::getCallSiteEncoding() const {59// If target does not have LEB128 directives, we would need the60// call site encoding to be udata4 so that the alternative path61// for not having LEB128 directives could work.62if (!getContext().getAsmInfo()->hasLEB128Directives())63return dwarf::DW_EH_PE_udata4;64return CallSiteEncoding;65}6667static bool isNullOrUndef(const Constant *C) {68// Check that the constant isn't all zeros or undefs.69if (C->isNullValue() || isa<UndefValue>(C))70return true;71if (!isa<ConstantAggregate>(C))72return false;73for (const auto *Operand : C->operand_values()) {74if (!isNullOrUndef(cast<Constant>(Operand)))75return false;76}77return true;78}7980static bool isSuitableForBSS(const GlobalVariable *GV) {81const Constant *C = GV->getInitializer();8283// Must have zero initializer.84if (!isNullOrUndef(C))85return false;8687// Leave constant zeros in readonly constant sections, so they can be shared.88if (GV->isConstant())89return false;9091// If the global has an explicit section specified, don't put it in BSS.92if (GV->hasSection())93return false;9495// Otherwise, put it in BSS!96return true;97}9899/// IsNullTerminatedString - Return true if the specified constant (which is100/// known to have a type that is an array of 1/2/4 byte elements) ends with a101/// nul value and contains no other nuls in it. Note that this is more general102/// than ConstantDataSequential::isString because we allow 2 & 4 byte strings.103static bool IsNullTerminatedString(const Constant *C) {104// First check: is we have constant array terminated with zero105if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(C)) {106unsigned NumElts = CDS->getNumElements();107assert(NumElts != 0 && "Can't have an empty CDS");108109if (CDS->getElementAsInteger(NumElts-1) != 0)110return false; // Not null terminated.111112// Verify that the null doesn't occur anywhere else in the string.113for (unsigned i = 0; i != NumElts-1; ++i)114if (CDS->getElementAsInteger(i) == 0)115return false;116return true;117}118119// Another possibility: [1 x i8] zeroinitializer120if (isa<ConstantAggregateZero>(C))121return cast<ArrayType>(C->getType())->getNumElements() == 1;122123return false;124}125126MCSymbol *TargetLoweringObjectFile::getSymbolWithGlobalValueBase(127const GlobalValue *GV, StringRef Suffix, const TargetMachine &TM) const {128assert(!Suffix.empty());129130SmallString<60> NameStr;131NameStr += GV->getDataLayout().getPrivateGlobalPrefix();132TM.getNameWithPrefix(NameStr, GV, *Mang);133NameStr.append(Suffix.begin(), Suffix.end());134return getContext().getOrCreateSymbol(NameStr);135}136137MCSymbol *TargetLoweringObjectFile::getCFIPersonalitySymbol(138const GlobalValue *GV, const TargetMachine &TM,139MachineModuleInfo *MMI) const {140return TM.getSymbol(GV);141}142143void TargetLoweringObjectFile::emitPersonalityValue(MCStreamer &Streamer,144const DataLayout &,145const MCSymbol *Sym) const {146}147148void TargetLoweringObjectFile::emitCGProfileMetadata(MCStreamer &Streamer,149Module &M) const {150MCContext &C = getContext();151SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;152M.getModuleFlagsMetadata(ModuleFlags);153154MDNode *CFGProfile = nullptr;155156for (const auto &MFE : ModuleFlags) {157StringRef Key = MFE.Key->getString();158if (Key == "CG Profile") {159CFGProfile = cast<MDNode>(MFE.Val);160break;161}162}163164if (!CFGProfile)165return;166167auto GetSym = [this](const MDOperand &MDO) -> MCSymbol * {168if (!MDO)169return nullptr;170auto *V = cast<ValueAsMetadata>(MDO);171const Function *F = cast<Function>(V->getValue()->stripPointerCasts());172if (F->hasDLLImportStorageClass())173return nullptr;174return TM->getSymbol(F);175};176177for (const auto &Edge : CFGProfile->operands()) {178MDNode *E = cast<MDNode>(Edge);179const MCSymbol *From = GetSym(E->getOperand(0));180const MCSymbol *To = GetSym(E->getOperand(1));181// Skip null functions. This can happen if functions are dead stripped after182// the CGProfile pass has been run.183if (!From || !To)184continue;185uint64_t Count = cast<ConstantAsMetadata>(E->getOperand(2))186->getValue()187->getUniqueInteger()188.getZExtValue();189Streamer.emitCGProfileEntry(190MCSymbolRefExpr::create(From, MCSymbolRefExpr::VK_None, C),191MCSymbolRefExpr::create(To, MCSymbolRefExpr::VK_None, C), Count);192}193}194195/// getKindForGlobal - This is a top-level target-independent classifier for196/// a global object. Given a global variable and information from the TM, this197/// function classifies the global in a target independent manner. This function198/// may be overridden by the target implementation.199SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalObject *GO,200const TargetMachine &TM){201assert(!GO->isDeclarationForLinker() &&202"Can only be used for global definitions");203204// Functions are classified as text sections.205if (isa<Function>(GO))206return SectionKind::getText();207208// Basic blocks are classified as text sections.209if (isa<BasicBlock>(GO))210return SectionKind::getText();211212// Global variables require more detailed analysis.213const auto *GVar = cast<GlobalVariable>(GO);214215// Handle thread-local data first.216if (GVar->isThreadLocal()) {217if (isSuitableForBSS(GVar) && !TM.Options.NoZerosInBSS) {218// Zero-initialized TLS variables with local linkage always get classified219// as ThreadBSSLocal.220if (GVar->hasLocalLinkage()) {221return SectionKind::getThreadBSSLocal();222}223return SectionKind::getThreadBSS();224}225return SectionKind::getThreadData();226}227228// Variables with common linkage always get classified as common.229if (GVar->hasCommonLinkage())230return SectionKind::getCommon();231232// Most non-mergeable zero data can be put in the BSS section unless otherwise233// specified.234if (isSuitableForBSS(GVar) && !TM.Options.NoZerosInBSS) {235if (GVar->hasLocalLinkage())236return SectionKind::getBSSLocal();237else if (GVar->hasExternalLinkage())238return SectionKind::getBSSExtern();239return SectionKind::getBSS();240}241242// Global variables with '!exclude' should get the exclude section kind if243// they have an explicit section and no other metadata.244if (GVar->hasSection())245if (MDNode *MD = GVar->getMetadata(LLVMContext::MD_exclude))246if (!MD->getNumOperands())247return SectionKind::getExclude();248249// If the global is marked constant, we can put it into a mergable section,250// a mergable string section, or general .data if it contains relocations.251if (GVar->isConstant()) {252// If the initializer for the global contains something that requires a253// relocation, then we may have to drop this into a writable data section254// even though it is marked const.255const Constant *C = GVar->getInitializer();256if (!C->needsRelocation()) {257// If the global is required to have a unique address, it can't be put258// into a mergable section: just drop it into the general read-only259// section instead.260if (!GVar->hasGlobalUnnamedAddr())261return SectionKind::getReadOnly();262263// If initializer is a null-terminated string, put it in a "cstring"264// section of the right width.265if (ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) {266if (IntegerType *ITy =267dyn_cast<IntegerType>(ATy->getElementType())) {268if ((ITy->getBitWidth() == 8 || ITy->getBitWidth() == 16 ||269ITy->getBitWidth() == 32) &&270IsNullTerminatedString(C)) {271if (ITy->getBitWidth() == 8)272return SectionKind::getMergeable1ByteCString();273if (ITy->getBitWidth() == 16)274return SectionKind::getMergeable2ByteCString();275276assert(ITy->getBitWidth() == 32 && "Unknown width");277return SectionKind::getMergeable4ByteCString();278}279}280}281282// Otherwise, just drop it into a mergable constant section. If we have283// a section for this size, use it, otherwise use the arbitrary sized284// mergable section.285switch (286GVar->getDataLayout().getTypeAllocSize(C->getType())) {287case 4: return SectionKind::getMergeableConst4();288case 8: return SectionKind::getMergeableConst8();289case 16: return SectionKind::getMergeableConst16();290case 32: return SectionKind::getMergeableConst32();291default:292return SectionKind::getReadOnly();293}294295} else {296// In static, ROPI and RWPI relocation models, the linker will resolve297// all addresses, so the relocation entries will actually be constants by298// the time the app starts up. However, we can't put this into a299// mergable section, because the linker doesn't take relocations into300// consideration when it tries to merge entries in the section.301Reloc::Model ReloModel = TM.getRelocationModel();302if (ReloModel == Reloc::Static || ReloModel == Reloc::ROPI ||303ReloModel == Reloc::RWPI || ReloModel == Reloc::ROPI_RWPI ||304!C->needsDynamicRelocation())305return SectionKind::getReadOnly();306307// Otherwise, the dynamic linker needs to fix it up, put it in the308// writable data.rel section.309return SectionKind::getReadOnlyWithRel();310}311}312313// Okay, this isn't a constant.314return SectionKind::getData();315}316317/// This method computes the appropriate section to emit the specified global318/// variable or function definition. This should not be passed external (or319/// available externally) globals.320MCSection *TargetLoweringObjectFile::SectionForGlobal(321const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {322// Select section name.323if (GO->hasSection())324return getExplicitSectionGlobal(GO, Kind, TM);325326if (auto *GVar = dyn_cast<GlobalVariable>(GO)) {327auto Attrs = GVar->getAttributes();328if ((Attrs.hasAttribute("bss-section") && Kind.isBSS()) ||329(Attrs.hasAttribute("data-section") && Kind.isData()) ||330(Attrs.hasAttribute("relro-section") && Kind.isReadOnlyWithRel()) ||331(Attrs.hasAttribute("rodata-section") && Kind.isReadOnly())) {332return getExplicitSectionGlobal(GO, Kind, TM);333}334}335336// Use default section depending on the 'type' of global337return SelectSectionForGlobal(GO, Kind, TM);338}339340/// This method computes the appropriate section to emit the specified global341/// variable or function definition. This should not be passed external (or342/// available externally) globals.343MCSection *344TargetLoweringObjectFile::SectionForGlobal(const GlobalObject *GO,345const TargetMachine &TM) const {346return SectionForGlobal(GO, getKindForGlobal(GO, TM), TM);347}348349MCSection *TargetLoweringObjectFile::getSectionForJumpTable(350const Function &F, const TargetMachine &TM) const {351Align Alignment(1);352return getSectionForConstant(F.getDataLayout(),353SectionKind::getReadOnly(), /*C=*/nullptr,354Alignment);355}356357bool TargetLoweringObjectFile::shouldPutJumpTableInFunctionSection(358bool UsesLabelDifference, const Function &F) const {359// In PIC mode, we need to emit the jump table to the same section as the360// function body itself, otherwise the label differences won't make sense.361// FIXME: Need a better predicate for this: what about custom entries?362if (UsesLabelDifference)363return true;364365// We should also do if the section name is NULL or function is declared366// in discardable section367// FIXME: this isn't the right predicate, should be based on the MCSection368// for the function.369return F.isWeakForLinker();370}371372/// Given a mergable constant with the specified size and relocation373/// information, return a section that it should be placed in.374MCSection *TargetLoweringObjectFile::getSectionForConstant(375const DataLayout &DL, SectionKind Kind, const Constant *C,376Align &Alignment) const {377if (Kind.isReadOnly() && ReadOnlySection != nullptr)378return ReadOnlySection;379380return DataSection;381}382383MCSection *TargetLoweringObjectFile::getSectionForMachineBasicBlock(384const Function &F, const MachineBasicBlock &MBB,385const TargetMachine &TM) const {386return nullptr;387}388389MCSection *TargetLoweringObjectFile::getUniqueSectionForFunction(390const Function &F, const TargetMachine &TM) const {391return nullptr;392}393394/// getTTypeGlobalReference - Return an MCExpr to use for a395/// reference to the specified global variable from exception396/// handling information.397const MCExpr *TargetLoweringObjectFile::getTTypeGlobalReference(398const GlobalValue *GV, unsigned Encoding, const TargetMachine &TM,399MachineModuleInfo *MMI, MCStreamer &Streamer) const {400const MCSymbolRefExpr *Ref =401MCSymbolRefExpr::create(TM.getSymbol(GV), getContext());402403return getTTypeReference(Ref, Encoding, Streamer);404}405406const MCExpr *TargetLoweringObjectFile::407getTTypeReference(const MCSymbolRefExpr *Sym, unsigned Encoding,408MCStreamer &Streamer) const {409switch (Encoding & 0x70) {410default:411report_fatal_error("We do not support this DWARF encoding yet!");412case dwarf::DW_EH_PE_absptr:413// Do nothing special414return Sym;415case dwarf::DW_EH_PE_pcrel: {416// Emit a label to the streamer for the current position. This gives us417// .-foo addressing.418MCSymbol *PCSym = getContext().createTempSymbol();419Streamer.emitLabel(PCSym);420const MCExpr *PC = MCSymbolRefExpr::create(PCSym, getContext());421return MCBinaryExpr::createSub(Sym, PC, getContext());422}423}424}425426const MCExpr *TargetLoweringObjectFile::getDebugThreadLocalSymbol(const MCSymbol *Sym) const {427// FIXME: It's not clear what, if any, default this should have - perhaps a428// null return could mean 'no location' & we should just do that here.429return MCSymbolRefExpr::create(Sym, getContext());430}431432void TargetLoweringObjectFile::getNameWithPrefix(433SmallVectorImpl<char> &OutName, const GlobalValue *GV,434const TargetMachine &TM) const {435Mang->getNameWithPrefix(OutName, GV, /*CannotUsePrivateLabel=*/false);436}437438439