brintos

brintos / llvm-project-archived public Read only

0
0
Text · 129.7 KiB · 122738c Raw
3387 lines · cpp
1//===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly ------===//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 contains a printer that converts from our internal representation10// of machine-dependent LLVM code to PowerPC assembly language. This printer is11// the output mechanism used by `llc'.12//13// Documentation at http://developer.apple.com/documentation/DeveloperTools/14// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html15//16//===----------------------------------------------------------------------===//17 18#include "MCTargetDesc/PPCInstPrinter.h"19#include "MCTargetDesc/PPCMCAsmInfo.h"20#include "MCTargetDesc/PPCMCTargetDesc.h"21#include "MCTargetDesc/PPCPredicates.h"22#include "MCTargetDesc/PPCTargetStreamer.h"23#include "PPC.h"24#include "PPCInstrInfo.h"25#include "PPCMachineFunctionInfo.h"26#include "PPCSubtarget.h"27#include "PPCTargetMachine.h"28#include "TargetInfo/PowerPCTargetInfo.h"29#include "llvm/ADT/MapVector.h"30#include "llvm/ADT/SetVector.h"31#include "llvm/ADT/Statistic.h"32#include "llvm/ADT/StringExtras.h"33#include "llvm/ADT/StringRef.h"34#include "llvm/ADT/Twine.h"35#include "llvm/BinaryFormat/ELF.h"36#include "llvm/CodeGen/AsmPrinter.h"37#include "llvm/CodeGen/MachineBasicBlock.h"38#include "llvm/CodeGen/MachineFrameInfo.h"39#include "llvm/CodeGen/MachineFunction.h"40#include "llvm/CodeGen/MachineInstr.h"41#include "llvm/CodeGen/MachineModuleInfoImpls.h"42#include "llvm/CodeGen/MachineOperand.h"43#include "llvm/CodeGen/MachineRegisterInfo.h"44#include "llvm/CodeGen/StackMaps.h"45#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"46#include "llvm/IR/DataLayout.h"47#include "llvm/IR/GlobalValue.h"48#include "llvm/IR/GlobalVariable.h"49#include "llvm/IR/Module.h"50#include "llvm/MC/MCAsmInfo.h"51#include "llvm/MC/MCContext.h"52#include "llvm/MC/MCDirectives.h"53#include "llvm/MC/MCExpr.h"54#include "llvm/MC/MCInst.h"55#include "llvm/MC/MCInstBuilder.h"56#include "llvm/MC/MCSectionELF.h"57#include "llvm/MC/MCSectionXCOFF.h"58#include "llvm/MC/MCStreamer.h"59#include "llvm/MC/MCSymbol.h"60#include "llvm/MC/MCSymbolELF.h"61#include "llvm/MC/MCSymbolXCOFF.h"62#include "llvm/MC/SectionKind.h"63#include "llvm/MC/TargetRegistry.h"64#include "llvm/Support/Casting.h"65#include "llvm/Support/CodeGen.h"66#include "llvm/Support/Compiler.h"67#include "llvm/Support/Debug.h"68#include "llvm/Support/Error.h"69#include "llvm/Support/ErrorHandling.h"70#include "llvm/Support/MathExtras.h"71#include "llvm/Support/Process.h"72#include "llvm/Support/Threading.h"73#include "llvm/Support/raw_ostream.h"74#include "llvm/Target/TargetMachine.h"75#include "llvm/TargetParser/PPCTargetParser.h"76#include "llvm/TargetParser/Triple.h"77#include "llvm/Transforms/Utils/ModuleUtils.h"78#include <cassert>79#include <cstdint>80#include <memory>81#include <new>82 83using namespace llvm;84using namespace llvm::XCOFF;85 86#define DEBUG_TYPE "asmprinter"87 88STATISTIC(NumTOCEntries, "Number of Total TOC Entries Emitted.");89STATISTIC(NumTOCConstPool, "Number of Constant Pool TOC Entries.");90STATISTIC(NumTOCGlobalInternal,91          "Number of Internal Linkage Global TOC Entries.");92STATISTIC(NumTOCGlobalExternal,93          "Number of External Linkage Global TOC Entries.");94STATISTIC(NumTOCJumpTable, "Number of Jump Table TOC Entries.");95STATISTIC(NumTOCThreadLocal, "Number of Thread Local TOC Entries.");96STATISTIC(NumTOCBlockAddress, "Number of Block Address TOC Entries.");97STATISTIC(NumTOCEHBlock, "Number of EH Block TOC Entries.");98 99static cl::opt<bool> EnableSSPCanaryBitInTB(100    "aix-ssp-tb-bit", cl::init(false),101    cl::desc("Enable Passing SSP Canary info in Trackback on AIX"), cl::Hidden);102 103// Specialize DenseMapInfo to allow104// std::pair<const MCSymbol *, PPCMCExpr::Specifier> in DenseMap.105// This specialization is needed here because that type is used as keys in the106// map representing TOC entries.107namespace llvm {108template <>109struct DenseMapInfo<std::pair<const MCSymbol *, PPCMCExpr::Specifier>> {110  using TOCKey = std::pair<const MCSymbol *, PPCMCExpr::Specifier>;111 112  static inline TOCKey getEmptyKey() { return {nullptr, PPC::S_None}; }113  static inline TOCKey getTombstoneKey() {114    return {(const MCSymbol *)1, PPC::S_None};115  }116  static unsigned getHashValue(const TOCKey &PairVal) {117    return detail::combineHashValue(118        DenseMapInfo<const MCSymbol *>::getHashValue(PairVal.first),119        DenseMapInfo<int>::getHashValue(PairVal.second));120  }121  static bool isEqual(const TOCKey &A, const TOCKey &B) { return A == B; }122};123} // end namespace llvm124 125namespace {126 127enum {128  // GNU attribute tags for PowerPC ABI129  Tag_GNU_Power_ABI_FP = 4,130  Tag_GNU_Power_ABI_Vector = 8,131  Tag_GNU_Power_ABI_Struct_Return = 12,132 133  // GNU attribute values for PowerPC float ABI, as combination of two parts134  Val_GNU_Power_ABI_NoFloat = 0b00,135  Val_GNU_Power_ABI_HardFloat_DP = 0b01,136  Val_GNU_Power_ABI_SoftFloat_DP = 0b10,137  Val_GNU_Power_ABI_HardFloat_SP = 0b11,138 139  Val_GNU_Power_ABI_LDBL_IBM128 = 0b0100,140  Val_GNU_Power_ABI_LDBL_64 = 0b1000,141  Val_GNU_Power_ABI_LDBL_IEEE128 = 0b1100,142};143 144class PPCAsmPrinter : public AsmPrinter {145protected:146  // For TLS on AIX, we need to be able to identify TOC entries of specific147  // specifier so we can add the right relocations when we generate the148  // entries. So each entry is represented by a pair of MCSymbol and149  // VariantKind. For example, we need to be able to identify the following150  // entry as a TLSGD entry so we can add the @m relocation:151  //   .tc .i[TC],i[TL]@m152  // By default, 0 is used for the specifier.153  MapVector<std::pair<const MCSymbol *, PPCMCExpr::Specifier>, MCSymbol *> TOC;154  const PPCSubtarget *Subtarget = nullptr;155 156  // Keep track of the number of TLS variables and their corresponding157  // addresses, which is then used for the assembly printing of158  // non-TOC-based local-exec variables.159  MapVector<const GlobalValue *, uint64_t> TLSVarsToAddressMapping;160 161public:162  explicit PPCAsmPrinter(TargetMachine &TM,163                         std::unique_ptr<MCStreamer> Streamer, char &ID)164      : AsmPrinter(TM, std::move(Streamer), ID) {}165 166  StringRef getPassName() const override { return "PowerPC Assembly Printer"; }167 168  enum TOCEntryType {169    TOCType_ConstantPool,170    TOCType_GlobalExternal,171    TOCType_GlobalInternal,172    TOCType_JumpTable,173    TOCType_ThreadLocal,174    TOCType_BlockAddress,175    TOCType_EHBlock176  };177 178  MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym, TOCEntryType Type,179                                   PPCMCExpr::Specifier Kind = PPC::S_None);180 181  bool doInitialization(Module &M) override {182    if (!TOC.empty())183      TOC.clear();184    return AsmPrinter::doInitialization(M);185  }186 187  const MCExpr *symbolWithSpecifier(const MCSymbol *S,188                                    PPCMCExpr::Specifier Kind);189  void emitInstruction(const MachineInstr *MI) override;190 191  /// This function is for PrintAsmOperand and PrintAsmMemoryOperand,192  /// invoked by EmitMSInlineAsmStr and EmitGCCInlineAsmStr only.193  /// The \p MI would be INLINEASM ONLY.194  void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);195 196  void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;197  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,198                       const char *ExtraCode, raw_ostream &O) override;199  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,200                             const char *ExtraCode, raw_ostream &O) override;201 202  void LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI);203  void LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI);204  void emitTlsCall(const MachineInstr *MI, PPCMCExpr::Specifier VK);205  void EmitAIXTlsCallHelper(const MachineInstr *MI);206  const MCExpr *getAdjustedFasterLocalExpr(const MachineOperand &MO,207                                           int64_t Offset);208  bool runOnMachineFunction(MachineFunction &MF) override {209    Subtarget = &MF.getSubtarget<PPCSubtarget>();210    bool Changed = AsmPrinter::runOnMachineFunction(MF);211    emitXRayTable();212    return Changed;213  }214};215 216/// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux217class PPCLinuxAsmPrinter : public PPCAsmPrinter {218public:219  static char ID;220 221  explicit PPCLinuxAsmPrinter(TargetMachine &TM,222                              std::unique_ptr<MCStreamer> Streamer)223      : PPCAsmPrinter(TM, std::move(Streamer), ID) {}224 225  StringRef getPassName() const override {226    return "Linux PPC Assembly Printer";227  }228 229  void emitGNUAttributes(Module &M);230 231  void emitStartOfAsmFile(Module &M) override;232  void emitEndOfAsmFile(Module &) override;233 234  void emitFunctionEntryLabel() override;235 236  void emitFunctionBodyStart() override;237  void emitFunctionBodyEnd() override;238  void emitInstruction(const MachineInstr *MI) override;239};240 241class PPCAIXAsmPrinter : public PPCAsmPrinter {242private:243  /// Symbols lowered from ExternalSymbolSDNodes, we will need to emit extern244  /// linkage for them in AIX.245  SmallSetVector<MCSymbol *, 8> ExtSymSDNodeSymbols;246 247  /// A format indicator and unique trailing identifier to form part of the248  /// sinit/sterm function names.249  std::string FormatIndicatorAndUniqueModId;250 251  // Record a list of GlobalAlias associated with a GlobalObject.252  // This is used for AIX's extra-label-at-definition aliasing strategy.253  DenseMap<const GlobalObject *, SmallVector<const GlobalAlias *, 1>>254      GOAliasMap;255 256  uint16_t getNumberOfVRSaved();257  void emitTracebackTable();258 259  SmallVector<const GlobalVariable *, 8> TOCDataGlobalVars;260 261  void emitGlobalVariableHelper(const GlobalVariable *);262 263  // Get the offset of an alias based on its AliaseeObject.264  uint64_t getAliasOffset(const Constant *C);265 266public:267  static char ID;268 269  PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)270      : PPCAsmPrinter(TM, std::move(Streamer), ID) {271    if (MAI->isLittleEndian())272      report_fatal_error(273          "cannot create AIX PPC Assembly Printer for a little-endian target");274  }275 276  StringRef getPassName() const override { return "AIX PPC Assembly Printer"; }277 278  bool doInitialization(Module &M) override;279 280  void emitXXStructorList(const DataLayout &DL, const Constant *List,281                          bool IsCtor) override;282 283  void SetupMachineFunction(MachineFunction &MF) override;284 285  void emitGlobalVariable(const GlobalVariable *GV) override;286 287  void emitFunctionDescriptor() override;288 289  void emitFunctionEntryLabel() override;290 291  void emitFunctionBodyEnd() override;292 293  void emitPGORefs(Module &M);294 295  void emitGCOVRefs();296 297  void emitEndOfAsmFile(Module &) override;298 299  void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override;300 301  void emitInstruction(const MachineInstr *MI) override;302 303  bool doFinalization(Module &M) override;304 305  void emitTTypeReference(const GlobalValue *GV, unsigned Encoding) override;306 307  void emitModuleCommandLines(Module &M) override;308};309 310} // end anonymous namespace311 312void PPCAsmPrinter::PrintSymbolOperand(const MachineOperand &MO,313                                       raw_ostream &O) {314  // Computing the address of a global symbol, not calling it.315  const GlobalValue *GV = MO.getGlobal();316  getSymbol(GV)->print(O, MAI);317  printOffset(MO.getOffset(), O);318}319 320void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,321                                 raw_ostream &O) {322  const DataLayout &DL = getDataLayout();323  const MachineOperand &MO = MI->getOperand(OpNo);324 325  switch (MO.getType()) {326  case MachineOperand::MO_Register: {327    // The MI is INLINEASM ONLY and UseVSXReg is always false.328    const char *RegName = PPCInstPrinter::getRegisterName(MO.getReg());329 330    // Linux assembler (Others?) does not take register mnemonics.331    // FIXME - What about special registers used in mfspr/mtspr?332    O << PPC::stripRegisterPrefix(RegName);333    return;334  }335  case MachineOperand::MO_Immediate:336    O << MO.getImm();337    return;338 339  case MachineOperand::MO_MachineBasicBlock:340    MO.getMBB()->getSymbol()->print(O, MAI);341    return;342  case MachineOperand::MO_ConstantPoolIndex:343    O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'344      << MO.getIndex();345    return;346  case MachineOperand::MO_BlockAddress:347    GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);348    return;349  case MachineOperand::MO_GlobalAddress: {350    PrintSymbolOperand(MO, O);351    return;352  }353 354  default:355    O << "<unknown operand type: " << (unsigned)MO.getType() << ">";356    return;357  }358}359 360/// PrintAsmOperand - Print out an operand for an inline asm expression.361///362bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,363                                    const char *ExtraCode, raw_ostream &O) {364  // Does this asm operand have a single letter operand modifier?365  if (ExtraCode && ExtraCode[0]) {366    if (ExtraCode[1] != 0) return true; // Unknown modifier.367 368    switch (ExtraCode[0]) {369    default:370      // See if this is a generic print operand371      return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);372    case 'L': // Write second word of DImode reference.373      // Verify that this operand has two consecutive registers.374      if (!MI->getOperand(OpNo).isReg() ||375          OpNo+1 == MI->getNumOperands() ||376          !MI->getOperand(OpNo+1).isReg())377        return true;378      ++OpNo;   // Return the high-part.379      break;380    case 'I':381      // Write 'i' if an integer constant, otherwise nothing.  Used to print382      // addi vs add, etc.383      if (MI->getOperand(OpNo).isImm())384        O << "i";385      return false;386    case 'x':387      if(!MI->getOperand(OpNo).isReg())388        return true;389      // This operand uses VSX numbering.390      // If the operand is a VMX register, convert it to a VSX register.391      Register Reg = MI->getOperand(OpNo).getReg();392      if (PPC::isVRRegister(Reg))393        Reg = PPC::VSX32 + (Reg - PPC::V0);394      else if (PPC::isVFRegister(Reg))395        Reg = PPC::VSX32 + (Reg - PPC::VF0);396      const char *RegName;397      RegName = PPCInstPrinter::getRegisterName(Reg);398      RegName = PPC::stripRegisterPrefix(RegName);399      O << RegName;400      return false;401    }402  }403 404  printOperand(MI, OpNo, O);405  return false;406}407 408// At the moment, all inline asm memory operands are a single register.409// In any case, the output of this routine should always be just one410// assembler operand.411bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,412                                          const char *ExtraCode,413                                          raw_ostream &O) {414  if (ExtraCode && ExtraCode[0]) {415    if (ExtraCode[1] != 0) return true; // Unknown modifier.416 417    switch (ExtraCode[0]) {418    default: return true;  // Unknown modifier.419    case 'L': // A memory reference to the upper word of a double word op.420      O << getDataLayout().getPointerSize() << "(";421      printOperand(MI, OpNo, O);422      O << ")";423      return false;424    case 'y': // A memory reference for an X-form instruction425      O << "0, ";426      printOperand(MI, OpNo, O);427      return false;428    case 'I':429      // Write 'i' if an integer constant, otherwise nothing.  Used to print430      // addi vs add, etc.431      if (MI->getOperand(OpNo).isImm())432        O << "i";433      return false;434    case 'U': // Print 'u' for update form.435    case 'X': // Print 'x' for indexed form.436      // FIXME: Currently for PowerPC memory operands are always loaded437      // into a register, so we never get an update or indexed form.438      // This is bad even for offset forms, since even if we know we439      // have a value in -16(r1), we will generate a load into r<n>440      // and then load from 0(r<n>).  Until that issue is fixed,441      // tolerate 'U' and 'X' but don't output anything.442      assert(MI->getOperand(OpNo).isReg());443      return false;444    }445  }446 447  assert(MI->getOperand(OpNo).isReg());448  O << "0(";449  printOperand(MI, OpNo, O);450  O << ")";451  return false;452}453 454static void collectTOCStats(PPCAsmPrinter::TOCEntryType Type) {455  ++NumTOCEntries;456  switch (Type) {457  case PPCAsmPrinter::TOCType_ConstantPool:458    ++NumTOCConstPool;459    break;460  case PPCAsmPrinter::TOCType_GlobalInternal:461    ++NumTOCGlobalInternal;462    break;463  case PPCAsmPrinter::TOCType_GlobalExternal:464    ++NumTOCGlobalExternal;465    break;466  case PPCAsmPrinter::TOCType_JumpTable:467    ++NumTOCJumpTable;468    break;469  case PPCAsmPrinter::TOCType_ThreadLocal:470    ++NumTOCThreadLocal;471    break;472  case PPCAsmPrinter::TOCType_BlockAddress:473    ++NumTOCBlockAddress;474    break;475  case PPCAsmPrinter::TOCType_EHBlock:476    ++NumTOCEHBlock;477    break;478  }479}480 481static CodeModel::Model getCodeModel(const PPCSubtarget &S,482                                     const TargetMachine &TM,483                                     const MachineOperand &MO) {484  CodeModel::Model ModuleModel = TM.getCodeModel();485 486  // If the operand is not a global address then there is no487  // global variable to carry an attribute.488  if (!(MO.getType() == MachineOperand::MO_GlobalAddress))489    return ModuleModel;490 491  const GlobalValue *GV = MO.getGlobal();492  assert(GV && "expected global for MO_GlobalAddress");493 494  return S.getCodeModel(TM, GV);495}496 497static void setOptionalCodeModel(MCSymbolXCOFF *XSym, CodeModel::Model CM) {498  switch (CM) {499  case CodeModel::Large:500    XSym->setPerSymbolCodeModel(MCSymbolXCOFF::CM_Large);501    return;502  case CodeModel::Small:503    XSym->setPerSymbolCodeModel(MCSymbolXCOFF::CM_Small);504    return;505  default:506    report_fatal_error("Invalid code model for AIX");507  }508}509 510/// lookUpOrCreateTOCEntry -- Given a symbol, look up whether a TOC entry511/// exists for it.  If not, create one.  Then return a symbol that references512/// the TOC entry.513MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym,514                                                TOCEntryType Type,515                                                PPCMCExpr::Specifier Spec) {516  // If this is a new TOC entry add statistics about it.517  auto [It, Inserted] = TOC.try_emplace({Sym, Spec});518  if (Inserted)519    collectTOCStats(Type);520 521  MCSymbol *&TOCEntry = It->second;522  if (!TOCEntry)523    TOCEntry = createTempSymbol("C");524  return TOCEntry;525}526 527void PPCAsmPrinter::LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI) {528  unsigned NumNOPBytes = MI.getOperand(1).getImm();529  530  auto &Ctx = OutStreamer->getContext();531  MCSymbol *MILabel = Ctx.createTempSymbol();532  OutStreamer->emitLabel(MILabel);533 534  SM.recordStackMap(*MILabel, MI);535  assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");536 537  // Scan ahead to trim the shadow.538  const MachineBasicBlock &MBB = *MI.getParent();539  MachineBasicBlock::const_iterator MII(MI);540  ++MII;541  while (NumNOPBytes > 0) {542    if (MII == MBB.end() || MII->isCall() ||543        MII->getOpcode() == PPC::DBG_VALUE ||544        MII->getOpcode() == TargetOpcode::PATCHPOINT ||545        MII->getOpcode() == TargetOpcode::STACKMAP)546      break;547    ++MII;548    NumNOPBytes -= 4;549  }550 551  // Emit nops.552  for (unsigned i = 0; i < NumNOPBytes; i += 4)553    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));554}555 556// Lower a patchpoint of the form:557// [<def>], <id>, <numBytes>, <target>, <numArgs>558void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI) {559  auto &Ctx = OutStreamer->getContext();560  MCSymbol *MILabel = Ctx.createTempSymbol();561  OutStreamer->emitLabel(MILabel);562 563  SM.recordPatchPoint(*MILabel, MI);564  PatchPointOpers Opers(&MI);565 566  unsigned EncodedBytes = 0;567  const MachineOperand &CalleeMO = Opers.getCallTarget();568 569  if (CalleeMO.isImm()) {570    int64_t CallTarget = CalleeMO.getImm();571    if (CallTarget) {572      assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&573             "High 16 bits of call target should be zero.");574      Register ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();575      EncodedBytes = 0;576      // Materialize the jump address:577      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI8)578                                      .addReg(ScratchReg)579                                      .addImm((CallTarget >> 32) & 0xFFFF));580      ++EncodedBytes;581      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::RLDIC)582                                      .addReg(ScratchReg)583                                      .addReg(ScratchReg)584                                      .addImm(32).addImm(16));585      ++EncodedBytes;586      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORIS8)587                                      .addReg(ScratchReg)588                                      .addReg(ScratchReg)589                                      .addImm((CallTarget >> 16) & 0xFFFF));590      ++EncodedBytes;591      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORI8)592                                      .addReg(ScratchReg)593                                      .addReg(ScratchReg)594                                      .addImm(CallTarget & 0xFFFF));595 596      // Save the current TOC pointer before the remote call.597      int TOCSaveOffset = Subtarget->getFrameLowering()->getTOCSaveOffset();598      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::STD)599                                      .addReg(PPC::X2)600                                      .addImm(TOCSaveOffset)601                                      .addReg(PPC::X1));602      ++EncodedBytes;603 604      // If we're on ELFv1, then we need to load the actual function pointer605      // from the function descriptor.606      if (!Subtarget->isELFv2ABI()) {607        // Load the new TOC pointer and the function address, but not r11608        // (needing this is rare, and loading it here would prevent passing it609        // via a 'nest' parameter.610        EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)611                                        .addReg(PPC::X2)612                                        .addImm(8)613                                        .addReg(ScratchReg));614        ++EncodedBytes;615        EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)616                                        .addReg(ScratchReg)617                                        .addImm(0)618                                        .addReg(ScratchReg));619        ++EncodedBytes;620      }621 622      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTCTR8)623                                      .addReg(ScratchReg));624      ++EncodedBytes;625      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BCTRL8));626      ++EncodedBytes;627 628      // Restore the TOC pointer after the call.629      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)630                                      .addReg(PPC::X2)631                                      .addImm(TOCSaveOffset)632                                      .addReg(PPC::X1));633      ++EncodedBytes;634    }635  } else if (CalleeMO.isGlobal()) {636    const GlobalValue *GValue = CalleeMO.getGlobal();637    MCSymbol *MOSymbol = getSymbol(GValue);638    const MCExpr *SymVar = MCSymbolRefExpr::create(MOSymbol, OutContext);639 640    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL8_NOP)641                                    .addExpr(SymVar));642    EncodedBytes += 2;643  }644 645  // Each instruction is 4 bytes.646  EncodedBytes *= 4;647 648  // Emit padding.649  unsigned NumBytes = Opers.getNumPatchBytes();650  assert(NumBytes >= EncodedBytes &&651         "Patchpoint can't request size less than the length of a call.");652  assert((NumBytes - EncodedBytes) % 4 == 0 &&653         "Invalid number of NOP bytes requested!");654  for (unsigned i = EncodedBytes; i < NumBytes; i += 4)655    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));656}657 658/// This helper function creates the TlsGetAddr/TlsGetMod MCSymbol for AIX. We659/// will create the csect and use the qual-name symbol instead of creating just660/// the external symbol.661static MCSymbol *createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc) {662  StringRef SymName;663  switch (MIOpc) {664  default:665    SymName = ".__tls_get_addr";666    break;667  case PPC::GETtlsTpointer32AIX:668    SymName = ".__get_tpointer";669    break;670  case PPC::GETtlsMOD32AIX:671  case PPC::GETtlsMOD64AIX:672    SymName = ".__tls_get_mod";673    break;674  }675  return Ctx676      .getXCOFFSection(SymName, SectionKind::getText(),677                       XCOFF::CsectProperties(XCOFF::XMC_PR, XCOFF::XTY_ER))678      ->getQualNameSymbol();679}680 681void PPCAsmPrinter::EmitAIXTlsCallHelper(const MachineInstr *MI) {682  assert(Subtarget->isAIXABI() &&683         "Only expecting to emit calls to get the thread pointer on AIX!");684 685  MCSymbol *TlsCall = createMCSymbolForTlsGetAddr(OutContext, MI->getOpcode());686  const MCExpr *TlsRef = MCSymbolRefExpr::create(TlsCall, OutContext);687  EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BLA).addExpr(TlsRef));688}689 690/// Given a GETtls[ld]ADDR[32] instruction, print a call to __tls_get_addr to691/// the current output stream.692void PPCAsmPrinter::emitTlsCall(const MachineInstr *MI,693                                PPCMCExpr::Specifier VK) {694  PPCMCExpr::Specifier Kind = PPC::S_None;695  unsigned Opcode = PPC::BL8_NOP_TLS;696 697  assert(MI->getNumOperands() >= 3 && "Expecting at least 3 operands from MI");698  if (MI->getOperand(2).getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG ||699      MI->getOperand(2).getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) {700    Kind = PPC::S_NOTOC;701    Opcode = PPC::BL8_NOTOC_TLS;702  }703  const Module *M = MF->getFunction().getParent();704 705  assert(MI->getOperand(0).isReg() &&706         ((Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::X3) ||707          (!Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::R3)) &&708         "GETtls[ld]ADDR[32] must define GPR3");709  assert(MI->getOperand(1).isReg() &&710         ((Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::X3) ||711          (!Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::R3)) &&712         "GETtls[ld]ADDR[32] must read GPR3");713 714  if (Subtarget->isAIXABI()) {715    // For TLSGD, the variable offset should already be in R4 and the region716    // handle should already be in R3. We generate an absolute branch to717    // .__tls_get_addr. For TLSLD, the module handle should already be in R3.718    // We generate an absolute branch to .__tls_get_mod.719    Register VarOffsetReg = Subtarget->isPPC64() ? PPC::X4 : PPC::R4;720    (void)VarOffsetReg;721    assert((MI->getOpcode() == PPC::GETtlsMOD32AIX ||722            MI->getOpcode() == PPC::GETtlsMOD64AIX ||723            (MI->getOperand(2).isReg() &&724             MI->getOperand(2).getReg() == VarOffsetReg)) &&725           "GETtls[ld]ADDR[32] must read GPR4");726    EmitAIXTlsCallHelper(MI);727    return;728  }729 730  MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol("__tls_get_addr");731 732  if (Subtarget->is32BitELFABI() && isPositionIndependent())733    Kind = PPC::S_PLT;734 735  const MCExpr *TlsRef = MCSymbolRefExpr::create(TlsGetAddr, Kind, OutContext);736 737  // Add 32768 offset to the symbol so we follow up the latest GOT/PLT ABI.738  if (Kind == PPC::S_PLT && Subtarget->isSecurePlt() &&739      M->getPICLevel() == PICLevel::BigPIC)740    TlsRef = MCBinaryExpr::createAdd(741        TlsRef, MCConstantExpr::create(32768, OutContext), OutContext);742  const MachineOperand &MO = MI->getOperand(2);743  const GlobalValue *GValue = MO.getGlobal();744  MCSymbol *MOSymbol = getSymbol(GValue);745  const MCExpr *SymVar = MCSymbolRefExpr::create(MOSymbol, VK, OutContext);746  EmitToStreamer(*OutStreamer,747                 MCInstBuilder(Subtarget->isPPC64() ? Opcode748                                                    : (unsigned)PPC::BL_TLS)749                     .addExpr(TlsRef)750                     .addExpr(SymVar));751}752 753/// Map a machine operand for a TOC pseudo-machine instruction to its754/// corresponding MCSymbol.755static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO,756                                           AsmPrinter &AP) {757  switch (MO.getType()) {758  case MachineOperand::MO_GlobalAddress:759    return AP.getSymbol(MO.getGlobal());760  case MachineOperand::MO_ConstantPoolIndex:761    return AP.GetCPISymbol(MO.getIndex());762  case MachineOperand::MO_JumpTableIndex:763    return AP.GetJTISymbol(MO.getIndex());764  case MachineOperand::MO_BlockAddress:765    return AP.GetBlockAddressSymbol(MO.getBlockAddress());766  default:767    llvm_unreachable("Unexpected operand type to get symbol.");768  }769}770 771static PPCAsmPrinter::TOCEntryType772getTOCEntryTypeForMO(const MachineOperand &MO) {773  // Use the target flags to determine if this MO is Thread Local.774  // If we don't do this it comes out as Global.775  if (PPCInstrInfo::hasTLSFlag(MO.getTargetFlags()))776    return PPCAsmPrinter::TOCType_ThreadLocal;777 778  switch (MO.getType()) {779  case MachineOperand::MO_GlobalAddress: {780    const GlobalValue *GlobalV = MO.getGlobal();781    GlobalValue::LinkageTypes Linkage = GlobalV->getLinkage();782    if (Linkage == GlobalValue::ExternalLinkage ||783        Linkage == GlobalValue::AvailableExternallyLinkage ||784        Linkage == GlobalValue::ExternalWeakLinkage)785      return PPCAsmPrinter::TOCType_GlobalExternal;786 787    return PPCAsmPrinter::TOCType_GlobalInternal;788  }789  case MachineOperand::MO_ConstantPoolIndex:790    return PPCAsmPrinter::TOCType_ConstantPool;791  case MachineOperand::MO_JumpTableIndex:792    return PPCAsmPrinter::TOCType_JumpTable;793  case MachineOperand::MO_BlockAddress:794    return PPCAsmPrinter::TOCType_BlockAddress;795  default:796    llvm_unreachable("Unexpected operand type to get TOC type.");797  }798}799 800const MCExpr *PPCAsmPrinter::symbolWithSpecifier(const MCSymbol *S,801                                                 PPCMCExpr::Specifier Spec) {802  return MCSymbolRefExpr::create(S, Spec, OutContext);803}804 805/// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to806/// the current output stream.807///808void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {809  PPC_MC::verifyInstructionPredicates(MI->getOpcode(),810                                      getSubtargetInfo().getFeatureBits());811 812  MCInst TmpInst;813  const bool IsPPC64 = Subtarget->isPPC64();814  const bool IsAIX = Subtarget->isAIXABI();815  const bool HasAIXSmallLocalTLS = Subtarget->hasAIXSmallLocalExecTLS() ||816                                   Subtarget->hasAIXSmallLocalDynamicTLS();817  const Module *M = MF->getFunction().getParent();818  PICLevel::Level PL = M->getPICLevel();819 820#ifndef NDEBUG821  // Validate that SPE and FPU are mutually exclusive in codegen822  if (!MI->isInlineAsm()) {823    for (const MachineOperand &MO: MI->operands()) {824      if (MO.isReg()) {825        Register Reg = MO.getReg();826        if (Subtarget->hasSPE()) {827          if (PPC::F4RCRegClass.contains(Reg) ||828              PPC::F8RCRegClass.contains(Reg) ||829              PPC::VFRCRegClass.contains(Reg) ||830              PPC::VRRCRegClass.contains(Reg) ||831              PPC::VSFRCRegClass.contains(Reg) ||832              PPC::VSSRCRegClass.contains(Reg)833              )834            llvm_unreachable("SPE targets cannot have FPRegs!");835        } else {836          if (PPC::SPERCRegClass.contains(Reg))837            llvm_unreachable("SPE register found in FPU-targeted code!");838        }839      }840    }841  }842#endif843 844  auto getTOCRelocAdjustedExprForXCOFF = [this](const MCExpr *Expr,845                                                ptrdiff_t OriginalOffset) {846    // Apply an offset to the TOC-based expression such that the adjusted847    // notional offset from the TOC base (to be encoded into the instruction's D848    // or DS field) is the signed 16-bit truncation of the original notional849    // offset from the TOC base.850    // This is consistent with the treatment used both by XL C/C++ and851    // by AIX ld -r.852    ptrdiff_t Adjustment =853        OriginalOffset - llvm::SignExtend32<16>(OriginalOffset);854    return MCBinaryExpr::createAdd(855        Expr, MCConstantExpr::create(-Adjustment, OutContext), OutContext);856  };857 858  auto getTOCEntryLoadingExprForXCOFF =859      [IsPPC64, getTOCRelocAdjustedExprForXCOFF,860       this](const MCSymbol *MOSymbol, const MCExpr *Expr,861             PPCMCExpr::Specifier VK = PPC::S_None) -> const MCExpr * {862    const unsigned EntryByteSize = IsPPC64 ? 8 : 4;863    const auto TOCEntryIter = TOC.find({MOSymbol, VK});864    assert(TOCEntryIter != TOC.end() &&865           "Could not find the TOC entry for this symbol.");866    const ptrdiff_t EntryDistanceFromTOCBase =867        (TOCEntryIter - TOC.begin()) * EntryByteSize;868    constexpr int16_t PositiveTOCRange = INT16_MAX;869 870    if (EntryDistanceFromTOCBase > PositiveTOCRange)871      return getTOCRelocAdjustedExprForXCOFF(Expr, EntryDistanceFromTOCBase);872 873    return Expr;874  };875  auto getSpecifier = [&](const MachineOperand &MO) {876    // For TLS initial-exec and local-exec accesses on AIX, we have one TOC877    // entry for the symbol (with the variable offset), which is differentiated878    // by MO_TPREL_FLAG.879    unsigned Flag = MO.getTargetFlags();880    if (Flag == PPCII::MO_TPREL_FLAG ||881        Flag == PPCII::MO_GOT_TPREL_PCREL_FLAG ||882        Flag == PPCII::MO_TPREL_PCREL_FLAG) {883      assert(MO.isGlobal() && "Only expecting a global MachineOperand here!\n");884      TLSModel::Model Model = TM.getTLSModel(MO.getGlobal());885      if (Model == TLSModel::LocalExec)886        return PPC::S_AIX_TLSLE;887      if (Model == TLSModel::InitialExec)888        return PPC::S_AIX_TLSIE;889      // On AIX, TLS model opt may have turned local-dynamic accesses into890      // initial-exec accesses.891      PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();892      if (Model == TLSModel::LocalDynamic &&893          FuncInfo->isAIXFuncUseTLSIEForLD()) {894        LLVM_DEBUG(895            dbgs() << "Current function uses IE access for default LD vars.\n");896        return PPC::S_AIX_TLSIE;897      }898      llvm_unreachable("Only expecting local-exec or initial-exec accesses!");899    }900    // For GD TLS access on AIX, we have two TOC entries for the symbol (one for901    // the variable offset and the other for the region handle). They are902    // differentiated by MO_TLSGD_FLAG and MO_TLSGDM_FLAG.903    if (Flag == PPCII::MO_TLSGDM_FLAG)904      return PPC::S_AIX_TLSGDM;905    if (Flag == PPCII::MO_TLSGD_FLAG || Flag == PPCII::MO_GOT_TLSGD_PCREL_FLAG)906      return PPC::S_AIX_TLSGD;907    // For local-dynamic TLS access on AIX, we have one TOC entry for the symbol908    // (the variable offset) and one shared TOC entry for the module handle.909    // They are differentiated by MO_TLSLD_FLAG and MO_TLSLDM_FLAG.910    if (Flag == PPCII::MO_TLSLD_FLAG && IsAIX)911      return PPC::S_AIX_TLSLD;912    if (Flag == PPCII::MO_TLSLDM_FLAG && IsAIX)913      return PPC::S_AIX_TLSML;914    return PPC::S_None;915  };916 917  // Lower multi-instruction pseudo operations.918  switch (MI->getOpcode()) {919  default: break;920  case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {921    assert(!Subtarget->isAIXABI() &&922           "AIX does not support patchable function entry!");923    const Function &F = MF->getFunction();924    unsigned Num = 0;925    (void)F.getFnAttribute("patchable-function-entry")926        .getValueAsString()927        .getAsInteger(10, Num);928    if (!Num)929      return;930    emitNops(Num);931    return;932  }933  case TargetOpcode::DBG_VALUE:934    llvm_unreachable("Should be handled target independently");935  case TargetOpcode::STACKMAP:936    return LowerSTACKMAP(SM, *MI);937  case TargetOpcode::PATCHPOINT:938    return LowerPATCHPOINT(SM, *MI);939 940  case PPC::MoveGOTtoLR: {941    // Transform %lr = MoveGOTtoLR942    // Into this: bl _GLOBAL_OFFSET_TABLE_@local-4943    // _GLOBAL_OFFSET_TABLE_@local-4 (instruction preceding944    // _GLOBAL_OFFSET_TABLE_) has exactly one instruction:945    //      blrl946    // This will return the pointer to _GLOBAL_OFFSET_TABLE_@local947    MCSymbol *GOTSymbol =948      OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));949    const MCExpr *OffsExpr = MCBinaryExpr::createSub(950        MCSymbolRefExpr::create(GOTSymbol, PPC::S_LOCAL, OutContext),951        MCConstantExpr::create(4, OutContext), OutContext);952 953    // Emit the 'bl'.954    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL).addExpr(OffsExpr));955    return;956  }957  case PPC::MovePCtoLR:958  case PPC::MovePCtoLR8: {959    // Transform %lr = MovePCtoLR960    // Into this, where the label is the PIC base:961    //     bl L1$pb962    // L1$pb:963    MCSymbol *PICBase = MF->getPICBaseSymbol();964 965    // Emit 'bcl 20,31,.+4' so the link stack is not corrupted.966    EmitToStreamer(*OutStreamer,967                   MCInstBuilder(PPC::BCLalways)968                       // FIXME: We would like an efficient form for this, so we969                       // don't have to do a lot of extra uniquing.970                       .addExpr(MCSymbolRefExpr::create(PICBase, OutContext)));971 972    // Emit the label.973    OutStreamer->emitLabel(PICBase);974    return;975  }976  case PPC::UpdateGBR: {977    // Transform %rd = UpdateGBR(%rt, %ri)978    // Into: lwz %rt, .L0$poff - .L0$pb(%ri)979    //       add %rd, %rt, %ri980    // or into (if secure plt mode is on):981    //       addis r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@ha982    //       addi r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@l983    // Get the offset from the GOT Base Register to the GOT984    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);985    if (Subtarget->isSecurePlt() && isPositionIndependent() ) {986      MCRegister PICR = TmpInst.getOperand(0).getReg();987      MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol(988          M->getPICLevel() == PICLevel::SmallPIC ? "_GLOBAL_OFFSET_TABLE_"989                                                 : ".LTOC");990      const MCExpr *PB =991          MCSymbolRefExpr::create(MF->getPICBaseSymbol(), OutContext);992 993      const MCExpr *DeltaExpr = MCBinaryExpr::createSub(994          MCSymbolRefExpr::create(BaseSymbol, OutContext), PB, OutContext);995 996      const MCExpr *DeltaHi =997          MCSpecifierExpr::create(DeltaExpr, PPC::S_HA, OutContext);998      EmitToStreamer(999          *OutStreamer,1000          MCInstBuilder(PPC::ADDIS).addReg(PICR).addReg(PICR).addExpr(DeltaHi));1001 1002      const MCExpr *DeltaLo =1003          MCSpecifierExpr::create(DeltaExpr, PPC::S_LO, OutContext);1004      EmitToStreamer(1005          *OutStreamer,1006          MCInstBuilder(PPC::ADDI).addReg(PICR).addReg(PICR).addExpr(DeltaLo));1007      return;1008    } else {1009      MCSymbol *PICOffset =1010        MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol(*MF);1011      TmpInst.setOpcode(PPC::LWZ);1012      const MCExpr *Exp = MCSymbolRefExpr::create(PICOffset, OutContext);1013      const MCExpr *PB =1014        MCSymbolRefExpr::create(MF->getPICBaseSymbol(),1015                                OutContext);1016      const MCOperand TR = TmpInst.getOperand(1);1017      const MCOperand PICR = TmpInst.getOperand(0);1018 1019      // Step 1: lwz %rt, .L$poff - .L$pb(%ri)1020      TmpInst.getOperand(1) =1021          MCOperand::createExpr(MCBinaryExpr::createSub(Exp, PB, OutContext));1022      TmpInst.getOperand(0) = TR;1023      TmpInst.getOperand(2) = PICR;1024      EmitToStreamer(*OutStreamer, TmpInst);1025 1026      TmpInst.setOpcode(PPC::ADD4);1027      TmpInst.getOperand(0) = PICR;1028      TmpInst.getOperand(1) = TR;1029      TmpInst.getOperand(2) = PICR;1030      EmitToStreamer(*OutStreamer, TmpInst);1031      return;1032    }1033  }1034  case PPC::LWZtoc: {1035    // Transform %rN = LWZtoc @op1, %r21036    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);1037 1038    // Change the opcode to LWZ.1039    TmpInst.setOpcode(PPC::LWZ);1040 1041    const MachineOperand &MO = MI->getOperand(1);1042    assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&1043           "Invalid operand for LWZtoc.");1044 1045    // Map the operand to its corresponding MCSymbol.1046    const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);1047 1048    // Create a reference to the GOT entry for the symbol. The GOT entry will be1049    // synthesized later.1050    if (PL == PICLevel::SmallPIC && !IsAIX) {1051      const MCExpr *Exp = symbolWithSpecifier(MOSymbol, PPC::S_GOT);1052      TmpInst.getOperand(1) = MCOperand::createExpr(Exp);1053      EmitToStreamer(*OutStreamer, TmpInst);1054      return;1055    }1056 1057    PPCMCExpr::Specifier VK = getSpecifier(MO);1058 1059    // Otherwise, use the TOC. 'TOCEntry' is a label used to reference the1060    // storage allocated in the TOC which contains the address of1061    // 'MOSymbol'. Said TOC entry will be synthesized later.1062    MCSymbol *TOCEntry =1063        lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);1064    const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry, OutContext);1065 1066    // AIX uses the label directly as the lwz displacement operand for1067    // references into the toc section. The displacement value will be generated1068    // relative to the toc-base.1069    if (IsAIX) {1070      assert(1071          getCodeModel(*Subtarget, TM, MO) == CodeModel::Small &&1072          "This pseudo should only be selected for 32-bit small code model.");1073      Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);1074      TmpInst.getOperand(1) = MCOperand::createExpr(Exp);1075 1076      // Print MO for better readability1077      if (isVerbose())1078        OutStreamer->getCommentOS() << MO << '\n';1079      EmitToStreamer(*OutStreamer, TmpInst);1080      return;1081    }1082 1083    // Create an explicit subtract expression between the local symbol and1084    // '.LTOC' to manifest the toc-relative offset.1085    const MCExpr *PB = MCSymbolRefExpr::create(1086        OutContext.getOrCreateSymbol(Twine(".LTOC")), OutContext);1087    Exp = MCBinaryExpr::createSub(Exp, PB, OutContext);1088    TmpInst.getOperand(1) = MCOperand::createExpr(Exp);1089    EmitToStreamer(*OutStreamer, TmpInst);1090    return;1091  }1092  case PPC::ADDItoc:1093  case PPC::ADDItoc8: {1094    assert(IsAIX && TM.getCodeModel() == CodeModel::Small &&1095           "PseudoOp only valid for small code model AIX");1096 1097    // Transform %rN = ADDItoc/8 %r2, @op1.1098    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);1099 1100    // Change the opcode to load address.1101    TmpInst.setOpcode((!IsPPC64) ? (PPC::LA) : (PPC::LA8));1102 1103    const MachineOperand &MO = MI->getOperand(2);1104    assert(MO.isGlobal() && "Invalid operand for ADDItoc[8].");1105 1106    // Map the operand to its corresponding MCSymbol.1107    const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);1108 1109    const MCExpr *Exp = MCSymbolRefExpr::create(MOSymbol, OutContext);1110 1111    TmpInst.getOperand(2) = MCOperand::createExpr(Exp);1112    EmitToStreamer(*OutStreamer, TmpInst);1113    return;1114  }1115  case PPC::LDtocJTI:1116  case PPC::LDtocCPT:1117  case PPC::LDtocBA:1118  case PPC::LDtoc: {1119    // Transform %x3 = LDtoc @min1, %x21120    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);1121 1122    // Change the opcode to LD.1123    TmpInst.setOpcode(PPC::LD);1124 1125    const MachineOperand &MO = MI->getOperand(1);1126    assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&1127           "Invalid operand!");1128 1129    // Map the operand to its corresponding MCSymbol.1130    const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);1131 1132    PPCMCExpr::Specifier VK = getSpecifier(MO);1133 1134    // Map the machine operand to its corresponding MCSymbol, then map the1135    // global address operand to be a reference to the TOC entry we will1136    // synthesize later.1137    MCSymbol *TOCEntry =1138        lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);1139 1140    PPCMCExpr::Specifier VKExpr = IsAIX ? PPC::S_None : PPC::S_TOC;1141    const MCExpr *Exp = symbolWithSpecifier(TOCEntry, VKExpr);1142    TmpInst.getOperand(1) = MCOperand::createExpr(1143        IsAIX ? getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK) : Exp);1144 1145    // Print MO for better readability1146    if (isVerbose() && IsAIX)1147      OutStreamer->getCommentOS() << MO << '\n';1148    EmitToStreamer(*OutStreamer, TmpInst);1149    return;1150  }1151  case PPC::ADDIStocHA: {1152    const MachineOperand &MO = MI->getOperand(2);1153 1154    assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&1155           "Invalid operand for ADDIStocHA.");1156    assert((IsAIX && !IsPPC64 &&1157            getCodeModel(*Subtarget, TM, MO) == CodeModel::Large) &&1158           "This pseudo should only be selected for 32-bit large code model on"1159           " AIX.");1160 1161    // Transform %rd = ADDIStocHA %rA, @sym(%r2)1162    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);1163 1164    // Change the opcode to ADDIS.1165    TmpInst.setOpcode(PPC::ADDIS);1166 1167    // Map the machine operand to its corresponding MCSymbol.1168    MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);1169 1170    PPCMCExpr::Specifier VK = getSpecifier(MO);1171 1172    // Map the global address operand to be a reference to the TOC entry we1173    // will synthesize later. 'TOCEntry' is a label used to reference the1174    // storage allocated in the TOC which contains the address of 'MOSymbol'.1175    // If the symbol does not have the toc-data attribute, then we create the1176    // TOC entry on AIX. If the toc-data attribute is used, the TOC entry1177    // contains the data rather than the address of the MOSymbol.1178    if (![](const MachineOperand &MO) {1179          if (!MO.isGlobal())1180            return false;1181 1182          const GlobalVariable *GV = dyn_cast<GlobalVariable>(MO.getGlobal());1183          if (!GV)1184            return false;1185          return GV->hasAttribute("toc-data");1186        }(MO)) {1187      MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);1188    }1189 1190    const MCExpr *Exp = symbolWithSpecifier(MOSymbol, PPC::S_U);1191    TmpInst.getOperand(2) = MCOperand::createExpr(Exp);1192    EmitToStreamer(*OutStreamer, TmpInst);1193    return;1194  }1195  case PPC::LWZtocL: {1196    const MachineOperand &MO = MI->getOperand(1);1197 1198    assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&1199           "Invalid operand for LWZtocL.");1200    assert(IsAIX && !IsPPC64 &&1201           getCodeModel(*Subtarget, TM, MO) == CodeModel::Large &&1202           "This pseudo should only be selected for 32-bit large code model on"1203           " AIX.");1204 1205    // Transform %rd = LWZtocL @sym, %rs.1206    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);1207 1208    // Change the opcode to lwz.1209    TmpInst.setOpcode(PPC::LWZ);1210 1211    // Map the machine operand to its corresponding MCSymbol.1212    MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);1213 1214    PPCMCExpr::Specifier VK = getSpecifier(MO);1215 1216    // Always use TOC on AIX. Map the global address operand to be a reference1217    // to the TOC entry we will synthesize later. 'TOCEntry' is a label used to1218    // reference the storage allocated in the TOC which contains the address of1219    // 'MOSymbol'.1220    MCSymbol *TOCEntry =1221        lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);1222    const MCExpr *Exp = symbolWithSpecifier(TOCEntry, PPC::S_L);1223    TmpInst.getOperand(1) = MCOperand::createExpr(Exp);1224    EmitToStreamer(*OutStreamer, TmpInst);1225    return;1226  }1227  case PPC::ADDIStocHA8: {1228    // Transform %xd = ADDIStocHA8 %x2, @sym1229    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);1230 1231    // Change the opcode to ADDIS8. If the global address is the address of1232    // an external symbol, is a jump table address, is a block address, or is a1233    // constant pool index with large code model enabled, then generate a TOC1234    // entry and reference that. Otherwise, reference the symbol directly.1235    TmpInst.setOpcode(PPC::ADDIS8);1236 1237    const MachineOperand &MO = MI->getOperand(2);1238    assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&1239           "Invalid operand for ADDIStocHA8!");1240 1241    const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);1242 1243    PPCMCExpr::Specifier VK = getSpecifier(MO);1244 1245    const bool GlobalToc =1246        MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal());1247 1248    const CodeModel::Model CM =1249        IsAIX ? getCodeModel(*Subtarget, TM, MO) : TM.getCodeModel();1250 1251    if (GlobalToc || MO.isJTI() || MO.isBlockAddress() ||1252        (MO.isCPI() && CM == CodeModel::Large))1253      MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);1254 1255    VK = IsAIX ? PPC::S_U : PPC::S_TOC_HA;1256 1257    const MCExpr *Exp = symbolWithSpecifier(MOSymbol, VK);1258 1259    if (!MO.isJTI() && MO.getOffset())1260      Exp = MCBinaryExpr::createAdd(Exp,1261                                    MCConstantExpr::create(MO.getOffset(),1262                                                           OutContext),1263                                    OutContext);1264 1265    TmpInst.getOperand(2) = MCOperand::createExpr(Exp);1266    EmitToStreamer(*OutStreamer, TmpInst);1267    return;1268  }1269  case PPC::LDtocL: {1270    // Transform %xd = LDtocL @sym, %xs1271    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);1272 1273    // Change the opcode to LD. If the global address is the address of1274    // an external symbol, is a jump table address, is a block address, or is1275    // a constant pool index with large code model enabled, then generate a1276    // TOC entry and reference that. Otherwise, reference the symbol directly.1277    TmpInst.setOpcode(PPC::LD);1278 1279    const MachineOperand &MO = MI->getOperand(1);1280    assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() ||1281            MO.isBlockAddress()) &&1282           "Invalid operand for LDtocL!");1283 1284    LLVM_DEBUG(assert(1285        (!MO.isGlobal() || Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&1286        "LDtocL used on symbol that could be accessed directly is "1287        "invalid. Must match ADDIStocHA8."));1288 1289    const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);1290 1291    PPCMCExpr::Specifier VK = getSpecifier(MO);1292    CodeModel::Model CM =1293        IsAIX ? getCodeModel(*Subtarget, TM, MO) : TM.getCodeModel();1294    if (!MO.isCPI() || CM == CodeModel::Large)1295      MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);1296 1297    VK = IsAIX ? PPC::S_L : PPC::S_TOC_LO;1298    const MCExpr *Exp = symbolWithSpecifier(MOSymbol, VK);1299    TmpInst.getOperand(1) = MCOperand::createExpr(Exp);1300    EmitToStreamer(*OutStreamer, TmpInst);1301    return;1302  }1303  case PPC::ADDItocL:1304  case PPC::ADDItocL8: {1305    // Transform %xd = ADDItocL %xs, @sym1306    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);1307 1308    unsigned Op = MI->getOpcode();1309 1310    // Change the opcode to load address for toc-data.1311    // ADDItocL is only used for 32-bit toc-data on AIX and will always use LA.1312    TmpInst.setOpcode(Op == PPC::ADDItocL8 ? (IsAIX ? PPC::LA8 : PPC::ADDI8)1313                                           : PPC::LA);1314 1315    const MachineOperand &MO = MI->getOperand(2);1316    assert((Op == PPC::ADDItocL8)1317               ? (MO.isGlobal() || MO.isCPI())1318               : MO.isGlobal() && "Invalid operand for ADDItocL8.");1319    assert(!(MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&1320           "Interposable definitions must use indirect accesses.");1321 1322    // Map the operand to its corresponding MCSymbol.1323    const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);1324 1325    const MCExpr *Exp = MCSymbolRefExpr::create(1326        MOSymbol, IsAIX ? PPC::S_L : PPC::S_TOC_LO, OutContext);1327 1328    TmpInst.getOperand(2) = MCOperand::createExpr(Exp);1329    EmitToStreamer(*OutStreamer, TmpInst);1330    return;1331  }1332  case PPC::ADDISgotTprelHA: {1333    // Transform: %xd = ADDISgotTprelHA %x2, @sym1334    // Into:      %xd = ADDIS8 %x2, sym@got@tlsgd@ha1335    assert(IsPPC64 && "Not supported for 32-bit PowerPC");1336    const MachineOperand &MO = MI->getOperand(2);1337    const GlobalValue *GValue = MO.getGlobal();1338    MCSymbol *MOSymbol = getSymbol(GValue);1339    const MCExpr *SymGotTprel =1340        symbolWithSpecifier(MOSymbol, PPC::S_GOT_TPREL_HA);1341    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)1342                                 .addReg(MI->getOperand(0).getReg())1343                                 .addReg(MI->getOperand(1).getReg())1344                                 .addExpr(SymGotTprel));1345    return;1346  }1347  case PPC::LDgotTprelL:1348  case PPC::LDgotTprelL32: {1349    // Transform %xd = LDgotTprelL @sym, %xs1350    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);1351 1352    // Change the opcode to LD.1353    TmpInst.setOpcode(IsPPC64 ? PPC::LD : PPC::LWZ);1354    const MachineOperand &MO = MI->getOperand(1);1355    const GlobalValue *GValue = MO.getGlobal();1356    MCSymbol *MOSymbol = getSymbol(GValue);1357    const MCExpr *Exp = symbolWithSpecifier(1358        MOSymbol, IsPPC64 ? PPC::S_GOT_TPREL_LO : PPC::S_GOT_TPREL);1359    TmpInst.getOperand(1) = MCOperand::createExpr(Exp);1360    EmitToStreamer(*OutStreamer, TmpInst);1361    return;1362  }1363 1364  case PPC::PPC32PICGOT: {1365    MCSymbol *GOTSymbol = OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));1366    MCSymbol *GOTRef = OutContext.createTempSymbol();1367    MCSymbol *NextInstr = OutContext.createTempSymbol();1368 1369    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL)1370      // FIXME: We would like an efficient form for this, so we don't have to do1371      // a lot of extra uniquing.1372      .addExpr(MCSymbolRefExpr::create(NextInstr, OutContext)));1373    const MCExpr *OffsExpr =1374      MCBinaryExpr::createSub(MCSymbolRefExpr::create(GOTSymbol, OutContext),1375                                MCSymbolRefExpr::create(GOTRef, OutContext),1376        OutContext);1377    OutStreamer->emitLabel(GOTRef);1378    OutStreamer->emitValue(OffsExpr, 4);1379    OutStreamer->emitLabel(NextInstr);1380    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR)1381                                 .addReg(MI->getOperand(0).getReg()));1382    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LWZ)1383                                 .addReg(MI->getOperand(1).getReg())1384                                 .addImm(0)1385                                 .addReg(MI->getOperand(0).getReg()));1386    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD4)1387                                 .addReg(MI->getOperand(0).getReg())1388                                 .addReg(MI->getOperand(1).getReg())1389                                 .addReg(MI->getOperand(0).getReg()));1390    return;1391  }1392  case PPC::PPC32GOT: {1393    MCSymbol *GOTSymbol =1394        OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));1395    const MCExpr *SymGotTlsL =1396        MCSpecifierExpr::create(GOTSymbol, PPC::S_LO, OutContext);1397    const MCExpr *SymGotTlsHA =1398        MCSpecifierExpr::create(GOTSymbol, PPC::S_HA, OutContext);1399    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI)1400                                 .addReg(MI->getOperand(0).getReg())1401                                 .addExpr(SymGotTlsL));1402    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)1403                                 .addReg(MI->getOperand(0).getReg())1404                                 .addReg(MI->getOperand(0).getReg())1405                                 .addExpr(SymGotTlsHA));1406    return;1407  }1408  case PPC::ADDIStlsgdHA: {1409    // Transform: %xd = ADDIStlsgdHA %x2, @sym1410    // Into:      %xd = ADDIS8 %x2, sym@got@tlsgd@ha1411    assert(IsPPC64 && "Not supported for 32-bit PowerPC");1412    const MachineOperand &MO = MI->getOperand(2);1413    const GlobalValue *GValue = MO.getGlobal();1414    MCSymbol *MOSymbol = getSymbol(GValue);1415    const MCExpr *SymGotTlsGD =1416        symbolWithSpecifier(MOSymbol, PPC::S_GOT_TLSGD_HA);1417    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)1418                                 .addReg(MI->getOperand(0).getReg())1419                                 .addReg(MI->getOperand(1).getReg())1420                                 .addExpr(SymGotTlsGD));1421    return;1422  }1423  case PPC::ADDItlsgdL:1424    // Transform: %xd = ADDItlsgdL %xs, @sym1425    // Into:      %xd = ADDI8 %xs, sym@got@tlsgd@l1426  case PPC::ADDItlsgdL32: {1427    // Transform: %rd = ADDItlsgdL32 %rs, @sym1428    // Into:      %rd = ADDI %rs, sym@got@tlsgd1429    const MachineOperand &MO = MI->getOperand(2);1430    const GlobalValue *GValue = MO.getGlobal();1431    MCSymbol *MOSymbol = getSymbol(GValue);1432    const MCExpr *SymGotTlsGD = symbolWithSpecifier(1433        MOSymbol, IsPPC64 ? PPC::S_GOT_TLSGD_LO : PPC::S_GOT_TLSGD);1434    EmitToStreamer(*OutStreamer,1435                   MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)1436                   .addReg(MI->getOperand(0).getReg())1437                   .addReg(MI->getOperand(1).getReg())1438                   .addExpr(SymGotTlsGD));1439    return;1440  }1441  case PPC::GETtlsMOD32AIX:1442  case PPC::GETtlsMOD64AIX:1443    // Transform: %r3 = GETtlsMODNNAIX %r3 (for NN == 32/64).1444    // Into: BLA .__tls_get_mod()1445    // Input parameter is a module handle (_$TLSML[TC]@ml) for all variables.1446  case PPC::GETtlsADDR:1447    // Transform: %x3 = GETtlsADDR %x3, @sym1448    // Into: BL8_NOP_TLS __tls_get_addr(sym at tlsgd)1449  case PPC::GETtlsADDRPCREL:1450  case PPC::GETtlsADDR32AIX:1451  case PPC::GETtlsADDR64AIX:1452    // Transform: %r3 = GETtlsADDRNNAIX %r3, %r4 (for NN == 32/64).1453    // Into: BLA .__tls_get_addr()1454    // Unlike on Linux, there is no symbol or relocation needed for this call.1455  case PPC::GETtlsADDR32: {1456    // Transform: %r3 = GETtlsADDR32 %r3, @sym1457    // Into: BL_TLS __tls_get_addr(sym at tlsgd)@PLT1458    emitTlsCall(MI, PPC::S_TLSGD);1459    return;1460  }1461  case PPC::GETtlsTpointer32AIX: {1462    // Transform: %r3 = GETtlsTpointer32AIX1463    // Into: BLA .__get_tpointer()1464    EmitAIXTlsCallHelper(MI);1465    return;1466  }1467  case PPC::ADDIStlsldHA: {1468    // Transform: %xd = ADDIStlsldHA %x2, @sym1469    // Into:      %xd = ADDIS8 %x2, sym@got@tlsld@ha1470    assert(IsPPC64 && "Not supported for 32-bit PowerPC");1471    const MachineOperand &MO = MI->getOperand(2);1472    const GlobalValue *GValue = MO.getGlobal();1473    MCSymbol *MOSymbol = getSymbol(GValue);1474    const MCExpr *SymGotTlsLD =1475        symbolWithSpecifier(MOSymbol, PPC::S_GOT_TLSLD_HA);1476    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)1477                                 .addReg(MI->getOperand(0).getReg())1478                                 .addReg(MI->getOperand(1).getReg())1479                                 .addExpr(SymGotTlsLD));1480    return;1481  }1482  case PPC::ADDItlsldL:1483    // Transform: %xd = ADDItlsldL %xs, @sym1484    // Into:      %xd = ADDI8 %xs, sym@got@tlsld@l1485  case PPC::ADDItlsldL32: {1486    // Transform: %rd = ADDItlsldL32 %rs, @sym1487    // Into:      %rd = ADDI %rs, sym@got@tlsld1488    const MachineOperand &MO = MI->getOperand(2);1489    const GlobalValue *GValue = MO.getGlobal();1490    MCSymbol *MOSymbol = getSymbol(GValue);1491    const MCExpr *SymGotTlsLD = symbolWithSpecifier(1492        MOSymbol, IsPPC64 ? PPC::S_GOT_TLSLD_LO : PPC::S_GOT_TLSLD);1493    EmitToStreamer(*OutStreamer,1494                   MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)1495                       .addReg(MI->getOperand(0).getReg())1496                       .addReg(MI->getOperand(1).getReg())1497                       .addExpr(SymGotTlsLD));1498    return;1499  }1500  case PPC::GETtlsldADDR:1501    // Transform: %x3 = GETtlsldADDR %x3, @sym1502    // Into: BL8_NOP_TLS __tls_get_addr(sym at tlsld)1503  case PPC::GETtlsldADDRPCREL:1504  case PPC::GETtlsldADDR32: {1505    // Transform: %r3 = GETtlsldADDR32 %r3, @sym1506    // Into: BL_TLS __tls_get_addr(sym at tlsld)@PLT1507    emitTlsCall(MI, PPC::S_TLSLD);1508    return;1509  }1510  case PPC::ADDISdtprelHA:1511    // Transform: %xd = ADDISdtprelHA %xs, @sym1512    // Into:      %xd = ADDIS8 %xs, sym@dtprel@ha1513  case PPC::ADDISdtprelHA32: {1514    // Transform: %rd = ADDISdtprelHA32 %rs, @sym1515    // Into:      %rd = ADDIS %rs, sym@dtprel@ha1516    const MachineOperand &MO = MI->getOperand(2);1517    const GlobalValue *GValue = MO.getGlobal();1518    MCSymbol *MOSymbol = getSymbol(GValue);1519    const MCExpr *SymDtprel = symbolWithSpecifier(MOSymbol, PPC::S_DTPREL_HA);1520    EmitToStreamer(1521        *OutStreamer,1522        MCInstBuilder(IsPPC64 ? PPC::ADDIS8 : PPC::ADDIS)1523            .addReg(MI->getOperand(0).getReg())1524            .addReg(MI->getOperand(1).getReg())1525            .addExpr(SymDtprel));1526    return;1527  }1528  case PPC::PADDIdtprel: {1529    // Transform: %rd = PADDIdtprel %rs, @sym1530    // Into:      %rd = PADDI8 %rs, sym@dtprel1531    const MachineOperand &MO = MI->getOperand(2);1532    const GlobalValue *GValue = MO.getGlobal();1533    MCSymbol *MOSymbol = getSymbol(GValue);1534    const MCExpr *SymDtprel = symbolWithSpecifier(MOSymbol, PPC::S_DTPREL);1535    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::PADDI8)1536                                     .addReg(MI->getOperand(0).getReg())1537                                     .addReg(MI->getOperand(1).getReg())1538                                     .addExpr(SymDtprel));1539    return;1540  }1541 1542  case PPC::ADDIdtprelL:1543    // Transform: %xd = ADDIdtprelL %xs, @sym1544    // Into:      %xd = ADDI8 %xs, sym@dtprel@l1545  case PPC::ADDIdtprelL32: {1546    // Transform: %rd = ADDIdtprelL32 %rs, @sym1547    // Into:      %rd = ADDI %rs, sym@dtprel@l1548    const MachineOperand &MO = MI->getOperand(2);1549    const GlobalValue *GValue = MO.getGlobal();1550    MCSymbol *MOSymbol = getSymbol(GValue);1551    const MCExpr *SymDtprel = symbolWithSpecifier(MOSymbol, PPC::S_DTPREL_LO);1552    EmitToStreamer(*OutStreamer,1553                   MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)1554                       .addReg(MI->getOperand(0).getReg())1555                       .addReg(MI->getOperand(1).getReg())1556                       .addExpr(SymDtprel));1557    return;1558  }1559  case PPC::MFOCRF:1560  case PPC::MFOCRF8:1561    if (!Subtarget->hasMFOCRF()) {1562      // Transform: %r3 = MFOCRF %cr71563      // Into:      %r3 = MFCR   ;; cr71564      unsigned NewOpcode =1565        MI->getOpcode() == PPC::MFOCRF ? PPC::MFCR : PPC::MFCR8;1566      OutStreamer->AddComment(PPCInstPrinter::1567                              getRegisterName(MI->getOperand(1).getReg()));1568      EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)1569                                  .addReg(MI->getOperand(0).getReg()));1570      return;1571    }1572    break;1573  case PPC::MTOCRF:1574  case PPC::MTOCRF8:1575    if (!Subtarget->hasMFOCRF()) {1576      // Transform: %cr7 = MTOCRF %r31577      // Into:      MTCRF mask, %r3 ;; cr71578      unsigned NewOpcode =1579        MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8;1580      unsigned Mask = 0x80 >> OutContext.getRegisterInfo()1581                              ->getEncodingValue(MI->getOperand(0).getReg());1582      OutStreamer->AddComment(PPCInstPrinter::1583                              getRegisterName(MI->getOperand(0).getReg()));1584      EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)1585                                     .addImm(Mask)1586                                     .addReg(MI->getOperand(1).getReg()));1587      return;1588    }1589    break;1590  case PPC::LD:1591  case PPC::STD:1592  case PPC::LWA_32:1593  case PPC::LWA: {1594    // Verify alignment is legal, so we don't create relocations1595    // that can't be supported.1596    unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1;1597    // For non-TOC-based local-exec TLS accesses with non-zero offsets, the1598    // machine operand (which is a TargetGlobalTLSAddress) is expected to be1599    // the same operand for both loads and stores.1600    for (const MachineOperand &TempMO : MI->operands()) {1601      if (((TempMO.getTargetFlags() == PPCII::MO_TPREL_FLAG ||1602            TempMO.getTargetFlags() == PPCII::MO_TLSLD_FLAG)) &&1603          TempMO.getOperandNo() == 1)1604        OpNum = 1;1605    }1606    const MachineOperand &MO = MI->getOperand(OpNum);1607    if (MO.isGlobal()) {1608      const DataLayout &DL = MO.getGlobal()->getDataLayout();1609      if (MO.getGlobal()->getPointerAlignment(DL) < 4)1610        llvm_unreachable("Global must be word-aligned for LD, STD, LWA!");1611    }1612    // As these load/stores share common code with the following load/stores,1613    // fall through to the subsequent cases in order to either process the1614    // non-TOC-based local-exec sequence or to process the instruction normally.1615    [[fallthrough]];1616  }1617  case PPC::LBZ:1618  case PPC::LBZ8:1619  case PPC::LHA:1620  case PPC::LHA8:1621  case PPC::LHZ:1622  case PPC::LHZ8:1623  case PPC::LWZ:1624  case PPC::LWZ8:1625  case PPC::STB:1626  case PPC::STB8:1627  case PPC::STH:1628  case PPC::STH8:1629  case PPC::STW:1630  case PPC::STW8:1631  case PPC::LFS:1632  case PPC::STFS:1633  case PPC::LFD:1634  case PPC::STFD:1635  case PPC::ADDI8: {1636    // A faster non-TOC-based local-[exec|dynamic] sequence is represented by1637    // `addi` or a load/store instruction (that directly loads or stores off of1638    // the thread pointer) with an immediate operand having the1639    // [MO_TPREL_FLAG|MO_TLSLD_FLAG]. Such instructions do not otherwise arise.1640    if (!HasAIXSmallLocalTLS)1641      break;1642    bool IsMIADDI8 = MI->getOpcode() == PPC::ADDI8;1643    unsigned OpNum = IsMIADDI8 ? 2 : 1;1644    const MachineOperand &MO = MI->getOperand(OpNum);1645    unsigned Flag = MO.getTargetFlags();1646    if (Flag == PPCII::MO_TPREL_FLAG ||1647        Flag == PPCII::MO_GOT_TPREL_PCREL_FLAG ||1648        Flag == PPCII::MO_TPREL_PCREL_FLAG || Flag == PPCII::MO_TLSLD_FLAG) {1649      LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);1650 1651      const MCExpr *Expr = getAdjustedFasterLocalExpr(MO, MO.getOffset());1652      if (Expr)1653        TmpInst.getOperand(OpNum) = MCOperand::createExpr(Expr);1654 1655      // Change the opcode to load address if the original opcode is an `addi`.1656      if (IsMIADDI8)1657        TmpInst.setOpcode(PPC::LA8);1658 1659      EmitToStreamer(*OutStreamer, TmpInst);1660      return;1661    }1662    // Now process the instruction normally.1663    break;1664  }1665  case PPC::PseudoEIEIO: {1666    EmitToStreamer(1667        *OutStreamer,1668        MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));1669    EmitToStreamer(1670        *OutStreamer,1671        MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));1672    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::EnforceIEIO));1673    return;1674  }1675  }1676 1677  LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);1678  EmitToStreamer(*OutStreamer, TmpInst);1679}1680 1681// For non-TOC-based local-[exec|dynamic] variables that have a non-zero offset,1682// we need to create a new MCExpr that adds the non-zero offset to the address1683// of the local-[exec|dynamic] variable that will be used in either an addi,1684// load or store. However, the final displacement for these instructions must be1685// between [-32768, 32768), so if the TLS address + its non-zero offset is1686// greater than 32KB, a new MCExpr is produced to accommodate this situation.1687const MCExpr *1688PPCAsmPrinter::getAdjustedFasterLocalExpr(const MachineOperand &MO,1689                                          int64_t Offset) {1690  // Non-zero offsets (for loads, stores or `addi`) require additional handling.1691  // When the offset is zero, there is no need to create an adjusted MCExpr.1692  if (!Offset)1693    return nullptr;1694 1695  assert(MO.isGlobal() && "Only expecting a global MachineOperand here!");1696  const GlobalValue *GValue = MO.getGlobal();1697  TLSModel::Model Model = TM.getTLSModel(GValue);1698  assert((Model == TLSModel::LocalExec || Model == TLSModel::LocalDynamic) &&1699         "Only local-[exec|dynamic] accesses are handled!");1700 1701  bool IsGlobalADeclaration = GValue->isDeclarationForLinker();1702  // Find the GlobalVariable that corresponds to the particular TLS variable1703  // in the TLS variable-to-address mapping. All TLS variables should exist1704  // within this map, with the exception of TLS variables marked as extern.1705  const auto TLSVarsMapEntryIter = TLSVarsToAddressMapping.find(GValue);1706  if (TLSVarsMapEntryIter == TLSVarsToAddressMapping.end())1707    assert(IsGlobalADeclaration &&1708           "Only expecting to find extern TLS variables not present in the TLS "1709           "variable-to-address map!");1710 1711  unsigned TLSVarAddress =1712      IsGlobalADeclaration ? 0 : TLSVarsMapEntryIter->second;1713  ptrdiff_t FinalAddress = (TLSVarAddress + Offset);1714  // If the address of the TLS variable + the offset is less than 32KB,1715  // or if the TLS variable is extern, we simply produce an MCExpr to add the1716  // non-zero offset to the TLS variable address.1717  // For when TLS variables are extern, this is safe to do because we can1718  // assume that the address of extern TLS variables are zero.1719  const MCExpr *Expr = MCSymbolRefExpr::create(1720      getSymbol(GValue),1721      (Model == TLSModel::LocalExec ? PPC::S_AIX_TLSLE : PPC::S_AIX_TLSLD),1722      OutContext);1723  Expr = MCBinaryExpr::createAdd(1724      Expr, MCConstantExpr::create(Offset, OutContext), OutContext);1725  if (FinalAddress >= 32768) {1726    // Handle the written offset for cases where:1727    //   TLS variable address + Offset > 32KB.1728 1729    // The assembly that is printed will look like:1730    //  TLSVar@le + Offset - Delta1731    // where Delta is a multiple of 64KB: ((FinalAddress + 32768) & ~0xFFFF).1732    ptrdiff_t Delta = ((FinalAddress + 32768) & ~0xFFFF);1733    // Check that the total instruction displacement fits within [-32768,32768).1734    [[maybe_unused]] ptrdiff_t InstDisp = TLSVarAddress + Offset - Delta;1735    assert(1736        ((InstDisp < 32768) && (InstDisp >= -32768)) &&1737        "Expecting the instruction displacement for local-[exec|dynamic] TLS "1738        "variables to be between [-32768, 32768)!");1739    Expr = MCBinaryExpr::createAdd(1740        Expr, MCConstantExpr::create(-Delta, OutContext), OutContext);1741  }1742 1743  return Expr;1744}1745 1746void PPCLinuxAsmPrinter::emitGNUAttributes(Module &M) {1747  // Emit float ABI into GNU attribute1748  Metadata *MD = M.getModuleFlag("float-abi");1749  MDString *FloatABI = dyn_cast_or_null<MDString>(MD);1750  if (!FloatABI)1751    return;1752  StringRef flt = FloatABI->getString();1753  // TODO: Support emitting soft-fp and hard double/single attributes.1754  if (flt == "doubledouble")1755    OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,1756                                  Val_GNU_Power_ABI_HardFloat_DP |1757                                      Val_GNU_Power_ABI_LDBL_IBM128);1758  else if (flt == "ieeequad")1759    OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,1760                                  Val_GNU_Power_ABI_HardFloat_DP |1761                                      Val_GNU_Power_ABI_LDBL_IEEE128);1762  else if (flt == "ieeedouble")1763    OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,1764                                  Val_GNU_Power_ABI_HardFloat_DP |1765                                      Val_GNU_Power_ABI_LDBL_64);1766}1767 1768void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {1769  if (!Subtarget->isPPC64())1770    return PPCAsmPrinter::emitInstruction(MI);1771 1772  switch (MI->getOpcode()) {1773  default:1774    break;1775  case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {1776    // .begin:1777    //   b .end # lis 0, FuncId[16..32]1778    //   nop    # li  0, FuncId[0..15]1779    //   std 0, -8(1)1780    //   mflr 01781    //   bl __xray_FunctionEntry1782    //   mtlr 01783    // .end:1784    //1785    // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number1786    // of instructions change.1787    // XRAY is only supported on PPC Linux little endian.1788    const Function &F = MF->getFunction();1789    unsigned Num = 0;1790    (void)F.getFnAttribute("patchable-function-entry")1791        .getValueAsString()1792        .getAsInteger(10, Num);1793 1794    if (!MAI->isLittleEndian() || Num)1795      break;1796    MCSymbol *BeginOfSled = OutContext.createTempSymbol();1797    MCSymbol *EndOfSled = OutContext.createTempSymbol();1798    OutStreamer->emitLabel(BeginOfSled);1799    EmitToStreamer(*OutStreamer,1800                   MCInstBuilder(PPC::B).addExpr(1801                       MCSymbolRefExpr::create(EndOfSled, OutContext)));1802    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));1803    EmitToStreamer(1804        *OutStreamer,1805        MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));1806    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));1807    EmitToStreamer(*OutStreamer,1808                   MCInstBuilder(PPC::BL8_NOP)1809                       .addExpr(MCSymbolRefExpr::create(1810                           OutContext.getOrCreateSymbol("__xray_FunctionEntry"),1811                           OutContext)));1812    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));1813    OutStreamer->emitLabel(EndOfSled);1814    recordSled(BeginOfSled, *MI, SledKind::FUNCTION_ENTER, 2);1815    break;1816  }1817  case TargetOpcode::PATCHABLE_RET: {1818    unsigned RetOpcode = MI->getOperand(0).getImm();1819    MCInst RetInst;1820    RetInst.setOpcode(RetOpcode);1821    for (const auto &MO : llvm::drop_begin(MI->operands())) {1822      MCOperand MCOp;1823      if (LowerPPCMachineOperandToMCOperand(MO, MCOp, *this))1824        RetInst.addOperand(MCOp);1825    }1826 1827    bool IsConditional;1828    if (RetOpcode == PPC::BCCLR) {1829      IsConditional = true;1830    } else if (RetOpcode == PPC::TCRETURNdi8 || RetOpcode == PPC::TCRETURNri8 ||1831               RetOpcode == PPC::TCRETURNai8) {1832      break;1833    } else if (RetOpcode == PPC::BLR8 || RetOpcode == PPC::TAILB8) {1834      IsConditional = false;1835    } else {1836      EmitToStreamer(*OutStreamer, RetInst);1837      return;1838    }1839 1840    MCSymbol *FallthroughLabel;1841    if (IsConditional) {1842      // Before:1843      //   bgtlr cr01844      //1845      // After:1846      //   ble cr0, .end1847      // .p2align 31848      // .begin:1849      //   blr    # lis 0, FuncId[16..32]1850      //   nop    # li  0, FuncId[0..15]1851      //   std 0, -8(1)1852      //   mflr 01853      //   bl __xray_FunctionExit1854      //   mtlr 01855      //   blr1856      // .end:1857      //1858      // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number1859      // of instructions change.1860      FallthroughLabel = OutContext.createTempSymbol();1861      EmitToStreamer(1862          *OutStreamer,1863          MCInstBuilder(PPC::BCC)1864              .addImm(PPC::InvertPredicate(1865                  static_cast<PPC::Predicate>(MI->getOperand(1).getImm())))1866              .addReg(MI->getOperand(2).getReg())1867              .addExpr(MCSymbolRefExpr::create(FallthroughLabel, OutContext)));1868      RetInst = MCInst();1869      RetInst.setOpcode(PPC::BLR8);1870    }1871    // .p2align 31872    // .begin:1873    //   b(lr)? # lis 0, FuncId[16..32]1874    //   nop    # li  0, FuncId[0..15]1875    //   std 0, -8(1)1876    //   mflr 01877    //   bl __xray_FunctionExit1878    //   mtlr 01879    //   b(lr)?1880    //1881    // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number1882    // of instructions change.1883    OutStreamer->emitCodeAlignment(Align(8), &getSubtargetInfo());1884    MCSymbol *BeginOfSled = OutContext.createTempSymbol();1885    OutStreamer->emitLabel(BeginOfSled);1886    EmitToStreamer(*OutStreamer, RetInst);1887    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));1888    EmitToStreamer(1889        *OutStreamer,1890        MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));1891    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));1892    EmitToStreamer(*OutStreamer,1893                   MCInstBuilder(PPC::BL8_NOP)1894                       .addExpr(MCSymbolRefExpr::create(1895                           OutContext.getOrCreateSymbol("__xray_FunctionExit"),1896                           OutContext)));1897    EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));1898    EmitToStreamer(*OutStreamer, RetInst);1899    if (IsConditional)1900      OutStreamer->emitLabel(FallthroughLabel);1901    recordSled(BeginOfSled, *MI, SledKind::FUNCTION_EXIT, 2);1902    return;1903  }1904  case TargetOpcode::PATCHABLE_FUNCTION_EXIT:1905    llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");1906  case TargetOpcode::PATCHABLE_TAIL_CALL:1907    // TODO: Define a trampoline `__xray_FunctionTailExit` and differentiate a1908    // normal function exit from a tail exit.1909    llvm_unreachable("Tail call is handled in the normal case. See comments "1910                     "around this assert.");1911  }1912  return PPCAsmPrinter::emitInstruction(MI);1913}1914 1915void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) {1916  if (static_cast<const PPCTargetMachine &>(TM).isELFv2ABI()) {1917    PPCTargetStreamer *TS =1918      static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());1919    TS->emitAbiVersion(2);1920  }1921 1922  if (static_cast<const PPCTargetMachine &>(TM).isPPC64() ||1923      !isPositionIndependent())1924    return AsmPrinter::emitStartOfAsmFile(M);1925 1926  if (M.getPICLevel() == PICLevel::SmallPIC)1927    return AsmPrinter::emitStartOfAsmFile(M);1928 1929  OutStreamer->switchSection(OutContext.getELFSection(1930      ".got2", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC));1931 1932  MCSymbol *TOCSym = OutContext.getOrCreateSymbol(Twine(".LTOC"));1933  MCSymbol *CurrentPos = OutContext.createTempSymbol();1934 1935  OutStreamer->emitLabel(CurrentPos);1936 1937  // The GOT pointer points to the middle of the GOT, in order to reference the1938  // entire 64kB range.  0x8000 is the midpoint.1939  const MCExpr *tocExpr =1940    MCBinaryExpr::createAdd(MCSymbolRefExpr::create(CurrentPos, OutContext),1941                            MCConstantExpr::create(0x8000, OutContext),1942                            OutContext);1943 1944  OutStreamer->emitAssignment(TOCSym, tocExpr);1945 1946  OutStreamer->switchSection(getObjFileLowering().getTextSection());1947}1948 1949void PPCLinuxAsmPrinter::emitFunctionEntryLabel() {1950  // linux/ppc32 - Normal entry label.1951  if (!Subtarget->isPPC64() &&1952      (!isPositionIndependent() ||1953       MF->getFunction().getParent()->getPICLevel() == PICLevel::SmallPIC))1954    return AsmPrinter::emitFunctionEntryLabel();1955 1956  if (!Subtarget->isPPC64()) {1957    const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();1958    if (PPCFI->usesPICBase() && !Subtarget->isSecurePlt()) {1959      MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol(*MF);1960      MCSymbol *PICBase = MF->getPICBaseSymbol();1961      OutStreamer->emitLabel(RelocSymbol);1962 1963      const MCExpr *OffsExpr =1964        MCBinaryExpr::createSub(1965          MCSymbolRefExpr::create(OutContext.getOrCreateSymbol(Twine(".LTOC")),1966                                                               OutContext),1967                                  MCSymbolRefExpr::create(PICBase, OutContext),1968          OutContext);1969      OutStreamer->emitValue(OffsExpr, 4);1970      OutStreamer->emitLabel(CurrentFnSym);1971      return;1972    } else1973      return AsmPrinter::emitFunctionEntryLabel();1974  }1975 1976  // ELFv2 ABI - Normal entry label.1977  if (Subtarget->isELFv2ABI()) {1978    // In the Large code model, we allow arbitrary displacements between1979    // the text section and its associated TOC section.  We place the1980    // full 8-byte offset to the TOC in memory immediately preceding1981    // the function global entry point.1982    if (TM.getCodeModel() == CodeModel::Large1983        && !MF->getRegInfo().use_empty(PPC::X2)) {1984      const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();1985 1986      MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));1987      MCSymbol *GlobalEPSymbol = PPCFI->getGlobalEPSymbol(*MF);1988      const MCExpr *TOCDeltaExpr =1989        MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext),1990                                MCSymbolRefExpr::create(GlobalEPSymbol,1991                                                        OutContext),1992                                OutContext);1993 1994      OutStreamer->emitLabel(PPCFI->getTOCOffsetSymbol(*MF));1995      OutStreamer->emitValue(TOCDeltaExpr, 8);1996    }1997    return AsmPrinter::emitFunctionEntryLabel();1998  }1999 2000  // Emit an official procedure descriptor.2001  MCSectionSubPair Current = OutStreamer->getCurrentSection();2002  MCSectionELF *Section = OutStreamer->getContext().getELFSection(2003      ".opd", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);2004  OutStreamer->switchSection(Section);2005  OutStreamer->emitLabel(CurrentFnSym);2006  OutStreamer->emitValueToAlignment(Align(8));2007  MCSymbol *Symbol1 = CurrentFnSymForSize;2008  // Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function2009  // entry point.2010  OutStreamer->emitValue(MCSymbolRefExpr::create(Symbol1, OutContext),2011                         8 /*size*/);2012  MCSymbol *Symbol2 = OutContext.getOrCreateSymbol(StringRef(".TOC."));2013  // Generates a R_PPC64_TOC relocation for TOC base insertion.2014  OutStreamer->emitValue(2015      MCSymbolRefExpr::create(Symbol2, PPC::S_TOCBASE, OutContext), 8 /*size*/);2016  // Emit a null environment pointer.2017  OutStreamer->emitIntValue(0, 8 /* size */);2018  OutStreamer->switchSection(Current.first, Current.second);2019}2020 2021void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) {2022  const DataLayout &DL = getDataLayout();2023 2024  bool isPPC64 = DL.getPointerSizeInBits() == 64;2025 2026  PPCTargetStreamer *TS =2027      static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());2028 2029  // If we are using any values provided by Glibc at fixed addresses,2030  // we need to ensure that the Glibc used at link time actually provides2031  // those values. All versions of Glibc that do will define the symbol2032  // named "__parse_hwcap_and_convert_at_platform".2033  if (static_cast<const PPCTargetMachine &>(TM).hasGlibcHWCAPAccess())2034    OutStreamer->emitSymbolValue(2035        GetExternalSymbolSymbol("__parse_hwcap_and_convert_at_platform"),2036        MAI->getCodePointerSize());2037  emitGNUAttributes(M);2038 2039  if (!TOC.empty()) {2040    const char *Name = isPPC64 ? ".toc" : ".got2";2041    MCSectionELF *Section = OutContext.getELFSection(2042        Name, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);2043    OutStreamer->switchSection(Section);2044    if (!isPPC64)2045      OutStreamer->emitValueToAlignment(Align(4));2046 2047    for (const auto &TOCMapPair : TOC) {2048      const MCSymbol *const TOCEntryTarget = TOCMapPair.first.first;2049      MCSymbol *const TOCEntryLabel = TOCMapPair.second;2050 2051      OutStreamer->emitLabel(TOCEntryLabel);2052      if (isPPC64)2053        TS->emitTCEntry(*TOCEntryTarget, TOCMapPair.first.second);2054      else2055        OutStreamer->emitSymbolValue(TOCEntryTarget, 4);2056    }2057  }2058 2059  PPCAsmPrinter::emitEndOfAsmFile(M);2060}2061 2062/// EmitFunctionBodyStart - Emit a global entry point prefix for ELFv2.2063void PPCLinuxAsmPrinter::emitFunctionBodyStart() {2064  // In the ELFv2 ABI, in functions that use the TOC register, we need to2065  // provide two entry points.  The ABI guarantees that when calling the2066  // local entry point, r2 is set up by the caller to contain the TOC base2067  // for this function, and when calling the global entry point, r12 is set2068  // up by the caller to hold the address of the global entry point.  We2069  // thus emit a prefix sequence along the following lines:2070  //2071  // func:2072  // .Lfunc_gepNN:2073  //         # global entry point2074  //         addis r2,r12,(.TOC.-.Lfunc_gepNN)@ha2075  //         addi  r2,r2,(.TOC.-.Lfunc_gepNN)@l2076  // .Lfunc_lepNN:2077  //         .localentry func, .Lfunc_lepNN-.Lfunc_gepNN2078  //         # local entry point, followed by function body2079  //2080  // For the Large code model, we create2081  //2082  // .Lfunc_tocNN:2083  //         .quad .TOC.-.Lfunc_gepNN      # done by EmitFunctionEntryLabel2084  // func:2085  // .Lfunc_gepNN:2086  //         # global entry point2087  //         ld    r2,.Lfunc_tocNN-.Lfunc_gepNN(r12)2088  //         add   r2,r2,r122089  // .Lfunc_lepNN:2090  //         .localentry func, .Lfunc_lepNN-.Lfunc_gepNN2091  //         # local entry point, followed by function body2092  //2093  // This ensures we have r2 set up correctly while executing the function2094  // body, no matter which entry point is called.2095  const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();2096  const bool UsesX2OrR2 = !MF->getRegInfo().use_empty(PPC::X2) ||2097                          !MF->getRegInfo().use_empty(PPC::R2);2098  const bool PCrelGEPRequired = Subtarget->isUsingPCRelativeCalls() &&2099                                UsesX2OrR2 && PPCFI->usesTOCBasePtr();2100  const bool NonPCrelGEPRequired = !Subtarget->isUsingPCRelativeCalls() &&2101                                   Subtarget->isELFv2ABI() && UsesX2OrR2;2102 2103  // Only do all that if the function uses R2 as the TOC pointer2104  // in the first place. We don't need the global entry point if the2105  // function uses R2 as an allocatable register.2106  if (NonPCrelGEPRequired || PCrelGEPRequired) {2107    // Note: The logic here must be synchronized with the code in the2108    // branch-selection pass which sets the offset of the first block in the2109    // function. This matters because it affects the alignment.2110    MCSymbol *GlobalEntryLabel = PPCFI->getGlobalEPSymbol(*MF);2111    OutStreamer->emitLabel(GlobalEntryLabel);2112    const MCSymbolRefExpr *GlobalEntryLabelExp =2113      MCSymbolRefExpr::create(GlobalEntryLabel, OutContext);2114 2115    if (TM.getCodeModel() != CodeModel::Large) {2116      MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));2117      const MCExpr *TOCDeltaExpr =2118        MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext),2119                                GlobalEntryLabelExp, OutContext);2120 2121      const MCExpr *TOCDeltaHi =2122          MCSpecifierExpr::create(TOCDeltaExpr, PPC::S_HA, OutContext);2123      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)2124                                   .addReg(PPC::X2)2125                                   .addReg(PPC::X12)2126                                   .addExpr(TOCDeltaHi));2127 2128      const MCExpr *TOCDeltaLo =2129          MCSpecifierExpr::create(TOCDeltaExpr, PPC::S_LO, OutContext);2130      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI)2131                                   .addReg(PPC::X2)2132                                   .addReg(PPC::X2)2133                                   .addExpr(TOCDeltaLo));2134    } else {2135      MCSymbol *TOCOffset = PPCFI->getTOCOffsetSymbol(*MF);2136      const MCExpr *TOCOffsetDeltaExpr =2137        MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCOffset, OutContext),2138                                GlobalEntryLabelExp, OutContext);2139 2140      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)2141                                   .addReg(PPC::X2)2142                                   .addExpr(TOCOffsetDeltaExpr)2143                                   .addReg(PPC::X12));2144      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD8)2145                                   .addReg(PPC::X2)2146                                   .addReg(PPC::X2)2147                                   .addReg(PPC::X12));2148    }2149 2150    MCSymbol *LocalEntryLabel = PPCFI->getLocalEPSymbol(*MF);2151    OutStreamer->emitLabel(LocalEntryLabel);2152    const MCSymbolRefExpr *LocalEntryLabelExp =2153       MCSymbolRefExpr::create(LocalEntryLabel, OutContext);2154    const MCExpr *LocalOffsetExp =2155      MCBinaryExpr::createSub(LocalEntryLabelExp,2156                              GlobalEntryLabelExp, OutContext);2157 2158    PPCTargetStreamer *TS =2159      static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());2160    TS->emitLocalEntry(static_cast<MCSymbolELF *>(CurrentFnSym),2161                       LocalOffsetExp);2162  } else if (Subtarget->isUsingPCRelativeCalls()) {2163    // When generating the entry point for a function we have a few scenarios2164    // based on whether or not that function uses R2 and whether or not that2165    // function makes calls (or is a leaf function).2166    // 1) A leaf function that does not use R2 (or treats it as callee-saved2167    //    and preserves it). In this case st_other=0 and both2168    //    the local and global entry points for the function are the same.2169    //    No special entry point code is required.2170    // 2) A function uses the TOC pointer R2. This function may or may not have2171    //    calls. In this case st_other=[2,6] and the global and local entry2172    //    points are different. Code to correctly setup the TOC pointer in R22173    //    is put between the global and local entry points. This case is2174    //    covered by the if statatement above.2175    // 3) A function does not use the TOC pointer R2 but does have calls.2176    //    In this case st_other=1 since we do not know whether or not any2177    //    of the callees clobber R2. This case is dealt with in this else if2178    //    block. Tail calls are considered calls and the st_other should also2179    //    be set to 1 in that case as well.2180    // 4) The function does not use the TOC pointer but R2 is used inside2181    //    the function. In this case st_other=1 once again.2182    // 5) This function uses inline asm. We mark R2 as reserved if the function2183    //    has inline asm as we have to assume that it may be used.2184    if (MF->getFrameInfo().hasCalls() || MF->getFrameInfo().hasTailCall() ||2185        MF->hasInlineAsm() || (!PPCFI->usesTOCBasePtr() && UsesX2OrR2)) {2186      PPCTargetStreamer *TS =2187          static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());2188      TS->emitLocalEntry(static_cast<MCSymbolELF *>(CurrentFnSym),2189                         MCConstantExpr::create(1, OutContext));2190    }2191  }2192}2193 2194/// EmitFunctionBodyEnd - Print the traceback table before the .size2195/// directive.2196///2197void PPCLinuxAsmPrinter::emitFunctionBodyEnd() {2198  // Only the 64-bit target requires a traceback table.  For now,2199  // we only emit the word of zeroes that GDB requires to find2200  // the end of the function, and zeroes for the eight-byte2201  // mandatory fields.2202  // FIXME: We should fill in the eight-byte mandatory fields as described in2203  // the PPC64 ELF ABI (this is a low-priority item because GDB does not2204  // currently make use of these fields).2205  if (Subtarget->isPPC64()) {2206    OutStreamer->emitIntValue(0, 4/*size*/);2207    OutStreamer->emitIntValue(0, 8/*size*/);2208  }2209}2210 2211char PPCLinuxAsmPrinter::ID = 0;2212 2213INITIALIZE_PASS(PPCLinuxAsmPrinter, "ppc-linux-asm-printer",2214                "Linux PPC Assembly Printer", false, false)2215 2216void PPCAIXAsmPrinter::emitLinkage(const GlobalValue *GV,2217                                   MCSymbol *GVSym) const {2218  MCSymbolAttr LinkageAttr = MCSA_Invalid;2219  switch (GV->getLinkage()) {2220  case GlobalValue::ExternalLinkage:2221    LinkageAttr = GV->isDeclaration() ? MCSA_Extern : MCSA_Global;2222    break;2223  case GlobalValue::LinkOnceAnyLinkage:2224  case GlobalValue::LinkOnceODRLinkage:2225  case GlobalValue::WeakAnyLinkage:2226  case GlobalValue::WeakODRLinkage:2227  case GlobalValue::ExternalWeakLinkage:2228    LinkageAttr = MCSA_Weak;2229    break;2230  case GlobalValue::AvailableExternallyLinkage:2231    LinkageAttr = MCSA_Extern;2232    break;2233  case GlobalValue::PrivateLinkage:2234    return;2235  case GlobalValue::InternalLinkage:2236    assert(GV->getVisibility() == GlobalValue::DefaultVisibility &&2237           "InternalLinkage should not have other visibility setting.");2238    LinkageAttr = MCSA_LGlobal;2239    break;2240  case GlobalValue::AppendingLinkage:2241    llvm_unreachable("Should never emit this");2242  case GlobalValue::CommonLinkage:2243    llvm_unreachable("CommonLinkage of XCOFF should not come to this path");2244  }2245 2246  assert(LinkageAttr != MCSA_Invalid && "LinkageAttr should not MCSA_Invalid.");2247 2248  MCSymbolAttr VisibilityAttr = MCSA_Invalid;2249  if (!TM.getIgnoreXCOFFVisibility()) {2250    if (GV->hasDLLExportStorageClass() && !GV->hasDefaultVisibility())2251      report_fatal_error(2252          "Cannot not be both dllexport and non-default visibility");2253    switch (GV->getVisibility()) {2254 2255    // TODO: "internal" Visibility needs to go here.2256    case GlobalValue::DefaultVisibility:2257      if (GV->hasDLLExportStorageClass())2258        VisibilityAttr = MAI->getExportedVisibilityAttr();2259      break;2260    case GlobalValue::HiddenVisibility:2261      VisibilityAttr = MAI->getHiddenVisibilityAttr();2262      break;2263    case GlobalValue::ProtectedVisibility:2264      VisibilityAttr = MAI->getProtectedVisibilityAttr();2265      break;2266    }2267  }2268 2269  // Do not emit the _$TLSML symbol.2270  if (GV->getThreadLocalMode() == GlobalVariable::LocalDynamicTLSModel &&2271      GV->hasName() && GV->getName() == "_$TLSML")2272    return;2273 2274  OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr,2275                                                    VisibilityAttr);2276}2277 2278void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {2279  // Setup CurrentFnDescSym and its containing csect.2280  auto *FnDescSec = static_cast<MCSectionXCOFF *>(2281      getObjFileLowering().getSectionForFunctionDescriptor(&MF.getFunction(),2282                                                           TM));2283  FnDescSec->setAlignment(Align(Subtarget->isPPC64() ? 8 : 4));2284 2285  CurrentFnDescSym = FnDescSec->getQualNameSymbol();2286 2287  return AsmPrinter::SetupMachineFunction(MF);2288}2289 2290uint16_t PPCAIXAsmPrinter::getNumberOfVRSaved() {2291  // Calculate the number of VRs be saved.2292  // Vector registers 20 through 31 are marked as reserved and cannot be used2293  // in the default ABI.2294  const PPCSubtarget &Subtarget = MF->getSubtarget<PPCSubtarget>();2295  if (Subtarget.isAIXABI() && Subtarget.hasAltivec() &&2296      TM.getAIXExtendedAltivecABI()) {2297    const MachineRegisterInfo &MRI = MF->getRegInfo();2298    for (unsigned Reg = PPC::V20; Reg <= PPC::V31; ++Reg)2299      if (MRI.isPhysRegModified(Reg))2300        // Number of VRs saved.2301        return PPC::V31 - Reg + 1;2302  }2303  return 0;2304}2305 2306void PPCAIXAsmPrinter::emitFunctionBodyEnd() {2307 2308  if (!TM.getXCOFFTracebackTable())2309    return;2310 2311  emitTracebackTable();2312 2313  // If ShouldEmitEHBlock returns true, then the eh info table2314  // will be emitted via `AIXException::endFunction`. Otherwise, we2315  // need to emit a dumy eh info table when VRs are saved. We could not2316  // consolidate these two places into one because there is no easy way2317  // to access register information in `AIXException` class.2318  if (!TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF) &&2319      (getNumberOfVRSaved() > 0)) {2320    // Emit dummy EH Info Table.2321    OutStreamer->switchSection(getObjFileLowering().getCompactUnwindSection());2322    MCSymbol *EHInfoLabel =2323        TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(MF);2324    OutStreamer->emitLabel(EHInfoLabel);2325 2326    // Version number.2327    OutStreamer->emitInt32(0);2328 2329    const DataLayout &DL = MMI->getModule()->getDataLayout();2330    const unsigned PointerSize = DL.getPointerSize();2331    // Add necessary paddings in 64 bit mode.2332    OutStreamer->emitValueToAlignment(Align(PointerSize));2333 2334    OutStreamer->emitIntValue(0, PointerSize);2335    OutStreamer->emitIntValue(0, PointerSize);2336    OutStreamer->switchSection(MF->getSection());2337  }2338}2339 2340void PPCAIXAsmPrinter::emitTracebackTable() {2341 2342  // Create a symbol for the end of function.2343  MCSymbol *FuncEnd = createTempSymbol(MF->getName());2344  OutStreamer->emitLabel(FuncEnd);2345 2346  OutStreamer->AddComment("Traceback table begin");2347  // Begin with a fullword of zero.2348  OutStreamer->emitIntValueInHexWithPadding(0, 4 /*size*/);2349 2350  SmallString<128> CommentString;2351  raw_svector_ostream CommentOS(CommentString);2352 2353  auto EmitComment = [&]() {2354    OutStreamer->AddComment(CommentOS.str());2355    CommentString.clear();2356  };2357 2358  auto EmitCommentAndValue = [&](uint64_t Value, int Size) {2359    EmitComment();2360    OutStreamer->emitIntValueInHexWithPadding(Value, Size);2361  };2362 2363  unsigned int Version = 0;2364  CommentOS << "Version = " << Version;2365  EmitCommentAndValue(Version, 1);2366 2367  // There is a lack of information in the IR to assist with determining the2368  // source language. AIX exception handling mechanism would only search for2369  // personality routine and LSDA area when such language supports exception2370  // handling. So to be conservatively correct and allow runtime to do its job,2371  // we need to set it to C++ for now.2372  TracebackTable::LanguageID LanguageIdentifier =2373      TracebackTable::CPlusPlus; // C++2374 2375  CommentOS << "Language = "2376            << getNameForTracebackTableLanguageId(LanguageIdentifier);2377  EmitCommentAndValue(LanguageIdentifier, 1);2378 2379  //  This is only populated for the third and fourth bytes.2380  uint32_t FirstHalfOfMandatoryField = 0;2381 2382  // Emit the 3rd byte of the mandatory field.2383 2384  // We always set traceback offset bit to true.2385  FirstHalfOfMandatoryField |= TracebackTable::HasTraceBackTableOffsetMask;2386 2387  const PPCFunctionInfo *FI = MF->getInfo<PPCFunctionInfo>();2388  const MachineRegisterInfo &MRI = MF->getRegInfo();2389 2390  // Check the function uses floating-point processor instructions or not2391  for (unsigned Reg = PPC::F0; Reg <= PPC::F31; ++Reg) {2392    if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {2393      FirstHalfOfMandatoryField |= TracebackTable::IsFloatingPointPresentMask;2394      break;2395    }2396  }2397 2398#define GENBOOLCOMMENT(Prefix, V, Field)                                       \2399  CommentOS << (Prefix) << ((V) & (TracebackTable::Field##Mask) ? "+" : "-")   \2400            << #Field2401 2402#define GENVALUECOMMENT(PrefixAndName, V, Field)                               \2403  CommentOS << (PrefixAndName) << " = "                                        \2404            << static_cast<unsigned>(((V) & (TracebackTable::Field##Mask)) >>  \2405                                     (TracebackTable::Field##Shift))2406 2407  GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsGlobalLinkage);2408  GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsOutOfLineEpilogOrPrologue);2409  EmitComment();2410 2411  GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasTraceBackTableOffset);2412  GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsInternalProcedure);2413  EmitComment();2414 2415  GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasControlledStorage);2416  GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsTOCless);2417  EmitComment();2418 2419  GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsFloatingPointPresent);2420  EmitComment();2421  GENBOOLCOMMENT("", FirstHalfOfMandatoryField,2422                 IsFloatingPointOperationLogOrAbortEnabled);2423  EmitComment();2424 2425  OutStreamer->emitIntValueInHexWithPadding(2426      (FirstHalfOfMandatoryField & 0x0000ff00) >> 8, 1);2427 2428  // Set the 4th byte of the mandatory field.2429  FirstHalfOfMandatoryField |= TracebackTable::IsFunctionNamePresentMask;2430 2431  const PPCRegisterInfo *RegInfo = Subtarget->getRegisterInfo();2432  Register FrameReg = RegInfo->getFrameRegister(*MF);2433  if (FrameReg == (Subtarget->isPPC64() ? PPC::X31 : PPC::R31))2434    FirstHalfOfMandatoryField |= TracebackTable::IsAllocaUsedMask;2435 2436  const SmallVectorImpl<Register> &MustSaveCRs = FI->getMustSaveCRs();2437  if (!MustSaveCRs.empty())2438    FirstHalfOfMandatoryField |= TracebackTable::IsCRSavedMask;2439 2440  if (FI->mustSaveLR())2441    FirstHalfOfMandatoryField |= TracebackTable::IsLRSavedMask;2442 2443  GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsInterruptHandler);2444  GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsFunctionNamePresent);2445  GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsAllocaUsed);2446  EmitComment();2447  GENVALUECOMMENT("OnConditionDirective", FirstHalfOfMandatoryField,2448                  OnConditionDirective);2449  GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsCRSaved);2450  GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsLRSaved);2451  EmitComment();2452  OutStreamer->emitIntValueInHexWithPadding((FirstHalfOfMandatoryField & 0xff),2453                                            1);2454 2455  // Set the 5th byte of mandatory field.2456  uint32_t SecondHalfOfMandatoryField = 0;2457 2458  SecondHalfOfMandatoryField |= MF->getFrameInfo().getStackSize()2459                                    ? TracebackTable::IsBackChainStoredMask2460                                    : 0;2461 2462  uint32_t FPRSaved = 0;2463  for (unsigned Reg = PPC::F14; Reg <= PPC::F31; ++Reg) {2464    if (MRI.isPhysRegModified(Reg)) {2465      FPRSaved = PPC::F31 - Reg + 1;2466      break;2467    }2468  }2469  SecondHalfOfMandatoryField |= (FPRSaved << TracebackTable::FPRSavedShift) &2470                                TracebackTable::FPRSavedMask;2471  GENBOOLCOMMENT("", SecondHalfOfMandatoryField, IsBackChainStored);2472  GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, IsFixup);2473  GENVALUECOMMENT(", NumOfFPRsSaved", SecondHalfOfMandatoryField, FPRSaved);2474  EmitComment();2475  OutStreamer->emitIntValueInHexWithPadding(2476      (SecondHalfOfMandatoryField & 0xff000000) >> 24, 1);2477 2478  // Set the 6th byte of mandatory field.2479 2480  // Check whether has Vector Instruction,We only treat instructions uses vector2481  // register as vector instructions.2482  bool HasVectorInst = false;2483  for (unsigned Reg = PPC::V0; Reg <= PPC::V31; ++Reg)2484    if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {2485      // Has VMX instruction.2486      HasVectorInst = true;2487      break;2488    }2489 2490  if (FI->hasVectorParms() || HasVectorInst)2491    SecondHalfOfMandatoryField |= TracebackTable::HasVectorInfoMask;2492 2493  uint16_t NumOfVRSaved = getNumberOfVRSaved();2494  bool ShouldEmitEHBlock =2495      TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF) || NumOfVRSaved > 0;2496 2497  if (ShouldEmitEHBlock)2498    SecondHalfOfMandatoryField |= TracebackTable::HasExtensionTableMask;2499 2500  uint32_t GPRSaved = 0;2501 2502  // X13 is reserved under 64-bit environment.2503  unsigned GPRBegin = Subtarget->isPPC64() ? PPC::X14 : PPC::R13;2504  unsigned GPREnd = Subtarget->isPPC64() ? PPC::X31 : PPC::R31;2505 2506  for (unsigned Reg = GPRBegin; Reg <= GPREnd; ++Reg) {2507    if (MRI.isPhysRegModified(Reg)) {2508      GPRSaved = GPREnd - Reg + 1;2509      break;2510    }2511  }2512 2513  SecondHalfOfMandatoryField |= (GPRSaved << TracebackTable::GPRSavedShift) &2514                                TracebackTable::GPRSavedMask;2515 2516  GENBOOLCOMMENT("", SecondHalfOfMandatoryField, HasExtensionTable);2517  GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasVectorInfo);2518  GENVALUECOMMENT(", NumOfGPRsSaved", SecondHalfOfMandatoryField, GPRSaved);2519  EmitComment();2520  OutStreamer->emitIntValueInHexWithPadding(2521      (SecondHalfOfMandatoryField & 0x00ff0000) >> 16, 1);2522 2523  // Set the 7th byte of mandatory field.2524  uint32_t NumberOfFixedParms = FI->getFixedParmsNum();2525  SecondHalfOfMandatoryField |=2526      (NumberOfFixedParms << TracebackTable::NumberOfFixedParmsShift) &2527      TracebackTable::NumberOfFixedParmsMask;2528  GENVALUECOMMENT("NumberOfFixedParms", SecondHalfOfMandatoryField,2529                  NumberOfFixedParms);2530  EmitComment();2531  OutStreamer->emitIntValueInHexWithPadding(2532      (SecondHalfOfMandatoryField & 0x0000ff00) >> 8, 1);2533 2534  // Set the 8th byte of mandatory field.2535 2536  // Always set parameter on stack.2537  SecondHalfOfMandatoryField |= TracebackTable::HasParmsOnStackMask;2538 2539  uint32_t NumberOfFPParms = FI->getFloatingPointParmsNum();2540  SecondHalfOfMandatoryField |=2541      (NumberOfFPParms << TracebackTable::NumberOfFloatingPointParmsShift) &2542      TracebackTable::NumberOfFloatingPointParmsMask;2543 2544  GENVALUECOMMENT("NumberOfFPParms", SecondHalfOfMandatoryField,2545                  NumberOfFloatingPointParms);2546  GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasParmsOnStack);2547  EmitComment();2548  OutStreamer->emitIntValueInHexWithPadding(SecondHalfOfMandatoryField & 0xff,2549                                            1);2550 2551  // Generate the optional fields of traceback table.2552 2553  // Parameter type.2554  if (NumberOfFixedParms || NumberOfFPParms) {2555    uint32_t ParmsTypeValue = FI->getParmsType();2556 2557    Expected<SmallString<32>> ParmsType =2558        FI->hasVectorParms()2559            ? XCOFF::parseParmsTypeWithVecInfo(2560                  ParmsTypeValue, NumberOfFixedParms, NumberOfFPParms,2561                  FI->getVectorParmsNum())2562            : XCOFF::parseParmsType(ParmsTypeValue, NumberOfFixedParms,2563                                    NumberOfFPParms);2564 2565    assert(ParmsType && toString(ParmsType.takeError()).c_str());2566    if (ParmsType) {2567      CommentOS << "Parameter type = " << ParmsType.get();2568      EmitComment();2569    }2570    OutStreamer->emitIntValueInHexWithPadding(ParmsTypeValue,2571                                              sizeof(ParmsTypeValue));2572  }2573  // Traceback table offset.2574  OutStreamer->AddComment("Function size");2575  if (FirstHalfOfMandatoryField & TracebackTable::HasTraceBackTableOffsetMask) {2576    MCSymbol *FuncSectSym = getObjFileLowering().getFunctionEntryPointSymbol(2577        &(MF->getFunction()), TM);2578    OutStreamer->emitAbsoluteSymbolDiff(FuncEnd, FuncSectSym, 4);2579  }2580 2581  // Since we unset the Int_Handler.2582  if (FirstHalfOfMandatoryField & TracebackTable::IsInterruptHandlerMask)2583    report_fatal_error("Hand_Mask not implement yet");2584 2585  if (FirstHalfOfMandatoryField & TracebackTable::HasControlledStorageMask)2586    report_fatal_error("Ctl_Info not implement yet");2587 2588  if (FirstHalfOfMandatoryField & TracebackTable::IsFunctionNamePresentMask) {2589    StringRef Name = MF->getName().substr(0, INT16_MAX);2590    int16_t NameLength = Name.size();2591    CommentOS << "Function name len = "2592              << static_cast<unsigned int>(NameLength);2593    EmitCommentAndValue(NameLength, 2);2594    OutStreamer->AddComment("Function Name");2595    OutStreamer->emitBytes(Name);2596  }2597 2598  if (FirstHalfOfMandatoryField & TracebackTable::IsAllocaUsedMask) {2599    uint8_t AllocReg = XCOFF::AllocRegNo;2600    OutStreamer->AddComment("AllocaUsed");2601    OutStreamer->emitIntValueInHex(AllocReg, sizeof(AllocReg));2602  }2603 2604  if (SecondHalfOfMandatoryField & TracebackTable::HasVectorInfoMask) {2605    uint16_t VRData = 0;2606    if (NumOfVRSaved) {2607      // Number of VRs saved.2608      VRData |= (NumOfVRSaved << TracebackTable::NumberOfVRSavedShift) &2609                TracebackTable::NumberOfVRSavedMask;2610      // This bit is supposed to set only when the special register2611      // VRSAVE is saved on stack.2612      // However, IBM XL compiler sets the bit when any vector registers2613      // are saved on the stack. We will follow XL's behavior on AIX2614      // so that we don't get surprise behavior change for C code.2615      VRData |= TracebackTable::IsVRSavedOnStackMask;2616    }2617 2618    // Set has_varargs.2619    if (FI->getVarArgsFrameIndex())2620      VRData |= TracebackTable::HasVarArgsMask;2621 2622    // Vector parameters number.2623    unsigned VectorParmsNum = FI->getVectorParmsNum();2624    VRData |= (VectorParmsNum << TracebackTable::NumberOfVectorParmsShift) &2625              TracebackTable::NumberOfVectorParmsMask;2626 2627    if (HasVectorInst)2628      VRData |= TracebackTable::HasVMXInstructionMask;2629 2630    GENVALUECOMMENT("NumOfVRsSaved", VRData, NumberOfVRSaved);2631    GENBOOLCOMMENT(", ", VRData, IsVRSavedOnStack);2632    GENBOOLCOMMENT(", ", VRData, HasVarArgs);2633    EmitComment();2634    OutStreamer->emitIntValueInHexWithPadding((VRData & 0xff00) >> 8, 1);2635 2636    GENVALUECOMMENT("NumOfVectorParams", VRData, NumberOfVectorParms);2637    GENBOOLCOMMENT(", ", VRData, HasVMXInstruction);2638    EmitComment();2639    OutStreamer->emitIntValueInHexWithPadding(VRData & 0x00ff, 1);2640 2641    uint32_t VecParmTypeValue = FI->getVecExtParmsType();2642 2643    Expected<SmallString<32>> VecParmsType =2644        XCOFF::parseVectorParmsType(VecParmTypeValue, VectorParmsNum);2645    assert(VecParmsType && toString(VecParmsType.takeError()).c_str());2646    if (VecParmsType) {2647      CommentOS << "Vector Parameter type = " << VecParmsType.get();2648      EmitComment();2649    }2650    OutStreamer->emitIntValueInHexWithPadding(VecParmTypeValue,2651                                              sizeof(VecParmTypeValue));2652    // Padding 2 bytes.2653    CommentOS << "Padding";2654    EmitCommentAndValue(0, 2);2655  }2656 2657  uint8_t ExtensionTableFlag = 0;2658  if (SecondHalfOfMandatoryField & TracebackTable::HasExtensionTableMask) {2659    if (ShouldEmitEHBlock)2660      ExtensionTableFlag |= ExtendedTBTableFlag::TB_EH_INFO;2661    if (EnableSSPCanaryBitInTB &&2662        TargetLoweringObjectFileXCOFF::ShouldSetSSPCanaryBitInTB(MF))2663      ExtensionTableFlag |= ExtendedTBTableFlag::TB_SSP_CANARY;2664 2665    CommentOS << "ExtensionTableFlag = "2666              << getExtendedTBTableFlagString(ExtensionTableFlag);2667    EmitCommentAndValue(ExtensionTableFlag, sizeof(ExtensionTableFlag));2668  }2669 2670  if (ExtensionTableFlag & ExtendedTBTableFlag::TB_EH_INFO) {2671    auto &Ctx = OutStreamer->getContext();2672    MCSymbol *EHInfoSym =2673        TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(MF);2674    MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(EHInfoSym, TOCType_EHBlock);2675    const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(2676                                     getObjFileLowering().getTOCBaseSection())2677                                     ->getQualNameSymbol();2678    const MCExpr *Exp =2679        MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCEntry, Ctx),2680                                MCSymbolRefExpr::create(TOCBaseSym, Ctx), Ctx);2681 2682    const DataLayout &DL = getDataLayout();2683    OutStreamer->emitValueToAlignment(Align(4));2684    OutStreamer->AddComment("EHInfo Table");2685    OutStreamer->emitValue(Exp, DL.getPointerSize());2686  }2687#undef GENBOOLCOMMENT2688#undef GENVALUECOMMENT2689}2690 2691static bool isSpecialLLVMGlobalArrayToSkip(const GlobalVariable *GV) {2692  return GV->hasAppendingLinkage() &&2693         StringSwitch<bool>(GV->getName())2694             // TODO: Linker could still eliminate the GV if we just skip2695             // handling llvm.used array. Skipping them for now until we or the2696             // AIX OS team come up with a good solution.2697             .Case("llvm.used", true)2698             // It's correct to just skip llvm.compiler.used array here.2699             .Case("llvm.compiler.used", true)2700             .Default(false);2701}2702 2703static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV) {2704  return StringSwitch<bool>(GV->getName())2705      .Cases({"llvm.global_ctors", "llvm.global_dtors"}, true)2706      .Default(false);2707}2708 2709uint64_t PPCAIXAsmPrinter::getAliasOffset(const Constant *C) {2710  if (auto *GA = dyn_cast<GlobalAlias>(C))2711    return getAliasOffset(GA->getAliasee());2712  if (auto *CE = dyn_cast<ConstantExpr>(C)) {2713    const MCExpr *LowC = lowerConstant(CE);2714    const MCBinaryExpr *CBE = dyn_cast<MCBinaryExpr>(LowC);2715    if (!CBE)2716      return 0;2717    if (CBE->getOpcode() != MCBinaryExpr::Add)2718      report_fatal_error("Only adding an offset is supported now.");2719    auto *RHS = dyn_cast<MCConstantExpr>(CBE->getRHS());2720    if (!RHS)2721      report_fatal_error("Unable to get the offset of alias.");2722    return RHS->getValue();2723  }2724  return 0;2725}2726 2727static void tocDataChecks(unsigned PointerSize, const GlobalVariable *GV) {2728  // TODO: These asserts should be updated as more support for the toc data2729  // transformation is added (struct support, etc.).2730  assert(2731      PointerSize >= GV->getAlign().valueOrOne().value() &&2732      "GlobalVariables with an alignment requirement stricter than TOC entry "2733      "size not supported by the toc data transformation.");2734 2735  Type *GVType = GV->getValueType();2736  assert(GVType->isSized() && "A GlobalVariable's size must be known to be "2737                              "supported by the toc data transformation.");2738  if (GV->getDataLayout().getTypeSizeInBits(GVType) >2739      PointerSize * 8)2740    report_fatal_error(2741        "A GlobalVariable with size larger than a TOC entry is not currently "2742        "supported by the toc data transformation.");2743  if (GV->hasPrivateLinkage())2744    report_fatal_error("A GlobalVariable with private linkage is not "2745                       "currently supported by the toc data transformation.");2746}2747 2748void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {2749  // Special LLVM global arrays have been handled at the initialization.2750  if (isSpecialLLVMGlobalArrayToSkip(GV) || isSpecialLLVMGlobalArrayForStaticInit(GV))2751    return;2752 2753  // Ignore non-emitted data.2754  if (GV->getSection() == "llvm.metadata")2755    return;2756 2757  // If the Global Variable has the toc-data attribute, it needs to be emitted2758  // when we emit the .toc section.2759  if (GV->hasAttribute("toc-data")) {2760    unsigned PointerSize = GV->getDataLayout().getPointerSize();2761    tocDataChecks(PointerSize, GV);2762    TOCDataGlobalVars.push_back(GV);2763    return;2764  }2765 2766  emitGlobalVariableHelper(GV);2767}2768 2769void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {2770  assert(!GV->getName().starts_with("llvm.") &&2771         "Unhandled intrinsic global variable.");2772 2773  if (GV->hasComdat())2774    report_fatal_error("COMDAT not yet supported by AIX.");2775 2776  auto *GVSym = static_cast<MCSymbolXCOFF *>(getSymbol(GV));2777 2778  if (GV->isDeclarationForLinker()) {2779    emitLinkage(GV, GVSym);2780    return;2781  }2782 2783  SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);2784  if (!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly() &&2785      !GVKind.isThreadLocal()) // Checks for both ThreadData and ThreadBSS.2786    report_fatal_error("Encountered a global variable kind that is "2787                       "not supported yet.");2788 2789  // Print GV in verbose mode2790  if (isVerbose()) {2791    if (GV->hasInitializer()) {2792      GV->printAsOperand(OutStreamer->getCommentOS(),2793                         /*PrintType=*/false, GV->getParent());2794      OutStreamer->getCommentOS() << '\n';2795    }2796  }2797 2798  auto *Csect = static_cast<MCSectionXCOFF *>(2799      getObjFileLowering().SectionForGlobal(GV, GVKind, TM));2800 2801  // Switch to the containing csect.2802  OutStreamer->switchSection(Csect);2803 2804  const DataLayout &DL = GV->getDataLayout();2805 2806  // Handle common and zero-initialized local symbols.2807  if (GV->hasCommonLinkage() || GVKind.isBSSLocal() ||2808      GVKind.isThreadBSSLocal()) {2809    Align Alignment = GV->getAlign().value_or(DL.getPreferredAlign(GV));2810    uint64_t Size = DL.getTypeAllocSize(GV->getValueType());2811    GVSym->setStorageClass(2812        TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV));2813 2814    if (GVKind.isBSSLocal() && Csect->getMappingClass() == XCOFF::XMC_TD) {2815      OutStreamer->emitZeros(Size);2816    } else if (GVKind.isBSSLocal() || GVKind.isThreadBSSLocal()) {2817      assert(Csect->getMappingClass() != XCOFF::XMC_TD &&2818             "BSS local toc-data already handled and TLS variables "2819             "incompatible with XMC_TD");2820      OutStreamer->emitXCOFFLocalCommonSymbol(2821          OutContext.getOrCreateSymbol(GVSym->getSymbolTableName()), Size,2822          GVSym, Alignment);2823    } else {2824      OutStreamer->emitCommonSymbol(GVSym, Size, Alignment);2825    }2826    return;2827  }2828 2829  MCSymbol *EmittedInitSym = GVSym;2830 2831  // Emit linkage for the global variable and its aliases.2832  emitLinkage(GV, EmittedInitSym);2833  for (const GlobalAlias *GA : GOAliasMap[GV])2834    emitLinkage(GA, getSymbol(GA));2835 2836  emitAlignment(getGVAlignment(GV, DL), GV);2837 2838  // When -fdata-sections is enabled, every GlobalVariable will2839  // be put into its own csect; therefore, label is not necessary here.2840  if (!TM.getDataSections() || GV->hasSection()) {2841    if (Csect->getMappingClass() != XCOFF::XMC_TD)2842      OutStreamer->emitLabel(EmittedInitSym);2843  }2844 2845  // No alias to emit.2846  if (!GOAliasMap[GV].size()) {2847    emitGlobalConstant(GV->getDataLayout(), GV->getInitializer());2848    return;2849  }2850 2851  // Aliases with the same offset should be aligned. Record the list of aliases2852  // associated with the offset.2853  AliasMapTy AliasList;2854  for (const GlobalAlias *GA : GOAliasMap[GV])2855    AliasList[getAliasOffset(GA->getAliasee())].push_back(GA);2856 2857  // Emit alias label and element value for global variable.2858  emitGlobalConstant(GV->getDataLayout(), GV->getInitializer(),2859                     &AliasList);2860}2861 2862void PPCAIXAsmPrinter::emitFunctionDescriptor() {2863  const DataLayout &DL = getDataLayout();2864  const unsigned PointerSize = DL.getPointerSizeInBits() == 64 ? 8 : 4;2865 2866  MCSectionSubPair Current = OutStreamer->getCurrentSection();2867  // Emit function descriptor.2868  OutStreamer->switchSection(2869      static_cast<MCSymbolXCOFF *>(CurrentFnDescSym)->getRepresentedCsect());2870 2871  // Emit aliasing label for function descriptor csect.2872  for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])2873    OutStreamer->emitLabel(getSymbol(Alias));2874 2875  // Emit function entry point address.2876  OutStreamer->emitValue(MCSymbolRefExpr::create(CurrentFnSym, OutContext),2877                         PointerSize);2878  // Emit TOC base address.2879  const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(2880                                   getObjFileLowering().getTOCBaseSection())2881                                   ->getQualNameSymbol();2882  OutStreamer->emitValue(MCSymbolRefExpr::create(TOCBaseSym, OutContext),2883                         PointerSize);2884  // Emit a null environment pointer.2885  OutStreamer->emitIntValue(0, PointerSize);2886 2887  OutStreamer->switchSection(Current.first, Current.second);2888}2889 2890void PPCAIXAsmPrinter::emitFunctionEntryLabel() {2891  // For functions without user defined section, it's not necessary to emit the2892  // label when we have individual function in its own csect.2893  if (!TM.getFunctionSections() || MF->getFunction().hasSection())2894    PPCAsmPrinter::emitFunctionEntryLabel();2895 2896  // Emit aliasing label for function entry point label.2897  for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])2898    OutStreamer->emitLabel(2899        getObjFileLowering().getFunctionEntryPointSymbol(Alias, TM));2900}2901 2902void PPCAIXAsmPrinter::emitPGORefs(Module &M) {2903  if (!OutContext.hasXCOFFSection(2904          "__llvm_prf_cnts",2905          XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))2906    return;2907 2908  // When inside a csect `foo`, a .ref directive referring to a csect `bar`2909  // translates into a relocation entry from `foo` to` bar`. The referring2910  // csect, `foo`, is identified by its address.  If multiple csects have the2911  // same address (because one or more of them are zero-length), the referring2912  // csect cannot be determined. Hence, we don't generate the .ref directives2913  // if `__llvm_prf_cnts` is an empty section.2914  bool HasNonZeroLengthPrfCntsSection = false;2915  const DataLayout &DL = M.getDataLayout();2916  for (GlobalVariable &GV : M.globals())2917    if (GV.hasSection() && GV.getSection() == "__llvm_prf_cnts" &&2918        DL.getTypeAllocSize(GV.getValueType()) > 0) {2919      HasNonZeroLengthPrfCntsSection = true;2920      break;2921    }2922 2923  if (HasNonZeroLengthPrfCntsSection) {2924    MCSection *CntsSection = OutContext.getXCOFFSection(2925        "__llvm_prf_cnts", SectionKind::getData(),2926        XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD),2927        /*MultiSymbolsAllowed*/ true);2928 2929    OutStreamer->switchSection(CntsSection);2930    if (OutContext.hasXCOFFSection(2931            "__llvm_prf_data",2932            XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {2933      MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_data[RW]");2934      OutStreamer->emitXCOFFRefDirective(S);2935    }2936    if (OutContext.hasXCOFFSection(2937            "__llvm_prf_names",2938            XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD))) {2939      MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_names[RO]");2940      OutStreamer->emitXCOFFRefDirective(S);2941    }2942    if (OutContext.hasXCOFFSection(2943            "__llvm_prf_vnds",2944            XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {2945      MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_vnds[RW]");2946      OutStreamer->emitXCOFFRefDirective(S);2947    }2948  }2949}2950 2951void PPCAIXAsmPrinter::emitGCOVRefs() {2952  if (!OutContext.hasXCOFFSection(2953          "__llvm_gcov_ctr_section",2954          XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))2955    return;2956 2957  MCSection *CtrSection = OutContext.getXCOFFSection(2958      "__llvm_gcov_ctr_section", SectionKind::getData(),2959      XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD),2960      /*MultiSymbolsAllowed*/ true);2961 2962  OutStreamer->switchSection(CtrSection);2963  const XCOFF::StorageMappingClass MappingClass =2964      TM.Options.XCOFFReadOnlyPointers ? XCOFF::XMC_RO : XCOFF::XMC_RW;2965  if (OutContext.hasXCOFFSection(2966          "__llvm_covinit",2967          XCOFF::CsectProperties(MappingClass, XCOFF::XTY_SD))) {2968    const char *SymbolStr = TM.Options.XCOFFReadOnlyPointers2969                                ? "__llvm_covinit[RO]"2970                                : "__llvm_covinit[RW]";2971    MCSymbol *S = OutContext.getOrCreateSymbol(SymbolStr);2972    OutStreamer->emitXCOFFRefDirective(S);2973  }2974}2975 2976void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {2977  // If there are no functions and there are no toc-data definitions in this2978  // module, we will never need to reference the TOC base.2979  if (M.empty() && TOCDataGlobalVars.empty())2980    return;2981 2982  emitPGORefs(M);2983  emitGCOVRefs();2984 2985  // Switch to section to emit TOC base.2986  OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());2987 2988  PPCTargetStreamer *TS =2989      static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());2990 2991  for (auto &I : TOC) {2992    MCSectionXCOFF *TCEntry;2993    // Setup the csect for the current TC entry. If the variant kind is2994    // VK_AIX_TLSGDM the entry represents the region handle, we create a2995    // new symbol to prefix the name with a dot.2996    // If TLS model opt is turned on, create a new symbol to prefix the name2997    // with a dot.2998    if (I.first.second == PPC::S_AIX_TLSGDM ||2999        (Subtarget->hasAIXShLibTLSModelOpt() &&3000         I.first.second == PPC::S_AIX_TLSLD)) {3001      SmallString<128> Name;3002      StringRef Prefix = ".";3003      Name += Prefix;3004      Name += static_cast<const MCSymbolXCOFF *>(I.first.first)3005                  ->getSymbolTableName();3006      MCSymbol *S = OutContext.getOrCreateSymbol(Name);3007      TCEntry = static_cast<MCSectionXCOFF *>(3008          getObjFileLowering().getSectionForTOCEntry(S, TM));3009    } else {3010      TCEntry = static_cast<MCSectionXCOFF *>(3011          getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));3012    }3013    OutStreamer->switchSection(TCEntry);3014 3015    OutStreamer->emitLabel(I.second);3016    TS->emitTCEntry(*I.first.first, I.first.second);3017  }3018 3019  // Traverse the list of global variables twice, emitting all of the3020  // non-common global variables before the common ones, as emitting a3021  // .comm directive changes the scope from .toc to the common symbol.3022  for (const auto *GV : TOCDataGlobalVars) {3023    if (!GV->hasCommonLinkage())3024      emitGlobalVariableHelper(GV);3025  }3026  for (const auto *GV : TOCDataGlobalVars) {3027    if (GV->hasCommonLinkage())3028      emitGlobalVariableHelper(GV);3029  }3030}3031 3032bool PPCAIXAsmPrinter::doInitialization(Module &M) {3033  const bool Result = PPCAsmPrinter::doInitialization(M);3034 3035  // Emit the .machine directive on AIX.3036  const Triple &Target = TM.getTargetTriple();3037  XCOFF::CFileCpuId TargetCpuId = XCOFF::TCPU_INVALID;3038  // Walk through the "target-cpu" attribute of functions and use the newest3039  // level as the CPU of the module.3040  for (auto &F : M) {3041    XCOFF::CFileCpuId FunCpuId =3042        XCOFF::getCpuID(TM.getSubtargetImpl(F)->getCPU());3043    if (FunCpuId > TargetCpuId)3044      TargetCpuId = FunCpuId;3045  }3046  // If there is no "target-cpu" attribute within the functions, take the3047  // "-mcpu" value. If both are omitted, use getNormalizedPPCTargetCPU() to3048  // determine the default CPU.3049  if (!TargetCpuId) {3050    StringRef TargetCPU = TM.getTargetCPU();3051    TargetCpuId = XCOFF::getCpuID(3052        TargetCPU.empty() ? PPC::getNormalizedPPCTargetCPU(Target) : TargetCPU);3053  }3054 3055  PPCTargetStreamer *TS =3056      static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());3057  TS->emitMachine(XCOFF::getTCPUString(TargetCpuId));3058 3059  auto setCsectAlignment = [this](const GlobalObject *GO) {3060    // Declarations have 0 alignment which is set by default.3061    if (GO->isDeclarationForLinker())3062      return;3063 3064    SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM);3065    auto *Csect = static_cast<MCSectionXCOFF *>(3066        getObjFileLowering().SectionForGlobal(GO, GOKind, TM));3067 3068    Align GOAlign = getGVAlignment(GO, GO->getDataLayout());3069    Csect->ensureMinAlignment(GOAlign);3070  };3071 3072  // For all TLS variables, calculate their corresponding addresses and store3073  // them into TLSVarsToAddressMapping, which will be used to determine whether3074  // or not local-exec TLS variables require special assembly printing.3075  uint64_t TLSVarAddress = 0;3076  auto DL = M.getDataLayout();3077  for (const auto &G : M.globals()) {3078    if (G.isThreadLocal() && !G.isDeclaration()) {3079      TLSVarAddress = alignTo(TLSVarAddress, getGVAlignment(&G, DL));3080      TLSVarsToAddressMapping[&G] = TLSVarAddress;3081      TLSVarAddress += DL.getTypeAllocSize(G.getValueType());3082    }3083  }3084 3085  // We need to know, up front, the alignment of csects for the assembly path,3086  // because once a .csect directive gets emitted, we could not change the3087  // alignment value on it.3088  for (const auto &G : M.globals()) {3089    if (isSpecialLLVMGlobalArrayToSkip(&G))3090      continue;3091 3092    if (isSpecialLLVMGlobalArrayForStaticInit(&G)) {3093      // Generate a format indicator and a unique module id to be a part of3094      // the sinit and sterm function names.3095      if (FormatIndicatorAndUniqueModId.empty()) {3096        std::string UniqueModuleId = getUniqueModuleId(&M);3097        if (UniqueModuleId != "")3098          // TODO: Use source file full path to generate the unique module id3099          // and add a format indicator as a part of function name in case we3100          // will support more than one format.3101          FormatIndicatorAndUniqueModId = "clang_" + UniqueModuleId.substr(1);3102        else {3103          // Use threadId, Pid, and current time as the unique module id when we3104          // cannot generate one based on a module's strong external symbols.3105          auto CurTime =3106              std::chrono::duration_cast<std::chrono::nanoseconds>(3107                  std::chrono::steady_clock::now().time_since_epoch())3108                  .count();3109          FormatIndicatorAndUniqueModId =3110              "clangPidTidTime_" + llvm::itostr(sys::Process::getProcessId()) +3111              "_" + llvm::itostr(llvm::get_threadid()) + "_" +3112              llvm::itostr(CurTime);3113        }3114      }3115 3116      emitSpecialLLVMGlobal(&G);3117      continue;3118    }3119 3120    setCsectAlignment(&G);3121    std::optional<CodeModel::Model> OptionalCodeModel = G.getCodeModel();3122    if (OptionalCodeModel)3123      setOptionalCodeModel(static_cast<MCSymbolXCOFF *>(getSymbol(&G)),3124                           *OptionalCodeModel);3125  }3126 3127  for (const auto &F : M)3128    setCsectAlignment(&F);3129 3130  // Construct an aliasing list for each GlobalObject.3131  for (const auto &Alias : M.aliases()) {3132    const GlobalObject *Aliasee = Alias.getAliaseeObject();3133    if (!Aliasee)3134      report_fatal_error(3135          "alias without a base object is not yet supported on AIX");3136 3137    if (Aliasee->hasCommonLinkage()) {3138      report_fatal_error("Aliases to common variables are not allowed on AIX:"3139                         "\n\tAlias attribute for " +3140                             Alias.getName() + " is invalid because " +3141                             Aliasee->getName() + " is common.",3142                         false);3143    }3144 3145    const GlobalVariable *GVar =3146        dyn_cast_or_null<GlobalVariable>(Alias.getAliaseeObject());3147    if (GVar) {3148      std::optional<CodeModel::Model> OptionalCodeModel = GVar->getCodeModel();3149      if (OptionalCodeModel)3150        setOptionalCodeModel(static_cast<MCSymbolXCOFF *>(getSymbol(&Alias)),3151                             *OptionalCodeModel);3152    }3153 3154    GOAliasMap[Aliasee].push_back(&Alias);3155  }3156 3157  return Result;3158}3159 3160void PPCAIXAsmPrinter::emitInstruction(const MachineInstr *MI) {3161  switch (MI->getOpcode()) {3162  default:3163    break;3164  case PPC::TW:3165  case PPC::TWI:3166  case PPC::TD:3167  case PPC::TDI: {3168    if (MI->getNumOperands() < 5)3169      break; 3170    const MachineOperand &LangMO = MI->getOperand(3);3171    const MachineOperand &ReasonMO = MI->getOperand(4);3172    if (!LangMO.isImm() || !ReasonMO.isImm())3173      break;3174    MCSymbol *TempSym = OutContext.createNamedTempSymbol();3175    OutStreamer->emitLabel(TempSym);3176    OutStreamer->emitXCOFFExceptDirective(3177        CurrentFnSym, TempSym, LangMO.getImm(), ReasonMO.getImm(),3178        Subtarget->isPPC64() ? MI->getMF()->getInstructionCount() * 83179                             : MI->getMF()->getInstructionCount() * 4,3180        hasDebugInfo());3181    break;3182  }3183  case PPC::GETtlsMOD32AIX:3184  case PPC::GETtlsMOD64AIX:3185  case PPC::GETtlsTpointer32AIX:3186  case PPC::GETtlsADDR64AIX:3187  case PPC::GETtlsADDR32AIX: {3188    // A reference to .__tls_get_mod/.__tls_get_addr/.__get_tpointer is unknown3189    // to the assembler so we need to emit an external symbol reference.3190    MCSymbol *TlsGetAddr =3191        createMCSymbolForTlsGetAddr(OutContext, MI->getOpcode());3192    ExtSymSDNodeSymbols.insert(TlsGetAddr);3193    break;3194  }3195  case PPC::BL8:3196  case PPC::BL:3197  case PPC::BL8_NOP:3198  case PPC::BL_NOP: {3199    const MachineOperand &MO = MI->getOperand(0);3200    if (MO.isSymbol()) {3201      auto *S = static_cast<MCSymbolXCOFF *>(3202          OutContext.getOrCreateSymbol(MO.getSymbolName()));3203      ExtSymSDNodeSymbols.insert(S);3204    }3205  } break;3206  case PPC::BL_TLS:3207  case PPC::BL8_TLS:3208  case PPC::BL8_TLS_:3209  case PPC::BL8_NOP_TLS:3210    report_fatal_error("TLS call not yet implemented");3211  case PPC::TAILB:3212  case PPC::TAILB8:3213  case PPC::TAILBA:3214  case PPC::TAILBA8:3215  case PPC::TAILBCTR:3216  case PPC::TAILBCTR8:3217    if (MI->getOperand(0).isSymbol())3218      report_fatal_error("Tail call for extern symbol not yet supported.");3219    break;3220  case PPC::DST:3221  case PPC::DST64:3222  case PPC::DSTT:3223  case PPC::DSTT64:3224  case PPC::DSTST:3225  case PPC::DSTST64:3226  case PPC::DSTSTT:3227  case PPC::DSTSTT64:3228    EmitToStreamer(3229        *OutStreamer,3230        MCInstBuilder(PPC::ORI).addReg(PPC::R0).addReg(PPC::R0).addImm(0));3231    return;3232  }3233  return PPCAsmPrinter::emitInstruction(MI);3234}3235 3236bool PPCAIXAsmPrinter::doFinalization(Module &M) {3237  // Do streamer related finalization for DWARF.3238  if (hasDebugInfo()) {3239    // Emit section end. This is used to tell the debug line section where the3240    // end is for a text section if we don't use .loc to represent the debug3241    // line.3242    auto *Sec = OutContext.getObjectFileInfo()->getTextSection();3243    OutStreamer->switchSectionNoPrint(Sec);3244    MCSymbol *Sym = Sec->getEndSymbol(OutContext);3245    OutStreamer->emitLabel(Sym);3246  }3247 3248  for (MCSymbol *Sym : ExtSymSDNodeSymbols)3249    OutStreamer->emitSymbolAttribute(Sym, MCSA_Extern);3250  return PPCAsmPrinter::doFinalization(M);3251}3252 3253static unsigned mapToSinitPriority(int P) {3254  if (P < 0 || P > 65535)3255    report_fatal_error("invalid init priority");3256 3257  if (P <= 20)3258    return P;3259 3260  if (P < 81)3261    return 20 + (P - 20) * 16;3262 3263  if (P <= 1124)3264    return 1004 + (P - 81);3265 3266  if (P < 64512)3267    return 2047 + (P - 1124) * 33878;3268 3269  return 2147482625u + (P - 64512);3270}3271 3272static std::string convertToSinitPriority(int Priority) {3273  // This helper function converts clang init priority to values used in sinit3274  // and sterm functions.3275  //3276  // The conversion strategies are:3277  // We map the reserved clang/gnu priority range [0, 100] into the sinit/sterm3278  // reserved priority range [0, 1023] by3279  // - directly mapping the first 21 and the last 20 elements of the ranges3280  // - linear interpolating the intermediate values with a step size of 16.3281  //3282  // We map the non reserved clang/gnu priority range of [101, 65535] into the3283  // sinit/sterm priority range [1024, 2147483648] by:3284  // - directly mapping the first and the last 1024 elements of the ranges3285  // - linear interpolating the intermediate values with a step size of 33878.3286  unsigned int P = mapToSinitPriority(Priority);3287 3288  std::string PrioritySuffix;3289  llvm::raw_string_ostream os(PrioritySuffix);3290  os << llvm::format_hex_no_prefix(P, 8);3291  return PrioritySuffix;3292}3293 3294void PPCAIXAsmPrinter::emitXXStructorList(const DataLayout &DL,3295                                          const Constant *List, bool IsCtor) {3296  SmallVector<Structor, 8> Structors;3297  preprocessXXStructorList(DL, List, Structors);3298  if (Structors.empty())3299    return;3300 3301  unsigned Index = 0;3302  for (Structor &S : Structors) {3303    if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(S.Func))3304      S.Func = CE->getOperand(0);3305 3306    llvm::GlobalAlias::create(3307        GlobalValue::ExternalLinkage,3308        (IsCtor ? llvm::Twine("__sinit") : llvm::Twine("__sterm")) +3309            llvm::Twine(convertToSinitPriority(S.Priority)) +3310            llvm::Twine("_", FormatIndicatorAndUniqueModId) +3311            llvm::Twine("_", llvm::utostr(Index++)),3312        cast<Function>(S.Func));3313  }3314}3315 3316void PPCAIXAsmPrinter::emitTTypeReference(const GlobalValue *GV,3317                                          unsigned Encoding) {3318  if (GV) {3319    TOCEntryType GlobalType = TOCType_GlobalInternal;3320    GlobalValue::LinkageTypes Linkage = GV->getLinkage();3321    if (Linkage == GlobalValue::ExternalLinkage ||3322        Linkage == GlobalValue::AvailableExternallyLinkage ||3323        Linkage == GlobalValue::ExternalWeakLinkage)3324      GlobalType = TOCType_GlobalExternal;3325    MCSymbol *TypeInfoSym = TM.getSymbol(GV);3326    MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(TypeInfoSym, GlobalType);3327    const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(3328                                     getObjFileLowering().getTOCBaseSection())3329                                     ->getQualNameSymbol();3330    auto &Ctx = OutStreamer->getContext();3331    const MCExpr *Exp =3332        MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCEntry, Ctx),3333                                MCSymbolRefExpr::create(TOCBaseSym, Ctx), Ctx);3334    OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding));3335  } else3336    OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding));3337}3338 3339// Return a pass that prints the PPC assembly code for a MachineFunction to the3340// given output stream.3341static AsmPrinter *3342createPPCAsmPrinterPass(TargetMachine &tm,3343                        std::unique_ptr<MCStreamer> &&Streamer) {3344  if (tm.getTargetTriple().isOSAIX())3345    return new PPCAIXAsmPrinter(tm, std::move(Streamer));3346 3347  return new PPCLinuxAsmPrinter(tm, std::move(Streamer));3348}3349 3350void PPCAIXAsmPrinter::emitModuleCommandLines(Module &M) {3351  const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline");3352  if (!NMD || !NMD->getNumOperands())3353    return;3354 3355  std::string S;3356  raw_string_ostream RSOS(S);3357  for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {3358    const MDNode *N = NMD->getOperand(i);3359    assert(N->getNumOperands() == 1 &&3360           "llvm.commandline metadata entry can have only one operand");3361    const MDString *MDS = cast<MDString>(N->getOperand(0));3362    // Add "@(#)" to support retrieving the command line information with the3363    // AIX "what" command3364    RSOS << "@(#)opt " << MDS->getString() << "\n";3365    RSOS.write('\0');3366  }3367  OutStreamer->emitXCOFFCInfoSym(".GCC.command.line", RSOS.str());3368}3369 3370char PPCAIXAsmPrinter::ID = 0;3371 3372INITIALIZE_PASS(PPCAIXAsmPrinter, "ppc-aix-asm-printer",3373                "AIX PPC Assembly Printer", false, false)3374 3375// Force static initialization.3376extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void3377LLVMInitializePowerPCAsmPrinter() {3378  TargetRegistry::RegisterAsmPrinter(getThePPC32Target(),3379                                     createPPCAsmPrinterPass);3380  TargetRegistry::RegisterAsmPrinter(getThePPC32LETarget(),3381                                     createPPCAsmPrinterPass);3382  TargetRegistry::RegisterAsmPrinter(getThePPC64Target(),3383                                     createPPCAsmPrinterPass);3384  TargetRegistry::RegisterAsmPrinter(getThePPC64LETarget(),3385                                     createPPCAsmPrinterPass);3386}3387