brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.3 KiB · 343bcce Raw
489 lines · cpp
1//===-- llvm/Target/TargetLoweringObjectFile.cpp - Object File Info -------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements classes used to handle lowerings specific to common10// object file formats.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/Target/TargetLoweringObjectFile.h"15#include "llvm/BinaryFormat/Dwarf.h"16#include "llvm/IR/Constants.h"17#include "llvm/IR/DataLayout.h"18#include "llvm/IR/DerivedTypes.h"19#include "llvm/IR/Function.h"20#include "llvm/IR/GlobalVariable.h"21#include "llvm/IR/Mangler.h"22#include "llvm/IR/Module.h"23#include "llvm/MC/MCAsmInfo.h"24#include "llvm/MC/MCContext.h"25#include "llvm/MC/MCExpr.h"26#include "llvm/MC/MCStreamer.h"27#include "llvm/MC/SectionKind.h"28#include "llvm/Support/ErrorHandling.h"29#include "llvm/Target/TargetMachine.h"30#include "llvm/Target/TargetOptions.h"31using namespace llvm;32 33//===----------------------------------------------------------------------===//34//                              Generic Code35//===----------------------------------------------------------------------===//36 37/// Initialize - this method must be called before any actual lowering is38/// done.  This specifies the current context for codegen, and gives the39/// lowering implementations a chance to set up their default sections.40void TargetLoweringObjectFile::Initialize(MCContext &ctx,41                                          const TargetMachine &TM) {42  // `Initialize` can be called more than once.43  delete Mang;44  Mang = new Mangler();45  initMCObjectFileInfo(ctx, TM.isPositionIndependent(),46                       TM.getCodeModel() == CodeModel::Large);47 48  // Reset various EH DWARF encodings.49  PersonalityEncoding = LSDAEncoding = TTypeEncoding = dwarf::DW_EH_PE_absptr;50  CallSiteEncoding = dwarf::DW_EH_PE_uleb128;51 52  this->TM = &TM;53}54 55TargetLoweringObjectFile::~TargetLoweringObjectFile() {56  delete Mang;57}58 59unsigned TargetLoweringObjectFile::getCallSiteEncoding() const {60  // If target does not have LEB128 directives, we would need the61  // call site encoding to be udata4 so that the alternative path62  // for not having LEB128 directives could work.63  if (!getContext().getAsmInfo()->hasLEB128Directives())64    return dwarf::DW_EH_PE_udata4;65  return CallSiteEncoding;66}67 68static bool isNullOrUndef(const Constant *C) {69  // Check that the constant isn't all zeros or undefs.70  if (C->isNullValue() || isa<UndefValue>(C))71    return true;72  if (!isa<ConstantAggregate>(C))73    return false;74  for (const auto *Operand : C->operand_values()) {75    if (!isNullOrUndef(cast<Constant>(Operand)))76      return false;77  }78  return true;79}80 81static bool isSuitableForBSS(const GlobalVariable *GV) {82  const Constant *C = GV->getInitializer();83 84  // Must have zero initializer.85  if (!isNullOrUndef(C))86    return false;87 88  // Leave constant zeros in readonly constant sections, so they can be shared.89  if (GV->isConstant())90    return false;91 92  // If the global has an explicit section specified, don't put it in BSS.93  if (GV->hasSection())94    return false;95 96  // Otherwise, put it in BSS!97  return true;98}99 100/// IsNullTerminatedString - Return true if the specified constant (which is101/// known to have a type that is an array of 1/2/4 byte elements) ends with a102/// nul value and contains no other nuls in it.  Note that this is more general103/// than ConstantDataSequential::isString because we allow 2 & 4 byte strings.104static bool IsNullTerminatedString(const Constant *C) {105  // First check: is we have constant array terminated with zero106  if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(C)) {107    uint64_t NumElts = CDS->getNumElements();108    assert(NumElts != 0 && "Can't have an empty CDS");109 110    if (CDS->getElementAsInteger(NumElts-1) != 0)111      return false; // Not null terminated.112 113    // Verify that the null doesn't occur anywhere else in the string.114    for (uint64_t i = 0; i != NumElts - 1; ++i)115      if (CDS->getElementAsInteger(i) == 0)116        return false;117    return true;118  }119 120  // Another possibility: [1 x i8] zeroinitializer121  if (isa<ConstantAggregateZero>(C))122    return cast<ArrayType>(C->getType())->getNumElements() == 1;123 124  return false;125}126 127MCSymbol *TargetLoweringObjectFile::getSymbolWithGlobalValueBase(128    const GlobalValue *GV, StringRef Suffix, const TargetMachine &TM) const {129  assert(!Suffix.empty());130 131  SmallString<60> NameStr;132  NameStr += GV->getDataLayout().getPrivateGlobalPrefix();133  TM.getNameWithPrefix(NameStr, GV, *Mang);134  NameStr.append(Suffix.begin(), Suffix.end());135  return getContext().getOrCreateSymbol(NameStr);136}137 138MCSymbol *TargetLoweringObjectFile::getCFIPersonalitySymbol(139    const GlobalValue *GV, const TargetMachine &TM,140    MachineModuleInfo *MMI) const {141  return TM.getSymbol(GV);142}143 144void TargetLoweringObjectFile::emitPersonalityValue(145    MCStreamer &Streamer, const DataLayout &, const MCSymbol *Sym,146    const MachineModuleInfo *MMI) const {}147 148void TargetLoweringObjectFile::emitCGProfileMetadata(MCStreamer &Streamer,149                                                     Module &M) const {150  MCContext &C = getContext();151  SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;152  M.getModuleFlagsMetadata(ModuleFlags);153 154  MDNode *CGProfile = nullptr;155 156  for (const auto &MFE : ModuleFlags) {157    StringRef Key = MFE.Key->getString();158    if (Key == "CG Profile") {159      CGProfile = cast<MDNode>(MFE.Val);160      break;161    }162  }163 164  if (!CGProfile)165    return;166 167  auto GetSym = [this](const MDOperand &MDO) -> MCSymbol * {168    if (!MDO)169      return nullptr;170    auto *V = cast<ValueAsMetadata>(MDO);171    const Function *F = cast<Function>(V->getValue()->stripPointerCasts());172    if (F->hasDLLImportStorageClass())173      return nullptr;174    return TM->getSymbol(F);175  };176 177  for (const auto &Edge : CGProfile->operands()) {178    MDNode *E = cast<MDNode>(Edge);179    const MCSymbol *From = GetSym(E->getOperand(0));180    const 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.183    if (!From || !To)184      continue;185    uint64_t Count = cast<ConstantAsMetadata>(E->getOperand(2))186                         ->getValue()187                         ->getUniqueInteger()188                         .getZExtValue();189    Streamer.emitCGProfileEntry(MCSymbolRefExpr::create(From, C),190                                MCSymbolRefExpr::create(To, C), Count);191  }192}193 194void TargetLoweringObjectFile::emitPseudoProbeDescMetadata(195    MCStreamer &Streamer, Module &M,196    std::function<void(MCStreamer &Streamer)> COMDATSymEmitter) const {197  NamedMDNode *FuncInfo = M.getNamedMetadata(PseudoProbeDescMetadataName);198  if (!FuncInfo)199    return;200 201  // Emit a descriptor for every function including functions that have an202  // available external linkage. We may not want this for imported functions203  // that has code in another thinLTO module but we don't have a good way to204  // tell them apart from inline functions defined in header files. Therefore205  // we put each descriptor in a separate comdat section and rely on the206  // linker to deduplicate.207  auto &C = getContext();208  for (const auto *Operand : FuncInfo->operands()) {209    const auto *MD = cast<MDNode>(Operand);210    auto *GUID = mdconst::extract<ConstantInt>(MD->getOperand(0));211    auto *Hash = mdconst::extract<ConstantInt>(MD->getOperand(1));212    auto *Name = cast<MDString>(MD->getOperand(2));213    auto *S = C.getObjectFileInfo()->getPseudoProbeDescSection(214        TM->getFunctionSections() ? Name->getString() : StringRef());215 216    Streamer.switchSection(S);217 218    // emit COFF COMDAT symbol.219    if (COMDATSymEmitter)220      COMDATSymEmitter(Streamer);221 222    Streamer.emitInt64(GUID->getZExtValue());223    Streamer.emitInt64(Hash->getZExtValue());224    Streamer.emitULEB128IntValue(Name->getString().size());225    Streamer.emitBytes(Name->getString());226  }227}228 229/// getKindForGlobal - This is a top-level target-independent classifier for230/// a global object.  Given a global variable and information from the TM, this231/// function classifies the global in a target independent manner. This function232/// may be overridden by the target implementation.233SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalObject *GO,234                                                       const TargetMachine &TM){235  assert(!GO->isDeclarationForLinker() &&236         "Can only be used for global definitions");237 238  // Functions are classified as text sections.239  if (isa<Function>(GO))240    return SectionKind::getText();241 242  // Basic blocks are classified as text sections.243  if (isa<BasicBlock>(GO))244    return SectionKind::getText();245 246  // Global variables require more detailed analysis.247  const auto *GVar = cast<GlobalVariable>(GO);248 249  // Handle thread-local data first.250  if (GVar->isThreadLocal()) {251    if (isSuitableForBSS(GVar) && !TM.Options.NoZerosInBSS) {252      // Zero-initialized TLS variables with local linkage always get classified253      // as ThreadBSSLocal.254      if (GVar->hasLocalLinkage()) {255        return SectionKind::getThreadBSSLocal();256      }257      return SectionKind::getThreadBSS();258    }259    return SectionKind::getThreadData();260  }261 262  // Variables with common linkage always get classified as common.263  if (GVar->hasCommonLinkage())264    return SectionKind::getCommon();265 266  // Most non-mergeable zero data can be put in the BSS section unless otherwise267  // specified.268  if (isSuitableForBSS(GVar) && !TM.Options.NoZerosInBSS) {269    if (GVar->hasLocalLinkage())270      return SectionKind::getBSSLocal();271    else if (GVar->hasExternalLinkage())272      return SectionKind::getBSSExtern();273    return SectionKind::getBSS();274  }275 276  // Global variables with '!exclude' should get the exclude section kind if277  // they have an explicit section and no other metadata.278  if (GVar->hasSection())279    if (MDNode *MD = GVar->getMetadata(LLVMContext::MD_exclude))280      if (!MD->getNumOperands())281        return SectionKind::getExclude();282 283  // If the global is marked constant, we can put it into a mergable section,284  // a mergable string section, or general .data if it contains relocations.285  if (GVar->isConstant()) {286    // If the initializer for the global contains something that requires a287    // relocation, then we may have to drop this into a writable data section288    // even though it is marked const.289    const Constant *C = GVar->getInitializer();290    if (!C->needsRelocation()) {291      // If the global is required to have a unique address, it can't be put292      // into a mergable section: just drop it into the general read-only293      // section instead.294      if (!GVar->hasGlobalUnnamedAddr())295        return SectionKind::getReadOnly();296 297      // If initializer is a null-terminated string, put it in a "cstring"298      // section of the right width.299      if (ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) {300        if (IntegerType *ITy =301              dyn_cast<IntegerType>(ATy->getElementType())) {302          if ((ITy->getBitWidth() == 8 || ITy->getBitWidth() == 16 ||303               ITy->getBitWidth() == 32) &&304              IsNullTerminatedString(C)) {305            if (ITy->getBitWidth() == 8)306              return SectionKind::getMergeable1ByteCString();307            if (ITy->getBitWidth() == 16)308              return SectionKind::getMergeable2ByteCString();309 310            assert(ITy->getBitWidth() == 32 && "Unknown width");311            return SectionKind::getMergeable4ByteCString();312          }313        }314      }315 316      // Otherwise, just drop it into a mergable constant section.  If we have317      // a section for this size, use it, otherwise use the arbitrary sized318      // mergable section.319      switch (320          GVar->getDataLayout().getTypeAllocSize(C->getType())) {321      case 4:  return SectionKind::getMergeableConst4();322      case 8:  return SectionKind::getMergeableConst8();323      case 16: return SectionKind::getMergeableConst16();324      case 32: return SectionKind::getMergeableConst32();325      default:326        return SectionKind::getReadOnly();327      }328 329    } else {330      // In static, ROPI and RWPI relocation models, the linker will resolve331      // all addresses, so the relocation entries will actually be constants by332      // the time the app starts up.  However, we can't put this into a333      // mergable section, because the linker doesn't take relocations into334      // consideration when it tries to merge entries in the section.335      Reloc::Model ReloModel = TM.getRelocationModel();336      if (ReloModel == Reloc::Static || ReloModel == Reloc::ROPI ||337          ReloModel == Reloc::RWPI || ReloModel == Reloc::ROPI_RWPI ||338          !C->needsDynamicRelocation())339        return SectionKind::getReadOnly();340 341      // Otherwise, the dynamic linker needs to fix it up, put it in the342      // writable data.rel section.343      return SectionKind::getReadOnlyWithRel();344    }345  }346 347  // Okay, this isn't a constant.348  return SectionKind::getData();349}350 351/// This method computes the appropriate section to emit the specified global352/// variable or function definition.  This should not be passed external (or353/// available externally) globals.354MCSection *TargetLoweringObjectFile::SectionForGlobal(355    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {356  // Select section name.357  if (GO->hasSection())358    return getExplicitSectionGlobal(GO, Kind, TM);359 360  if (auto *GVar = dyn_cast<GlobalVariable>(GO)) {361    auto Attrs = GVar->getAttributes();362    if ((Attrs.hasAttribute("bss-section") && Kind.isBSS()) ||363        (Attrs.hasAttribute("data-section") && Kind.isData()) ||364        (Attrs.hasAttribute("relro-section") && Kind.isReadOnlyWithRel()) ||365        (Attrs.hasAttribute("rodata-section") && Kind.isReadOnly()))  {366       return getExplicitSectionGlobal(GO, Kind, TM);367    }368  }369 370  // Use default section depending on the 'type' of global371  return SelectSectionForGlobal(GO, Kind, TM);372}373 374/// This method computes the appropriate section to emit the specified global375/// variable or function definition. This should not be passed external (or376/// available externally) globals.377MCSection *378TargetLoweringObjectFile::SectionForGlobal(const GlobalObject *GO,379                                           const TargetMachine &TM) const {380  return SectionForGlobal(GO, getKindForGlobal(GO, TM), TM);381}382 383MCSection *TargetLoweringObjectFile::getSectionForJumpTable(384    const Function &F, const TargetMachine &TM) const {385  return getSectionForJumpTable(F, TM, /*JTE=*/nullptr);386}387 388MCSection *TargetLoweringObjectFile::getSectionForJumpTable(389    const Function &F, const TargetMachine &TM,390    const MachineJumpTableEntry *JTE) const {391  Align Alignment(1);392  return getSectionForConstant(F.getDataLayout(),393                               SectionKind::getReadOnly(), /*C=*/nullptr,394                               Alignment);395}396 397bool TargetLoweringObjectFile::shouldPutJumpTableInFunctionSection(398    bool UsesLabelDifference, const Function &F) const {399  // In PIC mode, we need to emit the jump table to the same section as the400  // function body itself, otherwise the label differences won't make sense.401  // FIXME: Need a better predicate for this: what about custom entries?402  if (UsesLabelDifference)403    return true;404 405  // We should also do if the section name is NULL or function is declared406  // in discardable section407  // FIXME: this isn't the right predicate, should be based on the MCSection408  // for the function.409  return F.isWeakForLinker();410}411 412/// Given a mergable constant with the specified size and relocation413/// information, return a section that it should be placed in.414MCSection *TargetLoweringObjectFile::getSectionForConstant(415    const DataLayout &DL, SectionKind Kind, const Constant *C,416    Align &Alignment) const {417  if (Kind.isReadOnly() && ReadOnlySection != nullptr)418    return ReadOnlySection;419 420  return DataSection;421}422 423MCSection *TargetLoweringObjectFile::getSectionForConstant(424    const DataLayout &DL, SectionKind Kind, const Constant *C, Align &Alignment,425    StringRef SectionPrefix) const {426  // Fallback to `getSectionForConstant` without `SectionPrefix` parameter if it427  // is empty.428  if (SectionPrefix.empty())429    return getSectionForConstant(DL, Kind, C, Alignment);430  report_fatal_error(431      "TargetLoweringObjectFile::getSectionForConstant that "432      "accepts SectionPrefix is not implemented for the object file format");433}434 435MCSection *TargetLoweringObjectFile::getSectionForMachineBasicBlock(436    const Function &F, const MachineBasicBlock &MBB,437    const TargetMachine &TM) const {438  return nullptr;439}440 441MCSection *TargetLoweringObjectFile::getUniqueSectionForFunction(442    const Function &F, const TargetMachine &TM) const {443  return nullptr;444}445 446/// getTTypeGlobalReference - Return an MCExpr to use for a447/// reference to the specified global variable from exception448/// handling information.449const MCExpr *TargetLoweringObjectFile::getTTypeGlobalReference(450    const GlobalValue *GV, unsigned Encoding, const TargetMachine &TM,451    MachineModuleInfo *MMI, MCStreamer &Streamer) const {452  const MCSymbolRefExpr *Ref =453      MCSymbolRefExpr::create(TM.getSymbol(GV), getContext());454 455  return getTTypeReference(Ref, Encoding, Streamer);456}457 458const MCExpr *TargetLoweringObjectFile::459getTTypeReference(const MCSymbolRefExpr *Sym, unsigned Encoding,460                  MCStreamer &Streamer) const {461  switch (Encoding & 0x70) {462  default:463    report_fatal_error("We do not support this DWARF encoding yet!");464  case dwarf::DW_EH_PE_absptr:465    // Do nothing special466    return Sym;467  case dwarf::DW_EH_PE_pcrel: {468    // Emit a label to the streamer for the current position.  This gives us469    // .-foo addressing.470    MCSymbol *PCSym = getContext().createTempSymbol();471    Streamer.emitLabel(PCSym);472    const MCExpr *PC = MCSymbolRefExpr::create(PCSym, getContext());473    return MCBinaryExpr::createSub(Sym, PC, getContext());474  }475  }476}477 478const MCExpr *TargetLoweringObjectFile::getDebugThreadLocalSymbol(const MCSymbol *Sym) const {479  // FIXME: It's not clear what, if any, default this should have - perhaps a480  // null return could mean 'no location' & we should just do that here.481  return MCSymbolRefExpr::create(Sym, getContext());482}483 484void TargetLoweringObjectFile::getNameWithPrefix(485    SmallVectorImpl<char> &OutName, const GlobalValue *GV,486    const TargetMachine &TM) const {487  Mang->getNameWithPrefix(OutName, GV, /*CannotUsePrivateLabel=*/false);488}489