diff options
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp')
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 593 | 
1 files changed, 309 insertions, 284 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 4311df5dbeb8..bf5fe741bac8 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -83,8 +83,6 @@ protected:    const PPCSubtarget *Subtarget = nullptr;    StackMaps SM; -  virtual MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO); -  public:    explicit PPCAsmPrinter(TargetMachine &TM,                           std::unique_ptr<MCStreamer> Streamer) @@ -100,7 +98,7 @@ public:      return AsmPrinter::doInitialization(M);    } -  void EmitInstruction(const MachineInstr *MI) override; +  void emitInstruction(const MachineInstr *MI) override;    /// This function is for PrintAsmOperand and PrintAsmMemoryOperand,    /// invoked by EmitMSInlineAsmStr and EmitGCCInlineAsmStr only. @@ -113,7 +111,7 @@ public:    bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,                               const char *ExtraCode, raw_ostream &O) override; -  void EmitEndOfAsmFile(Module &M) override; +  void emitEndOfAsmFile(Module &M) override;    void LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI);    void LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI); @@ -137,37 +135,41 @@ public:      return "Linux PPC Assembly Printer";    } -  bool doFinalization(Module &M) override; -  void EmitStartOfAsmFile(Module &M) override; +  void emitStartOfAsmFile(Module &M) override; +  void emitEndOfAsmFile(Module &) override; -  void EmitFunctionEntryLabel() override; +  void emitFunctionEntryLabel() override; -  void EmitFunctionBodyStart() override; -  void EmitFunctionBodyEnd() override; -  void EmitInstruction(const MachineInstr *MI) override; +  void emitFunctionBodyStart() override; +  void emitFunctionBodyEnd() override; +  void emitInstruction(const MachineInstr *MI) override;  };  class PPCAIXAsmPrinter : public PPCAsmPrinter {  private:    static void ValidateGV(const GlobalVariable *GV); -protected: -  MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO) override;  public:    PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer) -      : PPCAsmPrinter(TM, std::move(Streamer)) {} +      : PPCAsmPrinter(TM, std::move(Streamer)) { +    if (MAI->isLittleEndian()) +      report_fatal_error( +          "cannot create AIX PPC Assembly Printer for a little-endian target"); +  }    StringRef getPassName() const override { return "AIX PPC Assembly Printer"; } +  bool doInitialization(Module &M) override; +    void SetupMachineFunction(MachineFunction &MF) override; -  const MCExpr *lowerConstant(const Constant *CV) override; +  void emitGlobalVariable(const GlobalVariable *GV) override; -  void EmitGlobalVariable(const GlobalVariable *GV) override; +  void emitFunctionDescriptor() override; -  void EmitFunctionDescriptor() override; +  void emitEndOfAsmFile(Module &) override; -  void EmitEndOfAsmFile(Module &) override; +  void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override;  };  } // end anonymous namespace @@ -176,23 +178,7 @@ void PPCAsmPrinter::PrintSymbolOperand(const MachineOperand &MO,                                         raw_ostream &O) {    // Computing the address of a global symbol, not calling it.    const GlobalValue *GV = MO.getGlobal(); -  MCSymbol *SymToPrint; - -  // External or weakly linked global variables need non-lazily-resolved stubs -  if (Subtarget->hasLazyResolverStub(GV)) { -    SymToPrint = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); -    MachineModuleInfoImpl::StubValueTy &StubSym = -        MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry( -            SymToPrint); -    if (!StubSym.getPointer()) -      StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV), -                                                   !GV->hasInternalLinkage()); -  } else { -    SymToPrint = getSymbol(GV); -  } - -  SymToPrint->print(O, MAI); - +  getSymbol(GV)->print(O, MAI);    printOffset(MO.getOffset(), O);  } @@ -208,9 +194,7 @@ void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,      // Linux assembler (Others?) does not take register mnemonics.      // FIXME - What about special registers used in mfspr/mtspr? -    if (!Subtarget->isDarwin()) -      RegName = PPCRegisterInfo::stripRegisterPrefix(RegName); -    O << RegName; +    O << PPCRegisterInfo::stripRegisterPrefix(RegName);      return;    }    case MachineOperand::MO_Immediate: @@ -298,18 +282,17 @@ bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,      switch (ExtraCode[0]) {      default: return true;  // Unknown modifier. +    case 'L': // A memory reference to the upper word of a double word op. +      O << getDataLayout().getPointerSize() << "("; +      printOperand(MI, OpNo, O); +      O << ")"; +      return false;      case 'y': // A memory reference for an X-form instruction -      { -        const char *RegName = "r0"; -        if (!Subtarget->isDarwin()) -          RegName = PPCRegisterInfo::stripRegisterPrefix(RegName); -        O << RegName << ", "; -        printOperand(MI, OpNo, O); -        return false; -      } +      O << "0, "; +      printOperand(MI, OpNo, O); +      return false;      case 'U': // Print 'u' for update form.      case 'X': // Print 'x' for indexed form. -    {        // FIXME: Currently for PowerPC memory operands are always loaded        // into a register, so we never get an update or indexed form.        // This is bad even for offset forms, since even if we know we @@ -319,7 +302,6 @@ bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,        assert(MI->getOperand(OpNo).isReg());        return false;      } -    }    }    assert(MI->getOperand(OpNo).isReg()); @@ -339,7 +321,7 @@ MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym) {    return TOCEntry;  } -void PPCAsmPrinter::EmitEndOfAsmFile(Module &M) { +void PPCAsmPrinter::emitEndOfAsmFile(Module &M) {    emitStackMaps(SM);  } @@ -348,7 +330,7 @@ void PPCAsmPrinter::LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI) {    auto &Ctx = OutStreamer->getContext();    MCSymbol *MILabel = Ctx.createTempSymbol(); -  OutStreamer->EmitLabel(MILabel); +  OutStreamer->emitLabel(MILabel);    SM.recordStackMap(*MILabel, MI);    assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); @@ -377,7 +359,7 @@ void PPCAsmPrinter::LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI) {  void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI) {    auto &Ctx = OutStreamer->getContext();    MCSymbol *MILabel = Ctx.createTempSymbol(); -  OutStreamer->EmitLabel(MILabel); +  OutStreamer->emitLabel(MILabel);    SM.recordPatchPoint(*MILabel, MI);    PatchPointOpers Opers(&MI); @@ -516,16 +498,17 @@ void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,  /// Map a machine operand for a TOC pseudo-machine instruction to its  /// corresponding MCSymbol. -MCSymbol *PPCAsmPrinter::getMCSymbolForTOCPseudoMO(const MachineOperand &MO) { +static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO, +                                           AsmPrinter &AP) {    switch (MO.getType()) {    case MachineOperand::MO_GlobalAddress: -    return getSymbol(MO.getGlobal()); +    return AP.getSymbol(MO.getGlobal());    case MachineOperand::MO_ConstantPoolIndex: -    return GetCPISymbol(MO.getIndex()); +    return AP.GetCPISymbol(MO.getIndex());    case MachineOperand::MO_JumpTableIndex: -    return GetJTISymbol(MO.getIndex()); +    return AP.GetJTISymbol(MO.getIndex());    case MachineOperand::MO_BlockAddress: -    return GetBlockAddressSymbol(MO.getBlockAddress()); +    return AP.GetBlockAddressSymbol(MO.getBlockAddress());    default:      llvm_unreachable("Unexpected operand type to get symbol.");    } @@ -534,9 +517,8 @@ MCSymbol *PPCAsmPrinter::getMCSymbolForTOCPseudoMO(const MachineOperand &MO) {  /// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to  /// the current output stream.  /// -void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { +void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {    MCInst TmpInst; -  const bool IsDarwin = TM.getTargetTriple().isOSDarwin();    const bool IsPPC64 = Subtarget->isPPC64();    const bool IsAIX = Subtarget->isAIXABI();    const Module *M = MF->getFunction().getParent(); @@ -614,7 +596,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {                         .addExpr(MCSymbolRefExpr::create(PICBase, OutContext)));      // Emit the label. -    OutStreamer->EmitLabel(PICBase); +    OutStreamer->emitLabel(PICBase);      return;    }    case PPC::UpdateGBR: { @@ -625,7 +607,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {      //       addis r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@ha      //       addi r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@l      // Get the offset from the GOT Base Register to the GOT -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);      if (Subtarget->isSecurePlt() && isPositionIndependent() ) {        unsigned PICR = TmpInst.getOperand(0).getReg();        MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol( @@ -637,19 +619,19 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {        const MCExpr *DeltaExpr = MCBinaryExpr::createSub(            MCSymbolRefExpr::create(BaseSymbol, OutContext), PB, OutContext); -      const MCExpr *DeltaHi = PPCMCExpr::createHa(DeltaExpr, false, OutContext); +      const MCExpr *DeltaHi = PPCMCExpr::createHa(DeltaExpr, OutContext);        EmitToStreamer(            *OutStreamer,            MCInstBuilder(PPC::ADDIS).addReg(PICR).addReg(PICR).addExpr(DeltaHi)); -      const MCExpr *DeltaLo = PPCMCExpr::createLo(DeltaExpr, false, OutContext); +      const MCExpr *DeltaLo = PPCMCExpr::createLo(DeltaExpr, OutContext);        EmitToStreamer(            *OutStreamer,            MCInstBuilder(PPC::ADDI).addReg(PICR).addReg(PICR).addExpr(DeltaLo));        return;      } else {        MCSymbol *PICOffset = -        MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol(); +        MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol(*MF);        TmpInst.setOpcode(PPC::LWZ);        const MCExpr *Exp =          MCSymbolRefExpr::create(PICOffset, MCSymbolRefExpr::VK_None, OutContext); @@ -676,10 +658,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {      }    }    case PPC::LWZtoc: { -    assert(!IsDarwin && "TOC is an ELF/XCOFF construct."); -      // Transform %rN = LWZtoc @op1, %r2 -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);      // Change the opcode to LWZ.      TmpInst.setOpcode(PPC::LWZ); @@ -689,7 +669,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {             "Invalid operand for LWZtoc.");      // Map the operand to its corresponding MCSymbol. -    const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO); +    const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);      // Create a reference to the GOT entry for the symbol. The GOT entry will be      // synthesized later. @@ -734,10 +714,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {    case PPC::LDtocCPT:    case PPC::LDtocBA:    case PPC::LDtoc: { -    assert(!IsDarwin && "TOC is an ELF/XCOFF construct"); -      // Transform %x3 = LDtoc @min1, %x2 -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);      // Change the opcode to LD.      TmpInst.setOpcode(PPC::LD); @@ -750,7 +728,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {      // global address operand to be a reference to the TOC entry we will      // synthesize later.      MCSymbol *TOCEntry = -        lookUpOrCreateTOCEntry(getMCSymbolForTOCPseudoMO(MO)); +        lookUpOrCreateTOCEntry(getMCSymbolForTOCPseudoMO(MO, *this));      const MCSymbolRefExpr::VariantKind VK =          IsAIX ? MCSymbolRefExpr::VK_None : MCSymbolRefExpr::VK_PPC_TOC; @@ -766,7 +744,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {             " AIX.");      // Transform %rd = ADDIStocHA %rA, @sym(%r2) -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);      // Change the opcode to ADDIS.      TmpInst.setOpcode(PPC::ADDIS); @@ -776,7 +754,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {             "Invalid operand for ADDIStocHA.");      // Map the machine operand to its corresponding MCSymbol. -    MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO); +    MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);      // Always use TOC on AIX. Map the global address operand to be a reference      // to the TOC entry we will synthesize later. 'TOCEntry' is a label used to @@ -796,7 +774,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {             " AIX.");      // Transform %rd = LWZtocL @sym, %rs. -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);      // Change the opcode to lwz.      TmpInst.setOpcode(PPC::LWZ); @@ -806,7 +784,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {             "Invalid operand for LWZtocL.");      // Map the machine operand to its corresponding MCSymbol. -    MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO); +    MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);      // Always use TOC on AIX. Map the global address operand to be a reference      // to the TOC entry we will synthesize later. 'TOCEntry' is a label used to @@ -821,10 +799,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {      return;    }    case PPC::ADDIStocHA8: { -    assert(!IsDarwin && "TOC is an ELF/XCOFF construct"); -      // Transform %xd = ADDIStocHA8 %x2, @sym -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);      // Change the opcode to ADDIS8. If the global address is the address of      // an external symbol, is a jump table address, is a block address, or is a @@ -836,7 +812,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {      assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&             "Invalid operand for ADDIStocHA8!"); -    const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO); +    const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);      const bool GlobalToc =          MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal()); @@ -861,10 +837,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {      return;    }    case PPC::LDtocL: { -    assert(!IsDarwin && "TOC is an ELF/XCOFF construct"); -      // Transform %xd = LDtocL @sym, %xs -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);      // Change the opcode to LD. If the global address is the address of      // an external symbol, is a jump table address, is a block address, or is @@ -882,7 +856,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {          "LDtocL used on symbol that could be accessed directly is "          "invalid. Must match ADDIStocHA8.")); -    const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO); +    const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);      if (!MO.isCPI() || TM.getCodeModel() == CodeModel::Large)        MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); @@ -897,7 +871,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {    }    case PPC::ADDItocL: {      // Transform %xd = ADDItocL %xs, @sym -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);      // Change the opcode to ADDI8. If the global address is external, then      // generate a TOC entry and reference that. Otherwise, reference the @@ -912,7 +886,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {          "Interposable definitions must use indirect access."));      const MCExpr *Exp = -        MCSymbolRefExpr::create(getMCSymbolForTOCPseudoMO(MO), +        MCSymbolRefExpr::create(getMCSymbolForTOCPseudoMO(MO, *this),                                  MCSymbolRefExpr::VK_PPC_TOC_LO, OutContext);      TmpInst.getOperand(2) = MCOperand::createExpr(Exp);      EmitToStreamer(*OutStreamer, TmpInst); @@ -937,7 +911,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {    case PPC::LDgotTprelL:    case PPC::LDgotTprelL32: {      // Transform %xd = LDgotTprelL @sym, %xs -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);      // Change the opcode to LD.      TmpInst.setOpcode(IsPPC64 ? PPC::LD : PPC::LWZ); @@ -966,9 +940,9 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {        MCBinaryExpr::createSub(MCSymbolRefExpr::create(GOTSymbol, OutContext),                                  MCSymbolRefExpr::create(GOTRef, OutContext),          OutContext); -    OutStreamer->EmitLabel(GOTRef); -    OutStreamer->EmitValue(OffsExpr, 4); -    OutStreamer->EmitLabel(NextInstr); +    OutStreamer->emitLabel(GOTRef); +    OutStreamer->emitValue(OffsExpr, 4); +    OutStreamer->emitLabel(NextInstr);      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR)                                   .addReg(MI->getOperand(0).getReg()));      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LWZ) @@ -1167,10 +1141,11 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {      // suite shows a handful of test cases that fail this check for      // Darwin.  Those need to be investigated before this sanity test      // can be enabled for those subtargets. -    if (!IsDarwin) { -      unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1; -      const MachineOperand &MO = MI->getOperand(OpNum); -      if (MO.isGlobal() && MO.getGlobal()->getAlignment() < 4) +    unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1; +    const MachineOperand &MO = MI->getOperand(OpNum); +    if (MO.isGlobal()) { +      const DataLayout &DL = MO.getGlobal()->getParent()->getDataLayout(); +      if (MO.getGlobal()->getPointerAlignment(DL) < 4)          llvm_unreachable("Global must be word-aligned for LD, STD, LWA!");      }      // Now process the instruction normally. @@ -1178,17 +1153,17 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {    }    } -  LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin); +  LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);    EmitToStreamer(*OutStreamer, TmpInst);  } -void PPCLinuxAsmPrinter::EmitInstruction(const MachineInstr *MI) { +void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {    if (!Subtarget->isPPC64()) -    return PPCAsmPrinter::EmitInstruction(MI); +    return PPCAsmPrinter::emitInstruction(MI);    switch (MI->getOpcode()) {    default: -    return PPCAsmPrinter::EmitInstruction(MI); +    return PPCAsmPrinter::emitInstruction(MI);    case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {      // .begin:      //   b .end # lis 0, FuncId[16..32] @@ -1203,7 +1178,7 @@ void PPCLinuxAsmPrinter::EmitInstruction(const MachineInstr *MI) {      // of instructions change.      MCSymbol *BeginOfSled = OutContext.createTempSymbol();      MCSymbol *EndOfSled = OutContext.createTempSymbol(); -    OutStreamer->EmitLabel(BeginOfSled); +    OutStreamer->emitLabel(BeginOfSled);      EmitToStreamer(*OutStreamer,                     MCInstBuilder(PPC::B).addExpr(                         MCSymbolRefExpr::create(EndOfSled, OutContext))); @@ -1218,8 +1193,8 @@ void PPCLinuxAsmPrinter::EmitInstruction(const MachineInstr *MI) {                             OutContext.getOrCreateSymbol("__xray_FunctionEntry"),                             OutContext)));      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0)); -    OutStreamer->EmitLabel(EndOfSled); -    recordSled(BeginOfSled, *MI, SledKind::FUNCTION_ENTER); +    OutStreamer->emitLabel(EndOfSled); +    recordSled(BeginOfSled, *MI, SledKind::FUNCTION_ENTER, 2);      break;    }    case TargetOpcode::PATCHABLE_RET: { @@ -1229,7 +1204,7 @@ void PPCLinuxAsmPrinter::EmitInstruction(const MachineInstr *MI) {      for (const auto &MO :           make_range(std::next(MI->operands_begin()), MI->operands_end())) {        MCOperand MCOp; -      if (LowerPPCMachineOperandToMCOperand(MO, MCOp, *this, false)) +      if (LowerPPCMachineOperandToMCOperand(MO, MCOp, *this))          RetInst.addOperand(MCOp);      } @@ -1289,9 +1264,9 @@ void PPCLinuxAsmPrinter::EmitInstruction(const MachineInstr *MI) {      //      // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number      // of instructions change. -    OutStreamer->EmitCodeAlignment(8); +    OutStreamer->emitCodeAlignment(8);      MCSymbol *BeginOfSled = OutContext.createTempSymbol(); -    OutStreamer->EmitLabel(BeginOfSled); +    OutStreamer->emitLabel(BeginOfSled);      EmitToStreamer(*OutStreamer, RetInst);      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));      EmitToStreamer( @@ -1306,8 +1281,8 @@ void PPCLinuxAsmPrinter::EmitInstruction(const MachineInstr *MI) {      EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));      EmitToStreamer(*OutStreamer, RetInst);      if (IsConditional) -      OutStreamer->EmitLabel(FallthroughLabel); -    recordSled(BeginOfSled, *MI, SledKind::FUNCTION_EXIT); +      OutStreamer->emitLabel(FallthroughLabel); +    recordSled(BeginOfSled, *MI, SledKind::FUNCTION_EXIT, 2);      break;    }    case TargetOpcode::PATCHABLE_FUNCTION_EXIT: @@ -1320,7 +1295,7 @@ void PPCLinuxAsmPrinter::EmitInstruction(const MachineInstr *MI) {    }  } -void PPCLinuxAsmPrinter::EmitStartOfAsmFile(Module &M) { +void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) {    if (static_cast<const PPCTargetMachine &>(TM).isELFv2ABI()) {      PPCTargetStreamer *TS =        static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer()); @@ -1331,10 +1306,10 @@ void PPCLinuxAsmPrinter::EmitStartOfAsmFile(Module &M) {    if (static_cast<const PPCTargetMachine &>(TM).isPPC64() ||        !isPositionIndependent()) -    return AsmPrinter::EmitStartOfAsmFile(M); +    return AsmPrinter::emitStartOfAsmFile(M);    if (M.getPICLevel() == PICLevel::SmallPIC) -    return AsmPrinter::EmitStartOfAsmFile(M); +    return AsmPrinter::emitStartOfAsmFile(M);    OutStreamer->SwitchSection(OutContext.getELFSection(        ".got2", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC)); @@ -1342,7 +1317,7 @@ void PPCLinuxAsmPrinter::EmitStartOfAsmFile(Module &M) {    MCSymbol *TOCSym = OutContext.getOrCreateSymbol(Twine(".LTOC"));    MCSymbol *CurrentPos = OutContext.createTempSymbol(); -  OutStreamer->EmitLabel(CurrentPos); +  OutStreamer->emitLabel(CurrentPos);    // The GOT pointer points to the middle of the GOT, in order to reference the    // entire 64kB range.  0x8000 is the midpoint. @@ -1351,24 +1326,24 @@ void PPCLinuxAsmPrinter::EmitStartOfAsmFile(Module &M) {                              MCConstantExpr::create(0x8000, OutContext),                              OutContext); -  OutStreamer->EmitAssignment(TOCSym, tocExpr); +  OutStreamer->emitAssignment(TOCSym, tocExpr);    OutStreamer->SwitchSection(getObjFileLowering().getTextSection());  } -void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() { +void PPCLinuxAsmPrinter::emitFunctionEntryLabel() {    // linux/ppc32 - Normal entry label.    if (!Subtarget->isPPC64() &&        (!isPositionIndependent() ||         MF->getFunction().getParent()->getPICLevel() == PICLevel::SmallPIC)) -    return AsmPrinter::EmitFunctionEntryLabel(); +    return AsmPrinter::emitFunctionEntryLabel();    if (!Subtarget->isPPC64()) {      const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();      if (PPCFI->usesPICBase() && !Subtarget->isSecurePlt()) { -      MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol(); +      MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol(*MF);        MCSymbol *PICBase = MF->getPICBaseSymbol(); -      OutStreamer->EmitLabel(RelocSymbol); +      OutStreamer->emitLabel(RelocSymbol);        const MCExpr *OffsExpr =          MCBinaryExpr::createSub( @@ -1376,11 +1351,11 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {                                                                 OutContext),                                    MCSymbolRefExpr::create(PICBase, OutContext),            OutContext); -      OutStreamer->EmitValue(OffsExpr, 4); -      OutStreamer->EmitLabel(CurrentFnSym); +      OutStreamer->emitValue(OffsExpr, 4); +      OutStreamer->emitLabel(CurrentFnSym);        return;      } else -      return AsmPrinter::EmitFunctionEntryLabel(); +      return AsmPrinter::emitFunctionEntryLabel();    }    // ELFv2 ABI - Normal entry label. @@ -1394,17 +1369,17 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {        const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();        MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC.")); -      MCSymbol *GlobalEPSymbol = PPCFI->getGlobalEPSymbol(); +      MCSymbol *GlobalEPSymbol = PPCFI->getGlobalEPSymbol(*MF);        const MCExpr *TOCDeltaExpr =          MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext),                                  MCSymbolRefExpr::create(GlobalEPSymbol,                                                          OutContext),                                  OutContext); -      OutStreamer->EmitLabel(PPCFI->getTOCOffsetSymbol()); -      OutStreamer->EmitValue(TOCDeltaExpr, 8); +      OutStreamer->emitLabel(PPCFI->getTOCOffsetSymbol(*MF)); +      OutStreamer->emitValue(TOCDeltaExpr, 8);      } -    return AsmPrinter::EmitFunctionEntryLabel(); +    return AsmPrinter::emitFunctionEntryLabel();    }    // Emit an official procedure descriptor. @@ -1412,61 +1387,56 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {    MCSectionELF *Section = OutStreamer->getContext().getELFSection(        ".opd", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);    OutStreamer->SwitchSection(Section); -  OutStreamer->EmitLabel(CurrentFnSym); -  OutStreamer->EmitValueToAlignment(8); +  OutStreamer->emitLabel(CurrentFnSym); +  OutStreamer->emitValueToAlignment(8);    MCSymbol *Symbol1 = CurrentFnSymForSize;    // Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function    // entry point. -  OutStreamer->EmitValue(MCSymbolRefExpr::create(Symbol1, OutContext), +  OutStreamer->emitValue(MCSymbolRefExpr::create(Symbol1, OutContext),                           8 /*size*/);    MCSymbol *Symbol2 = OutContext.getOrCreateSymbol(StringRef(".TOC."));    // Generates a R_PPC64_TOC relocation for TOC base insertion. -  OutStreamer->EmitValue( +  OutStreamer->emitValue(      MCSymbolRefExpr::create(Symbol2, MCSymbolRefExpr::VK_PPC_TOCBASE, OutContext),      8/*size*/);    // Emit a null environment pointer. -  OutStreamer->EmitIntValue(0, 8 /* size */); +  OutStreamer->emitIntValue(0, 8 /* size */);    OutStreamer->SwitchSection(Current.first, Current.second);  } -bool PPCLinuxAsmPrinter::doFinalization(Module &M) { +void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) {    const DataLayout &DL = getDataLayout();    bool isPPC64 = DL.getPointerSizeInBits() == 64; -  PPCTargetStreamer &TS = -      static_cast<PPCTargetStreamer &>(*OutStreamer->getTargetStreamer()); +  PPCTargetStreamer *TS = +      static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());    if (!TOC.empty()) { -    MCSectionELF *Section; - -    if (isPPC64) -      Section = OutStreamer->getContext().getELFSection( -          ".toc", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); -        else -          Section = OutStreamer->getContext().getELFSection( -              ".got2", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); +    const char *Name = isPPC64 ? ".toc" : ".got2"; +    MCSectionELF *Section = OutContext.getELFSection( +        Name, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);      OutStreamer->SwitchSection(Section); +    if (!isPPC64) +      OutStreamer->emitValueToAlignment(4);      for (const auto &TOCMapPair : TOC) {        const MCSymbol *const TOCEntryTarget = TOCMapPair.first;        MCSymbol *const TOCEntryLabel = TOCMapPair.second; -      OutStreamer->EmitLabel(TOCEntryLabel); -      if (isPPC64) { -        TS.emitTCEntry(*TOCEntryTarget); -      } else { -        OutStreamer->EmitValueToAlignment(4); -        OutStreamer->EmitSymbolValue(TOCEntryTarget, 4); -      } +      OutStreamer->emitLabel(TOCEntryLabel); +      if (isPPC64 && TS != nullptr) +        TS->emitTCEntry(*TOCEntryTarget); +      else +        OutStreamer->emitSymbolValue(TOCEntryTarget, 4);      }    } -  return AsmPrinter::doFinalization(M); +  PPCAsmPrinter::emitEndOfAsmFile(M);  }  /// EmitFunctionBodyStart - Emit a global entry point prefix for ELFv2. -void PPCLinuxAsmPrinter::EmitFunctionBodyStart() { +void PPCLinuxAsmPrinter::emitFunctionBodyStart() {    // In the ELFv2 ABI, in functions that use the TOC register, we need to    // provide two entry points.  The ABI guarantees that when calling the    // local entry point, r2 is set up by the caller to contain the TOC base @@ -1498,16 +1468,23 @@ void PPCLinuxAsmPrinter::EmitFunctionBodyStart() {    //    // This ensures we have r2 set up correctly while executing the function    // body, no matter which entry point is called. -  if (Subtarget->isELFv2ABI() -      // Only do all that if the function uses r2 in the first place. -      && !MF->getRegInfo().use_empty(PPC::X2)) { +  const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>(); +  const bool UsesX2OrR2 = !MF->getRegInfo().use_empty(PPC::X2) || +                          !MF->getRegInfo().use_empty(PPC::R2); +  const bool PCrelGEPRequired = Subtarget->isUsingPCRelativeCalls() && +                                UsesX2OrR2 && PPCFI->usesTOCBasePtr(); +  const bool NonPCrelGEPRequired = !Subtarget->isUsingPCRelativeCalls() && +                                   Subtarget->isELFv2ABI() && UsesX2OrR2; + +  // Only do all that if the function uses R2 as the TOC pointer +  // in the first place. We don't need the global entry point if the +  // function uses R2 as an allocatable register. +  if (NonPCrelGEPRequired || PCrelGEPRequired) {      // Note: The logic here must be synchronized with the code in the      // branch-selection pass which sets the offset of the first block in the      // function. This matters because it affects the alignment. -    const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>(); - -    MCSymbol *GlobalEntryLabel = PPCFI->getGlobalEPSymbol(); -    OutStreamer->EmitLabel(GlobalEntryLabel); +    MCSymbol *GlobalEntryLabel = PPCFI->getGlobalEPSymbol(*MF); +    OutStreamer->emitLabel(GlobalEntryLabel);      const MCSymbolRefExpr *GlobalEntryLabelExp =        MCSymbolRefExpr::create(GlobalEntryLabel, OutContext); @@ -1517,21 +1494,19 @@ void PPCLinuxAsmPrinter::EmitFunctionBodyStart() {          MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext),                                  GlobalEntryLabelExp, OutContext); -      const MCExpr *TOCDeltaHi = -        PPCMCExpr::createHa(TOCDeltaExpr, false, OutContext); +      const MCExpr *TOCDeltaHi = PPCMCExpr::createHa(TOCDeltaExpr, OutContext);        EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)                                     .addReg(PPC::X2)                                     .addReg(PPC::X12)                                     .addExpr(TOCDeltaHi)); -      const MCExpr *TOCDeltaLo = -        PPCMCExpr::createLo(TOCDeltaExpr, false, OutContext); +      const MCExpr *TOCDeltaLo = PPCMCExpr::createLo(TOCDeltaExpr, OutContext);        EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI)                                     .addReg(PPC::X2)                                     .addReg(PPC::X2)                                     .addExpr(TOCDeltaLo));      } else { -      MCSymbol *TOCOffset = PPCFI->getTOCOffsetSymbol(); +      MCSymbol *TOCOffset = PPCFI->getTOCOffsetSymbol(*MF);        const MCExpr *TOCOffsetDeltaExpr =          MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCOffset, OutContext),                                  GlobalEntryLabelExp, OutContext); @@ -1546,8 +1521,8 @@ void PPCLinuxAsmPrinter::EmitFunctionBodyStart() {                                     .addReg(PPC::X12));      } -    MCSymbol *LocalEntryLabel = PPCFI->getLocalEPSymbol(); -    OutStreamer->EmitLabel(LocalEntryLabel); +    MCSymbol *LocalEntryLabel = PPCFI->getLocalEPSymbol(*MF); +    OutStreamer->emitLabel(LocalEntryLabel);      const MCSymbolRefExpr *LocalEntryLabelExp =         MCSymbolRefExpr::create(LocalEntryLabel, OutContext);      const MCExpr *LocalOffsetExp = @@ -1559,13 +1534,43 @@ void PPCLinuxAsmPrinter::EmitFunctionBodyStart() {      if (TS)        TS->emitLocalEntry(cast<MCSymbolELF>(CurrentFnSym), LocalOffsetExp); +  } else if (Subtarget->isUsingPCRelativeCalls()) { +    // When generating the entry point for a function we have a few scenarios +    // based on whether or not that function uses R2 and whether or not that +    // function makes calls (or is a leaf function). +    // 1) A leaf function that does not use R2 (or treats it as callee-saved +    //    and preserves it). In this case st_other=0 and both +    //    the local and global entry points for the function are the same. +    //    No special entry point code is required. +    // 2) A function uses the TOC pointer R2. This function may or may not have +    //    calls. In this case st_other=[2,6] and the global and local entry +    //    points are different. Code to correctly setup the TOC pointer in R2 +    //    is put between the global and local entry points. This case is +    //    covered by the if statatement above. +    // 3) A function does not use the TOC pointer R2 but does have calls. +    //    In this case st_other=1 since we do not know whether or not any +    //    of the callees clobber R2. This case is dealt with in this else if +    //    block. Tail calls are considered calls and the st_other should also +    //    be set to 1 in that case as well. +    // 4) The function does not use the TOC pointer but R2 is used inside +    //    the function. In this case st_other=1 once again. +    // 5) This function uses inline asm. We mark R2 as reserved if the function +    //    has inline asm as we have to assume that it may be used. +    if (MF->getFrameInfo().hasCalls() || MF->getFrameInfo().hasTailCall() || +        MF->hasInlineAsm() || (!PPCFI->usesTOCBasePtr() && UsesX2OrR2)) { +      PPCTargetStreamer *TS = +          static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer()); +      if (TS) +        TS->emitLocalEntry(cast<MCSymbolELF>(CurrentFnSym), +                           MCConstantExpr::create(1, OutContext)); +    }    }  }  /// EmitFunctionBodyEnd - Print the traceback table before the .size  /// directive.  /// -void PPCLinuxAsmPrinter::EmitFunctionBodyEnd() { +void PPCLinuxAsmPrinter::emitFunctionBodyEnd() {    // Only the 64-bit target requires a traceback table.  For now,    // we only emit the word of zeroes that GDB requires to find    // the end of the function, and zeroes for the eight-byte @@ -1574,19 +1579,73 @@ void PPCLinuxAsmPrinter::EmitFunctionBodyEnd() {    // the PPC64 ELF ABI (this is a low-priority item because GDB does not    // currently make use of these fields).    if (Subtarget->isPPC64()) { -    OutStreamer->EmitIntValue(0, 4/*size*/); -    OutStreamer->EmitIntValue(0, 8/*size*/); +    OutStreamer->emitIntValue(0, 4/*size*/); +    OutStreamer->emitIntValue(0, 8/*size*/); +  } +} + +void PPCAIXAsmPrinter::emitLinkage(const GlobalValue *GV, +                                   MCSymbol *GVSym) const { + +  assert(MAI->hasVisibilityOnlyWithLinkage() && +         "AIX's linkage directives take a visibility setting."); + +  MCSymbolAttr LinkageAttr = MCSA_Invalid; +  switch (GV->getLinkage()) { +  case GlobalValue::ExternalLinkage: +    LinkageAttr = GV->isDeclaration() ? MCSA_Extern : MCSA_Global; +    break; +  case GlobalValue::LinkOnceAnyLinkage: +  case GlobalValue::LinkOnceODRLinkage: +  case GlobalValue::WeakAnyLinkage: +  case GlobalValue::WeakODRLinkage: +  case GlobalValue::ExternalWeakLinkage: +    LinkageAttr = MCSA_Weak; +    break; +  case GlobalValue::AvailableExternallyLinkage: +    LinkageAttr = MCSA_Extern; +    break; +  case GlobalValue::PrivateLinkage: +    return; +  case GlobalValue::InternalLinkage: +    assert(GV->getVisibility() == GlobalValue::DefaultVisibility && +           "InternalLinkage should not have other visibility setting."); +    LinkageAttr = MCSA_LGlobal; +    break; +  case GlobalValue::AppendingLinkage: +    llvm_unreachable("Should never emit this"); +  case GlobalValue::CommonLinkage: +    llvm_unreachable("CommonLinkage of XCOFF should not come to this path");    } + +  assert(LinkageAttr != MCSA_Invalid && "LinkageAttr should not MCSA_Invalid."); + +  MCSymbolAttr VisibilityAttr = MCSA_Invalid; +  switch (GV->getVisibility()) { + +  // TODO: "exported" and "internal" Visibility needs to go here. +  case GlobalValue::DefaultVisibility: +    break; +  case GlobalValue::HiddenVisibility: +    VisibilityAttr = MAI->getHiddenVisibilityAttr(); +    break; +  case GlobalValue::ProtectedVisibility: +    VisibilityAttr = MAI->getProtectedVisibilityAttr(); +    break; +  } + +  OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr, +                                                    VisibilityAttr);  }  void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) { -  // Get the function descriptor symbol. -  CurrentFnDescSym = getSymbol(&MF.getFunction()); -  // Set the containing csect. -  MCSectionXCOFF *FnDescSec = OutStreamer->getContext().getXCOFFSection( -      CurrentFnDescSym->getName(), XCOFF::XMC_DS, XCOFF::XTY_SD, -      XCOFF::C_HIDEXT, SectionKind::getData()); -  cast<MCSymbolXCOFF>(CurrentFnDescSym)->setContainingCsect(FnDescSec); +  // Setup CurrentFnDescSym and its containing csect. +  MCSectionXCOFF *FnDescSec = +      cast<MCSectionXCOFF>(getObjFileLowering().getSectionForFunctionDescriptor( +          &MF.getFunction(), TM)); +  FnDescSec->setAlignment(Align(Subtarget->isPPC64() ? 8 : 4)); + +  CurrentFnDescSym = FnDescSec->getQualNameSymbol();    return AsmPrinter::SetupMachineFunction(MF);  } @@ -1603,31 +1662,20 @@ void PPCAIXAsmPrinter::ValidateGV(const GlobalVariable *GV) {      report_fatal_error("COMDAT not yet supported by AIX.");  } -const MCExpr *PPCAIXAsmPrinter::lowerConstant(const Constant *CV) { -  if (const Function *F = dyn_cast<Function>(CV)) { -    MCSymbolXCOFF *FSym = cast<MCSymbolXCOFF>(getSymbol(F)); -    if (!FSym->hasContainingCsect()) { -      const XCOFF::StorageClass SC = -          F->isDeclaration() -              ? TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(F) -              : XCOFF::C_HIDEXT; -      MCSectionXCOFF *Csect = OutStreamer->getContext().getXCOFFSection( -          FSym->getName(), XCOFF::XMC_DS, -          F->isDeclaration() ? XCOFF::XTY_ER : XCOFF::XTY_SD, SC, -          SectionKind::getData()); -      FSym->setContainingCsect(Csect); -    } -    return MCSymbolRefExpr::create( -        FSym->getContainingCsect()->getQualNameSymbol(), OutContext); -  } -  return PPCAsmPrinter::lowerConstant(CV); +static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV) { +  return StringSwitch<bool>(GV->getName()) +      .Cases("llvm.global_ctors", "llvm.global_dtors", true) +      .Default(false);  } -void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { +void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {    ValidateGV(GV); -  // External global variables are already handled. -  if (!GV->hasInitializer()) +  // TODO: Update the handling of global arrays for static init when we support +  // the ".ref" directive. +  // Otherwise, we can skip these arrays, because the AIX linker collects +  // static init functions simply based on their name. +  if (isSpecialLLVMGlobalArrayForStaticInit(GV))      return;    // Create the symbol, set its storage class. @@ -1635,156 +1683,133 @@ void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {    GVSym->setStorageClass(        TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV)); +  if (GV->isDeclarationForLinker()) { +    emitLinkage(GV, GVSym); +    return; +  } +    SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM); -  if ((!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly()) || -      GVKind.isMergeable2ByteCString() || GVKind.isMergeable4ByteCString()) +  if (!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly())      report_fatal_error("Encountered a global variable kind that is "                         "not supported yet."); -  // Create the containing csect and switch to it.    MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(        getObjFileLowering().SectionForGlobal(GV, GVKind, TM)); + +  // Switch to the containing csect.    OutStreamer->SwitchSection(Csect); -  GVSym->setContainingCsect(Csect);    const DataLayout &DL = GV->getParent()->getDataLayout();    // Handle common symbols.    if (GVKind.isCommon() || GVKind.isBSSLocal()) { -    unsigned Align = -      GV->getAlignment() ? GV->getAlignment() : DL.getPreferredAlignment(GV); +    Align Alignment = GV->getAlign().getValueOr(DL.getPreferredAlign(GV));      uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType());      if (GVKind.isBSSLocal()) -      OutStreamer->EmitXCOFFLocalCommonSymbol( -          GVSym, Size, Csect->getQualNameSymbol(), Align); +      OutStreamer->emitXCOFFLocalCommonSymbol( +          OutContext.getOrCreateSymbol(GVSym->getUnqualifiedName()), Size, +          GVSym, Alignment.value());      else -      OutStreamer->EmitCommonSymbol(Csect->getQualNameSymbol(), Size, Align); +      OutStreamer->emitCommonSymbol(GVSym, Size, Alignment.value());      return;    }    MCSymbol *EmittedInitSym = GVSym; -  EmitLinkage(GV, EmittedInitSym); -  EmitAlignment(getGVAlignment(GV, DL), GV); -  OutStreamer->EmitLabel(EmittedInitSym); -  EmitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer()); +  emitLinkage(GV, EmittedInitSym); +  emitAlignment(getGVAlignment(GV, DL), GV); +  OutStreamer->emitLabel(EmittedInitSym); +  emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer());  } -void PPCAIXAsmPrinter::EmitFunctionDescriptor() { +void PPCAIXAsmPrinter::emitFunctionDescriptor() {    const DataLayout &DL = getDataLayout();    const unsigned PointerSize = DL.getPointerSizeInBits() == 64 ? 8 : 4;    MCSectionSubPair Current = OutStreamer->getCurrentSection();    // Emit function descriptor.    OutStreamer->SwitchSection( -      cast<MCSymbolXCOFF>(CurrentFnDescSym)->getContainingCsect()); -  OutStreamer->EmitLabel(CurrentFnDescSym); +      cast<MCSymbolXCOFF>(CurrentFnDescSym)->getRepresentedCsect());    // Emit function entry point address. -  OutStreamer->EmitValue(MCSymbolRefExpr::create(CurrentFnSym, OutContext), +  OutStreamer->emitValue(MCSymbolRefExpr::create(CurrentFnSym, OutContext),                           PointerSize);    // Emit TOC base address. -  const MCSectionXCOFF *TOCBaseSec = OutStreamer->getContext().getXCOFFSection( -      StringRef("TOC"), XCOFF::XMC_TC0, XCOFF::XTY_SD, XCOFF::C_HIDEXT, -      SectionKind::getData()); -  const MCSymbol *TOCBaseSym = TOCBaseSec->getQualNameSymbol(); -  OutStreamer->EmitValue(MCSymbolRefExpr::create(TOCBaseSym, OutContext), +  const MCSymbol *TOCBaseSym = +      cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection()) +          ->getQualNameSymbol(); +  OutStreamer->emitValue(MCSymbolRefExpr::create(TOCBaseSym, OutContext),                           PointerSize);    // Emit a null environment pointer. -  OutStreamer->EmitIntValue(0, PointerSize); +  OutStreamer->emitIntValue(0, PointerSize);    OutStreamer->SwitchSection(Current.first, Current.second);  } -void PPCAIXAsmPrinter::EmitEndOfAsmFile(Module &M) { +void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {    // If there are no functions in this module, we will never need to reference    // the TOC base.    if (M.empty())      return; -  // Emit TOC base. -  MCSectionXCOFF *TOCBaseSection = OutStreamer->getContext().getXCOFFSection( -      StringRef("TOC"), XCOFF::XMC_TC0, XCOFF::XTY_SD, XCOFF::C_HIDEXT, -      SectionKind::getData()); -  // The TOC-base always has 0 size, but 4 byte alignment. -  TOCBaseSection->setAlignment(Align(4));    // Switch to section to emit TOC base. -  OutStreamer->SwitchSection(TOCBaseSection); +  OutStreamer->SwitchSection(getObjFileLowering().getTOCBaseSection()); -  PPCTargetStreamer &TS = -      static_cast<PPCTargetStreamer &>(*OutStreamer->getTargetStreamer()); +  PPCTargetStreamer *TS = +      static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer()); + +  const unsigned EntryByteSize = Subtarget->isPPC64() ? 8 : 4; +  const unsigned TOCEntriesByteSize = TOC.size() * EntryByteSize; +  // TODO: If TOC entries' size is larger than 32768, then we run out of +  // positive displacement to reach the TOC entry. We need to decide how to +  // handle entries' size larger than that later. +  if (TOCEntriesByteSize > 32767) { +    report_fatal_error("Handling of TOC entry displacement larger than 32767 " +                       "is not yet implemented."); +  }    for (auto &I : TOC) {      // Setup the csect for the current TC entry. -    MCSectionXCOFF *TCEntry = OutStreamer->getContext().getXCOFFSection( -        cast<MCSymbolXCOFF>(I.first)->getUnqualifiedName(), XCOFF::XMC_TC, -        XCOFF::XTY_SD, XCOFF::C_HIDEXT, SectionKind::getData()); -    cast<MCSymbolXCOFF>(I.second)->setContainingCsect(TCEntry); +    MCSectionXCOFF *TCEntry = cast<MCSectionXCOFF>( +        getObjFileLowering().getSectionForTOCEntry(I.first));      OutStreamer->SwitchSection(TCEntry); -    OutStreamer->EmitLabel(I.second); -    TS.emitTCEntry(*I.first); +    OutStreamer->emitLabel(I.second); +    if (TS != nullptr) +      TS->emitTCEntry(*I.first);    }  } -MCSymbol * -PPCAIXAsmPrinter::getMCSymbolForTOCPseudoMO(const MachineOperand &MO) { -  const GlobalObject *GO = nullptr; - -  // If the MO is a function or certain kind of globals, we want to make sure to -  // refer to the csect symbol, otherwise we can just do the default handling. -  if (MO.getType() != MachineOperand::MO_GlobalAddress || -      !(GO = dyn_cast<const GlobalObject>(MO.getGlobal()))) -    return PPCAsmPrinter::getMCSymbolForTOCPseudoMO(MO); - -  // Do an early error check for globals we don't support. This will go away -  // eventually. -  const auto *GV = dyn_cast<const GlobalVariable>(GO); -  if (GV) { -    ValidateGV(GV); -  } +bool PPCAIXAsmPrinter::doInitialization(Module &M) { +  if (M.alias_size() > 0u) +    report_fatal_error( +        "module has aliases, which LLVM does not yet support for AIX"); -  MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(getSymbol(GO)); - -  // If the global object is a global variable without initializer or is a -  // declaration of a function, then XSym is an external referenced symbol. -  // Hence we may need to explictly create a MCSectionXCOFF for it so that we -  // can return its symbol later. -  if (GO->isDeclaration()) { -    if (!XSym->hasContainingCsect()) { -      // Make sure the storage class is set. -      const XCOFF::StorageClass SC = -          TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GO); -      XSym->setStorageClass(SC); - -      MCSectionXCOFF *Csect = OutStreamer->getContext().getXCOFFSection( -          XSym->getName(), isa<Function>(GO) ? XCOFF::XMC_DS : XCOFF::XMC_UA, -          XCOFF::XTY_ER, SC, SectionKind::getMetadata()); -      XSym->setContainingCsect(Csect); -    } +  const bool Result = PPCAsmPrinter::doInitialization(M); -    return XSym->getContainingCsect()->getQualNameSymbol(); -  } +  auto setCsectAlignment = [this](const GlobalObject *GO) { +    // Declarations have 0 alignment which is set by default. +    if (GO->isDeclarationForLinker()) +      return; -  // Handle initialized global variables and defined functions. -  SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM); - -  if (GOKind.isText()) { -    // If the MO is a function, we want to make sure to refer to the function -    // descriptor csect. -    return OutStreamer->getContext() -        .getXCOFFSection(XSym->getName(), XCOFF::XMC_DS, XCOFF::XTY_SD, -                         XCOFF::C_HIDEXT, SectionKind::getData()) -        ->getQualNameSymbol(); -  } else if (GOKind.isCommon() || GOKind.isBSSLocal()) { -    // If the operand is a common then we should refer to the csect symbol. -    return cast<MCSectionXCOFF>( -               getObjFileLowering().SectionForGlobal(GO, GOKind, TM)) -        ->getQualNameSymbol(); -  } +    SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM); +    MCSectionXCOFF *Csect = cast<MCSectionXCOFF>( +        getObjFileLowering().SectionForGlobal(GO, GOKind, TM)); + +    Align GOAlign = getGVAlignment(GO, GO->getParent()->getDataLayout()); +    if (GOAlign > Csect->getAlignment()) +      Csect->setAlignment(GOAlign); +  }; + +  // We need to know, up front, the alignment of csects for the assembly path, +  // because once a .csect directive gets emitted, we could not change the +  // alignment value on it. +  for (const auto &G : M.globals()) +    setCsectAlignment(&G); + +  for (const auto &F : M) +    setCsectAlignment(&F); -  // Other global variables are refered to by labels inside of a single csect, -  // so refer to the label directly. -  return getSymbol(GV); +  return Result;  }  /// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code  | 
