xref: /openbsd-src/gnu/llvm/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp (revision a96b36398fcfb4953e8190127da8bf074c7552f1)
109467b48Spatrick //===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly ------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file contains a printer that converts from our internal representation
1009467b48Spatrick // of machine-dependent LLVM code to PowerPC assembly language. This printer is
1109467b48Spatrick // the output mechanism used by `llc'.
1209467b48Spatrick //
1309467b48Spatrick // Documentation at http://developer.apple.com/documentation/DeveloperTools/
1409467b48Spatrick // Reference/Assembler/ASMIntroduction/chapter_1_section_1.html
1509467b48Spatrick //
1609467b48Spatrick //===----------------------------------------------------------------------===//
1709467b48Spatrick 
1809467b48Spatrick #include "MCTargetDesc/PPCInstPrinter.h"
1909467b48Spatrick #include "MCTargetDesc/PPCMCExpr.h"
2009467b48Spatrick #include "MCTargetDesc/PPCMCTargetDesc.h"
2109467b48Spatrick #include "MCTargetDesc/PPCPredicates.h"
2209467b48Spatrick #include "PPC.h"
2309467b48Spatrick #include "PPCInstrInfo.h"
2409467b48Spatrick #include "PPCMachineFunctionInfo.h"
2509467b48Spatrick #include "PPCSubtarget.h"
2609467b48Spatrick #include "PPCTargetMachine.h"
2709467b48Spatrick #include "PPCTargetStreamer.h"
2809467b48Spatrick #include "TargetInfo/PowerPCTargetInfo.h"
2909467b48Spatrick #include "llvm/ADT/MapVector.h"
30a0747c9fSpatrick #include "llvm/ADT/SmallPtrSet.h"
3109467b48Spatrick #include "llvm/ADT/StringRef.h"
3209467b48Spatrick #include "llvm/ADT/Triple.h"
3309467b48Spatrick #include "llvm/ADT/Twine.h"
3409467b48Spatrick #include "llvm/BinaryFormat/ELF.h"
3509467b48Spatrick #include "llvm/CodeGen/AsmPrinter.h"
3609467b48Spatrick #include "llvm/CodeGen/MachineBasicBlock.h"
37*a96b3639Srobert #include "llvm/CodeGen/MachineFrameInfo.h"
3809467b48Spatrick #include "llvm/CodeGen/MachineFunction.h"
3909467b48Spatrick #include "llvm/CodeGen/MachineInstr.h"
4009467b48Spatrick #include "llvm/CodeGen/MachineModuleInfoImpls.h"
4109467b48Spatrick #include "llvm/CodeGen/MachineOperand.h"
4209467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
4309467b48Spatrick #include "llvm/CodeGen/StackMaps.h"
4409467b48Spatrick #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
4509467b48Spatrick #include "llvm/IR/DataLayout.h"
4609467b48Spatrick #include "llvm/IR/GlobalValue.h"
4709467b48Spatrick #include "llvm/IR/GlobalVariable.h"
4809467b48Spatrick #include "llvm/IR/Module.h"
4909467b48Spatrick #include "llvm/MC/MCAsmInfo.h"
5009467b48Spatrick #include "llvm/MC/MCContext.h"
51a0747c9fSpatrick #include "llvm/MC/MCDirectives.h"
5209467b48Spatrick #include "llvm/MC/MCExpr.h"
5309467b48Spatrick #include "llvm/MC/MCInst.h"
5409467b48Spatrick #include "llvm/MC/MCInstBuilder.h"
5509467b48Spatrick #include "llvm/MC/MCSectionELF.h"
5609467b48Spatrick #include "llvm/MC/MCSectionXCOFF.h"
5709467b48Spatrick #include "llvm/MC/MCStreamer.h"
5809467b48Spatrick #include "llvm/MC/MCSymbol.h"
5909467b48Spatrick #include "llvm/MC/MCSymbolELF.h"
6009467b48Spatrick #include "llvm/MC/MCSymbolXCOFF.h"
6109467b48Spatrick #include "llvm/MC/SectionKind.h"
62*a96b3639Srobert #include "llvm/MC/TargetRegistry.h"
6309467b48Spatrick #include "llvm/Support/Casting.h"
6409467b48Spatrick #include "llvm/Support/CodeGen.h"
6509467b48Spatrick #include "llvm/Support/Debug.h"
66a0747c9fSpatrick #include "llvm/Support/Error.h"
6709467b48Spatrick #include "llvm/Support/ErrorHandling.h"
68a0747c9fSpatrick #include "llvm/Support/Process.h"
6909467b48Spatrick #include "llvm/Support/raw_ostream.h"
7009467b48Spatrick #include "llvm/Target/TargetMachine.h"
71a0747c9fSpatrick #include "llvm/Transforms/Utils/ModuleUtils.h"
7209467b48Spatrick #include <algorithm>
7309467b48Spatrick #include <cassert>
7409467b48Spatrick #include <cstdint>
7509467b48Spatrick #include <memory>
7609467b48Spatrick #include <new>
7709467b48Spatrick 
7809467b48Spatrick using namespace llvm;
79a0747c9fSpatrick using namespace llvm::XCOFF;
8009467b48Spatrick 
8109467b48Spatrick #define DEBUG_TYPE "asmprinter"
8209467b48Spatrick 
83a0747c9fSpatrick static cl::opt<bool> EnableSSPCanaryBitInTB(
84a0747c9fSpatrick     "aix-ssp-tb-bit", cl::init(false),
85a0747c9fSpatrick     cl::desc("Enable Passing SSP Canary info in Trackback on AIX"), cl::Hidden);
86a0747c9fSpatrick 
87a0747c9fSpatrick // Specialize DenseMapInfo to allow
88a0747c9fSpatrick // std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind> in DenseMap.
89a0747c9fSpatrick // This specialization is needed here because that type is used as keys in the
90a0747c9fSpatrick // map representing TOC entries.
91a0747c9fSpatrick namespace llvm {
92a0747c9fSpatrick template <>
93a0747c9fSpatrick struct DenseMapInfo<std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>> {
94a0747c9fSpatrick   using TOCKey = std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>;
95a0747c9fSpatrick 
getEmptyKeyllvm::DenseMapInfo96a0747c9fSpatrick   static inline TOCKey getEmptyKey() {
97a0747c9fSpatrick     return {nullptr, MCSymbolRefExpr::VariantKind::VK_None};
98a0747c9fSpatrick   }
getTombstoneKeyllvm::DenseMapInfo99a0747c9fSpatrick   static inline TOCKey getTombstoneKey() {
100a0747c9fSpatrick     return {nullptr, MCSymbolRefExpr::VariantKind::VK_Invalid};
101a0747c9fSpatrick   }
getHashValuellvm::DenseMapInfo102a0747c9fSpatrick   static unsigned getHashValue(const TOCKey &PairVal) {
103a0747c9fSpatrick     return detail::combineHashValue(
104a0747c9fSpatrick         DenseMapInfo<const MCSymbol *>::getHashValue(PairVal.first),
105a0747c9fSpatrick         DenseMapInfo<int>::getHashValue(PairVal.second));
106a0747c9fSpatrick   }
isEqualllvm::DenseMapInfo107a0747c9fSpatrick   static bool isEqual(const TOCKey &A, const TOCKey &B) { return A == B; }
108a0747c9fSpatrick };
109a0747c9fSpatrick } // end namespace llvm
110a0747c9fSpatrick 
11109467b48Spatrick namespace {
11209467b48Spatrick 
113*a96b3639Srobert enum {
114*a96b3639Srobert   // GNU attribute tags for PowerPC ABI
115*a96b3639Srobert   Tag_GNU_Power_ABI_FP = 4,
116*a96b3639Srobert   Tag_GNU_Power_ABI_Vector = 8,
117*a96b3639Srobert   Tag_GNU_Power_ABI_Struct_Return = 12,
118*a96b3639Srobert 
119*a96b3639Srobert   // GNU attribute values for PowerPC float ABI, as combination of two parts
120*a96b3639Srobert   Val_GNU_Power_ABI_NoFloat = 0b00,
121*a96b3639Srobert   Val_GNU_Power_ABI_HardFloat_DP = 0b01,
122*a96b3639Srobert   Val_GNU_Power_ABI_SoftFloat_DP = 0b10,
123*a96b3639Srobert   Val_GNU_Power_ABI_HardFloat_SP = 0b11,
124*a96b3639Srobert 
125*a96b3639Srobert   Val_GNU_Power_ABI_LDBL_IBM128 = 0b0100,
126*a96b3639Srobert   Val_GNU_Power_ABI_LDBL_64 = 0b1000,
127*a96b3639Srobert   Val_GNU_Power_ABI_LDBL_IEEE128 = 0b1100,
128*a96b3639Srobert };
129*a96b3639Srobert 
13009467b48Spatrick class PPCAsmPrinter : public AsmPrinter {
13109467b48Spatrick protected:
132a0747c9fSpatrick   // For TLS on AIX, we need to be able to identify TOC entries of specific
133a0747c9fSpatrick   // VariantKind so we can add the right relocations when we generate the
134a0747c9fSpatrick   // entries. So each entry is represented by a pair of MCSymbol and
135a0747c9fSpatrick   // VariantKind. For example, we need to be able to identify the following
136a0747c9fSpatrick   // entry as a TLSGD entry so we can add the @m relocation:
137a0747c9fSpatrick   //   .tc .i[TC],i[TL]@m
138a0747c9fSpatrick   // By default, VK_None is used for the VariantKind.
139a0747c9fSpatrick   MapVector<std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>,
140a0747c9fSpatrick             MCSymbol *>
141a0747c9fSpatrick       TOC;
14209467b48Spatrick   const PPCSubtarget *Subtarget = nullptr;
14309467b48Spatrick 
14409467b48Spatrick public:
PPCAsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)14509467b48Spatrick   explicit PPCAsmPrinter(TargetMachine &TM,
14609467b48Spatrick                          std::unique_ptr<MCStreamer> Streamer)
147*a96b3639Srobert       : AsmPrinter(TM, std::move(Streamer)) {}
14809467b48Spatrick 
getPassName() const14909467b48Spatrick   StringRef getPassName() const override { return "PowerPC Assembly Printer"; }
15009467b48Spatrick 
151a0747c9fSpatrick   MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym,
152a0747c9fSpatrick                                    MCSymbolRefExpr::VariantKind Kind =
153a0747c9fSpatrick                                        MCSymbolRefExpr::VariantKind::VK_None);
15409467b48Spatrick 
doInitialization(Module & M)15509467b48Spatrick   bool doInitialization(Module &M) override {
15609467b48Spatrick     if (!TOC.empty())
15709467b48Spatrick       TOC.clear();
15809467b48Spatrick     return AsmPrinter::doInitialization(M);
15909467b48Spatrick   }
16009467b48Spatrick 
161adae0cfdSpatrick   void emitInstruction(const MachineInstr *MI) override;
16209467b48Spatrick 
16309467b48Spatrick   /// This function is for PrintAsmOperand and PrintAsmMemoryOperand,
16409467b48Spatrick   /// invoked by EmitMSInlineAsmStr and EmitGCCInlineAsmStr only.
16509467b48Spatrick   /// The \p MI would be INLINEASM ONLY.
16609467b48Spatrick   void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
16709467b48Spatrick 
16809467b48Spatrick   void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;
16909467b48Spatrick   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
17009467b48Spatrick                        const char *ExtraCode, raw_ostream &O) override;
17109467b48Spatrick   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
17209467b48Spatrick                              const char *ExtraCode, raw_ostream &O) override;
17309467b48Spatrick 
17409467b48Spatrick   void LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI);
17509467b48Spatrick   void LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI);
17609467b48Spatrick   void EmitTlsCall(const MachineInstr *MI, MCSymbolRefExpr::VariantKind VK);
runOnMachineFunction(MachineFunction & MF)17709467b48Spatrick   bool runOnMachineFunction(MachineFunction &MF) override {
17809467b48Spatrick     Subtarget = &MF.getSubtarget<PPCSubtarget>();
17909467b48Spatrick     bool Changed = AsmPrinter::runOnMachineFunction(MF);
18009467b48Spatrick     emitXRayTable();
18109467b48Spatrick     return Changed;
18209467b48Spatrick   }
18309467b48Spatrick };
18409467b48Spatrick 
18509467b48Spatrick /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux
18609467b48Spatrick class PPCLinuxAsmPrinter : public PPCAsmPrinter {
18709467b48Spatrick public:
PPCLinuxAsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)18809467b48Spatrick   explicit PPCLinuxAsmPrinter(TargetMachine &TM,
18909467b48Spatrick                               std::unique_ptr<MCStreamer> Streamer)
19009467b48Spatrick       : PPCAsmPrinter(TM, std::move(Streamer)) {}
19109467b48Spatrick 
getPassName() const19209467b48Spatrick   StringRef getPassName() const override {
19309467b48Spatrick     return "Linux PPC Assembly Printer";
19409467b48Spatrick   }
19509467b48Spatrick 
196*a96b3639Srobert   void emitGNUAttributes(Module &M);
197*a96b3639Srobert 
198adae0cfdSpatrick   void emitStartOfAsmFile(Module &M) override;
199adae0cfdSpatrick   void emitEndOfAsmFile(Module &) override;
20009467b48Spatrick 
201adae0cfdSpatrick   void emitFunctionEntryLabel() override;
20209467b48Spatrick 
203adae0cfdSpatrick   void emitFunctionBodyStart() override;
204adae0cfdSpatrick   void emitFunctionBodyEnd() override;
205adae0cfdSpatrick   void emitInstruction(const MachineInstr *MI) override;
20609467b48Spatrick };
20709467b48Spatrick 
20809467b48Spatrick class PPCAIXAsmPrinter : public PPCAsmPrinter {
20909467b48Spatrick private:
210a0747c9fSpatrick   /// Symbols lowered from ExternalSymbolSDNodes, we will need to emit extern
211a0747c9fSpatrick   /// linkage for them in AIX.
212a0747c9fSpatrick   SmallPtrSet<MCSymbol *, 8> ExtSymSDNodeSymbols;
213a0747c9fSpatrick 
214a0747c9fSpatrick   /// A format indicator and unique trailing identifier to form part of the
215a0747c9fSpatrick   /// sinit/sterm function names.
216a0747c9fSpatrick   std::string FormatIndicatorAndUniqueModId;
217a0747c9fSpatrick 
218a0747c9fSpatrick   // Record a list of GlobalAlias associated with a GlobalObject.
219a0747c9fSpatrick   // This is used for AIX's extra-label-at-definition aliasing strategy.
220a0747c9fSpatrick   DenseMap<const GlobalObject *, SmallVector<const GlobalAlias *, 1>>
221a0747c9fSpatrick       GOAliasMap;
222a0747c9fSpatrick 
223a0747c9fSpatrick   uint16_t getNumberOfVRSaved();
224a0747c9fSpatrick   void emitTracebackTable();
225a0747c9fSpatrick 
226a0747c9fSpatrick   SmallVector<const GlobalVariable *, 8> TOCDataGlobalVars;
227a0747c9fSpatrick 
228a0747c9fSpatrick   void emitGlobalVariableHelper(const GlobalVariable *);
22909467b48Spatrick 
230*a96b3639Srobert   // Get the offset of an alias based on its AliaseeObject.
231*a96b3639Srobert   uint64_t getAliasOffset(const Constant *C);
232*a96b3639Srobert 
23309467b48Spatrick public:
PPCAIXAsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)23409467b48Spatrick   PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
235adae0cfdSpatrick       : PPCAsmPrinter(TM, std::move(Streamer)) {
236adae0cfdSpatrick     if (MAI->isLittleEndian())
237adae0cfdSpatrick       report_fatal_error(
238adae0cfdSpatrick           "cannot create AIX PPC Assembly Printer for a little-endian target");
239adae0cfdSpatrick   }
24009467b48Spatrick 
getPassName() const24109467b48Spatrick   StringRef getPassName() const override { return "AIX PPC Assembly Printer"; }
24209467b48Spatrick 
243adae0cfdSpatrick   bool doInitialization(Module &M) override;
244adae0cfdSpatrick 
245a0747c9fSpatrick   void emitXXStructorList(const DataLayout &DL, const Constant *List,
246a0747c9fSpatrick                           bool IsCtor) override;
247a0747c9fSpatrick 
24809467b48Spatrick   void SetupMachineFunction(MachineFunction &MF) override;
24909467b48Spatrick 
250adae0cfdSpatrick   void emitGlobalVariable(const GlobalVariable *GV) override;
25109467b48Spatrick 
252adae0cfdSpatrick   void emitFunctionDescriptor() override;
25309467b48Spatrick 
254a0747c9fSpatrick   void emitFunctionEntryLabel() override;
255a0747c9fSpatrick 
256a0747c9fSpatrick   void emitFunctionBodyEnd() override;
257a0747c9fSpatrick 
258*a96b3639Srobert   void emitPGORefs();
259*a96b3639Srobert 
260adae0cfdSpatrick   void emitEndOfAsmFile(Module &) override;
26109467b48Spatrick 
262adae0cfdSpatrick   void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override;
263a0747c9fSpatrick 
264a0747c9fSpatrick   void emitInstruction(const MachineInstr *MI) override;
265a0747c9fSpatrick 
266a0747c9fSpatrick   bool doFinalization(Module &M) override;
267a0747c9fSpatrick 
268a0747c9fSpatrick   void emitTTypeReference(const GlobalValue *GV, unsigned Encoding) override;
26909467b48Spatrick };
27009467b48Spatrick 
27109467b48Spatrick } // end anonymous namespace
27209467b48Spatrick 
PrintSymbolOperand(const MachineOperand & MO,raw_ostream & O)27309467b48Spatrick void PPCAsmPrinter::PrintSymbolOperand(const MachineOperand &MO,
27409467b48Spatrick                                        raw_ostream &O) {
27509467b48Spatrick   // Computing the address of a global symbol, not calling it.
27609467b48Spatrick   const GlobalValue *GV = MO.getGlobal();
277adae0cfdSpatrick   getSymbol(GV)->print(O, MAI);
27809467b48Spatrick   printOffset(MO.getOffset(), O);
27909467b48Spatrick }
28009467b48Spatrick 
printOperand(const MachineInstr * MI,unsigned OpNo,raw_ostream & O)28109467b48Spatrick void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
28209467b48Spatrick                                  raw_ostream &O) {
28309467b48Spatrick   const DataLayout &DL = getDataLayout();
28409467b48Spatrick   const MachineOperand &MO = MI->getOperand(OpNo);
28509467b48Spatrick 
28609467b48Spatrick   switch (MO.getType()) {
28709467b48Spatrick   case MachineOperand::MO_Register: {
28809467b48Spatrick     // The MI is INLINEASM ONLY and UseVSXReg is always false.
28909467b48Spatrick     const char *RegName = PPCInstPrinter::getRegisterName(MO.getReg());
29009467b48Spatrick 
29109467b48Spatrick     // Linux assembler (Others?) does not take register mnemonics.
29209467b48Spatrick     // FIXME - What about special registers used in mfspr/mtspr?
293adae0cfdSpatrick     O << PPCRegisterInfo::stripRegisterPrefix(RegName);
29409467b48Spatrick     return;
29509467b48Spatrick   }
29609467b48Spatrick   case MachineOperand::MO_Immediate:
29709467b48Spatrick     O << MO.getImm();
29809467b48Spatrick     return;
29909467b48Spatrick 
30009467b48Spatrick   case MachineOperand::MO_MachineBasicBlock:
30109467b48Spatrick     MO.getMBB()->getSymbol()->print(O, MAI);
30209467b48Spatrick     return;
30309467b48Spatrick   case MachineOperand::MO_ConstantPoolIndex:
30409467b48Spatrick     O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
30509467b48Spatrick       << MO.getIndex();
30609467b48Spatrick     return;
30709467b48Spatrick   case MachineOperand::MO_BlockAddress:
30809467b48Spatrick     GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);
30909467b48Spatrick     return;
31009467b48Spatrick   case MachineOperand::MO_GlobalAddress: {
31109467b48Spatrick     PrintSymbolOperand(MO, O);
31209467b48Spatrick     return;
31309467b48Spatrick   }
31409467b48Spatrick 
31509467b48Spatrick   default:
31609467b48Spatrick     O << "<unknown operand type: " << (unsigned)MO.getType() << ">";
31709467b48Spatrick     return;
31809467b48Spatrick   }
31909467b48Spatrick }
32009467b48Spatrick 
32109467b48Spatrick /// PrintAsmOperand - Print out an operand for an inline asm expression.
32209467b48Spatrick ///
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & O)32309467b48Spatrick bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
32409467b48Spatrick                                     const char *ExtraCode, raw_ostream &O) {
32509467b48Spatrick   // Does this asm operand have a single letter operand modifier?
32609467b48Spatrick   if (ExtraCode && ExtraCode[0]) {
32709467b48Spatrick     if (ExtraCode[1] != 0) return true; // Unknown modifier.
32809467b48Spatrick 
32909467b48Spatrick     switch (ExtraCode[0]) {
33009467b48Spatrick     default:
33109467b48Spatrick       // See if this is a generic print operand
33209467b48Spatrick       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
33309467b48Spatrick     case 'L': // Write second word of DImode reference.
33409467b48Spatrick       // Verify that this operand has two consecutive registers.
33509467b48Spatrick       if (!MI->getOperand(OpNo).isReg() ||
33609467b48Spatrick           OpNo+1 == MI->getNumOperands() ||
33709467b48Spatrick           !MI->getOperand(OpNo+1).isReg())
33809467b48Spatrick         return true;
33909467b48Spatrick       ++OpNo;   // Return the high-part.
34009467b48Spatrick       break;
34109467b48Spatrick     case 'I':
34209467b48Spatrick       // Write 'i' if an integer constant, otherwise nothing.  Used to print
34309467b48Spatrick       // addi vs add, etc.
34409467b48Spatrick       if (MI->getOperand(OpNo).isImm())
34509467b48Spatrick         O << "i";
34609467b48Spatrick       return false;
34709467b48Spatrick     case 'x':
34809467b48Spatrick       if(!MI->getOperand(OpNo).isReg())
34909467b48Spatrick         return true;
35009467b48Spatrick       // This operand uses VSX numbering.
35109467b48Spatrick       // If the operand is a VMX register, convert it to a VSX register.
35209467b48Spatrick       Register Reg = MI->getOperand(OpNo).getReg();
35309467b48Spatrick       if (PPCInstrInfo::isVRRegister(Reg))
35409467b48Spatrick         Reg = PPC::VSX32 + (Reg - PPC::V0);
35509467b48Spatrick       else if (PPCInstrInfo::isVFRegister(Reg))
35609467b48Spatrick         Reg = PPC::VSX32 + (Reg - PPC::VF0);
35709467b48Spatrick       const char *RegName;
35809467b48Spatrick       RegName = PPCInstPrinter::getRegisterName(Reg);
35909467b48Spatrick       RegName = PPCRegisterInfo::stripRegisterPrefix(RegName);
36009467b48Spatrick       O << RegName;
36109467b48Spatrick       return false;
36209467b48Spatrick     }
36309467b48Spatrick   }
36409467b48Spatrick 
36509467b48Spatrick   printOperand(MI, OpNo, O);
36609467b48Spatrick   return false;
36709467b48Spatrick }
36809467b48Spatrick 
36909467b48Spatrick // At the moment, all inline asm memory operands are a single register.
37009467b48Spatrick // In any case, the output of this routine should always be just one
37109467b48Spatrick // assembler operand.
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & O)37209467b48Spatrick bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
37309467b48Spatrick                                           const char *ExtraCode,
37409467b48Spatrick                                           raw_ostream &O) {
37509467b48Spatrick   if (ExtraCode && ExtraCode[0]) {
37609467b48Spatrick     if (ExtraCode[1] != 0) return true; // Unknown modifier.
37709467b48Spatrick 
37809467b48Spatrick     switch (ExtraCode[0]) {
37909467b48Spatrick     default: return true;  // Unknown modifier.
3807299aa8dSpatrick     case 'L': // A memory reference to the upper word of a double word op.
3817299aa8dSpatrick       O << getDataLayout().getPointerSize() << "(";
3827299aa8dSpatrick       printOperand(MI, OpNo, O);
3837299aa8dSpatrick       O << ")";
3847299aa8dSpatrick       return false;
38509467b48Spatrick     case 'y': // A memory reference for an X-form instruction
386adae0cfdSpatrick       O << "0, ";
38709467b48Spatrick       printOperand(MI, OpNo, O);
38809467b48Spatrick       return false;
389a0747c9fSpatrick     case 'I':
390a0747c9fSpatrick       // Write 'i' if an integer constant, otherwise nothing.  Used to print
391a0747c9fSpatrick       // addi vs add, etc.
392a0747c9fSpatrick       if (MI->getOperand(OpNo).isImm())
393a0747c9fSpatrick         O << "i";
394a0747c9fSpatrick       return false;
39509467b48Spatrick     case 'U': // Print 'u' for update form.
39609467b48Spatrick     case 'X': // Print 'x' for indexed form.
39709467b48Spatrick       // FIXME: Currently for PowerPC memory operands are always loaded
39809467b48Spatrick       // into a register, so we never get an update or indexed form.
39909467b48Spatrick       // This is bad even for offset forms, since even if we know we
40009467b48Spatrick       // have a value in -16(r1), we will generate a load into r<n>
40109467b48Spatrick       // and then load from 0(r<n>).  Until that issue is fixed,
40209467b48Spatrick       // tolerate 'U' and 'X' but don't output anything.
40309467b48Spatrick       assert(MI->getOperand(OpNo).isReg());
40409467b48Spatrick       return false;
40509467b48Spatrick     }
40609467b48Spatrick   }
40709467b48Spatrick 
40809467b48Spatrick   assert(MI->getOperand(OpNo).isReg());
40909467b48Spatrick   O << "0(";
41009467b48Spatrick   printOperand(MI, OpNo, O);
41109467b48Spatrick   O << ")";
41209467b48Spatrick   return false;
41309467b48Spatrick }
41409467b48Spatrick 
41509467b48Spatrick /// lookUpOrCreateTOCEntry -- Given a symbol, look up whether a TOC entry
41609467b48Spatrick /// exists for it.  If not, create one.  Then return a symbol that references
41709467b48Spatrick /// the TOC entry.
418a0747c9fSpatrick MCSymbol *
lookUpOrCreateTOCEntry(const MCSymbol * Sym,MCSymbolRefExpr::VariantKind Kind)419a0747c9fSpatrick PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym,
420a0747c9fSpatrick                                       MCSymbolRefExpr::VariantKind Kind) {
421a0747c9fSpatrick   MCSymbol *&TOCEntry = TOC[{Sym, Kind}];
42209467b48Spatrick   if (!TOCEntry)
42309467b48Spatrick     TOCEntry = createTempSymbol("C");
42409467b48Spatrick   return TOCEntry;
42509467b48Spatrick }
42609467b48Spatrick 
LowerSTACKMAP(StackMaps & SM,const MachineInstr & MI)42709467b48Spatrick void PPCAsmPrinter::LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI) {
42809467b48Spatrick   unsigned NumNOPBytes = MI.getOperand(1).getImm();
42909467b48Spatrick 
43009467b48Spatrick   auto &Ctx = OutStreamer->getContext();
43109467b48Spatrick   MCSymbol *MILabel = Ctx.createTempSymbol();
432adae0cfdSpatrick   OutStreamer->emitLabel(MILabel);
43309467b48Spatrick 
43409467b48Spatrick   SM.recordStackMap(*MILabel, MI);
43509467b48Spatrick   assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
43609467b48Spatrick 
43709467b48Spatrick   // Scan ahead to trim the shadow.
43809467b48Spatrick   const MachineBasicBlock &MBB = *MI.getParent();
43909467b48Spatrick   MachineBasicBlock::const_iterator MII(MI);
44009467b48Spatrick   ++MII;
44109467b48Spatrick   while (NumNOPBytes > 0) {
44209467b48Spatrick     if (MII == MBB.end() || MII->isCall() ||
44309467b48Spatrick         MII->getOpcode() == PPC::DBG_VALUE ||
44409467b48Spatrick         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
44509467b48Spatrick         MII->getOpcode() == TargetOpcode::STACKMAP)
44609467b48Spatrick       break;
44709467b48Spatrick     ++MII;
44809467b48Spatrick     NumNOPBytes -= 4;
44909467b48Spatrick   }
45009467b48Spatrick 
45109467b48Spatrick   // Emit nops.
45209467b48Spatrick   for (unsigned i = 0; i < NumNOPBytes; i += 4)
45309467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
45409467b48Spatrick }
45509467b48Spatrick 
45609467b48Spatrick // Lower a patchpoint of the form:
45709467b48Spatrick // [<def>], <id>, <numBytes>, <target>, <numArgs>
LowerPATCHPOINT(StackMaps & SM,const MachineInstr & MI)45809467b48Spatrick void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI) {
45909467b48Spatrick   auto &Ctx = OutStreamer->getContext();
46009467b48Spatrick   MCSymbol *MILabel = Ctx.createTempSymbol();
461adae0cfdSpatrick   OutStreamer->emitLabel(MILabel);
46209467b48Spatrick 
46309467b48Spatrick   SM.recordPatchPoint(*MILabel, MI);
46409467b48Spatrick   PatchPointOpers Opers(&MI);
46509467b48Spatrick 
46609467b48Spatrick   unsigned EncodedBytes = 0;
46709467b48Spatrick   const MachineOperand &CalleeMO = Opers.getCallTarget();
46809467b48Spatrick 
46909467b48Spatrick   if (CalleeMO.isImm()) {
47009467b48Spatrick     int64_t CallTarget = CalleeMO.getImm();
47109467b48Spatrick     if (CallTarget) {
47209467b48Spatrick       assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
47309467b48Spatrick              "High 16 bits of call target should be zero.");
47409467b48Spatrick       Register ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
47509467b48Spatrick       EncodedBytes = 0;
47609467b48Spatrick       // Materialize the jump address:
47709467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI8)
47809467b48Spatrick                                       .addReg(ScratchReg)
47909467b48Spatrick                                       .addImm((CallTarget >> 32) & 0xFFFF));
48009467b48Spatrick       ++EncodedBytes;
48109467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::RLDIC)
48209467b48Spatrick                                       .addReg(ScratchReg)
48309467b48Spatrick                                       .addReg(ScratchReg)
48409467b48Spatrick                                       .addImm(32).addImm(16));
48509467b48Spatrick       ++EncodedBytes;
48609467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORIS8)
48709467b48Spatrick                                       .addReg(ScratchReg)
48809467b48Spatrick                                       .addReg(ScratchReg)
48909467b48Spatrick                                       .addImm((CallTarget >> 16) & 0xFFFF));
49009467b48Spatrick       ++EncodedBytes;
49109467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORI8)
49209467b48Spatrick                                       .addReg(ScratchReg)
49309467b48Spatrick                                       .addReg(ScratchReg)
49409467b48Spatrick                                       .addImm(CallTarget & 0xFFFF));
49509467b48Spatrick 
49609467b48Spatrick       // Save the current TOC pointer before the remote call.
49709467b48Spatrick       int TOCSaveOffset = Subtarget->getFrameLowering()->getTOCSaveOffset();
49809467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::STD)
49909467b48Spatrick                                       .addReg(PPC::X2)
50009467b48Spatrick                                       .addImm(TOCSaveOffset)
50109467b48Spatrick                                       .addReg(PPC::X1));
50209467b48Spatrick       ++EncodedBytes;
50309467b48Spatrick 
50409467b48Spatrick       // If we're on ELFv1, then we need to load the actual function pointer
50509467b48Spatrick       // from the function descriptor.
50609467b48Spatrick       if (!Subtarget->isELFv2ABI()) {
50709467b48Spatrick         // Load the new TOC pointer and the function address, but not r11
50809467b48Spatrick         // (needing this is rare, and loading it here would prevent passing it
50909467b48Spatrick         // via a 'nest' parameter.
51009467b48Spatrick         EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
51109467b48Spatrick                                         .addReg(PPC::X2)
51209467b48Spatrick                                         .addImm(8)
51309467b48Spatrick                                         .addReg(ScratchReg));
51409467b48Spatrick         ++EncodedBytes;
51509467b48Spatrick         EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
51609467b48Spatrick                                         .addReg(ScratchReg)
51709467b48Spatrick                                         .addImm(0)
51809467b48Spatrick                                         .addReg(ScratchReg));
51909467b48Spatrick         ++EncodedBytes;
52009467b48Spatrick       }
52109467b48Spatrick 
52209467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTCTR8)
52309467b48Spatrick                                       .addReg(ScratchReg));
52409467b48Spatrick       ++EncodedBytes;
52509467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BCTRL8));
52609467b48Spatrick       ++EncodedBytes;
52709467b48Spatrick 
52809467b48Spatrick       // Restore the TOC pointer after the call.
52909467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
53009467b48Spatrick                                       .addReg(PPC::X2)
53109467b48Spatrick                                       .addImm(TOCSaveOffset)
53209467b48Spatrick                                       .addReg(PPC::X1));
53309467b48Spatrick       ++EncodedBytes;
53409467b48Spatrick     }
53509467b48Spatrick   } else if (CalleeMO.isGlobal()) {
53609467b48Spatrick     const GlobalValue *GValue = CalleeMO.getGlobal();
53709467b48Spatrick     MCSymbol *MOSymbol = getSymbol(GValue);
53809467b48Spatrick     const MCExpr *SymVar = MCSymbolRefExpr::create(MOSymbol, OutContext);
53909467b48Spatrick 
54009467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL8_NOP)
54109467b48Spatrick                                     .addExpr(SymVar));
54209467b48Spatrick     EncodedBytes += 2;
54309467b48Spatrick   }
54409467b48Spatrick 
54509467b48Spatrick   // Each instruction is 4 bytes.
54609467b48Spatrick   EncodedBytes *= 4;
54709467b48Spatrick 
54809467b48Spatrick   // Emit padding.
54909467b48Spatrick   unsigned NumBytes = Opers.getNumPatchBytes();
55009467b48Spatrick   assert(NumBytes >= EncodedBytes &&
55109467b48Spatrick          "Patchpoint can't request size less than the length of a call.");
55209467b48Spatrick   assert((NumBytes - EncodedBytes) % 4 == 0 &&
55309467b48Spatrick          "Invalid number of NOP bytes requested!");
55409467b48Spatrick   for (unsigned i = EncodedBytes; i < NumBytes; i += 4)
55509467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
55609467b48Spatrick }
55709467b48Spatrick 
558a0747c9fSpatrick /// This helper function creates the TlsGetAddr MCSymbol for AIX. We will
559a0747c9fSpatrick /// create the csect and use the qual-name symbol instead of creating just the
560a0747c9fSpatrick /// external symbol.
createMCSymbolForTlsGetAddr(MCContext & Ctx)561a0747c9fSpatrick static MCSymbol *createMCSymbolForTlsGetAddr(MCContext &Ctx) {
562a0747c9fSpatrick   return Ctx
563a0747c9fSpatrick       .getXCOFFSection(".__tls_get_addr", SectionKind::getText(),
564a0747c9fSpatrick                        XCOFF::CsectProperties(XCOFF::XMC_PR, XCOFF::XTY_ER))
565a0747c9fSpatrick       ->getQualNameSymbol();
566a0747c9fSpatrick }
567a0747c9fSpatrick 
56809467b48Spatrick /// EmitTlsCall -- Given a GETtls[ld]ADDR[32] instruction, print a
56909467b48Spatrick /// call to __tls_get_addr to the current output stream.
EmitTlsCall(const MachineInstr * MI,MCSymbolRefExpr::VariantKind VK)57009467b48Spatrick void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,
57109467b48Spatrick                                 MCSymbolRefExpr::VariantKind VK) {
57209467b48Spatrick   MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
573a0747c9fSpatrick   unsigned Opcode = PPC::BL8_NOP_TLS;
574a0747c9fSpatrick 
575a0747c9fSpatrick   assert(MI->getNumOperands() >= 3 && "Expecting at least 3 operands from MI");
576a0747c9fSpatrick   if (MI->getOperand(2).getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG ||
577a0747c9fSpatrick       MI->getOperand(2).getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) {
578a0747c9fSpatrick     Kind = MCSymbolRefExpr::VK_PPC_NOTOC;
579a0747c9fSpatrick     Opcode = PPC::BL8_NOTOC_TLS;
580a0747c9fSpatrick   }
58109467b48Spatrick   const Module *M = MF->getFunction().getParent();
58209467b48Spatrick 
58309467b48Spatrick   assert(MI->getOperand(0).isReg() &&
58409467b48Spatrick          ((Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::X3) ||
58509467b48Spatrick           (!Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::R3)) &&
58609467b48Spatrick          "GETtls[ld]ADDR[32] must define GPR3");
58709467b48Spatrick   assert(MI->getOperand(1).isReg() &&
58809467b48Spatrick          ((Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::X3) ||
58909467b48Spatrick           (!Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::R3)) &&
59009467b48Spatrick          "GETtls[ld]ADDR[32] must read GPR3");
59109467b48Spatrick 
592a0747c9fSpatrick   if (Subtarget->isAIXABI()) {
593a0747c9fSpatrick     // On AIX, the variable offset should already be in R4 and the region handle
594a0747c9fSpatrick     // should already be in R3.
595a0747c9fSpatrick     // For TLSGD, which currently is the only supported access model, we only
596a0747c9fSpatrick     // need to generate an absolute branch to .__tls_get_addr.
597a0747c9fSpatrick     Register VarOffsetReg = Subtarget->isPPC64() ? PPC::X4 : PPC::R4;
598a0747c9fSpatrick     (void)VarOffsetReg;
599a0747c9fSpatrick     assert(MI->getOperand(2).isReg() &&
600a0747c9fSpatrick            MI->getOperand(2).getReg() == VarOffsetReg &&
601a0747c9fSpatrick            "GETtls[ld]ADDR[32] must read GPR4");
602a0747c9fSpatrick     MCSymbol *TlsGetAddr = createMCSymbolForTlsGetAddr(OutContext);
603a0747c9fSpatrick     const MCExpr *TlsRef = MCSymbolRefExpr::create(
604a0747c9fSpatrick         TlsGetAddr, MCSymbolRefExpr::VK_None, OutContext);
605a0747c9fSpatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BLA).addExpr(TlsRef));
606a0747c9fSpatrick     return;
607a0747c9fSpatrick   }
608a0747c9fSpatrick 
609a0747c9fSpatrick   MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol("__tls_get_addr");
610a0747c9fSpatrick 
61109467b48Spatrick   if (Subtarget->is32BitELFABI() && isPositionIndependent())
61209467b48Spatrick     Kind = MCSymbolRefExpr::VK_PLT;
61309467b48Spatrick 
61409467b48Spatrick   const MCExpr *TlsRef =
61509467b48Spatrick     MCSymbolRefExpr::create(TlsGetAddr, Kind, OutContext);
61609467b48Spatrick 
61709467b48Spatrick   // Add 32768 offset to the symbol so we follow up the latest GOT/PLT ABI.
61809467b48Spatrick   if (Kind == MCSymbolRefExpr::VK_PLT && Subtarget->isSecurePlt() &&
61909467b48Spatrick       M->getPICLevel() == PICLevel::BigPIC)
62009467b48Spatrick     TlsRef = MCBinaryExpr::createAdd(
62109467b48Spatrick         TlsRef, MCConstantExpr::create(32768, OutContext), OutContext);
62209467b48Spatrick   const MachineOperand &MO = MI->getOperand(2);
62309467b48Spatrick   const GlobalValue *GValue = MO.getGlobal();
62409467b48Spatrick   MCSymbol *MOSymbol = getSymbol(GValue);
62509467b48Spatrick   const MCExpr *SymVar = MCSymbolRefExpr::create(MOSymbol, VK, OutContext);
62609467b48Spatrick   EmitToStreamer(*OutStreamer,
627a0747c9fSpatrick                  MCInstBuilder(Subtarget->isPPC64() ? Opcode
628a0747c9fSpatrick                                                     : (unsigned)PPC::BL_TLS)
62909467b48Spatrick                      .addExpr(TlsRef)
63009467b48Spatrick                      .addExpr(SymVar));
63109467b48Spatrick }
63209467b48Spatrick 
63309467b48Spatrick /// Map a machine operand for a TOC pseudo-machine instruction to its
63409467b48Spatrick /// corresponding MCSymbol.
getMCSymbolForTOCPseudoMO(const MachineOperand & MO,AsmPrinter & AP)635adae0cfdSpatrick static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO,
636adae0cfdSpatrick                                            AsmPrinter &AP) {
63709467b48Spatrick   switch (MO.getType()) {
63809467b48Spatrick   case MachineOperand::MO_GlobalAddress:
639adae0cfdSpatrick     return AP.getSymbol(MO.getGlobal());
64009467b48Spatrick   case MachineOperand::MO_ConstantPoolIndex:
641adae0cfdSpatrick     return AP.GetCPISymbol(MO.getIndex());
64209467b48Spatrick   case MachineOperand::MO_JumpTableIndex:
643adae0cfdSpatrick     return AP.GetJTISymbol(MO.getIndex());
64409467b48Spatrick   case MachineOperand::MO_BlockAddress:
645adae0cfdSpatrick     return AP.GetBlockAddressSymbol(MO.getBlockAddress());
64609467b48Spatrick   default:
64709467b48Spatrick     llvm_unreachable("Unexpected operand type to get symbol.");
64809467b48Spatrick   }
64909467b48Spatrick }
65009467b48Spatrick 
65109467b48Spatrick /// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to
65209467b48Spatrick /// the current output stream.
65309467b48Spatrick ///
emitInstruction(const MachineInstr * MI)654adae0cfdSpatrick void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
655*a96b3639Srobert   PPC_MC::verifyInstructionPredicates(MI->getOpcode(),
656*a96b3639Srobert                                       getSubtargetInfo().getFeatureBits());
657*a96b3639Srobert 
65809467b48Spatrick   MCInst TmpInst;
65909467b48Spatrick   const bool IsPPC64 = Subtarget->isPPC64();
66009467b48Spatrick   const bool IsAIX = Subtarget->isAIXABI();
66109467b48Spatrick   const Module *M = MF->getFunction().getParent();
66209467b48Spatrick   PICLevel::Level PL = M->getPICLevel();
66309467b48Spatrick 
66409467b48Spatrick #ifndef NDEBUG
66509467b48Spatrick   // Validate that SPE and FPU are mutually exclusive in codegen
66609467b48Spatrick   if (!MI->isInlineAsm()) {
66709467b48Spatrick     for (const MachineOperand &MO: MI->operands()) {
66809467b48Spatrick       if (MO.isReg()) {
66909467b48Spatrick         Register Reg = MO.getReg();
67009467b48Spatrick         if (Subtarget->hasSPE()) {
67109467b48Spatrick           if (PPC::F4RCRegClass.contains(Reg) ||
67209467b48Spatrick               PPC::F8RCRegClass.contains(Reg) ||
67309467b48Spatrick               PPC::VFRCRegClass.contains(Reg) ||
67409467b48Spatrick               PPC::VRRCRegClass.contains(Reg) ||
67509467b48Spatrick               PPC::VSFRCRegClass.contains(Reg) ||
67609467b48Spatrick               PPC::VSSRCRegClass.contains(Reg)
67709467b48Spatrick               )
67809467b48Spatrick             llvm_unreachable("SPE targets cannot have FPRegs!");
67909467b48Spatrick         } else {
68009467b48Spatrick           if (PPC::SPERCRegClass.contains(Reg))
68109467b48Spatrick             llvm_unreachable("SPE register found in FPU-targeted code!");
68209467b48Spatrick         }
68309467b48Spatrick       }
68409467b48Spatrick     }
68509467b48Spatrick   }
68609467b48Spatrick #endif
687a0747c9fSpatrick 
688a0747c9fSpatrick   auto getTOCRelocAdjustedExprForXCOFF = [this](const MCExpr *Expr,
689a0747c9fSpatrick                                                 ptrdiff_t OriginalOffset) {
690a0747c9fSpatrick     // Apply an offset to the TOC-based expression such that the adjusted
691a0747c9fSpatrick     // notional offset from the TOC base (to be encoded into the instruction's D
692a0747c9fSpatrick     // or DS field) is the signed 16-bit truncation of the original notional
693a0747c9fSpatrick     // offset from the TOC base.
694a0747c9fSpatrick     // This is consistent with the treatment used both by XL C/C++ and
695a0747c9fSpatrick     // by AIX ld -r.
696a0747c9fSpatrick     ptrdiff_t Adjustment =
697a0747c9fSpatrick         OriginalOffset - llvm::SignExtend32<16>(OriginalOffset);
698a0747c9fSpatrick     return MCBinaryExpr::createAdd(
699a0747c9fSpatrick         Expr, MCConstantExpr::create(-Adjustment, OutContext), OutContext);
700a0747c9fSpatrick   };
701a0747c9fSpatrick 
702a0747c9fSpatrick   auto getTOCEntryLoadingExprForXCOFF =
703a0747c9fSpatrick       [IsPPC64, getTOCRelocAdjustedExprForXCOFF,
704a0747c9fSpatrick        this](const MCSymbol *MOSymbol, const MCExpr *Expr,
705a0747c9fSpatrick              MCSymbolRefExpr::VariantKind VK =
706a0747c9fSpatrick                  MCSymbolRefExpr::VariantKind::VK_None) -> const MCExpr * {
707a0747c9fSpatrick     const unsigned EntryByteSize = IsPPC64 ? 8 : 4;
708a0747c9fSpatrick     const auto TOCEntryIter = TOC.find({MOSymbol, VK});
709a0747c9fSpatrick     assert(TOCEntryIter != TOC.end() &&
710a0747c9fSpatrick            "Could not find the TOC entry for this symbol.");
711a0747c9fSpatrick     const ptrdiff_t EntryDistanceFromTOCBase =
712a0747c9fSpatrick         (TOCEntryIter - TOC.begin()) * EntryByteSize;
713a0747c9fSpatrick     constexpr int16_t PositiveTOCRange = INT16_MAX;
714a0747c9fSpatrick 
715a0747c9fSpatrick     if (EntryDistanceFromTOCBase > PositiveTOCRange)
716a0747c9fSpatrick       return getTOCRelocAdjustedExprForXCOFF(Expr, EntryDistanceFromTOCBase);
717a0747c9fSpatrick 
718a0747c9fSpatrick     return Expr;
719a0747c9fSpatrick   };
720a0747c9fSpatrick   auto GetVKForMO = [&](const MachineOperand &MO) {
721a0747c9fSpatrick     // For GD TLS access on AIX, we have two TOC entries for the symbol (one for
722a0747c9fSpatrick     // the variable offset and the other for the region handle). They are
723a0747c9fSpatrick     // differentiated by MO_TLSGD_FLAG and MO_TLSGDM_FLAG.
724a0747c9fSpatrick     if (MO.getTargetFlags() & PPCII::MO_TLSGDM_FLAG)
725a0747c9fSpatrick       return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM;
726a0747c9fSpatrick     if (MO.getTargetFlags() & PPCII::MO_TLSGD_FLAG)
727a0747c9fSpatrick       return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD;
728a0747c9fSpatrick     return MCSymbolRefExpr::VariantKind::VK_None;
729a0747c9fSpatrick   };
730a0747c9fSpatrick 
73109467b48Spatrick   // Lower multi-instruction pseudo operations.
73209467b48Spatrick   switch (MI->getOpcode()) {
73309467b48Spatrick   default: break;
73409467b48Spatrick   case TargetOpcode::DBG_VALUE:
73509467b48Spatrick     llvm_unreachable("Should be handled target independently");
73609467b48Spatrick   case TargetOpcode::STACKMAP:
73709467b48Spatrick     return LowerSTACKMAP(SM, *MI);
73809467b48Spatrick   case TargetOpcode::PATCHPOINT:
73909467b48Spatrick     return LowerPATCHPOINT(SM, *MI);
74009467b48Spatrick 
74109467b48Spatrick   case PPC::MoveGOTtoLR: {
74209467b48Spatrick     // Transform %lr = MoveGOTtoLR
74309467b48Spatrick     // Into this: bl _GLOBAL_OFFSET_TABLE_@local-4
74409467b48Spatrick     // _GLOBAL_OFFSET_TABLE_@local-4 (instruction preceding
74509467b48Spatrick     // _GLOBAL_OFFSET_TABLE_) has exactly one instruction:
74609467b48Spatrick     //      blrl
74709467b48Spatrick     // This will return the pointer to _GLOBAL_OFFSET_TABLE_@local
74809467b48Spatrick     MCSymbol *GOTSymbol =
74909467b48Spatrick       OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));
75009467b48Spatrick     const MCExpr *OffsExpr =
75109467b48Spatrick       MCBinaryExpr::createSub(MCSymbolRefExpr::create(GOTSymbol,
75209467b48Spatrick                                                       MCSymbolRefExpr::VK_PPC_LOCAL,
75309467b48Spatrick                                                       OutContext),
75409467b48Spatrick                               MCConstantExpr::create(4, OutContext),
75509467b48Spatrick                               OutContext);
75609467b48Spatrick 
75709467b48Spatrick     // Emit the 'bl'.
75809467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL).addExpr(OffsExpr));
75909467b48Spatrick     return;
76009467b48Spatrick   }
76109467b48Spatrick   case PPC::MovePCtoLR:
76209467b48Spatrick   case PPC::MovePCtoLR8: {
76309467b48Spatrick     // Transform %lr = MovePCtoLR
76409467b48Spatrick     // Into this, where the label is the PIC base:
76509467b48Spatrick     //     bl L1$pb
76609467b48Spatrick     // L1$pb:
76709467b48Spatrick     MCSymbol *PICBase = MF->getPICBaseSymbol();
76809467b48Spatrick 
76909467b48Spatrick     // Emit the 'bl'.
77009467b48Spatrick     EmitToStreamer(*OutStreamer,
77109467b48Spatrick                    MCInstBuilder(PPC::BL)
77209467b48Spatrick                        // FIXME: We would like an efficient form for this, so we
77309467b48Spatrick                        // don't have to do a lot of extra uniquing.
77409467b48Spatrick                        .addExpr(MCSymbolRefExpr::create(PICBase, OutContext)));
77509467b48Spatrick 
77609467b48Spatrick     // Emit the label.
777adae0cfdSpatrick     OutStreamer->emitLabel(PICBase);
77809467b48Spatrick     return;
77909467b48Spatrick   }
78009467b48Spatrick   case PPC::UpdateGBR: {
78109467b48Spatrick     // Transform %rd = UpdateGBR(%rt, %ri)
78209467b48Spatrick     // Into: lwz %rt, .L0$poff - .L0$pb(%ri)
78309467b48Spatrick     //       add %rd, %rt, %ri
78409467b48Spatrick     // or into (if secure plt mode is on):
78509467b48Spatrick     //       addis r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@ha
78609467b48Spatrick     //       addi r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@l
78709467b48Spatrick     // Get the offset from the GOT Base Register to the GOT
788adae0cfdSpatrick     LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
78909467b48Spatrick     if (Subtarget->isSecurePlt() && isPositionIndependent() ) {
79009467b48Spatrick       unsigned PICR = TmpInst.getOperand(0).getReg();
79109467b48Spatrick       MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol(
79209467b48Spatrick           M->getPICLevel() == PICLevel::SmallPIC ? "_GLOBAL_OFFSET_TABLE_"
79309467b48Spatrick                                                  : ".LTOC");
79409467b48Spatrick       const MCExpr *PB =
79509467b48Spatrick           MCSymbolRefExpr::create(MF->getPICBaseSymbol(), OutContext);
79609467b48Spatrick 
79709467b48Spatrick       const MCExpr *DeltaExpr = MCBinaryExpr::createSub(
79809467b48Spatrick           MCSymbolRefExpr::create(BaseSymbol, OutContext), PB, OutContext);
79909467b48Spatrick 
800adae0cfdSpatrick       const MCExpr *DeltaHi = PPCMCExpr::createHa(DeltaExpr, OutContext);
80109467b48Spatrick       EmitToStreamer(
80209467b48Spatrick           *OutStreamer,
80309467b48Spatrick           MCInstBuilder(PPC::ADDIS).addReg(PICR).addReg(PICR).addExpr(DeltaHi));
80409467b48Spatrick 
805adae0cfdSpatrick       const MCExpr *DeltaLo = PPCMCExpr::createLo(DeltaExpr, OutContext);
80609467b48Spatrick       EmitToStreamer(
80709467b48Spatrick           *OutStreamer,
80809467b48Spatrick           MCInstBuilder(PPC::ADDI).addReg(PICR).addReg(PICR).addExpr(DeltaLo));
80909467b48Spatrick       return;
81009467b48Spatrick     } else {
81109467b48Spatrick       MCSymbol *PICOffset =
812adae0cfdSpatrick         MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol(*MF);
81309467b48Spatrick       TmpInst.setOpcode(PPC::LWZ);
81409467b48Spatrick       const MCExpr *Exp =
81509467b48Spatrick         MCSymbolRefExpr::create(PICOffset, MCSymbolRefExpr::VK_None, OutContext);
81609467b48Spatrick       const MCExpr *PB =
81709467b48Spatrick         MCSymbolRefExpr::create(MF->getPICBaseSymbol(),
81809467b48Spatrick                                 MCSymbolRefExpr::VK_None,
81909467b48Spatrick                                 OutContext);
82009467b48Spatrick       const MCOperand TR = TmpInst.getOperand(1);
82109467b48Spatrick       const MCOperand PICR = TmpInst.getOperand(0);
82209467b48Spatrick 
82309467b48Spatrick       // Step 1: lwz %rt, .L$poff - .L$pb(%ri)
82409467b48Spatrick       TmpInst.getOperand(1) =
82509467b48Spatrick           MCOperand::createExpr(MCBinaryExpr::createSub(Exp, PB, OutContext));
82609467b48Spatrick       TmpInst.getOperand(0) = TR;
82709467b48Spatrick       TmpInst.getOperand(2) = PICR;
82809467b48Spatrick       EmitToStreamer(*OutStreamer, TmpInst);
82909467b48Spatrick 
83009467b48Spatrick       TmpInst.setOpcode(PPC::ADD4);
83109467b48Spatrick       TmpInst.getOperand(0) = PICR;
83209467b48Spatrick       TmpInst.getOperand(1) = TR;
83309467b48Spatrick       TmpInst.getOperand(2) = PICR;
83409467b48Spatrick       EmitToStreamer(*OutStreamer, TmpInst);
83509467b48Spatrick       return;
83609467b48Spatrick     }
83709467b48Spatrick   }
838e836804dSmortimer   case PPC::RETGUARD_LOAD_PC: {
839e836804dSmortimer     unsigned DEST = MI->getOperand(0).getReg();
840e836804dSmortimer     unsigned LR  = MI->getOperand(1).getReg();
841e836804dSmortimer     MCSymbol *HereSym = MI->getOperand(2).getMCSymbol();
842e836804dSmortimer 
843e836804dSmortimer     unsigned MTLR = PPC::MTLR;
844e836804dSmortimer     unsigned MFLR = PPC::MFLR;
845e836804dSmortimer     unsigned BL   = PPC::BL;
846e836804dSmortimer     if (Subtarget->isPPC64()) {
847e836804dSmortimer       MTLR = PPC::MTLR8;
848e836804dSmortimer       MFLR = PPC::MFLR8;
849e836804dSmortimer       BL   = PPC::BL8;
850e836804dSmortimer     }
851e836804dSmortimer 
852e836804dSmortimer     // Cache the current LR
853e836804dSmortimer     EmitToStreamer(*OutStreamer, MCInstBuilder(MFLR)
854e836804dSmortimer                                  .addReg(LR));
855e836804dSmortimer 
856e836804dSmortimer     // Create the BL forward
857e836804dSmortimer     const MCExpr *HereExpr = MCSymbolRefExpr::create(HereSym, OutContext);
858e836804dSmortimer     EmitToStreamer(*OutStreamer, MCInstBuilder(BL)
859e836804dSmortimer                                  .addExpr(HereExpr));
860adae0cfdSpatrick     OutStreamer->emitLabel(HereSym);
861e836804dSmortimer 
862e836804dSmortimer     // Grab the result
863e836804dSmortimer     EmitToStreamer(*OutStreamer, MCInstBuilder(MFLR)
864e836804dSmortimer                                  .addReg(DEST));
865e836804dSmortimer     // Restore LR
866e836804dSmortimer     EmitToStreamer(*OutStreamer, MCInstBuilder(MTLR)
867e836804dSmortimer                                  .addReg(LR));
868e836804dSmortimer     return;
869e836804dSmortimer   }
870e836804dSmortimer   case PPC::RETGUARD_LOAD_GOT: {
871e836804dSmortimer     if (Subtarget->isSecurePlt() && isPositionIndependent() ) {
872e836804dSmortimer       StringRef GOTName = (PL == PICLevel::SmallPIC ?
873e836804dSmortimer                                  "_GLOBAL_OFFSET_TABLE_" : ".LTOC");
874e836804dSmortimer       unsigned DEST     = MI->getOperand(0).getReg();
875e836804dSmortimer       unsigned HERE     = MI->getOperand(1).getReg();
876e836804dSmortimer       MCSymbol *HereSym = MI->getOperand(2).getMCSymbol();
877e836804dSmortimer       MCSymbol *GOTSym  = OutContext.getOrCreateSymbol(GOTName);
878e836804dSmortimer       const MCExpr *HereExpr = MCSymbolRefExpr::create(HereSym, OutContext);
879e836804dSmortimer       const MCExpr *GOTExpr  = MCSymbolRefExpr::create(GOTSym, OutContext);
880e836804dSmortimer 
881e836804dSmortimer       // Get offset from Here to GOT
882e836804dSmortimer       const MCExpr *GOTDeltaExpr =
883e836804dSmortimer         MCBinaryExpr::createSub(GOTExpr, HereExpr, OutContext);
884e836804dSmortimer       const MCExpr *GOTDeltaHi =
885adae0cfdSpatrick         PPCMCExpr::createHa(GOTDeltaExpr, OutContext);
886e836804dSmortimer       const MCExpr *GOTDeltaLo =
887adae0cfdSpatrick         PPCMCExpr::createLo(GOTDeltaExpr, OutContext);
888e836804dSmortimer 
889e836804dSmortimer       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
890e836804dSmortimer                                    .addReg(DEST)
891e836804dSmortimer                                    .addReg(HERE)
892e836804dSmortimer                                    .addExpr(GOTDeltaHi));
893e836804dSmortimer       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI)
894e836804dSmortimer                                    .addReg(DEST)
895e836804dSmortimer                                    .addReg(DEST)
896e836804dSmortimer                                    .addExpr(GOTDeltaLo));
897e836804dSmortimer     }
898e836804dSmortimer     return;
899e836804dSmortimer   }
900e836804dSmortimer   case PPC::RETGUARD_LOAD_COOKIE: {
901e836804dSmortimer     unsigned DEST       = MI->getOperand(0).getReg();
902e836804dSmortimer     MCSymbol *CookieSym = getSymbol(MI->getOperand(1).getGlobal());
903e836804dSmortimer     const MCExpr *CookieExprHa = MCSymbolRefExpr::create(
904e836804dSmortimer         CookieSym, MCSymbolRefExpr::VK_PPC_HA, OutContext);
905e836804dSmortimer     const MCExpr *CookieExprLo = MCSymbolRefExpr::create(
906e836804dSmortimer         CookieSym, MCSymbolRefExpr::VK_PPC_LO, OutContext);
907e836804dSmortimer 
908e836804dSmortimer     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LIS)
909e836804dSmortimer                                  .addReg(DEST)
910e836804dSmortimer                                  .addExpr(CookieExprHa));
911e836804dSmortimer     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LWZ)
912e836804dSmortimer                                  .addReg(DEST)
913e836804dSmortimer                                  .addExpr(CookieExprLo)
914e836804dSmortimer                                  .addReg(DEST));
915e836804dSmortimer     return;
916e836804dSmortimer   }
91709467b48Spatrick   case PPC::LWZtoc: {
91809467b48Spatrick     // Transform %rN = LWZtoc @op1, %r2
919adae0cfdSpatrick     LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
92009467b48Spatrick 
92109467b48Spatrick     // Change the opcode to LWZ.
92209467b48Spatrick     TmpInst.setOpcode(PPC::LWZ);
92309467b48Spatrick 
92409467b48Spatrick     const MachineOperand &MO = MI->getOperand(1);
92509467b48Spatrick     assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
92609467b48Spatrick            "Invalid operand for LWZtoc.");
92709467b48Spatrick 
92809467b48Spatrick     // Map the operand to its corresponding MCSymbol.
929adae0cfdSpatrick     const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
93009467b48Spatrick 
93109467b48Spatrick     // Create a reference to the GOT entry for the symbol. The GOT entry will be
93209467b48Spatrick     // synthesized later.
93309467b48Spatrick     if (PL == PICLevel::SmallPIC && !IsAIX) {
93409467b48Spatrick       const MCExpr *Exp =
93509467b48Spatrick         MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_GOT,
93609467b48Spatrick                                 OutContext);
93709467b48Spatrick       TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
93809467b48Spatrick       EmitToStreamer(*OutStreamer, TmpInst);
93909467b48Spatrick       return;
94009467b48Spatrick     }
94109467b48Spatrick 
942a0747c9fSpatrick     MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);
943a0747c9fSpatrick 
94409467b48Spatrick     // Otherwise, use the TOC. 'TOCEntry' is a label used to reference the
94509467b48Spatrick     // storage allocated in the TOC which contains the address of
94609467b48Spatrick     // 'MOSymbol'. Said TOC entry will be synthesized later.
947a0747c9fSpatrick     MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol, VK);
94809467b48Spatrick     const MCExpr *Exp =
94909467b48Spatrick         MCSymbolRefExpr::create(TOCEntry, MCSymbolRefExpr::VK_None, OutContext);
95009467b48Spatrick 
95109467b48Spatrick     // AIX uses the label directly as the lwz displacement operand for
95209467b48Spatrick     // references into the toc section. The displacement value will be generated
95309467b48Spatrick     // relative to the toc-base.
95409467b48Spatrick     if (IsAIX) {
95509467b48Spatrick       assert(
95609467b48Spatrick           TM.getCodeModel() == CodeModel::Small &&
95709467b48Spatrick           "This pseudo should only be selected for 32-bit small code model.");
958a0747c9fSpatrick       Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);
95909467b48Spatrick       TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
960a0747c9fSpatrick 
961a0747c9fSpatrick       // Print MO for better readability
962a0747c9fSpatrick       if (isVerbose())
963*a96b3639Srobert         OutStreamer->getCommentOS() << MO << '\n';
96409467b48Spatrick       EmitToStreamer(*OutStreamer, TmpInst);
96509467b48Spatrick       return;
96609467b48Spatrick     }
96709467b48Spatrick 
96809467b48Spatrick     // Create an explicit subtract expression between the local symbol and
96909467b48Spatrick     // '.LTOC' to manifest the toc-relative offset.
97009467b48Spatrick     const MCExpr *PB = MCSymbolRefExpr::create(
97109467b48Spatrick         OutContext.getOrCreateSymbol(Twine(".LTOC")), OutContext);
97209467b48Spatrick     Exp = MCBinaryExpr::createSub(Exp, PB, OutContext);
97309467b48Spatrick     TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
97409467b48Spatrick     EmitToStreamer(*OutStreamer, TmpInst);
97509467b48Spatrick     return;
97609467b48Spatrick   }
977*a96b3639Srobert   case PPC::ADDItoc:
978*a96b3639Srobert   case PPC::ADDItoc8: {
979a0747c9fSpatrick     assert(IsAIX && TM.getCodeModel() == CodeModel::Small &&
980*a96b3639Srobert            "PseudoOp only valid for small code model AIX");
981a0747c9fSpatrick 
982*a96b3639Srobert     // Transform %rN = ADDItoc/8 @op1, %r2.
983a0747c9fSpatrick     LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
984a0747c9fSpatrick 
985a0747c9fSpatrick     // Change the opcode to load address.
986*a96b3639Srobert     TmpInst.setOpcode((!IsPPC64) ? (PPC::LA) : (PPC::LA8));
987a0747c9fSpatrick 
988a0747c9fSpatrick     const MachineOperand &MO = MI->getOperand(1);
989*a96b3639Srobert     assert(MO.isGlobal() && "Invalid operand for ADDItoc[8].");
990a0747c9fSpatrick 
991a0747c9fSpatrick     // Map the operand to its corresponding MCSymbol.
992a0747c9fSpatrick     const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
993a0747c9fSpatrick 
994a0747c9fSpatrick     const MCExpr *Exp =
995a0747c9fSpatrick         MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_None, OutContext);
996a0747c9fSpatrick 
997a0747c9fSpatrick     TmpInst.getOperand(1) = TmpInst.getOperand(2);
998a0747c9fSpatrick     TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
999a0747c9fSpatrick     EmitToStreamer(*OutStreamer, TmpInst);
1000a0747c9fSpatrick     return;
1001a0747c9fSpatrick   }
100209467b48Spatrick   case PPC::LDtocJTI:
100309467b48Spatrick   case PPC::LDtocCPT:
100409467b48Spatrick   case PPC::LDtocBA:
100509467b48Spatrick   case PPC::LDtoc: {
100609467b48Spatrick     // Transform %x3 = LDtoc @min1, %x2
1007adae0cfdSpatrick     LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
100809467b48Spatrick 
100909467b48Spatrick     // Change the opcode to LD.
101009467b48Spatrick     TmpInst.setOpcode(PPC::LD);
101109467b48Spatrick 
101209467b48Spatrick     const MachineOperand &MO = MI->getOperand(1);
101309467b48Spatrick     assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
101409467b48Spatrick            "Invalid operand!");
101509467b48Spatrick 
1016a0747c9fSpatrick     // Map the operand to its corresponding MCSymbol.
1017a0747c9fSpatrick     const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
1018a0747c9fSpatrick 
1019a0747c9fSpatrick     MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);
1020a0747c9fSpatrick 
102109467b48Spatrick     // Map the machine operand to its corresponding MCSymbol, then map the
102209467b48Spatrick     // global address operand to be a reference to the TOC entry we will
102309467b48Spatrick     // synthesize later.
1024a0747c9fSpatrick     MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol, VK);
102509467b48Spatrick 
1026a0747c9fSpatrick     MCSymbolRefExpr::VariantKind VKExpr =
102709467b48Spatrick         IsAIX ? MCSymbolRefExpr::VK_None : MCSymbolRefExpr::VK_PPC_TOC;
1028a0747c9fSpatrick     const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry, VKExpr, OutContext);
1029a0747c9fSpatrick     TmpInst.getOperand(1) = MCOperand::createExpr(
1030a0747c9fSpatrick         IsAIX ? getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK) : Exp);
1031a0747c9fSpatrick 
1032a0747c9fSpatrick     // Print MO for better readability
1033a0747c9fSpatrick     if (isVerbose() && IsAIX)
1034*a96b3639Srobert       OutStreamer->getCommentOS() << MO << '\n';
103509467b48Spatrick     EmitToStreamer(*OutStreamer, TmpInst);
103609467b48Spatrick     return;
103709467b48Spatrick   }
103809467b48Spatrick   case PPC::ADDIStocHA: {
103909467b48Spatrick     assert((IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large) &&
104009467b48Spatrick            "This pseudo should only be selected for 32-bit large code model on"
104109467b48Spatrick            " AIX.");
104209467b48Spatrick 
104309467b48Spatrick     // Transform %rd = ADDIStocHA %rA, @sym(%r2)
1044adae0cfdSpatrick     LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
104509467b48Spatrick 
104609467b48Spatrick     // Change the opcode to ADDIS.
104709467b48Spatrick     TmpInst.setOpcode(PPC::ADDIS);
104809467b48Spatrick 
104909467b48Spatrick     const MachineOperand &MO = MI->getOperand(2);
105009467b48Spatrick     assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
105109467b48Spatrick            "Invalid operand for ADDIStocHA.");
105209467b48Spatrick 
105309467b48Spatrick     // Map the machine operand to its corresponding MCSymbol.
1054adae0cfdSpatrick     MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
105509467b48Spatrick 
1056a0747c9fSpatrick     MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);
1057a0747c9fSpatrick 
105809467b48Spatrick     // Always use TOC on AIX. Map the global address operand to be a reference
105909467b48Spatrick     // to the TOC entry we will synthesize later. 'TOCEntry' is a label used to
106009467b48Spatrick     // reference the storage allocated in the TOC which contains the address of
106109467b48Spatrick     // 'MOSymbol'.
1062a0747c9fSpatrick     MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol, VK);
106309467b48Spatrick     const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry,
106409467b48Spatrick                                                 MCSymbolRefExpr::VK_PPC_U,
106509467b48Spatrick                                                 OutContext);
106609467b48Spatrick     TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
106709467b48Spatrick     EmitToStreamer(*OutStreamer, TmpInst);
106809467b48Spatrick     return;
106909467b48Spatrick   }
107009467b48Spatrick   case PPC::LWZtocL: {
107109467b48Spatrick     assert(IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large &&
107209467b48Spatrick            "This pseudo should only be selected for 32-bit large code model on"
107309467b48Spatrick            " AIX.");
107409467b48Spatrick 
107509467b48Spatrick     // Transform %rd = LWZtocL @sym, %rs.
1076adae0cfdSpatrick     LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
107709467b48Spatrick 
107809467b48Spatrick     // Change the opcode to lwz.
107909467b48Spatrick     TmpInst.setOpcode(PPC::LWZ);
108009467b48Spatrick 
108109467b48Spatrick     const MachineOperand &MO = MI->getOperand(1);
108209467b48Spatrick     assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
108309467b48Spatrick            "Invalid operand for LWZtocL.");
108409467b48Spatrick 
108509467b48Spatrick     // Map the machine operand to its corresponding MCSymbol.
1086adae0cfdSpatrick     MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
108709467b48Spatrick 
1088a0747c9fSpatrick     MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);
1089a0747c9fSpatrick 
109009467b48Spatrick     // Always use TOC on AIX. Map the global address operand to be a reference
109109467b48Spatrick     // to the TOC entry we will synthesize later. 'TOCEntry' is a label used to
109209467b48Spatrick     // reference the storage allocated in the TOC which contains the address of
109309467b48Spatrick     // 'MOSymbol'.
1094a0747c9fSpatrick     MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol, VK);
109509467b48Spatrick     const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry,
109609467b48Spatrick                                                 MCSymbolRefExpr::VK_PPC_L,
109709467b48Spatrick                                                 OutContext);
109809467b48Spatrick     TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
109909467b48Spatrick     EmitToStreamer(*OutStreamer, TmpInst);
110009467b48Spatrick     return;
110109467b48Spatrick   }
110209467b48Spatrick   case PPC::ADDIStocHA8: {
110309467b48Spatrick     // Transform %xd = ADDIStocHA8 %x2, @sym
1104adae0cfdSpatrick     LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
110509467b48Spatrick 
110609467b48Spatrick     // Change the opcode to ADDIS8. If the global address is the address of
110709467b48Spatrick     // an external symbol, is a jump table address, is a block address, or is a
110809467b48Spatrick     // constant pool index with large code model enabled, then generate a TOC
110909467b48Spatrick     // entry and reference that. Otherwise, reference the symbol directly.
111009467b48Spatrick     TmpInst.setOpcode(PPC::ADDIS8);
111109467b48Spatrick 
111209467b48Spatrick     const MachineOperand &MO = MI->getOperand(2);
111309467b48Spatrick     assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
111409467b48Spatrick            "Invalid operand for ADDIStocHA8!");
111509467b48Spatrick 
1116adae0cfdSpatrick     const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
111709467b48Spatrick 
1118a0747c9fSpatrick     MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);
1119a0747c9fSpatrick 
112009467b48Spatrick     const bool GlobalToc =
112109467b48Spatrick         MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal());
112209467b48Spatrick     if (GlobalToc || MO.isJTI() || MO.isBlockAddress() ||
112309467b48Spatrick         (MO.isCPI() && TM.getCodeModel() == CodeModel::Large))
1124a0747c9fSpatrick       MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, VK);
112509467b48Spatrick 
1126a0747c9fSpatrick     VK = IsAIX ? MCSymbolRefExpr::VK_PPC_U : MCSymbolRefExpr::VK_PPC_TOC_HA;
112709467b48Spatrick 
112809467b48Spatrick     const MCExpr *Exp =
112909467b48Spatrick         MCSymbolRefExpr::create(MOSymbol, VK, OutContext);
113009467b48Spatrick 
113109467b48Spatrick     if (!MO.isJTI() && MO.getOffset())
113209467b48Spatrick       Exp = MCBinaryExpr::createAdd(Exp,
113309467b48Spatrick                                     MCConstantExpr::create(MO.getOffset(),
113409467b48Spatrick                                                            OutContext),
113509467b48Spatrick                                     OutContext);
113609467b48Spatrick 
113709467b48Spatrick     TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
113809467b48Spatrick     EmitToStreamer(*OutStreamer, TmpInst);
113909467b48Spatrick     return;
114009467b48Spatrick   }
114109467b48Spatrick   case PPC::LDtocL: {
114209467b48Spatrick     // Transform %xd = LDtocL @sym, %xs
1143adae0cfdSpatrick     LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
114409467b48Spatrick 
114509467b48Spatrick     // Change the opcode to LD. If the global address is the address of
114609467b48Spatrick     // an external symbol, is a jump table address, is a block address, or is
114709467b48Spatrick     // a constant pool index with large code model enabled, then generate a
114809467b48Spatrick     // TOC entry and reference that. Otherwise, reference the symbol directly.
114909467b48Spatrick     TmpInst.setOpcode(PPC::LD);
115009467b48Spatrick 
115109467b48Spatrick     const MachineOperand &MO = MI->getOperand(1);
115209467b48Spatrick     assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() ||
115309467b48Spatrick             MO.isBlockAddress()) &&
115409467b48Spatrick            "Invalid operand for LDtocL!");
115509467b48Spatrick 
115609467b48Spatrick     LLVM_DEBUG(assert(
115709467b48Spatrick         (!MO.isGlobal() || Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&
115809467b48Spatrick         "LDtocL used on symbol that could be accessed directly is "
115909467b48Spatrick         "invalid. Must match ADDIStocHA8."));
116009467b48Spatrick 
1161adae0cfdSpatrick     const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
116209467b48Spatrick 
1163a0747c9fSpatrick     MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);
116409467b48Spatrick 
1165a0747c9fSpatrick     if (!MO.isCPI() || TM.getCodeModel() == CodeModel::Large)
1166a0747c9fSpatrick       MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, VK);
1167a0747c9fSpatrick 
1168a0747c9fSpatrick     VK = IsAIX ? MCSymbolRefExpr::VK_PPC_L : MCSymbolRefExpr::VK_PPC_TOC_LO;
116909467b48Spatrick     const MCExpr *Exp =
117009467b48Spatrick         MCSymbolRefExpr::create(MOSymbol, VK, OutContext);
117109467b48Spatrick     TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
117209467b48Spatrick     EmitToStreamer(*OutStreamer, TmpInst);
117309467b48Spatrick     return;
117409467b48Spatrick   }
117509467b48Spatrick   case PPC::ADDItocL: {
117609467b48Spatrick     // Transform %xd = ADDItocL %xs, @sym
1177adae0cfdSpatrick     LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
117809467b48Spatrick 
117909467b48Spatrick     // Change the opcode to ADDI8. If the global address is external, then
118009467b48Spatrick     // generate a TOC entry and reference that. Otherwise, reference the
118109467b48Spatrick     // symbol directly.
118209467b48Spatrick     TmpInst.setOpcode(PPC::ADDI8);
118309467b48Spatrick 
118409467b48Spatrick     const MachineOperand &MO = MI->getOperand(2);
118509467b48Spatrick     assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL.");
118609467b48Spatrick 
118709467b48Spatrick     LLVM_DEBUG(assert(
118809467b48Spatrick         !(MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&
118909467b48Spatrick         "Interposable definitions must use indirect access."));
119009467b48Spatrick 
119109467b48Spatrick     const MCExpr *Exp =
1192adae0cfdSpatrick         MCSymbolRefExpr::create(getMCSymbolForTOCPseudoMO(MO, *this),
119309467b48Spatrick                                 MCSymbolRefExpr::VK_PPC_TOC_LO, OutContext);
119409467b48Spatrick     TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
119509467b48Spatrick     EmitToStreamer(*OutStreamer, TmpInst);
119609467b48Spatrick     return;
119709467b48Spatrick   }
119809467b48Spatrick   case PPC::ADDISgotTprelHA: {
119909467b48Spatrick     // Transform: %xd = ADDISgotTprelHA %x2, @sym
120009467b48Spatrick     // Into:      %xd = ADDIS8 %x2, sym@got@tlsgd@ha
120109467b48Spatrick     assert(IsPPC64 && "Not supported for 32-bit PowerPC");
120209467b48Spatrick     const MachineOperand &MO = MI->getOperand(2);
120309467b48Spatrick     const GlobalValue *GValue = MO.getGlobal();
120409467b48Spatrick     MCSymbol *MOSymbol = getSymbol(GValue);
120509467b48Spatrick     const MCExpr *SymGotTprel =
120609467b48Spatrick         MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA,
120709467b48Spatrick                                 OutContext);
120809467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
120909467b48Spatrick                                  .addReg(MI->getOperand(0).getReg())
121009467b48Spatrick                                  .addReg(MI->getOperand(1).getReg())
121109467b48Spatrick                                  .addExpr(SymGotTprel));
121209467b48Spatrick     return;
121309467b48Spatrick   }
121409467b48Spatrick   case PPC::LDgotTprelL:
121509467b48Spatrick   case PPC::LDgotTprelL32: {
121609467b48Spatrick     // Transform %xd = LDgotTprelL @sym, %xs
1217adae0cfdSpatrick     LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
121809467b48Spatrick 
121909467b48Spatrick     // Change the opcode to LD.
122009467b48Spatrick     TmpInst.setOpcode(IsPPC64 ? PPC::LD : PPC::LWZ);
122109467b48Spatrick     const MachineOperand &MO = MI->getOperand(1);
122209467b48Spatrick     const GlobalValue *GValue = MO.getGlobal();
122309467b48Spatrick     MCSymbol *MOSymbol = getSymbol(GValue);
122409467b48Spatrick     const MCExpr *Exp = MCSymbolRefExpr::create(
122509467b48Spatrick         MOSymbol, IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO
122609467b48Spatrick                           : MCSymbolRefExpr::VK_PPC_GOT_TPREL,
122709467b48Spatrick         OutContext);
122809467b48Spatrick     TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
122909467b48Spatrick     EmitToStreamer(*OutStreamer, TmpInst);
123009467b48Spatrick     return;
123109467b48Spatrick   }
123209467b48Spatrick 
123309467b48Spatrick   case PPC::PPC32PICGOT: {
123409467b48Spatrick     MCSymbol *GOTSymbol = OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));
123509467b48Spatrick     MCSymbol *GOTRef = OutContext.createTempSymbol();
123609467b48Spatrick     MCSymbol *NextInstr = OutContext.createTempSymbol();
123709467b48Spatrick 
123809467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL)
123909467b48Spatrick       // FIXME: We would like an efficient form for this, so we don't have to do
124009467b48Spatrick       // a lot of extra uniquing.
124109467b48Spatrick       .addExpr(MCSymbolRefExpr::create(NextInstr, OutContext)));
124209467b48Spatrick     const MCExpr *OffsExpr =
124309467b48Spatrick       MCBinaryExpr::createSub(MCSymbolRefExpr::create(GOTSymbol, OutContext),
124409467b48Spatrick                                 MCSymbolRefExpr::create(GOTRef, OutContext),
124509467b48Spatrick         OutContext);
1246adae0cfdSpatrick     OutStreamer->emitLabel(GOTRef);
1247adae0cfdSpatrick     OutStreamer->emitValue(OffsExpr, 4);
1248adae0cfdSpatrick     OutStreamer->emitLabel(NextInstr);
124909467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR)
125009467b48Spatrick                                  .addReg(MI->getOperand(0).getReg()));
125109467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LWZ)
125209467b48Spatrick                                  .addReg(MI->getOperand(1).getReg())
125309467b48Spatrick                                  .addImm(0)
125409467b48Spatrick                                  .addReg(MI->getOperand(0).getReg()));
125509467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD4)
125609467b48Spatrick                                  .addReg(MI->getOperand(0).getReg())
125709467b48Spatrick                                  .addReg(MI->getOperand(1).getReg())
125809467b48Spatrick                                  .addReg(MI->getOperand(0).getReg()));
125909467b48Spatrick     return;
126009467b48Spatrick   }
126109467b48Spatrick   case PPC::PPC32GOT: {
126209467b48Spatrick     MCSymbol *GOTSymbol =
126309467b48Spatrick         OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));
126409467b48Spatrick     const MCExpr *SymGotTlsL = MCSymbolRefExpr::create(
126509467b48Spatrick         GOTSymbol, MCSymbolRefExpr::VK_PPC_LO, OutContext);
126609467b48Spatrick     const MCExpr *SymGotTlsHA = MCSymbolRefExpr::create(
126709467b48Spatrick         GOTSymbol, MCSymbolRefExpr::VK_PPC_HA, OutContext);
126809467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI)
126909467b48Spatrick                                  .addReg(MI->getOperand(0).getReg())
127009467b48Spatrick                                  .addExpr(SymGotTlsL));
127109467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
127209467b48Spatrick                                  .addReg(MI->getOperand(0).getReg())
127309467b48Spatrick                                  .addReg(MI->getOperand(0).getReg())
127409467b48Spatrick                                  .addExpr(SymGotTlsHA));
127509467b48Spatrick     return;
127609467b48Spatrick   }
127709467b48Spatrick   case PPC::ADDIStlsgdHA: {
127809467b48Spatrick     // Transform: %xd = ADDIStlsgdHA %x2, @sym
127909467b48Spatrick     // Into:      %xd = ADDIS8 %x2, sym@got@tlsgd@ha
128009467b48Spatrick     assert(IsPPC64 && "Not supported for 32-bit PowerPC");
128109467b48Spatrick     const MachineOperand &MO = MI->getOperand(2);
128209467b48Spatrick     const GlobalValue *GValue = MO.getGlobal();
128309467b48Spatrick     MCSymbol *MOSymbol = getSymbol(GValue);
128409467b48Spatrick     const MCExpr *SymGotTlsGD =
128509467b48Spatrick       MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA,
128609467b48Spatrick                               OutContext);
128709467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
128809467b48Spatrick                                  .addReg(MI->getOperand(0).getReg())
128909467b48Spatrick                                  .addReg(MI->getOperand(1).getReg())
129009467b48Spatrick                                  .addExpr(SymGotTlsGD));
129109467b48Spatrick     return;
129209467b48Spatrick   }
129309467b48Spatrick   case PPC::ADDItlsgdL:
129409467b48Spatrick     // Transform: %xd = ADDItlsgdL %xs, @sym
129509467b48Spatrick     // Into:      %xd = ADDI8 %xs, sym@got@tlsgd@l
129609467b48Spatrick   case PPC::ADDItlsgdL32: {
129709467b48Spatrick     // Transform: %rd = ADDItlsgdL32 %rs, @sym
129809467b48Spatrick     // Into:      %rd = ADDI %rs, sym@got@tlsgd
129909467b48Spatrick     const MachineOperand &MO = MI->getOperand(2);
130009467b48Spatrick     const GlobalValue *GValue = MO.getGlobal();
130109467b48Spatrick     MCSymbol *MOSymbol = getSymbol(GValue);
130209467b48Spatrick     const MCExpr *SymGotTlsGD = MCSymbolRefExpr::create(
130309467b48Spatrick         MOSymbol, IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO
130409467b48Spatrick                           : MCSymbolRefExpr::VK_PPC_GOT_TLSGD,
130509467b48Spatrick         OutContext);
130609467b48Spatrick     EmitToStreamer(*OutStreamer,
130709467b48Spatrick                    MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
130809467b48Spatrick                    .addReg(MI->getOperand(0).getReg())
130909467b48Spatrick                    .addReg(MI->getOperand(1).getReg())
131009467b48Spatrick                    .addExpr(SymGotTlsGD));
131109467b48Spatrick     return;
131209467b48Spatrick   }
131309467b48Spatrick   case PPC::GETtlsADDR:
131409467b48Spatrick     // Transform: %x3 = GETtlsADDR %x3, @sym
131509467b48Spatrick     // Into: BL8_NOP_TLS __tls_get_addr(sym at tlsgd)
1316a0747c9fSpatrick   case PPC::GETtlsADDRPCREL:
1317a0747c9fSpatrick   case PPC::GETtlsADDR32AIX:
1318a0747c9fSpatrick   case PPC::GETtlsADDR64AIX:
1319a0747c9fSpatrick     // Transform: %r3 = GETtlsADDRNNAIX %r3, %r4 (for NN == 32/64).
1320a0747c9fSpatrick     // Into: BLA .__tls_get_addr()
1321a0747c9fSpatrick     // Unlike on Linux, there is no symbol or relocation needed for this call.
132209467b48Spatrick   case PPC::GETtlsADDR32: {
132309467b48Spatrick     // Transform: %r3 = GETtlsADDR32 %r3, @sym
132409467b48Spatrick     // Into: BL_TLS __tls_get_addr(sym at tlsgd)@PLT
132509467b48Spatrick     EmitTlsCall(MI, MCSymbolRefExpr::VK_PPC_TLSGD);
132609467b48Spatrick     return;
132709467b48Spatrick   }
132809467b48Spatrick   case PPC::ADDIStlsldHA: {
132909467b48Spatrick     // Transform: %xd = ADDIStlsldHA %x2, @sym
133009467b48Spatrick     // Into:      %xd = ADDIS8 %x2, sym@got@tlsld@ha
133109467b48Spatrick     assert(IsPPC64 && "Not supported for 32-bit PowerPC");
133209467b48Spatrick     const MachineOperand &MO = MI->getOperand(2);
133309467b48Spatrick     const GlobalValue *GValue = MO.getGlobal();
133409467b48Spatrick     MCSymbol *MOSymbol = getSymbol(GValue);
133509467b48Spatrick     const MCExpr *SymGotTlsLD =
133609467b48Spatrick       MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA,
133709467b48Spatrick                               OutContext);
133809467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
133909467b48Spatrick                                  .addReg(MI->getOperand(0).getReg())
134009467b48Spatrick                                  .addReg(MI->getOperand(1).getReg())
134109467b48Spatrick                                  .addExpr(SymGotTlsLD));
134209467b48Spatrick     return;
134309467b48Spatrick   }
134409467b48Spatrick   case PPC::ADDItlsldL:
134509467b48Spatrick     // Transform: %xd = ADDItlsldL %xs, @sym
134609467b48Spatrick     // Into:      %xd = ADDI8 %xs, sym@got@tlsld@l
134709467b48Spatrick   case PPC::ADDItlsldL32: {
134809467b48Spatrick     // Transform: %rd = ADDItlsldL32 %rs, @sym
134909467b48Spatrick     // Into:      %rd = ADDI %rs, sym@got@tlsld
135009467b48Spatrick     const MachineOperand &MO = MI->getOperand(2);
135109467b48Spatrick     const GlobalValue *GValue = MO.getGlobal();
135209467b48Spatrick     MCSymbol *MOSymbol = getSymbol(GValue);
135309467b48Spatrick     const MCExpr *SymGotTlsLD = MCSymbolRefExpr::create(
135409467b48Spatrick         MOSymbol, IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO
135509467b48Spatrick                           : MCSymbolRefExpr::VK_PPC_GOT_TLSLD,
135609467b48Spatrick         OutContext);
135709467b48Spatrick     EmitToStreamer(*OutStreamer,
135809467b48Spatrick                    MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
135909467b48Spatrick                        .addReg(MI->getOperand(0).getReg())
136009467b48Spatrick                        .addReg(MI->getOperand(1).getReg())
136109467b48Spatrick                        .addExpr(SymGotTlsLD));
136209467b48Spatrick     return;
136309467b48Spatrick   }
136409467b48Spatrick   case PPC::GETtlsldADDR:
136509467b48Spatrick     // Transform: %x3 = GETtlsldADDR %x3, @sym
136609467b48Spatrick     // Into: BL8_NOP_TLS __tls_get_addr(sym at tlsld)
1367a0747c9fSpatrick   case PPC::GETtlsldADDRPCREL:
136809467b48Spatrick   case PPC::GETtlsldADDR32: {
136909467b48Spatrick     // Transform: %r3 = GETtlsldADDR32 %r3, @sym
137009467b48Spatrick     // Into: BL_TLS __tls_get_addr(sym at tlsld)@PLT
137109467b48Spatrick     EmitTlsCall(MI, MCSymbolRefExpr::VK_PPC_TLSLD);
137209467b48Spatrick     return;
137309467b48Spatrick   }
137409467b48Spatrick   case PPC::ADDISdtprelHA:
137509467b48Spatrick     // Transform: %xd = ADDISdtprelHA %xs, @sym
137609467b48Spatrick     // Into:      %xd = ADDIS8 %xs, sym@dtprel@ha
137709467b48Spatrick   case PPC::ADDISdtprelHA32: {
137809467b48Spatrick     // Transform: %rd = ADDISdtprelHA32 %rs, @sym
137909467b48Spatrick     // Into:      %rd = ADDIS %rs, sym@dtprel@ha
138009467b48Spatrick     const MachineOperand &MO = MI->getOperand(2);
138109467b48Spatrick     const GlobalValue *GValue = MO.getGlobal();
138209467b48Spatrick     MCSymbol *MOSymbol = getSymbol(GValue);
138309467b48Spatrick     const MCExpr *SymDtprel =
138409467b48Spatrick       MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_HA,
138509467b48Spatrick                               OutContext);
138609467b48Spatrick     EmitToStreamer(
138709467b48Spatrick         *OutStreamer,
138809467b48Spatrick         MCInstBuilder(IsPPC64 ? PPC::ADDIS8 : PPC::ADDIS)
138909467b48Spatrick             .addReg(MI->getOperand(0).getReg())
139009467b48Spatrick             .addReg(MI->getOperand(1).getReg())
139109467b48Spatrick             .addExpr(SymDtprel));
139209467b48Spatrick     return;
139309467b48Spatrick   }
1394a0747c9fSpatrick   case PPC::PADDIdtprel: {
1395a0747c9fSpatrick     // Transform: %rd = PADDIdtprel %rs, @sym
1396a0747c9fSpatrick     // Into:      %rd = PADDI8 %rs, sym@dtprel
1397a0747c9fSpatrick     const MachineOperand &MO = MI->getOperand(2);
1398a0747c9fSpatrick     const GlobalValue *GValue = MO.getGlobal();
1399a0747c9fSpatrick     MCSymbol *MOSymbol = getSymbol(GValue);
1400a0747c9fSpatrick     const MCExpr *SymDtprel = MCSymbolRefExpr::create(
1401a0747c9fSpatrick         MOSymbol, MCSymbolRefExpr::VK_DTPREL, OutContext);
1402a0747c9fSpatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::PADDI8)
1403a0747c9fSpatrick                                      .addReg(MI->getOperand(0).getReg())
1404a0747c9fSpatrick                                      .addReg(MI->getOperand(1).getReg())
1405a0747c9fSpatrick                                      .addExpr(SymDtprel));
1406a0747c9fSpatrick     return;
1407a0747c9fSpatrick   }
1408a0747c9fSpatrick 
140909467b48Spatrick   case PPC::ADDIdtprelL:
141009467b48Spatrick     // Transform: %xd = ADDIdtprelL %xs, @sym
141109467b48Spatrick     // Into:      %xd = ADDI8 %xs, sym@dtprel@l
141209467b48Spatrick   case PPC::ADDIdtprelL32: {
141309467b48Spatrick     // Transform: %rd = ADDIdtprelL32 %rs, @sym
141409467b48Spatrick     // Into:      %rd = ADDI %rs, sym@dtprel@l
141509467b48Spatrick     const MachineOperand &MO = MI->getOperand(2);
141609467b48Spatrick     const GlobalValue *GValue = MO.getGlobal();
141709467b48Spatrick     MCSymbol *MOSymbol = getSymbol(GValue);
141809467b48Spatrick     const MCExpr *SymDtprel =
141909467b48Spatrick       MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_LO,
142009467b48Spatrick                               OutContext);
142109467b48Spatrick     EmitToStreamer(*OutStreamer,
142209467b48Spatrick                    MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
142309467b48Spatrick                        .addReg(MI->getOperand(0).getReg())
142409467b48Spatrick                        .addReg(MI->getOperand(1).getReg())
142509467b48Spatrick                        .addExpr(SymDtprel));
142609467b48Spatrick     return;
142709467b48Spatrick   }
142809467b48Spatrick   case PPC::MFOCRF:
142909467b48Spatrick   case PPC::MFOCRF8:
143009467b48Spatrick     if (!Subtarget->hasMFOCRF()) {
143109467b48Spatrick       // Transform: %r3 = MFOCRF %cr7
143209467b48Spatrick       // Into:      %r3 = MFCR   ;; cr7
143309467b48Spatrick       unsigned NewOpcode =
143409467b48Spatrick         MI->getOpcode() == PPC::MFOCRF ? PPC::MFCR : PPC::MFCR8;
143509467b48Spatrick       OutStreamer->AddComment(PPCInstPrinter::
143609467b48Spatrick                               getRegisterName(MI->getOperand(1).getReg()));
143709467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)
143809467b48Spatrick                                   .addReg(MI->getOperand(0).getReg()));
143909467b48Spatrick       return;
144009467b48Spatrick     }
144109467b48Spatrick     break;
144209467b48Spatrick   case PPC::MTOCRF:
144309467b48Spatrick   case PPC::MTOCRF8:
144409467b48Spatrick     if (!Subtarget->hasMFOCRF()) {
144509467b48Spatrick       // Transform: %cr7 = MTOCRF %r3
144609467b48Spatrick       // Into:      MTCRF mask, %r3 ;; cr7
144709467b48Spatrick       unsigned NewOpcode =
144809467b48Spatrick         MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8;
144909467b48Spatrick       unsigned Mask = 0x80 >> OutContext.getRegisterInfo()
145009467b48Spatrick                               ->getEncodingValue(MI->getOperand(0).getReg());
145109467b48Spatrick       OutStreamer->AddComment(PPCInstPrinter::
145209467b48Spatrick                               getRegisterName(MI->getOperand(0).getReg()));
145309467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)
145409467b48Spatrick                                      .addImm(Mask)
145509467b48Spatrick                                      .addReg(MI->getOperand(1).getReg()));
145609467b48Spatrick       return;
145709467b48Spatrick     }
145809467b48Spatrick     break;
145909467b48Spatrick   case PPC::LD:
146009467b48Spatrick   case PPC::STD:
146109467b48Spatrick   case PPC::LWA_32:
146209467b48Spatrick   case PPC::LWA: {
146309467b48Spatrick     // Verify alignment is legal, so we don't create relocations
146409467b48Spatrick     // that can't be supported.
146509467b48Spatrick     unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1;
146609467b48Spatrick     const MachineOperand &MO = MI->getOperand(OpNum);
1467adae0cfdSpatrick     if (MO.isGlobal()) {
1468adae0cfdSpatrick       const DataLayout &DL = MO.getGlobal()->getParent()->getDataLayout();
1469adae0cfdSpatrick       if (MO.getGlobal()->getPointerAlignment(DL) < 4)
147009467b48Spatrick         llvm_unreachable("Global must be word-aligned for LD, STD, LWA!");
147109467b48Spatrick     }
147209467b48Spatrick     // Now process the instruction normally.
147309467b48Spatrick     break;
147409467b48Spatrick   }
1475a0747c9fSpatrick   case PPC::PseudoEIEIO: {
1476a0747c9fSpatrick     EmitToStreamer(
1477a0747c9fSpatrick         *OutStreamer,
1478a0747c9fSpatrick         MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1479a0747c9fSpatrick     EmitToStreamer(
1480a0747c9fSpatrick         *OutStreamer,
1481a0747c9fSpatrick         MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1482a0747c9fSpatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::EnforceIEIO));
1483a0747c9fSpatrick     return;
1484a0747c9fSpatrick   }
148509467b48Spatrick   }
148609467b48Spatrick 
1487adae0cfdSpatrick   LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
148809467b48Spatrick   EmitToStreamer(*OutStreamer, TmpInst);
148909467b48Spatrick }
149009467b48Spatrick 
emitGNUAttributes(Module & M)1491*a96b3639Srobert void PPCLinuxAsmPrinter::emitGNUAttributes(Module &M) {
1492*a96b3639Srobert   // Emit float ABI into GNU attribute
1493*a96b3639Srobert   Metadata *MD = M.getModuleFlag("float-abi");
1494*a96b3639Srobert   MDString *FloatABI = dyn_cast_or_null<MDString>(MD);
1495*a96b3639Srobert   if (!FloatABI)
1496*a96b3639Srobert     return;
1497*a96b3639Srobert   StringRef flt = FloatABI->getString();
1498*a96b3639Srobert   // TODO: Support emitting soft-fp and hard double/single attributes.
1499*a96b3639Srobert   if (flt == "doubledouble")
1500*a96b3639Srobert     OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1501*a96b3639Srobert                                   Val_GNU_Power_ABI_HardFloat_DP |
1502*a96b3639Srobert                                       Val_GNU_Power_ABI_LDBL_IBM128);
1503*a96b3639Srobert   else if (flt == "ieeequad")
1504*a96b3639Srobert     OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1505*a96b3639Srobert                                   Val_GNU_Power_ABI_HardFloat_DP |
1506*a96b3639Srobert                                       Val_GNU_Power_ABI_LDBL_IEEE128);
1507*a96b3639Srobert   else if (flt == "ieeedouble")
1508*a96b3639Srobert     OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1509*a96b3639Srobert                                   Val_GNU_Power_ABI_HardFloat_DP |
1510*a96b3639Srobert                                       Val_GNU_Power_ABI_LDBL_64);
1511*a96b3639Srobert }
1512*a96b3639Srobert 
emitInstruction(const MachineInstr * MI)1513adae0cfdSpatrick void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {
151409467b48Spatrick   if (!Subtarget->isPPC64())
1515adae0cfdSpatrick     return PPCAsmPrinter::emitInstruction(MI);
151609467b48Spatrick 
151709467b48Spatrick   switch (MI->getOpcode()) {
151809467b48Spatrick   default:
1519adae0cfdSpatrick     return PPCAsmPrinter::emitInstruction(MI);
152009467b48Spatrick   case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
152109467b48Spatrick     // .begin:
152209467b48Spatrick     //   b .end # lis 0, FuncId[16..32]
152309467b48Spatrick     //   nop    # li  0, FuncId[0..15]
152409467b48Spatrick     //   std 0, -8(1)
152509467b48Spatrick     //   mflr 0
152609467b48Spatrick     //   bl __xray_FunctionEntry
152709467b48Spatrick     //   mtlr 0
152809467b48Spatrick     // .end:
152909467b48Spatrick     //
153009467b48Spatrick     // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
153109467b48Spatrick     // of instructions change.
153209467b48Spatrick     MCSymbol *BeginOfSled = OutContext.createTempSymbol();
153309467b48Spatrick     MCSymbol *EndOfSled = OutContext.createTempSymbol();
1534adae0cfdSpatrick     OutStreamer->emitLabel(BeginOfSled);
153509467b48Spatrick     EmitToStreamer(*OutStreamer,
153609467b48Spatrick                    MCInstBuilder(PPC::B).addExpr(
153709467b48Spatrick                        MCSymbolRefExpr::create(EndOfSled, OutContext)));
153809467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
153909467b48Spatrick     EmitToStreamer(
154009467b48Spatrick         *OutStreamer,
154109467b48Spatrick         MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
154209467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
154309467b48Spatrick     EmitToStreamer(*OutStreamer,
154409467b48Spatrick                    MCInstBuilder(PPC::BL8_NOP)
154509467b48Spatrick                        .addExpr(MCSymbolRefExpr::create(
154609467b48Spatrick                            OutContext.getOrCreateSymbol("__xray_FunctionEntry"),
154709467b48Spatrick                            OutContext)));
154809467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1549adae0cfdSpatrick     OutStreamer->emitLabel(EndOfSled);
1550adae0cfdSpatrick     recordSled(BeginOfSled, *MI, SledKind::FUNCTION_ENTER, 2);
155109467b48Spatrick     break;
155209467b48Spatrick   }
155309467b48Spatrick   case TargetOpcode::PATCHABLE_RET: {
155409467b48Spatrick     unsigned RetOpcode = MI->getOperand(0).getImm();
155509467b48Spatrick     MCInst RetInst;
155609467b48Spatrick     RetInst.setOpcode(RetOpcode);
1557a0747c9fSpatrick     for (const auto &MO : llvm::drop_begin(MI->operands())) {
155809467b48Spatrick       MCOperand MCOp;
1559adae0cfdSpatrick       if (LowerPPCMachineOperandToMCOperand(MO, MCOp, *this))
156009467b48Spatrick         RetInst.addOperand(MCOp);
156109467b48Spatrick     }
156209467b48Spatrick 
156309467b48Spatrick     bool IsConditional;
156409467b48Spatrick     if (RetOpcode == PPC::BCCLR) {
156509467b48Spatrick       IsConditional = true;
156609467b48Spatrick     } else if (RetOpcode == PPC::TCRETURNdi8 || RetOpcode == PPC::TCRETURNri8 ||
156709467b48Spatrick                RetOpcode == PPC::TCRETURNai8) {
156809467b48Spatrick       break;
156909467b48Spatrick     } else if (RetOpcode == PPC::BLR8 || RetOpcode == PPC::TAILB8) {
157009467b48Spatrick       IsConditional = false;
157109467b48Spatrick     } else {
157209467b48Spatrick       EmitToStreamer(*OutStreamer, RetInst);
157309467b48Spatrick       break;
157409467b48Spatrick     }
157509467b48Spatrick 
157609467b48Spatrick     MCSymbol *FallthroughLabel;
157709467b48Spatrick     if (IsConditional) {
157809467b48Spatrick       // Before:
157909467b48Spatrick       //   bgtlr cr0
158009467b48Spatrick       //
158109467b48Spatrick       // After:
158209467b48Spatrick       //   ble cr0, .end
158309467b48Spatrick       // .p2align 3
158409467b48Spatrick       // .begin:
158509467b48Spatrick       //   blr    # lis 0, FuncId[16..32]
158609467b48Spatrick       //   nop    # li  0, FuncId[0..15]
158709467b48Spatrick       //   std 0, -8(1)
158809467b48Spatrick       //   mflr 0
158909467b48Spatrick       //   bl __xray_FunctionExit
159009467b48Spatrick       //   mtlr 0
159109467b48Spatrick       //   blr
159209467b48Spatrick       // .end:
159309467b48Spatrick       //
159409467b48Spatrick       // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
159509467b48Spatrick       // of instructions change.
159609467b48Spatrick       FallthroughLabel = OutContext.createTempSymbol();
159709467b48Spatrick       EmitToStreamer(
159809467b48Spatrick           *OutStreamer,
159909467b48Spatrick           MCInstBuilder(PPC::BCC)
160009467b48Spatrick               .addImm(PPC::InvertPredicate(
160109467b48Spatrick                   static_cast<PPC::Predicate>(MI->getOperand(1).getImm())))
160209467b48Spatrick               .addReg(MI->getOperand(2).getReg())
160309467b48Spatrick               .addExpr(MCSymbolRefExpr::create(FallthroughLabel, OutContext)));
160409467b48Spatrick       RetInst = MCInst();
160509467b48Spatrick       RetInst.setOpcode(PPC::BLR8);
160609467b48Spatrick     }
160709467b48Spatrick     // .p2align 3
160809467b48Spatrick     // .begin:
160909467b48Spatrick     //   b(lr)? # lis 0, FuncId[16..32]
161009467b48Spatrick     //   nop    # li  0, FuncId[0..15]
161109467b48Spatrick     //   std 0, -8(1)
161209467b48Spatrick     //   mflr 0
161309467b48Spatrick     //   bl __xray_FunctionExit
161409467b48Spatrick     //   mtlr 0
161509467b48Spatrick     //   b(lr)?
161609467b48Spatrick     //
161709467b48Spatrick     // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
161809467b48Spatrick     // of instructions change.
1619*a96b3639Srobert     OutStreamer->emitCodeAlignment(Align(8), &getSubtargetInfo());
162009467b48Spatrick     MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1621adae0cfdSpatrick     OutStreamer->emitLabel(BeginOfSled);
162209467b48Spatrick     EmitToStreamer(*OutStreamer, RetInst);
162309467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
162409467b48Spatrick     EmitToStreamer(
162509467b48Spatrick         *OutStreamer,
162609467b48Spatrick         MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
162709467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
162809467b48Spatrick     EmitToStreamer(*OutStreamer,
162909467b48Spatrick                    MCInstBuilder(PPC::BL8_NOP)
163009467b48Spatrick                        .addExpr(MCSymbolRefExpr::create(
163109467b48Spatrick                            OutContext.getOrCreateSymbol("__xray_FunctionExit"),
163209467b48Spatrick                            OutContext)));
163309467b48Spatrick     EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
163409467b48Spatrick     EmitToStreamer(*OutStreamer, RetInst);
163509467b48Spatrick     if (IsConditional)
1636adae0cfdSpatrick       OutStreamer->emitLabel(FallthroughLabel);
1637adae0cfdSpatrick     recordSled(BeginOfSled, *MI, SledKind::FUNCTION_EXIT, 2);
163809467b48Spatrick     break;
163909467b48Spatrick   }
164009467b48Spatrick   case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
164109467b48Spatrick     llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");
164209467b48Spatrick   case TargetOpcode::PATCHABLE_TAIL_CALL:
164309467b48Spatrick     // TODO: Define a trampoline `__xray_FunctionTailExit` and differentiate a
164409467b48Spatrick     // normal function exit from a tail exit.
164509467b48Spatrick     llvm_unreachable("Tail call is handled in the normal case. See comments "
164609467b48Spatrick                      "around this assert.");
164709467b48Spatrick   }
164809467b48Spatrick }
164909467b48Spatrick 
emitStartOfAsmFile(Module & M)1650adae0cfdSpatrick void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) {
165109467b48Spatrick   if (static_cast<const PPCTargetMachine &>(TM).isELFv2ABI()) {
165209467b48Spatrick     PPCTargetStreamer *TS =
165309467b48Spatrick       static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
165409467b48Spatrick     TS->emitAbiVersion(2);
165509467b48Spatrick   }
165609467b48Spatrick 
165709467b48Spatrick   if (static_cast<const PPCTargetMachine &>(TM).isPPC64() ||
165809467b48Spatrick       !isPositionIndependent())
1659adae0cfdSpatrick     return AsmPrinter::emitStartOfAsmFile(M);
166009467b48Spatrick 
166109467b48Spatrick   if (M.getPICLevel() == PICLevel::SmallPIC)
1662adae0cfdSpatrick     return AsmPrinter::emitStartOfAsmFile(M);
166309467b48Spatrick 
1664*a96b3639Srobert   OutStreamer->switchSection(OutContext.getELFSection(
166509467b48Spatrick       ".got2", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC));
166609467b48Spatrick 
166709467b48Spatrick   MCSymbol *TOCSym = OutContext.getOrCreateSymbol(Twine(".LTOC"));
166809467b48Spatrick   MCSymbol *CurrentPos = OutContext.createTempSymbol();
166909467b48Spatrick 
1670adae0cfdSpatrick   OutStreamer->emitLabel(CurrentPos);
167109467b48Spatrick 
167209467b48Spatrick   // The GOT pointer points to the middle of the GOT, in order to reference the
167309467b48Spatrick   // entire 64kB range.  0x8000 is the midpoint.
167409467b48Spatrick   const MCExpr *tocExpr =
167509467b48Spatrick     MCBinaryExpr::createAdd(MCSymbolRefExpr::create(CurrentPos, OutContext),
167609467b48Spatrick                             MCConstantExpr::create(0x8000, OutContext),
167709467b48Spatrick                             OutContext);
167809467b48Spatrick 
1679adae0cfdSpatrick   OutStreamer->emitAssignment(TOCSym, tocExpr);
168009467b48Spatrick 
1681*a96b3639Srobert   OutStreamer->switchSection(getObjFileLowering().getTextSection());
168209467b48Spatrick }
168309467b48Spatrick 
emitFunctionEntryLabel()1684adae0cfdSpatrick void PPCLinuxAsmPrinter::emitFunctionEntryLabel() {
168509467b48Spatrick   // linux/ppc32 - Normal entry label.
168609467b48Spatrick   if (!Subtarget->isPPC64() &&
168709467b48Spatrick       (!isPositionIndependent() ||
168809467b48Spatrick        MF->getFunction().getParent()->getPICLevel() == PICLevel::SmallPIC))
1689adae0cfdSpatrick     return AsmPrinter::emitFunctionEntryLabel();
169009467b48Spatrick 
169109467b48Spatrick   if (!Subtarget->isPPC64()) {
169209467b48Spatrick     const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
169309467b48Spatrick     if (PPCFI->usesPICBase() && !Subtarget->isSecurePlt()) {
1694adae0cfdSpatrick       MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol(*MF);
169509467b48Spatrick       MCSymbol *PICBase = MF->getPICBaseSymbol();
1696adae0cfdSpatrick       OutStreamer->emitLabel(RelocSymbol);
169709467b48Spatrick 
169809467b48Spatrick       const MCExpr *OffsExpr =
169909467b48Spatrick         MCBinaryExpr::createSub(
170009467b48Spatrick           MCSymbolRefExpr::create(OutContext.getOrCreateSymbol(Twine(".LTOC")),
170109467b48Spatrick                                                                OutContext),
170209467b48Spatrick                                   MCSymbolRefExpr::create(PICBase, OutContext),
170309467b48Spatrick           OutContext);
1704adae0cfdSpatrick       OutStreamer->emitValue(OffsExpr, 4);
1705adae0cfdSpatrick       OutStreamer->emitLabel(CurrentFnSym);
170609467b48Spatrick       return;
170709467b48Spatrick     } else
1708adae0cfdSpatrick       return AsmPrinter::emitFunctionEntryLabel();
170909467b48Spatrick   }
171009467b48Spatrick 
171109467b48Spatrick   // ELFv2 ABI - Normal entry label.
171209467b48Spatrick   if (Subtarget->isELFv2ABI()) {
171309467b48Spatrick     // In the Large code model, we allow arbitrary displacements between
171409467b48Spatrick     // the text section and its associated TOC section.  We place the
171509467b48Spatrick     // full 8-byte offset to the TOC in memory immediately preceding
171609467b48Spatrick     // the function global entry point.
171709467b48Spatrick     if (TM.getCodeModel() == CodeModel::Large
171809467b48Spatrick         && !MF->getRegInfo().use_empty(PPC::X2)) {
171909467b48Spatrick       const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
172009467b48Spatrick 
172109467b48Spatrick       MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));
1722adae0cfdSpatrick       MCSymbol *GlobalEPSymbol = PPCFI->getGlobalEPSymbol(*MF);
172309467b48Spatrick       const MCExpr *TOCDeltaExpr =
172409467b48Spatrick         MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext),
172509467b48Spatrick                                 MCSymbolRefExpr::create(GlobalEPSymbol,
172609467b48Spatrick                                                         OutContext),
172709467b48Spatrick                                 OutContext);
172809467b48Spatrick 
1729adae0cfdSpatrick       OutStreamer->emitLabel(PPCFI->getTOCOffsetSymbol(*MF));
1730adae0cfdSpatrick       OutStreamer->emitValue(TOCDeltaExpr, 8);
173109467b48Spatrick     }
1732adae0cfdSpatrick     return AsmPrinter::emitFunctionEntryLabel();
173309467b48Spatrick   }
173409467b48Spatrick 
173509467b48Spatrick   // Emit an official procedure descriptor.
173609467b48Spatrick   MCSectionSubPair Current = OutStreamer->getCurrentSection();
173709467b48Spatrick   MCSectionELF *Section = OutStreamer->getContext().getELFSection(
173809467b48Spatrick       ".opd", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
1739*a96b3639Srobert   OutStreamer->switchSection(Section);
1740adae0cfdSpatrick   OutStreamer->emitLabel(CurrentFnSym);
1741*a96b3639Srobert   OutStreamer->emitValueToAlignment(Align(8));
174209467b48Spatrick   MCSymbol *Symbol1 = CurrentFnSymForSize;
174309467b48Spatrick   // Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function
174409467b48Spatrick   // entry point.
1745adae0cfdSpatrick   OutStreamer->emitValue(MCSymbolRefExpr::create(Symbol1, OutContext),
174609467b48Spatrick                          8 /*size*/);
174709467b48Spatrick   MCSymbol *Symbol2 = OutContext.getOrCreateSymbol(StringRef(".TOC."));
174809467b48Spatrick   // Generates a R_PPC64_TOC relocation for TOC base insertion.
1749adae0cfdSpatrick   OutStreamer->emitValue(
175009467b48Spatrick     MCSymbolRefExpr::create(Symbol2, MCSymbolRefExpr::VK_PPC_TOCBASE, OutContext),
175109467b48Spatrick     8/*size*/);
175209467b48Spatrick   // Emit a null environment pointer.
1753adae0cfdSpatrick   OutStreamer->emitIntValue(0, 8 /* size */);
1754*a96b3639Srobert   OutStreamer->switchSection(Current.first, Current.second);
175509467b48Spatrick }
175609467b48Spatrick 
emitEndOfAsmFile(Module & M)1757adae0cfdSpatrick void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) {
175809467b48Spatrick   const DataLayout &DL = getDataLayout();
175909467b48Spatrick 
176009467b48Spatrick   bool isPPC64 = DL.getPointerSizeInBits() == 64;
176109467b48Spatrick 
1762adae0cfdSpatrick   PPCTargetStreamer *TS =
1763adae0cfdSpatrick       static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
176409467b48Spatrick 
1765*a96b3639Srobert   emitGNUAttributes(M);
1766*a96b3639Srobert 
176709467b48Spatrick   if (!TOC.empty()) {
1768adae0cfdSpatrick     const char *Name = isPPC64 ? ".toc" : ".got2";
1769adae0cfdSpatrick     MCSectionELF *Section = OutContext.getELFSection(
1770adae0cfdSpatrick         Name, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
1771*a96b3639Srobert     OutStreamer->switchSection(Section);
1772adae0cfdSpatrick     if (!isPPC64)
1773*a96b3639Srobert       OutStreamer->emitValueToAlignment(Align(4));
177409467b48Spatrick 
177509467b48Spatrick     for (const auto &TOCMapPair : TOC) {
1776a0747c9fSpatrick       const MCSymbol *const TOCEntryTarget = TOCMapPair.first.first;
177709467b48Spatrick       MCSymbol *const TOCEntryLabel = TOCMapPair.second;
177809467b48Spatrick 
1779adae0cfdSpatrick       OutStreamer->emitLabel(TOCEntryLabel);
1780*a96b3639Srobert       if (isPPC64)
1781a0747c9fSpatrick         TS->emitTCEntry(*TOCEntryTarget, TOCMapPair.first.second);
1782adae0cfdSpatrick       else
1783adae0cfdSpatrick         OutStreamer->emitSymbolValue(TOCEntryTarget, 4);
178409467b48Spatrick     }
178509467b48Spatrick   }
178609467b48Spatrick 
1787adae0cfdSpatrick   PPCAsmPrinter::emitEndOfAsmFile(M);
178809467b48Spatrick }
178909467b48Spatrick 
179009467b48Spatrick /// EmitFunctionBodyStart - Emit a global entry point prefix for ELFv2.
emitFunctionBodyStart()1791adae0cfdSpatrick void PPCLinuxAsmPrinter::emitFunctionBodyStart() {
179209467b48Spatrick   // In the ELFv2 ABI, in functions that use the TOC register, we need to
179309467b48Spatrick   // provide two entry points.  The ABI guarantees that when calling the
179409467b48Spatrick   // local entry point, r2 is set up by the caller to contain the TOC base
179509467b48Spatrick   // for this function, and when calling the global entry point, r12 is set
179609467b48Spatrick   // up by the caller to hold the address of the global entry point.  We
179709467b48Spatrick   // thus emit a prefix sequence along the following lines:
179809467b48Spatrick   //
179909467b48Spatrick   // func:
180009467b48Spatrick   // .Lfunc_gepNN:
180109467b48Spatrick   //         # global entry point
180209467b48Spatrick   //         addis r2,r12,(.TOC.-.Lfunc_gepNN)@ha
180309467b48Spatrick   //         addi  r2,r2,(.TOC.-.Lfunc_gepNN)@l
180409467b48Spatrick   // .Lfunc_lepNN:
180509467b48Spatrick   //         .localentry func, .Lfunc_lepNN-.Lfunc_gepNN
180609467b48Spatrick   //         # local entry point, followed by function body
180709467b48Spatrick   //
180809467b48Spatrick   // For the Large code model, we create
180909467b48Spatrick   //
181009467b48Spatrick   // .Lfunc_tocNN:
181109467b48Spatrick   //         .quad .TOC.-.Lfunc_gepNN      # done by EmitFunctionEntryLabel
181209467b48Spatrick   // func:
181309467b48Spatrick   // .Lfunc_gepNN:
181409467b48Spatrick   //         # global entry point
181509467b48Spatrick   //         ld    r2,.Lfunc_tocNN-.Lfunc_gepNN(r12)
181609467b48Spatrick   //         add   r2,r2,r12
181709467b48Spatrick   // .Lfunc_lepNN:
181809467b48Spatrick   //         .localentry func, .Lfunc_lepNN-.Lfunc_gepNN
181909467b48Spatrick   //         # local entry point, followed by function body
182009467b48Spatrick   //
182109467b48Spatrick   // This ensures we have r2 set up correctly while executing the function
182209467b48Spatrick   // body, no matter which entry point is called.
1823adae0cfdSpatrick   const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
1824adae0cfdSpatrick   const bool UsesX2OrR2 = !MF->getRegInfo().use_empty(PPC::X2) ||
1825adae0cfdSpatrick                           !MF->getRegInfo().use_empty(PPC::R2);
1826adae0cfdSpatrick   const bool PCrelGEPRequired = Subtarget->isUsingPCRelativeCalls() &&
1827adae0cfdSpatrick                                 UsesX2OrR2 && PPCFI->usesTOCBasePtr();
1828adae0cfdSpatrick   const bool NonPCrelGEPRequired = !Subtarget->isUsingPCRelativeCalls() &&
1829adae0cfdSpatrick                                    Subtarget->isELFv2ABI() && UsesX2OrR2;
1830adae0cfdSpatrick 
1831adae0cfdSpatrick   // Only do all that if the function uses R2 as the TOC pointer
1832adae0cfdSpatrick   // in the first place. We don't need the global entry point if the
1833adae0cfdSpatrick   // function uses R2 as an allocatable register.
1834adae0cfdSpatrick   if (NonPCrelGEPRequired || PCrelGEPRequired) {
183509467b48Spatrick     // Note: The logic here must be synchronized with the code in the
183609467b48Spatrick     // branch-selection pass which sets the offset of the first block in the
183709467b48Spatrick     // function. This matters because it affects the alignment.
1838adae0cfdSpatrick     MCSymbol *GlobalEntryLabel = PPCFI->getGlobalEPSymbol(*MF);
1839adae0cfdSpatrick     OutStreamer->emitLabel(GlobalEntryLabel);
184009467b48Spatrick     const MCSymbolRefExpr *GlobalEntryLabelExp =
184109467b48Spatrick       MCSymbolRefExpr::create(GlobalEntryLabel, OutContext);
184209467b48Spatrick 
184309467b48Spatrick     if (TM.getCodeModel() != CodeModel::Large) {
184409467b48Spatrick       MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));
184509467b48Spatrick       const MCExpr *TOCDeltaExpr =
184609467b48Spatrick         MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext),
184709467b48Spatrick                                 GlobalEntryLabelExp, OutContext);
184809467b48Spatrick 
1849adae0cfdSpatrick       const MCExpr *TOCDeltaHi = PPCMCExpr::createHa(TOCDeltaExpr, OutContext);
185009467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
185109467b48Spatrick                                    .addReg(PPC::X2)
185209467b48Spatrick                                    .addReg(PPC::X12)
185309467b48Spatrick                                    .addExpr(TOCDeltaHi));
185409467b48Spatrick 
1855adae0cfdSpatrick       const MCExpr *TOCDeltaLo = PPCMCExpr::createLo(TOCDeltaExpr, OutContext);
185609467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI)
185709467b48Spatrick                                    .addReg(PPC::X2)
185809467b48Spatrick                                    .addReg(PPC::X2)
185909467b48Spatrick                                    .addExpr(TOCDeltaLo));
186009467b48Spatrick     } else {
1861adae0cfdSpatrick       MCSymbol *TOCOffset = PPCFI->getTOCOffsetSymbol(*MF);
186209467b48Spatrick       const MCExpr *TOCOffsetDeltaExpr =
186309467b48Spatrick         MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCOffset, OutContext),
186409467b48Spatrick                                 GlobalEntryLabelExp, OutContext);
186509467b48Spatrick 
186609467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
186709467b48Spatrick                                    .addReg(PPC::X2)
186809467b48Spatrick                                    .addExpr(TOCOffsetDeltaExpr)
186909467b48Spatrick                                    .addReg(PPC::X12));
187009467b48Spatrick       EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD8)
187109467b48Spatrick                                    .addReg(PPC::X2)
187209467b48Spatrick                                    .addReg(PPC::X2)
187309467b48Spatrick                                    .addReg(PPC::X12));
187409467b48Spatrick     }
187509467b48Spatrick 
1876adae0cfdSpatrick     MCSymbol *LocalEntryLabel = PPCFI->getLocalEPSymbol(*MF);
1877adae0cfdSpatrick     OutStreamer->emitLabel(LocalEntryLabel);
187809467b48Spatrick     const MCSymbolRefExpr *LocalEntryLabelExp =
187909467b48Spatrick        MCSymbolRefExpr::create(LocalEntryLabel, OutContext);
188009467b48Spatrick     const MCExpr *LocalOffsetExp =
188109467b48Spatrick       MCBinaryExpr::createSub(LocalEntryLabelExp,
188209467b48Spatrick                               GlobalEntryLabelExp, OutContext);
188309467b48Spatrick 
188409467b48Spatrick     PPCTargetStreamer *TS =
188509467b48Spatrick       static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
188609467b48Spatrick     TS->emitLocalEntry(cast<MCSymbolELF>(CurrentFnSym), LocalOffsetExp);
1887adae0cfdSpatrick   } else if (Subtarget->isUsingPCRelativeCalls()) {
1888adae0cfdSpatrick     // When generating the entry point for a function we have a few scenarios
1889adae0cfdSpatrick     // based on whether or not that function uses R2 and whether or not that
1890adae0cfdSpatrick     // function makes calls (or is a leaf function).
1891adae0cfdSpatrick     // 1) A leaf function that does not use R2 (or treats it as callee-saved
1892adae0cfdSpatrick     //    and preserves it). In this case st_other=0 and both
1893adae0cfdSpatrick     //    the local and global entry points for the function are the same.
1894adae0cfdSpatrick     //    No special entry point code is required.
1895adae0cfdSpatrick     // 2) A function uses the TOC pointer R2. This function may or may not have
1896adae0cfdSpatrick     //    calls. In this case st_other=[2,6] and the global and local entry
1897adae0cfdSpatrick     //    points are different. Code to correctly setup the TOC pointer in R2
1898adae0cfdSpatrick     //    is put between the global and local entry points. This case is
1899adae0cfdSpatrick     //    covered by the if statatement above.
1900adae0cfdSpatrick     // 3) A function does not use the TOC pointer R2 but does have calls.
1901adae0cfdSpatrick     //    In this case st_other=1 since we do not know whether or not any
1902adae0cfdSpatrick     //    of the callees clobber R2. This case is dealt with in this else if
1903adae0cfdSpatrick     //    block. Tail calls are considered calls and the st_other should also
1904adae0cfdSpatrick     //    be set to 1 in that case as well.
1905adae0cfdSpatrick     // 4) The function does not use the TOC pointer but R2 is used inside
1906adae0cfdSpatrick     //    the function. In this case st_other=1 once again.
1907adae0cfdSpatrick     // 5) This function uses inline asm. We mark R2 as reserved if the function
1908adae0cfdSpatrick     //    has inline asm as we have to assume that it may be used.
1909adae0cfdSpatrick     if (MF->getFrameInfo().hasCalls() || MF->getFrameInfo().hasTailCall() ||
1910adae0cfdSpatrick         MF->hasInlineAsm() || (!PPCFI->usesTOCBasePtr() && UsesX2OrR2)) {
1911adae0cfdSpatrick       PPCTargetStreamer *TS =
1912adae0cfdSpatrick           static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
1913adae0cfdSpatrick       TS->emitLocalEntry(cast<MCSymbolELF>(CurrentFnSym),
1914adae0cfdSpatrick                          MCConstantExpr::create(1, OutContext));
1915adae0cfdSpatrick     }
191609467b48Spatrick   }
191709467b48Spatrick }
191809467b48Spatrick 
191909467b48Spatrick /// EmitFunctionBodyEnd - Print the traceback table before the .size
192009467b48Spatrick /// directive.
192109467b48Spatrick ///
emitFunctionBodyEnd()1922adae0cfdSpatrick void PPCLinuxAsmPrinter::emitFunctionBodyEnd() {
192309467b48Spatrick   // Only the 64-bit target requires a traceback table.  For now,
192409467b48Spatrick   // we only emit the word of zeroes that GDB requires to find
192509467b48Spatrick   // the end of the function, and zeroes for the eight-byte
192609467b48Spatrick   // mandatory fields.
192709467b48Spatrick   // FIXME: We should fill in the eight-byte mandatory fields as described in
192809467b48Spatrick   // the PPC64 ELF ABI (this is a low-priority item because GDB does not
192909467b48Spatrick   // currently make use of these fields).
193009467b48Spatrick   if (Subtarget->isPPC64()) {
1931adae0cfdSpatrick     OutStreamer->emitIntValue(0, 4/*size*/);
1932adae0cfdSpatrick     OutStreamer->emitIntValue(0, 8/*size*/);
193309467b48Spatrick   }
193409467b48Spatrick }
193509467b48Spatrick 
emitLinkage(const GlobalValue * GV,MCSymbol * GVSym) const1936adae0cfdSpatrick void PPCAIXAsmPrinter::emitLinkage(const GlobalValue *GV,
1937adae0cfdSpatrick                                    MCSymbol *GVSym) const {
1938adae0cfdSpatrick 
1939adae0cfdSpatrick   assert(MAI->hasVisibilityOnlyWithLinkage() &&
1940adae0cfdSpatrick          "AIX's linkage directives take a visibility setting.");
1941adae0cfdSpatrick 
1942adae0cfdSpatrick   MCSymbolAttr LinkageAttr = MCSA_Invalid;
1943adae0cfdSpatrick   switch (GV->getLinkage()) {
1944adae0cfdSpatrick   case GlobalValue::ExternalLinkage:
1945adae0cfdSpatrick     LinkageAttr = GV->isDeclaration() ? MCSA_Extern : MCSA_Global;
1946adae0cfdSpatrick     break;
1947adae0cfdSpatrick   case GlobalValue::LinkOnceAnyLinkage:
1948adae0cfdSpatrick   case GlobalValue::LinkOnceODRLinkage:
1949adae0cfdSpatrick   case GlobalValue::WeakAnyLinkage:
1950adae0cfdSpatrick   case GlobalValue::WeakODRLinkage:
1951adae0cfdSpatrick   case GlobalValue::ExternalWeakLinkage:
1952adae0cfdSpatrick     LinkageAttr = MCSA_Weak;
1953adae0cfdSpatrick     break;
1954adae0cfdSpatrick   case GlobalValue::AvailableExternallyLinkage:
1955adae0cfdSpatrick     LinkageAttr = MCSA_Extern;
1956adae0cfdSpatrick     break;
1957adae0cfdSpatrick   case GlobalValue::PrivateLinkage:
1958adae0cfdSpatrick     return;
1959adae0cfdSpatrick   case GlobalValue::InternalLinkage:
1960adae0cfdSpatrick     assert(GV->getVisibility() == GlobalValue::DefaultVisibility &&
1961adae0cfdSpatrick            "InternalLinkage should not have other visibility setting.");
1962adae0cfdSpatrick     LinkageAttr = MCSA_LGlobal;
1963adae0cfdSpatrick     break;
1964adae0cfdSpatrick   case GlobalValue::AppendingLinkage:
1965adae0cfdSpatrick     llvm_unreachable("Should never emit this");
1966adae0cfdSpatrick   case GlobalValue::CommonLinkage:
1967adae0cfdSpatrick     llvm_unreachable("CommonLinkage of XCOFF should not come to this path");
1968adae0cfdSpatrick   }
1969adae0cfdSpatrick 
1970adae0cfdSpatrick   assert(LinkageAttr != MCSA_Invalid && "LinkageAttr should not MCSA_Invalid.");
1971adae0cfdSpatrick 
1972adae0cfdSpatrick   MCSymbolAttr VisibilityAttr = MCSA_Invalid;
1973a0747c9fSpatrick   if (!TM.getIgnoreXCOFFVisibility()) {
1974*a96b3639Srobert     if (GV->hasDLLExportStorageClass() && !GV->hasDefaultVisibility())
1975*a96b3639Srobert       report_fatal_error(
1976*a96b3639Srobert           "Cannot not be both dllexport and non-default visibility");
1977adae0cfdSpatrick     switch (GV->getVisibility()) {
1978adae0cfdSpatrick 
1979*a96b3639Srobert     // TODO: "internal" Visibility needs to go here.
1980adae0cfdSpatrick     case GlobalValue::DefaultVisibility:
1981*a96b3639Srobert       if (GV->hasDLLExportStorageClass())
1982*a96b3639Srobert         VisibilityAttr = MAI->getExportedVisibilityAttr();
1983adae0cfdSpatrick       break;
1984adae0cfdSpatrick     case GlobalValue::HiddenVisibility:
1985adae0cfdSpatrick       VisibilityAttr = MAI->getHiddenVisibilityAttr();
1986adae0cfdSpatrick       break;
1987adae0cfdSpatrick     case GlobalValue::ProtectedVisibility:
1988adae0cfdSpatrick       VisibilityAttr = MAI->getProtectedVisibilityAttr();
1989adae0cfdSpatrick       break;
1990adae0cfdSpatrick     }
1991a0747c9fSpatrick   }
1992adae0cfdSpatrick 
1993adae0cfdSpatrick   OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr,
1994adae0cfdSpatrick                                                     VisibilityAttr);
1995adae0cfdSpatrick }
1996adae0cfdSpatrick 
SetupMachineFunction(MachineFunction & MF)199709467b48Spatrick void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {
1998adae0cfdSpatrick   // Setup CurrentFnDescSym and its containing csect.
1999adae0cfdSpatrick   MCSectionXCOFF *FnDescSec =
2000adae0cfdSpatrick       cast<MCSectionXCOFF>(getObjFileLowering().getSectionForFunctionDescriptor(
2001adae0cfdSpatrick           &MF.getFunction(), TM));
2002adae0cfdSpatrick   FnDescSec->setAlignment(Align(Subtarget->isPPC64() ? 8 : 4));
2003adae0cfdSpatrick 
2004adae0cfdSpatrick   CurrentFnDescSym = FnDescSec->getQualNameSymbol();
200509467b48Spatrick 
200609467b48Spatrick   return AsmPrinter::SetupMachineFunction(MF);
200709467b48Spatrick }
200809467b48Spatrick 
getNumberOfVRSaved()2009a0747c9fSpatrick uint16_t PPCAIXAsmPrinter::getNumberOfVRSaved() {
2010a0747c9fSpatrick   // Calculate the number of VRs be saved.
2011a0747c9fSpatrick   // Vector registers 20 through 31 are marked as reserved and cannot be used
2012a0747c9fSpatrick   // in the default ABI.
2013a0747c9fSpatrick   const PPCSubtarget &Subtarget = MF->getSubtarget<PPCSubtarget>();
2014a0747c9fSpatrick   if (Subtarget.isAIXABI() && Subtarget.hasAltivec() &&
2015a0747c9fSpatrick       TM.getAIXExtendedAltivecABI()) {
2016a0747c9fSpatrick     const MachineRegisterInfo &MRI = MF->getRegInfo();
2017a0747c9fSpatrick     for (unsigned Reg = PPC::V20; Reg <= PPC::V31; ++Reg)
2018a0747c9fSpatrick       if (MRI.isPhysRegModified(Reg))
2019a0747c9fSpatrick         // Number of VRs saved.
2020a0747c9fSpatrick         return PPC::V31 - Reg + 1;
2021a0747c9fSpatrick   }
2022a0747c9fSpatrick   return 0;
2023a0747c9fSpatrick }
202409467b48Spatrick 
emitFunctionBodyEnd()2025a0747c9fSpatrick void PPCAIXAsmPrinter::emitFunctionBodyEnd() {
202609467b48Spatrick 
2027a0747c9fSpatrick   if (!TM.getXCOFFTracebackTable())
2028a0747c9fSpatrick     return;
2029a0747c9fSpatrick 
2030a0747c9fSpatrick   emitTracebackTable();
2031a0747c9fSpatrick 
2032a0747c9fSpatrick   // If ShouldEmitEHBlock returns true, then the eh info table
2033a0747c9fSpatrick   // will be emitted via `AIXException::endFunction`. Otherwise, we
2034a0747c9fSpatrick   // need to emit a dumy eh info table when VRs are saved. We could not
2035a0747c9fSpatrick   // consolidate these two places into one because there is no easy way
2036a0747c9fSpatrick   // to access register information in `AIXException` class.
2037a0747c9fSpatrick   if (!TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF) &&
2038a0747c9fSpatrick       (getNumberOfVRSaved() > 0)) {
2039a0747c9fSpatrick     // Emit dummy EH Info Table.
2040*a96b3639Srobert     OutStreamer->switchSection(getObjFileLowering().getCompactUnwindSection());
2041a0747c9fSpatrick     MCSymbol *EHInfoLabel =
2042a0747c9fSpatrick         TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(MF);
2043a0747c9fSpatrick     OutStreamer->emitLabel(EHInfoLabel);
2044a0747c9fSpatrick 
2045a0747c9fSpatrick     // Version number.
2046a0747c9fSpatrick     OutStreamer->emitInt32(0);
2047a0747c9fSpatrick 
2048a0747c9fSpatrick     const DataLayout &DL = MMI->getModule()->getDataLayout();
2049a0747c9fSpatrick     const unsigned PointerSize = DL.getPointerSize();
2050a0747c9fSpatrick     // Add necessary paddings in 64 bit mode.
2051*a96b3639Srobert     OutStreamer->emitValueToAlignment(Align(PointerSize));
2052a0747c9fSpatrick 
2053a0747c9fSpatrick     OutStreamer->emitIntValue(0, PointerSize);
2054a0747c9fSpatrick     OutStreamer->emitIntValue(0, PointerSize);
2055*a96b3639Srobert     OutStreamer->switchSection(MF->getSection());
2056a0747c9fSpatrick   }
2057a0747c9fSpatrick }
2058a0747c9fSpatrick 
emitTracebackTable()2059a0747c9fSpatrick void PPCAIXAsmPrinter::emitTracebackTable() {
2060a0747c9fSpatrick 
2061a0747c9fSpatrick   // Create a symbol for the end of function.
2062a0747c9fSpatrick   MCSymbol *FuncEnd = createTempSymbol(MF->getName());
2063a0747c9fSpatrick   OutStreamer->emitLabel(FuncEnd);
2064a0747c9fSpatrick 
2065a0747c9fSpatrick   OutStreamer->AddComment("Traceback table begin");
2066a0747c9fSpatrick   // Begin with a fullword of zero.
2067a0747c9fSpatrick   OutStreamer->emitIntValueInHexWithPadding(0, 4 /*size*/);
2068a0747c9fSpatrick 
2069a0747c9fSpatrick   SmallString<128> CommentString;
2070a0747c9fSpatrick   raw_svector_ostream CommentOS(CommentString);
2071a0747c9fSpatrick 
2072a0747c9fSpatrick   auto EmitComment = [&]() {
2073a0747c9fSpatrick     OutStreamer->AddComment(CommentOS.str());
2074a0747c9fSpatrick     CommentString.clear();
2075a0747c9fSpatrick   };
2076a0747c9fSpatrick 
2077a0747c9fSpatrick   auto EmitCommentAndValue = [&](uint64_t Value, int Size) {
2078a0747c9fSpatrick     EmitComment();
2079a0747c9fSpatrick     OutStreamer->emitIntValueInHexWithPadding(Value, Size);
2080a0747c9fSpatrick   };
2081a0747c9fSpatrick 
2082a0747c9fSpatrick   unsigned int Version = 0;
2083a0747c9fSpatrick   CommentOS << "Version = " << Version;
2084a0747c9fSpatrick   EmitCommentAndValue(Version, 1);
2085a0747c9fSpatrick 
2086a0747c9fSpatrick   // There is a lack of information in the IR to assist with determining the
2087a0747c9fSpatrick   // source language. AIX exception handling mechanism would only search for
2088a0747c9fSpatrick   // personality routine and LSDA area when such language supports exception
2089a0747c9fSpatrick   // handling. So to be conservatively correct and allow runtime to do its job,
2090a0747c9fSpatrick   // we need to set it to C++ for now.
2091a0747c9fSpatrick   TracebackTable::LanguageID LanguageIdentifier =
2092a0747c9fSpatrick       TracebackTable::CPlusPlus; // C++
2093a0747c9fSpatrick 
2094a0747c9fSpatrick   CommentOS << "Language = "
2095a0747c9fSpatrick             << getNameForTracebackTableLanguageId(LanguageIdentifier);
2096a0747c9fSpatrick   EmitCommentAndValue(LanguageIdentifier, 1);
2097a0747c9fSpatrick 
2098a0747c9fSpatrick   //  This is only populated for the third and fourth bytes.
2099a0747c9fSpatrick   uint32_t FirstHalfOfMandatoryField = 0;
2100a0747c9fSpatrick 
2101a0747c9fSpatrick   // Emit the 3rd byte of the mandatory field.
2102a0747c9fSpatrick 
2103a0747c9fSpatrick   // We always set traceback offset bit to true.
2104a0747c9fSpatrick   FirstHalfOfMandatoryField |= TracebackTable::HasTraceBackTableOffsetMask;
2105a0747c9fSpatrick 
2106a0747c9fSpatrick   const PPCFunctionInfo *FI = MF->getInfo<PPCFunctionInfo>();
2107a0747c9fSpatrick   const MachineRegisterInfo &MRI = MF->getRegInfo();
2108a0747c9fSpatrick 
2109a0747c9fSpatrick   // Check the function uses floating-point processor instructions or not
2110a0747c9fSpatrick   for (unsigned Reg = PPC::F0; Reg <= PPC::F31; ++Reg) {
2111a0747c9fSpatrick     if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {
2112a0747c9fSpatrick       FirstHalfOfMandatoryField |= TracebackTable::IsFloatingPointPresentMask;
2113a0747c9fSpatrick       break;
2114a0747c9fSpatrick     }
2115a0747c9fSpatrick   }
2116a0747c9fSpatrick 
2117a0747c9fSpatrick #define GENBOOLCOMMENT(Prefix, V, Field)                                       \
2118a0747c9fSpatrick   CommentOS << (Prefix) << ((V) & (TracebackTable::Field##Mask) ? "+" : "-")   \
2119a0747c9fSpatrick             << #Field
2120a0747c9fSpatrick 
2121a0747c9fSpatrick #define GENVALUECOMMENT(PrefixAndName, V, Field)                               \
2122a0747c9fSpatrick   CommentOS << (PrefixAndName) << " = "                                        \
2123a0747c9fSpatrick             << static_cast<unsigned>(((V) & (TracebackTable::Field##Mask)) >>  \
2124a0747c9fSpatrick                                      (TracebackTable::Field##Shift))
2125a0747c9fSpatrick 
2126a0747c9fSpatrick   GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsGlobaLinkage);
2127a0747c9fSpatrick   GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsOutOfLineEpilogOrPrologue);
2128a0747c9fSpatrick   EmitComment();
2129a0747c9fSpatrick 
2130a0747c9fSpatrick   GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasTraceBackTableOffset);
2131a0747c9fSpatrick   GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsInternalProcedure);
2132a0747c9fSpatrick   EmitComment();
2133a0747c9fSpatrick 
2134a0747c9fSpatrick   GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasControlledStorage);
2135a0747c9fSpatrick   GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsTOCless);
2136a0747c9fSpatrick   EmitComment();
2137a0747c9fSpatrick 
2138a0747c9fSpatrick   GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsFloatingPointPresent);
2139a0747c9fSpatrick   EmitComment();
2140a0747c9fSpatrick   GENBOOLCOMMENT("", FirstHalfOfMandatoryField,
2141a0747c9fSpatrick                  IsFloatingPointOperationLogOrAbortEnabled);
2142a0747c9fSpatrick   EmitComment();
2143a0747c9fSpatrick 
2144a0747c9fSpatrick   OutStreamer->emitIntValueInHexWithPadding(
2145a0747c9fSpatrick       (FirstHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2146a0747c9fSpatrick 
2147a0747c9fSpatrick   // Set the 4th byte of the mandatory field.
2148a0747c9fSpatrick   FirstHalfOfMandatoryField |= TracebackTable::IsFunctionNamePresentMask;
2149a0747c9fSpatrick 
2150*a96b3639Srobert   const PPCRegisterInfo *RegInfo =
2151*a96b3639Srobert       static_cast<const PPCRegisterInfo *>(Subtarget->getRegisterInfo());
2152*a96b3639Srobert   Register FrameReg = RegInfo->getFrameRegister(*MF);
2153*a96b3639Srobert   if (FrameReg == (Subtarget->isPPC64() ? PPC::X31 : PPC::R31))
2154a0747c9fSpatrick     FirstHalfOfMandatoryField |= TracebackTable::IsAllocaUsedMask;
2155a0747c9fSpatrick 
2156a0747c9fSpatrick   const SmallVectorImpl<Register> &MustSaveCRs = FI->getMustSaveCRs();
2157a0747c9fSpatrick   if (!MustSaveCRs.empty())
2158a0747c9fSpatrick     FirstHalfOfMandatoryField |= TracebackTable::IsCRSavedMask;
2159a0747c9fSpatrick 
2160a0747c9fSpatrick   if (FI->mustSaveLR())
2161a0747c9fSpatrick     FirstHalfOfMandatoryField |= TracebackTable::IsLRSavedMask;
2162a0747c9fSpatrick 
2163a0747c9fSpatrick   GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsInterruptHandler);
2164a0747c9fSpatrick   GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsFunctionNamePresent);
2165a0747c9fSpatrick   GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsAllocaUsed);
2166a0747c9fSpatrick   EmitComment();
2167a0747c9fSpatrick   GENVALUECOMMENT("OnConditionDirective", FirstHalfOfMandatoryField,
2168a0747c9fSpatrick                   OnConditionDirective);
2169a0747c9fSpatrick   GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsCRSaved);
2170a0747c9fSpatrick   GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsLRSaved);
2171a0747c9fSpatrick   EmitComment();
2172a0747c9fSpatrick   OutStreamer->emitIntValueInHexWithPadding((FirstHalfOfMandatoryField & 0xff),
2173a0747c9fSpatrick                                             1);
2174a0747c9fSpatrick 
2175a0747c9fSpatrick   // Set the 5th byte of mandatory field.
2176a0747c9fSpatrick   uint32_t SecondHalfOfMandatoryField = 0;
2177a0747c9fSpatrick 
2178a0747c9fSpatrick   // Always store back chain.
2179a0747c9fSpatrick   SecondHalfOfMandatoryField |= TracebackTable::IsBackChainStoredMask;
2180a0747c9fSpatrick 
2181a0747c9fSpatrick   uint32_t FPRSaved = 0;
2182a0747c9fSpatrick   for (unsigned Reg = PPC::F14; Reg <= PPC::F31; ++Reg) {
2183a0747c9fSpatrick     if (MRI.isPhysRegModified(Reg)) {
2184a0747c9fSpatrick       FPRSaved = PPC::F31 - Reg + 1;
2185a0747c9fSpatrick       break;
2186a0747c9fSpatrick     }
2187a0747c9fSpatrick   }
2188a0747c9fSpatrick   SecondHalfOfMandatoryField |= (FPRSaved << TracebackTable::FPRSavedShift) &
2189a0747c9fSpatrick                                 TracebackTable::FPRSavedMask;
2190a0747c9fSpatrick   GENBOOLCOMMENT("", SecondHalfOfMandatoryField, IsBackChainStored);
2191a0747c9fSpatrick   GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, IsFixup);
2192a0747c9fSpatrick   GENVALUECOMMENT(", NumOfFPRsSaved", SecondHalfOfMandatoryField, FPRSaved);
2193a0747c9fSpatrick   EmitComment();
2194a0747c9fSpatrick   OutStreamer->emitIntValueInHexWithPadding(
2195a0747c9fSpatrick       (SecondHalfOfMandatoryField & 0xff000000) >> 24, 1);
2196a0747c9fSpatrick 
2197a0747c9fSpatrick   // Set the 6th byte of mandatory field.
2198a0747c9fSpatrick 
2199a0747c9fSpatrick   // Check whether has Vector Instruction,We only treat instructions uses vector
2200a0747c9fSpatrick   // register as vector instructions.
2201a0747c9fSpatrick   bool HasVectorInst = false;
2202a0747c9fSpatrick   for (unsigned Reg = PPC::V0; Reg <= PPC::V31; ++Reg)
2203a0747c9fSpatrick     if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {
2204a0747c9fSpatrick       // Has VMX instruction.
2205a0747c9fSpatrick       HasVectorInst = true;
2206a0747c9fSpatrick       break;
2207a0747c9fSpatrick     }
2208a0747c9fSpatrick 
2209a0747c9fSpatrick   if (FI->hasVectorParms() || HasVectorInst)
2210a0747c9fSpatrick     SecondHalfOfMandatoryField |= TracebackTable::HasVectorInfoMask;
2211a0747c9fSpatrick 
2212a0747c9fSpatrick   uint16_t NumOfVRSaved = getNumberOfVRSaved();
2213a0747c9fSpatrick   bool ShouldEmitEHBlock =
2214a0747c9fSpatrick       TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF) || NumOfVRSaved > 0;
2215a0747c9fSpatrick 
2216a0747c9fSpatrick   if (ShouldEmitEHBlock)
2217a0747c9fSpatrick     SecondHalfOfMandatoryField |= TracebackTable::HasExtensionTableMask;
2218a0747c9fSpatrick 
2219a0747c9fSpatrick   uint32_t GPRSaved = 0;
2220a0747c9fSpatrick 
2221a0747c9fSpatrick   // X13 is reserved under 64-bit environment.
2222a0747c9fSpatrick   unsigned GPRBegin = Subtarget->isPPC64() ? PPC::X14 : PPC::R13;
2223a0747c9fSpatrick   unsigned GPREnd = Subtarget->isPPC64() ? PPC::X31 : PPC::R31;
2224a0747c9fSpatrick 
2225a0747c9fSpatrick   for (unsigned Reg = GPRBegin; Reg <= GPREnd; ++Reg) {
2226a0747c9fSpatrick     if (MRI.isPhysRegModified(Reg)) {
2227a0747c9fSpatrick       GPRSaved = GPREnd - Reg + 1;
2228a0747c9fSpatrick       break;
2229a0747c9fSpatrick     }
2230a0747c9fSpatrick   }
2231a0747c9fSpatrick 
2232a0747c9fSpatrick   SecondHalfOfMandatoryField |= (GPRSaved << TracebackTable::GPRSavedShift) &
2233a0747c9fSpatrick                                 TracebackTable::GPRSavedMask;
2234a0747c9fSpatrick 
2235a0747c9fSpatrick   GENBOOLCOMMENT("", SecondHalfOfMandatoryField, HasExtensionTable);
2236a0747c9fSpatrick   GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasVectorInfo);
2237a0747c9fSpatrick   GENVALUECOMMENT(", NumOfGPRsSaved", SecondHalfOfMandatoryField, GPRSaved);
2238a0747c9fSpatrick   EmitComment();
2239a0747c9fSpatrick   OutStreamer->emitIntValueInHexWithPadding(
2240a0747c9fSpatrick       (SecondHalfOfMandatoryField & 0x00ff0000) >> 16, 1);
2241a0747c9fSpatrick 
2242a0747c9fSpatrick   // Set the 7th byte of mandatory field.
2243a0747c9fSpatrick   uint32_t NumberOfFixedParms = FI->getFixedParmsNum();
2244a0747c9fSpatrick   SecondHalfOfMandatoryField |=
2245a0747c9fSpatrick       (NumberOfFixedParms << TracebackTable::NumberOfFixedParmsShift) &
2246a0747c9fSpatrick       TracebackTable::NumberOfFixedParmsMask;
2247a0747c9fSpatrick   GENVALUECOMMENT("NumberOfFixedParms", SecondHalfOfMandatoryField,
2248a0747c9fSpatrick                   NumberOfFixedParms);
2249a0747c9fSpatrick   EmitComment();
2250a0747c9fSpatrick   OutStreamer->emitIntValueInHexWithPadding(
2251a0747c9fSpatrick       (SecondHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2252a0747c9fSpatrick 
2253a0747c9fSpatrick   // Set the 8th byte of mandatory field.
2254a0747c9fSpatrick 
2255a0747c9fSpatrick   // Always set parameter on stack.
2256a0747c9fSpatrick   SecondHalfOfMandatoryField |= TracebackTable::HasParmsOnStackMask;
2257a0747c9fSpatrick 
2258a0747c9fSpatrick   uint32_t NumberOfFPParms = FI->getFloatingPointParmsNum();
2259a0747c9fSpatrick   SecondHalfOfMandatoryField |=
2260a0747c9fSpatrick       (NumberOfFPParms << TracebackTable::NumberOfFloatingPointParmsShift) &
2261a0747c9fSpatrick       TracebackTable::NumberOfFloatingPointParmsMask;
2262a0747c9fSpatrick 
2263a0747c9fSpatrick   GENVALUECOMMENT("NumberOfFPParms", SecondHalfOfMandatoryField,
2264a0747c9fSpatrick                   NumberOfFloatingPointParms);
2265a0747c9fSpatrick   GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasParmsOnStack);
2266a0747c9fSpatrick   EmitComment();
2267a0747c9fSpatrick   OutStreamer->emitIntValueInHexWithPadding(SecondHalfOfMandatoryField & 0xff,
2268a0747c9fSpatrick                                             1);
2269a0747c9fSpatrick 
2270a0747c9fSpatrick   // Generate the optional fields of traceback table.
2271a0747c9fSpatrick 
2272a0747c9fSpatrick   // Parameter type.
2273a0747c9fSpatrick   if (NumberOfFixedParms || NumberOfFPParms) {
2274a0747c9fSpatrick     uint32_t ParmsTypeValue = FI->getParmsType();
2275a0747c9fSpatrick 
2276a0747c9fSpatrick     Expected<SmallString<32>> ParmsType =
2277a0747c9fSpatrick         FI->hasVectorParms()
2278a0747c9fSpatrick             ? XCOFF::parseParmsTypeWithVecInfo(
2279a0747c9fSpatrick                   ParmsTypeValue, NumberOfFixedParms, NumberOfFPParms,
2280a0747c9fSpatrick                   FI->getVectorParmsNum())
2281a0747c9fSpatrick             : XCOFF::parseParmsType(ParmsTypeValue, NumberOfFixedParms,
2282a0747c9fSpatrick                                     NumberOfFPParms);
2283a0747c9fSpatrick 
2284a0747c9fSpatrick     assert(ParmsType && toString(ParmsType.takeError()).c_str());
2285a0747c9fSpatrick     if (ParmsType) {
2286a0747c9fSpatrick       CommentOS << "Parameter type = " << ParmsType.get();
2287a0747c9fSpatrick       EmitComment();
2288a0747c9fSpatrick     }
2289a0747c9fSpatrick     OutStreamer->emitIntValueInHexWithPadding(ParmsTypeValue,
2290a0747c9fSpatrick                                               sizeof(ParmsTypeValue));
2291a0747c9fSpatrick   }
2292a0747c9fSpatrick   // Traceback table offset.
2293a0747c9fSpatrick   OutStreamer->AddComment("Function size");
2294a0747c9fSpatrick   if (FirstHalfOfMandatoryField & TracebackTable::HasTraceBackTableOffsetMask) {
2295a0747c9fSpatrick     MCSymbol *FuncSectSym = getObjFileLowering().getFunctionEntryPointSymbol(
2296a0747c9fSpatrick         &(MF->getFunction()), TM);
2297a0747c9fSpatrick     OutStreamer->emitAbsoluteSymbolDiff(FuncEnd, FuncSectSym, 4);
2298a0747c9fSpatrick   }
2299a0747c9fSpatrick 
2300a0747c9fSpatrick   // Since we unset the Int_Handler.
2301a0747c9fSpatrick   if (FirstHalfOfMandatoryField & TracebackTable::IsInterruptHandlerMask)
2302a0747c9fSpatrick     report_fatal_error("Hand_Mask not implement yet");
2303a0747c9fSpatrick 
2304a0747c9fSpatrick   if (FirstHalfOfMandatoryField & TracebackTable::HasControlledStorageMask)
2305a0747c9fSpatrick     report_fatal_error("Ctl_Info not implement yet");
2306a0747c9fSpatrick 
2307a0747c9fSpatrick   if (FirstHalfOfMandatoryField & TracebackTable::IsFunctionNamePresentMask) {
2308a0747c9fSpatrick     StringRef Name = MF->getName().substr(0, INT16_MAX);
2309a0747c9fSpatrick     int16_t NameLength = Name.size();
2310a0747c9fSpatrick     CommentOS << "Function name len = "
2311a0747c9fSpatrick               << static_cast<unsigned int>(NameLength);
2312a0747c9fSpatrick     EmitCommentAndValue(NameLength, 2);
2313a0747c9fSpatrick     OutStreamer->AddComment("Function Name");
2314a0747c9fSpatrick     OutStreamer->emitBytes(Name);
2315a0747c9fSpatrick   }
2316a0747c9fSpatrick 
2317a0747c9fSpatrick   if (FirstHalfOfMandatoryField & TracebackTable::IsAllocaUsedMask) {
2318a0747c9fSpatrick     uint8_t AllocReg = XCOFF::AllocRegNo;
2319a0747c9fSpatrick     OutStreamer->AddComment("AllocaUsed");
2320a0747c9fSpatrick     OutStreamer->emitIntValueInHex(AllocReg, sizeof(AllocReg));
2321a0747c9fSpatrick   }
2322a0747c9fSpatrick 
2323a0747c9fSpatrick   if (SecondHalfOfMandatoryField & TracebackTable::HasVectorInfoMask) {
2324a0747c9fSpatrick     uint16_t VRData = 0;
2325a0747c9fSpatrick     if (NumOfVRSaved) {
2326a0747c9fSpatrick       // Number of VRs saved.
2327a0747c9fSpatrick       VRData |= (NumOfVRSaved << TracebackTable::NumberOfVRSavedShift) &
2328a0747c9fSpatrick                 TracebackTable::NumberOfVRSavedMask;
2329a0747c9fSpatrick       // This bit is supposed to set only when the special register
2330a0747c9fSpatrick       // VRSAVE is saved on stack.
2331a0747c9fSpatrick       // However, IBM XL compiler sets the bit when any vector registers
2332a0747c9fSpatrick       // are saved on the stack. We will follow XL's behavior on AIX
2333a0747c9fSpatrick       // so that we don't get surprise behavior change for C code.
2334a0747c9fSpatrick       VRData |= TracebackTable::IsVRSavedOnStackMask;
2335a0747c9fSpatrick     }
2336a0747c9fSpatrick 
2337a0747c9fSpatrick     // Set has_varargs.
2338a0747c9fSpatrick     if (FI->getVarArgsFrameIndex())
2339a0747c9fSpatrick       VRData |= TracebackTable::HasVarArgsMask;
2340a0747c9fSpatrick 
2341a0747c9fSpatrick     // Vector parameters number.
2342a0747c9fSpatrick     unsigned VectorParmsNum = FI->getVectorParmsNum();
2343a0747c9fSpatrick     VRData |= (VectorParmsNum << TracebackTable::NumberOfVectorParmsShift) &
2344a0747c9fSpatrick               TracebackTable::NumberOfVectorParmsMask;
2345a0747c9fSpatrick 
2346a0747c9fSpatrick     if (HasVectorInst)
2347a0747c9fSpatrick       VRData |= TracebackTable::HasVMXInstructionMask;
2348a0747c9fSpatrick 
2349a0747c9fSpatrick     GENVALUECOMMENT("NumOfVRsSaved", VRData, NumberOfVRSaved);
2350a0747c9fSpatrick     GENBOOLCOMMENT(", ", VRData, IsVRSavedOnStack);
2351a0747c9fSpatrick     GENBOOLCOMMENT(", ", VRData, HasVarArgs);
2352a0747c9fSpatrick     EmitComment();
2353a0747c9fSpatrick     OutStreamer->emitIntValueInHexWithPadding((VRData & 0xff00) >> 8, 1);
2354a0747c9fSpatrick 
2355a0747c9fSpatrick     GENVALUECOMMENT("NumOfVectorParams", VRData, NumberOfVectorParms);
2356a0747c9fSpatrick     GENBOOLCOMMENT(", ", VRData, HasVMXInstruction);
2357a0747c9fSpatrick     EmitComment();
2358a0747c9fSpatrick     OutStreamer->emitIntValueInHexWithPadding(VRData & 0x00ff, 1);
2359a0747c9fSpatrick 
2360a0747c9fSpatrick     uint32_t VecParmTypeValue = FI->getVecExtParmsType();
2361a0747c9fSpatrick 
2362a0747c9fSpatrick     Expected<SmallString<32>> VecParmsType =
2363a0747c9fSpatrick         XCOFF::parseVectorParmsType(VecParmTypeValue, VectorParmsNum);
2364a0747c9fSpatrick     assert(VecParmsType && toString(VecParmsType.takeError()).c_str());
2365a0747c9fSpatrick     if (VecParmsType) {
2366a0747c9fSpatrick       CommentOS << "Vector Parameter type = " << VecParmsType.get();
2367a0747c9fSpatrick       EmitComment();
2368a0747c9fSpatrick     }
2369a0747c9fSpatrick     OutStreamer->emitIntValueInHexWithPadding(VecParmTypeValue,
2370a0747c9fSpatrick                                               sizeof(VecParmTypeValue));
2371a0747c9fSpatrick     // Padding 2 bytes.
2372a0747c9fSpatrick     CommentOS << "Padding";
2373a0747c9fSpatrick     EmitCommentAndValue(0, 2);
2374a0747c9fSpatrick   }
2375a0747c9fSpatrick 
2376a0747c9fSpatrick   uint8_t ExtensionTableFlag = 0;
2377a0747c9fSpatrick   if (SecondHalfOfMandatoryField & TracebackTable::HasExtensionTableMask) {
2378a0747c9fSpatrick     if (ShouldEmitEHBlock)
2379a0747c9fSpatrick       ExtensionTableFlag |= ExtendedTBTableFlag::TB_EH_INFO;
2380a0747c9fSpatrick     if (EnableSSPCanaryBitInTB &&
2381a0747c9fSpatrick         TargetLoweringObjectFileXCOFF::ShouldSetSSPCanaryBitInTB(MF))
2382a0747c9fSpatrick       ExtensionTableFlag |= ExtendedTBTableFlag::TB_SSP_CANARY;
2383a0747c9fSpatrick 
2384a0747c9fSpatrick     CommentOS << "ExtensionTableFlag = "
2385a0747c9fSpatrick               << getExtendedTBTableFlagString(ExtensionTableFlag);
2386a0747c9fSpatrick     EmitCommentAndValue(ExtensionTableFlag, sizeof(ExtensionTableFlag));
2387a0747c9fSpatrick   }
2388a0747c9fSpatrick 
2389a0747c9fSpatrick   if (ExtensionTableFlag & ExtendedTBTableFlag::TB_EH_INFO) {
2390a0747c9fSpatrick     auto &Ctx = OutStreamer->getContext();
2391a0747c9fSpatrick     MCSymbol *EHInfoSym =
2392a0747c9fSpatrick         TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(MF);
2393a0747c9fSpatrick     MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(EHInfoSym);
2394a0747c9fSpatrick     const MCSymbol *TOCBaseSym =
2395a0747c9fSpatrick         cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection())
2396a0747c9fSpatrick             ->getQualNameSymbol();
2397a0747c9fSpatrick     const MCExpr *Exp =
2398a0747c9fSpatrick         MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCEntry, Ctx),
2399a0747c9fSpatrick                                 MCSymbolRefExpr::create(TOCBaseSym, Ctx), Ctx);
2400a0747c9fSpatrick 
2401a0747c9fSpatrick     const DataLayout &DL = getDataLayout();
2402*a96b3639Srobert     OutStreamer->emitValueToAlignment(Align(4));
2403a0747c9fSpatrick     OutStreamer->AddComment("EHInfo Table");
2404a0747c9fSpatrick     OutStreamer->emitValue(Exp, DL.getPointerSize());
2405a0747c9fSpatrick   }
2406a0747c9fSpatrick #undef GENBOOLCOMMENT
2407a0747c9fSpatrick #undef GENVALUECOMMENT
2408a0747c9fSpatrick }
2409a0747c9fSpatrick 
isSpecialLLVMGlobalArrayToSkip(const GlobalVariable * GV)2410a0747c9fSpatrick static bool isSpecialLLVMGlobalArrayToSkip(const GlobalVariable *GV) {
2411a0747c9fSpatrick   return GV->hasAppendingLinkage() &&
2412a0747c9fSpatrick          StringSwitch<bool>(GV->getName())
2413a0747c9fSpatrick              // TODO: Linker could still eliminate the GV if we just skip
2414a0747c9fSpatrick              // handling llvm.used array. Skipping them for now until we or the
2415a0747c9fSpatrick              // AIX OS team come up with a good solution.
2416a0747c9fSpatrick              .Case("llvm.used", true)
2417a0747c9fSpatrick              // It's correct to just skip llvm.compiler.used array here.
2418a0747c9fSpatrick              .Case("llvm.compiler.used", true)
2419a0747c9fSpatrick              .Default(false);
242009467b48Spatrick }
242109467b48Spatrick 
isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable * GV)2422adae0cfdSpatrick static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV) {
2423adae0cfdSpatrick   return StringSwitch<bool>(GV->getName())
2424adae0cfdSpatrick       .Cases("llvm.global_ctors", "llvm.global_dtors", true)
2425adae0cfdSpatrick       .Default(false);
242609467b48Spatrick }
242709467b48Spatrick 
getAliasOffset(const Constant * C)2428*a96b3639Srobert uint64_t PPCAIXAsmPrinter::getAliasOffset(const Constant *C) {
2429*a96b3639Srobert   if (auto *GA = dyn_cast<GlobalAlias>(C))
2430*a96b3639Srobert     return getAliasOffset(GA->getAliasee());
2431*a96b3639Srobert   if (auto *CE = dyn_cast<ConstantExpr>(C)) {
2432*a96b3639Srobert     const MCExpr *LowC = lowerConstant(CE);
2433*a96b3639Srobert     const MCBinaryExpr *CBE = dyn_cast<MCBinaryExpr>(LowC);
2434*a96b3639Srobert     if (!CBE)
2435*a96b3639Srobert       return 0;
2436*a96b3639Srobert     if (CBE->getOpcode() != MCBinaryExpr::Add)
2437*a96b3639Srobert       report_fatal_error("Only adding an offset is supported now.");
2438*a96b3639Srobert     auto *RHS = dyn_cast<MCConstantExpr>(CBE->getRHS());
2439*a96b3639Srobert     if (!RHS)
2440*a96b3639Srobert       report_fatal_error("Unable to get the offset of alias.");
2441*a96b3639Srobert     return RHS->getValue();
2442*a96b3639Srobert   }
2443*a96b3639Srobert   return 0;
2444*a96b3639Srobert }
2445*a96b3639Srobert 
emitGlobalVariable(const GlobalVariable * GV)2446adae0cfdSpatrick void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
2447a0747c9fSpatrick   // Special LLVM global arrays have been handled at the initialization.
2448a0747c9fSpatrick   if (isSpecialLLVMGlobalArrayToSkip(GV) || isSpecialLLVMGlobalArrayForStaticInit(GV))
244909467b48Spatrick     return;
245009467b48Spatrick 
2451a0747c9fSpatrick   // If the Global Variable has the toc-data attribute, it needs to be emitted
2452a0747c9fSpatrick   // when we emit the .toc section.
2453a0747c9fSpatrick   if (GV->hasAttribute("toc-data")) {
2454a0747c9fSpatrick     TOCDataGlobalVars.push_back(GV);
2455a0747c9fSpatrick     return;
2456a0747c9fSpatrick   }
2457a0747c9fSpatrick 
2458a0747c9fSpatrick   emitGlobalVariableHelper(GV);
2459a0747c9fSpatrick }
2460a0747c9fSpatrick 
emitGlobalVariableHelper(const GlobalVariable * GV)2461a0747c9fSpatrick void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {
2462a0747c9fSpatrick   assert(!GV->getName().startswith("llvm.") &&
2463a0747c9fSpatrick          "Unhandled intrinsic global variable.");
2464a0747c9fSpatrick 
2465a0747c9fSpatrick   if (GV->hasComdat())
2466a0747c9fSpatrick     report_fatal_error("COMDAT not yet supported by AIX.");
2467a0747c9fSpatrick 
246809467b48Spatrick   MCSymbolXCOFF *GVSym = cast<MCSymbolXCOFF>(getSymbol(GV));
246909467b48Spatrick 
2470adae0cfdSpatrick   if (GV->isDeclarationForLinker()) {
2471adae0cfdSpatrick     emitLinkage(GV, GVSym);
2472adae0cfdSpatrick     return;
2473adae0cfdSpatrick   }
2474adae0cfdSpatrick 
247509467b48Spatrick   SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
2476a0747c9fSpatrick   if (!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly() &&
2477a0747c9fSpatrick       !GVKind.isThreadLocal()) // Checks for both ThreadData and ThreadBSS.
247809467b48Spatrick     report_fatal_error("Encountered a global variable kind that is "
247909467b48Spatrick                        "not supported yet.");
248009467b48Spatrick 
2481a0747c9fSpatrick   // Print GV in verbose mode
2482a0747c9fSpatrick   if (isVerbose()) {
2483a0747c9fSpatrick     if (GV->hasInitializer()) {
2484*a96b3639Srobert       GV->printAsOperand(OutStreamer->getCommentOS(),
2485a0747c9fSpatrick                          /*PrintType=*/false, GV->getParent());
2486*a96b3639Srobert       OutStreamer->getCommentOS() << '\n';
2487a0747c9fSpatrick     }
2488a0747c9fSpatrick   }
2489a0747c9fSpatrick 
249009467b48Spatrick   MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(
249109467b48Spatrick       getObjFileLowering().SectionForGlobal(GV, GVKind, TM));
2492adae0cfdSpatrick 
2493adae0cfdSpatrick   // Switch to the containing csect.
2494*a96b3639Srobert   OutStreamer->switchSection(Csect);
249509467b48Spatrick 
249609467b48Spatrick   const DataLayout &DL = GV->getParent()->getDataLayout();
249709467b48Spatrick 
2498a0747c9fSpatrick   // Handle common and zero-initialized local symbols.
2499a0747c9fSpatrick   if (GV->hasCommonLinkage() || GVKind.isBSSLocal() ||
2500a0747c9fSpatrick       GVKind.isThreadBSSLocal()) {
2501*a96b3639Srobert     Align Alignment = GV->getAlign().value_or(DL.getPreferredAlign(GV));
2502a0747c9fSpatrick     uint64_t Size = DL.getTypeAllocSize(GV->getValueType());
2503a0747c9fSpatrick     GVSym->setStorageClass(
2504a0747c9fSpatrick         TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV));
250509467b48Spatrick 
2506a0747c9fSpatrick     if (GVKind.isBSSLocal() || GVKind.isThreadBSSLocal())
2507adae0cfdSpatrick       OutStreamer->emitXCOFFLocalCommonSymbol(
2508a0747c9fSpatrick           OutContext.getOrCreateSymbol(GVSym->getSymbolTableName()), Size,
2509*a96b3639Srobert           GVSym, Alignment);
251009467b48Spatrick     else
2511*a96b3639Srobert       OutStreamer->emitCommonSymbol(GVSym, Size, Alignment);
251209467b48Spatrick     return;
251309467b48Spatrick   }
251409467b48Spatrick 
251509467b48Spatrick   MCSymbol *EmittedInitSym = GVSym;
2516*a96b3639Srobert 
2517*a96b3639Srobert   // Emit linkage for the global variable and its aliases.
2518adae0cfdSpatrick   emitLinkage(GV, EmittedInitSym);
2519*a96b3639Srobert   for (const GlobalAlias *GA : GOAliasMap[GV])
2520*a96b3639Srobert     emitLinkage(GA, getSymbol(GA));
2521*a96b3639Srobert 
2522adae0cfdSpatrick   emitAlignment(getGVAlignment(GV, DL), GV);
2523a0747c9fSpatrick 
2524a0747c9fSpatrick   // When -fdata-sections is enabled, every GlobalVariable will
2525a0747c9fSpatrick   // be put into its own csect; therefore, label is not necessary here.
2526*a96b3639Srobert   if (!TM.getDataSections() || GV->hasSection())
2527adae0cfdSpatrick     OutStreamer->emitLabel(EmittedInitSym);
2528*a96b3639Srobert 
2529*a96b3639Srobert   // No alias to emit.
2530*a96b3639Srobert   if (!GOAliasMap[GV].size()) {
2531*a96b3639Srobert     emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer());
2532*a96b3639Srobert     return;
2533a0747c9fSpatrick   }
2534a0747c9fSpatrick 
2535*a96b3639Srobert   // Aliases with the same offset should be aligned. Record the list of aliases
2536*a96b3639Srobert   // associated with the offset.
2537*a96b3639Srobert   AliasMapTy AliasList;
2538*a96b3639Srobert   for (const GlobalAlias *GA : GOAliasMap[GV])
2539*a96b3639Srobert     AliasList[getAliasOffset(GA->getAliasee())].push_back(GA);
2540a0747c9fSpatrick 
2541*a96b3639Srobert   // Emit alias label and element value for global variable.
2542*a96b3639Srobert   emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer(),
2543*a96b3639Srobert                      &AliasList);
254409467b48Spatrick }
254509467b48Spatrick 
emitFunctionDescriptor()2546adae0cfdSpatrick void PPCAIXAsmPrinter::emitFunctionDescriptor() {
254709467b48Spatrick   const DataLayout &DL = getDataLayout();
254809467b48Spatrick   const unsigned PointerSize = DL.getPointerSizeInBits() == 64 ? 8 : 4;
254909467b48Spatrick 
255009467b48Spatrick   MCSectionSubPair Current = OutStreamer->getCurrentSection();
255109467b48Spatrick   // Emit function descriptor.
2552*a96b3639Srobert   OutStreamer->switchSection(
2553adae0cfdSpatrick       cast<MCSymbolXCOFF>(CurrentFnDescSym)->getRepresentedCsect());
2554a0747c9fSpatrick 
2555a0747c9fSpatrick   // Emit aliasing label for function descriptor csect.
2556*a96b3639Srobert   for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])
2557a0747c9fSpatrick     OutStreamer->emitLabel(getSymbol(Alias));
2558a0747c9fSpatrick 
255909467b48Spatrick   // Emit function entry point address.
2560adae0cfdSpatrick   OutStreamer->emitValue(MCSymbolRefExpr::create(CurrentFnSym, OutContext),
256109467b48Spatrick                          PointerSize);
256209467b48Spatrick   // Emit TOC base address.
2563adae0cfdSpatrick   const MCSymbol *TOCBaseSym =
2564adae0cfdSpatrick       cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection())
2565adae0cfdSpatrick           ->getQualNameSymbol();
2566adae0cfdSpatrick   OutStreamer->emitValue(MCSymbolRefExpr::create(TOCBaseSym, OutContext),
256709467b48Spatrick                          PointerSize);
256809467b48Spatrick   // Emit a null environment pointer.
2569adae0cfdSpatrick   OutStreamer->emitIntValue(0, PointerSize);
257009467b48Spatrick 
2571*a96b3639Srobert   OutStreamer->switchSection(Current.first, Current.second);
257209467b48Spatrick }
257309467b48Spatrick 
emitFunctionEntryLabel()2574a0747c9fSpatrick void PPCAIXAsmPrinter::emitFunctionEntryLabel() {
2575a0747c9fSpatrick   // It's not necessary to emit the label when we have individual
2576a0747c9fSpatrick   // function in its own csect.
2577a0747c9fSpatrick   if (!TM.getFunctionSections())
2578a0747c9fSpatrick     PPCAsmPrinter::emitFunctionEntryLabel();
2579a0747c9fSpatrick 
2580a0747c9fSpatrick   // Emit aliasing label for function entry point label.
2581*a96b3639Srobert   for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])
2582a0747c9fSpatrick     OutStreamer->emitLabel(
2583a0747c9fSpatrick         getObjFileLowering().getFunctionEntryPointSymbol(Alias, TM));
2584*a96b3639Srobert }
2585*a96b3639Srobert 
emitPGORefs()2586*a96b3639Srobert void PPCAIXAsmPrinter::emitPGORefs() {
2587*a96b3639Srobert   if (OutContext.hasXCOFFSection(
2588*a96b3639Srobert           "__llvm_prf_cnts",
2589*a96b3639Srobert           XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {
2590*a96b3639Srobert     MCSection *CntsSection = OutContext.getXCOFFSection(
2591*a96b3639Srobert         "__llvm_prf_cnts", SectionKind::getData(),
2592*a96b3639Srobert         XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD),
2593*a96b3639Srobert         /*MultiSymbolsAllowed*/ true);
2594*a96b3639Srobert 
2595*a96b3639Srobert     OutStreamer->switchSection(CntsSection);
2596*a96b3639Srobert     if (OutContext.hasXCOFFSection(
2597*a96b3639Srobert             "__llvm_prf_data",
2598*a96b3639Srobert             XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))
2599*a96b3639Srobert       OutStreamer->emitXCOFFRefDirective("__llvm_prf_data[RW]");
2600*a96b3639Srobert     if (OutContext.hasXCOFFSection(
2601*a96b3639Srobert             "__llvm_prf_names",
2602*a96b3639Srobert             XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD)))
2603*a96b3639Srobert       OutStreamer->emitXCOFFRefDirective("__llvm_prf_names[RO]");
2604*a96b3639Srobert     if (OutContext.hasXCOFFSection(
2605*a96b3639Srobert             "__llvm_prf_vnds",
2606*a96b3639Srobert             XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))
2607*a96b3639Srobert       OutStreamer->emitXCOFFRefDirective("__llvm_prf_vnds[RW]");
2608*a96b3639Srobert   }
2609a0747c9fSpatrick }
2610a0747c9fSpatrick 
emitEndOfAsmFile(Module & M)2611adae0cfdSpatrick void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
2612a0747c9fSpatrick   // If there are no functions and there are no toc-data definitions in this
2613a0747c9fSpatrick   // module, we will never need to reference the TOC base.
2614a0747c9fSpatrick   if (M.empty() && TOCDataGlobalVars.empty())
261509467b48Spatrick     return;
261609467b48Spatrick 
2617*a96b3639Srobert   emitPGORefs();
2618*a96b3639Srobert 
261909467b48Spatrick   // Switch to section to emit TOC base.
2620*a96b3639Srobert   OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());
262109467b48Spatrick 
2622adae0cfdSpatrick   PPCTargetStreamer *TS =
2623adae0cfdSpatrick       static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2624adae0cfdSpatrick 
262509467b48Spatrick   for (auto &I : TOC) {
2626a0747c9fSpatrick     MCSectionXCOFF *TCEntry;
2627a0747c9fSpatrick     // Setup the csect for the current TC entry. If the variant kind is
2628a0747c9fSpatrick     // VK_PPC_AIX_TLSGDM the entry represents the region handle, we create a
2629a0747c9fSpatrick     // new symbol to prefix the name with a dot.
2630a0747c9fSpatrick     if (I.first.second == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM) {
2631a0747c9fSpatrick       SmallString<128> Name;
2632a0747c9fSpatrick       StringRef Prefix = ".";
2633a0747c9fSpatrick       Name += Prefix;
2634*a96b3639Srobert       Name += cast<MCSymbolXCOFF>(I.first.first)->getSymbolTableName();
2635a0747c9fSpatrick       MCSymbol *S = OutContext.getOrCreateSymbol(Name);
2636a0747c9fSpatrick       TCEntry = cast<MCSectionXCOFF>(
2637a0747c9fSpatrick           getObjFileLowering().getSectionForTOCEntry(S, TM));
2638a0747c9fSpatrick     } else {
2639a0747c9fSpatrick       TCEntry = cast<MCSectionXCOFF>(
2640a0747c9fSpatrick           getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));
2641a0747c9fSpatrick     }
2642*a96b3639Srobert     OutStreamer->switchSection(TCEntry);
264309467b48Spatrick 
2644adae0cfdSpatrick     OutStreamer->emitLabel(I.second);
2645a0747c9fSpatrick     TS->emitTCEntry(*I.first.first, I.first.second);
264609467b48Spatrick   }
2647a0747c9fSpatrick 
2648a0747c9fSpatrick   for (const auto *GV : TOCDataGlobalVars)
2649a0747c9fSpatrick     emitGlobalVariableHelper(GV);
265009467b48Spatrick }
265109467b48Spatrick 
doInitialization(Module & M)2652adae0cfdSpatrick bool PPCAIXAsmPrinter::doInitialization(Module &M) {
2653adae0cfdSpatrick   const bool Result = PPCAsmPrinter::doInitialization(M);
265409467b48Spatrick 
2655adae0cfdSpatrick   auto setCsectAlignment = [this](const GlobalObject *GO) {
2656adae0cfdSpatrick     // Declarations have 0 alignment which is set by default.
2657adae0cfdSpatrick     if (GO->isDeclarationForLinker())
2658adae0cfdSpatrick       return;
265909467b48Spatrick 
266009467b48Spatrick     SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM);
2661adae0cfdSpatrick     MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(
2662adae0cfdSpatrick         getObjFileLowering().SectionForGlobal(GO, GOKind, TM));
266309467b48Spatrick 
2664adae0cfdSpatrick     Align GOAlign = getGVAlignment(GO, GO->getParent()->getDataLayout());
2665*a96b3639Srobert     Csect->ensureMinAlignment(GOAlign);
2666adae0cfdSpatrick   };
266709467b48Spatrick 
2668adae0cfdSpatrick   // We need to know, up front, the alignment of csects for the assembly path,
2669adae0cfdSpatrick   // because once a .csect directive gets emitted, we could not change the
2670adae0cfdSpatrick   // alignment value on it.
2671a0747c9fSpatrick   for (const auto &G : M.globals()) {
2672a0747c9fSpatrick     if (isSpecialLLVMGlobalArrayToSkip(&G))
2673a0747c9fSpatrick       continue;
2674a0747c9fSpatrick 
2675a0747c9fSpatrick     if (isSpecialLLVMGlobalArrayForStaticInit(&G)) {
2676a0747c9fSpatrick       // Generate a format indicator and a unique module id to be a part of
2677a0747c9fSpatrick       // the sinit and sterm function names.
2678a0747c9fSpatrick       if (FormatIndicatorAndUniqueModId.empty()) {
2679a0747c9fSpatrick         std::string UniqueModuleId = getUniqueModuleId(&M);
2680a0747c9fSpatrick         if (UniqueModuleId != "")
2681a0747c9fSpatrick           // TODO: Use source file full path to generate the unique module id
2682a0747c9fSpatrick           // and add a format indicator as a part of function name in case we
2683a0747c9fSpatrick           // will support more than one format.
2684a0747c9fSpatrick           FormatIndicatorAndUniqueModId = "clang_" + UniqueModuleId.substr(1);
2685a0747c9fSpatrick         else
2686a0747c9fSpatrick           // Use the Pid and current time as the unique module id when we cannot
2687a0747c9fSpatrick           // generate one based on a module's strong external symbols.
2688a0747c9fSpatrick           // FIXME: Adjust the comment accordingly after we use source file full
2689a0747c9fSpatrick           // path instead.
2690a0747c9fSpatrick           FormatIndicatorAndUniqueModId =
2691a0747c9fSpatrick               "clangPidTime_" + llvm::itostr(sys::Process::getProcessId()) +
2692a0747c9fSpatrick               "_" + llvm::itostr(time(nullptr));
2693a0747c9fSpatrick       }
2694a0747c9fSpatrick 
2695a0747c9fSpatrick       emitSpecialLLVMGlobal(&G);
2696a0747c9fSpatrick       continue;
2697a0747c9fSpatrick     }
2698a0747c9fSpatrick 
2699adae0cfdSpatrick     setCsectAlignment(&G);
2700a0747c9fSpatrick   }
2701adae0cfdSpatrick 
2702adae0cfdSpatrick   for (const auto &F : M)
2703adae0cfdSpatrick     setCsectAlignment(&F);
2704adae0cfdSpatrick 
2705a0747c9fSpatrick   // Construct an aliasing list for each GlobalObject.
2706a0747c9fSpatrick   for (const auto &Alias : M.aliases()) {
2707*a96b3639Srobert     const GlobalObject *Base = Alias.getAliaseeObject();
2708a0747c9fSpatrick     if (!Base)
2709a0747c9fSpatrick       report_fatal_error(
2710a0747c9fSpatrick           "alias without a base object is not yet supported on AIX");
2711a0747c9fSpatrick     GOAliasMap[Base].push_back(&Alias);
2712a0747c9fSpatrick   }
2713a0747c9fSpatrick 
2714adae0cfdSpatrick   return Result;
271509467b48Spatrick }
271609467b48Spatrick 
emitInstruction(const MachineInstr * MI)2717a0747c9fSpatrick void PPCAIXAsmPrinter::emitInstruction(const MachineInstr *MI) {
2718a0747c9fSpatrick   switch (MI->getOpcode()) {
2719a0747c9fSpatrick   default:
2720a0747c9fSpatrick     break;
2721*a96b3639Srobert   case PPC::TW:
2722*a96b3639Srobert   case PPC::TWI:
2723*a96b3639Srobert   case PPC::TD:
2724*a96b3639Srobert   case PPC::TDI: {
2725*a96b3639Srobert     if (MI->getNumOperands() < 5)
2726*a96b3639Srobert       break;
2727*a96b3639Srobert     const MachineOperand &LangMO = MI->getOperand(3);
2728*a96b3639Srobert     const MachineOperand &ReasonMO = MI->getOperand(4);
2729*a96b3639Srobert     if (!LangMO.isImm() || !ReasonMO.isImm())
2730*a96b3639Srobert       break;
2731*a96b3639Srobert     MCSymbol *TempSym = OutContext.createNamedTempSymbol();
2732*a96b3639Srobert     OutStreamer->emitLabel(TempSym);
2733*a96b3639Srobert     OutStreamer->emitXCOFFExceptDirective(CurrentFnSym, TempSym,
2734*a96b3639Srobert                  LangMO.getImm(), ReasonMO.getImm(),
2735*a96b3639Srobert                  Subtarget->isPPC64() ? MI->getMF()->getInstructionCount() * 8 :
2736*a96b3639Srobert                  MI->getMF()->getInstructionCount() * 4,
2737*a96b3639Srobert 		 MMI->hasDebugInfo());
2738*a96b3639Srobert     break;
2739*a96b3639Srobert   }
2740a0747c9fSpatrick   case PPC::GETtlsADDR64AIX:
2741a0747c9fSpatrick   case PPC::GETtlsADDR32AIX: {
2742a0747c9fSpatrick     // The reference to .__tls_get_addr is unknown to the assembler
2743a0747c9fSpatrick     // so we need to emit an external symbol reference.
2744a0747c9fSpatrick     MCSymbol *TlsGetAddr = createMCSymbolForTlsGetAddr(OutContext);
2745a0747c9fSpatrick     ExtSymSDNodeSymbols.insert(TlsGetAddr);
2746a0747c9fSpatrick     break;
2747a0747c9fSpatrick   }
2748a0747c9fSpatrick   case PPC::BL8:
2749a0747c9fSpatrick   case PPC::BL:
2750a0747c9fSpatrick   case PPC::BL8_NOP:
2751a0747c9fSpatrick   case PPC::BL_NOP: {
2752a0747c9fSpatrick     const MachineOperand &MO = MI->getOperand(0);
2753a0747c9fSpatrick     if (MO.isSymbol()) {
2754a0747c9fSpatrick       MCSymbolXCOFF *S =
2755a0747c9fSpatrick           cast<MCSymbolXCOFF>(OutContext.getOrCreateSymbol(MO.getSymbolName()));
2756a0747c9fSpatrick       ExtSymSDNodeSymbols.insert(S);
2757a0747c9fSpatrick     }
2758a0747c9fSpatrick   } break;
2759a0747c9fSpatrick   case PPC::BL_TLS:
2760a0747c9fSpatrick   case PPC::BL8_TLS:
2761a0747c9fSpatrick   case PPC::BL8_TLS_:
2762a0747c9fSpatrick   case PPC::BL8_NOP_TLS:
2763a0747c9fSpatrick     report_fatal_error("TLS call not yet implemented");
2764a0747c9fSpatrick   case PPC::TAILB:
2765a0747c9fSpatrick   case PPC::TAILB8:
2766a0747c9fSpatrick   case PPC::TAILBA:
2767a0747c9fSpatrick   case PPC::TAILBA8:
2768a0747c9fSpatrick   case PPC::TAILBCTR:
2769a0747c9fSpatrick   case PPC::TAILBCTR8:
2770a0747c9fSpatrick     if (MI->getOperand(0).isSymbol())
2771a0747c9fSpatrick       report_fatal_error("Tail call for extern symbol not yet supported.");
2772a0747c9fSpatrick     break;
2773a0747c9fSpatrick   case PPC::DST:
2774a0747c9fSpatrick   case PPC::DST64:
2775a0747c9fSpatrick   case PPC::DSTT:
2776a0747c9fSpatrick   case PPC::DSTT64:
2777a0747c9fSpatrick   case PPC::DSTST:
2778a0747c9fSpatrick   case PPC::DSTST64:
2779a0747c9fSpatrick   case PPC::DSTSTT:
2780a0747c9fSpatrick   case PPC::DSTSTT64:
2781a0747c9fSpatrick     EmitToStreamer(
2782a0747c9fSpatrick         *OutStreamer,
2783a0747c9fSpatrick         MCInstBuilder(PPC::ORI).addReg(PPC::R0).addReg(PPC::R0).addImm(0));
2784a0747c9fSpatrick     return;
2785a0747c9fSpatrick   }
2786a0747c9fSpatrick   return PPCAsmPrinter::emitInstruction(MI);
2787a0747c9fSpatrick }
2788a0747c9fSpatrick 
doFinalization(Module & M)2789a0747c9fSpatrick bool PPCAIXAsmPrinter::doFinalization(Module &M) {
2790a0747c9fSpatrick   // Do streamer related finalization for DWARF.
2791a0747c9fSpatrick   if (!MAI->usesDwarfFileAndLocDirectives() && MMI->hasDebugInfo())
2792a0747c9fSpatrick     OutStreamer->doFinalizationAtSectionEnd(
2793a0747c9fSpatrick         OutStreamer->getContext().getObjectFileInfo()->getTextSection());
2794a0747c9fSpatrick 
2795a0747c9fSpatrick   for (MCSymbol *Sym : ExtSymSDNodeSymbols)
2796a0747c9fSpatrick     OutStreamer->emitSymbolAttribute(Sym, MCSA_Extern);
2797a0747c9fSpatrick   return PPCAsmPrinter::doFinalization(M);
2798a0747c9fSpatrick }
2799a0747c9fSpatrick 
mapToSinitPriority(int P)2800a0747c9fSpatrick static unsigned mapToSinitPriority(int P) {
2801a0747c9fSpatrick   if (P < 0 || P > 65535)
2802a0747c9fSpatrick     report_fatal_error("invalid init priority");
2803a0747c9fSpatrick 
2804a0747c9fSpatrick   if (P <= 20)
2805a0747c9fSpatrick     return P;
2806a0747c9fSpatrick 
2807a0747c9fSpatrick   if (P < 81)
2808a0747c9fSpatrick     return 20 + (P - 20) * 16;
2809a0747c9fSpatrick 
2810a0747c9fSpatrick   if (P <= 1124)
2811a0747c9fSpatrick     return 1004 + (P - 81);
2812a0747c9fSpatrick 
2813a0747c9fSpatrick   if (P < 64512)
2814a0747c9fSpatrick     return 2047 + (P - 1124) * 33878;
2815a0747c9fSpatrick 
2816a0747c9fSpatrick   return 2147482625u + (P - 64512);
2817a0747c9fSpatrick }
2818a0747c9fSpatrick 
convertToSinitPriority(int Priority)2819a0747c9fSpatrick static std::string convertToSinitPriority(int Priority) {
2820a0747c9fSpatrick   // This helper function converts clang init priority to values used in sinit
2821a0747c9fSpatrick   // and sterm functions.
2822a0747c9fSpatrick   //
2823a0747c9fSpatrick   // The conversion strategies are:
2824a0747c9fSpatrick   // We map the reserved clang/gnu priority range [0, 100] into the sinit/sterm
2825a0747c9fSpatrick   // reserved priority range [0, 1023] by
2826a0747c9fSpatrick   // - directly mapping the first 21 and the last 20 elements of the ranges
2827a0747c9fSpatrick   // - linear interpolating the intermediate values with a step size of 16.
2828a0747c9fSpatrick   //
2829a0747c9fSpatrick   // We map the non reserved clang/gnu priority range of [101, 65535] into the
2830a0747c9fSpatrick   // sinit/sterm priority range [1024, 2147483648] by:
2831a0747c9fSpatrick   // - directly mapping the first and the last 1024 elements of the ranges
2832a0747c9fSpatrick   // - linear interpolating the intermediate values with a step size of 33878.
2833a0747c9fSpatrick   unsigned int P = mapToSinitPriority(Priority);
2834a0747c9fSpatrick 
2835a0747c9fSpatrick   std::string PrioritySuffix;
2836a0747c9fSpatrick   llvm::raw_string_ostream os(PrioritySuffix);
2837a0747c9fSpatrick   os << llvm::format_hex_no_prefix(P, 8);
2838a0747c9fSpatrick   os.flush();
2839a0747c9fSpatrick   return PrioritySuffix;
2840a0747c9fSpatrick }
2841a0747c9fSpatrick 
emitXXStructorList(const DataLayout & DL,const Constant * List,bool IsCtor)2842a0747c9fSpatrick void PPCAIXAsmPrinter::emitXXStructorList(const DataLayout &DL,
2843a0747c9fSpatrick                                           const Constant *List, bool IsCtor) {
2844a0747c9fSpatrick   SmallVector<Structor, 8> Structors;
2845a0747c9fSpatrick   preprocessXXStructorList(DL, List, Structors);
2846a0747c9fSpatrick   if (Structors.empty())
2847a0747c9fSpatrick     return;
2848a0747c9fSpatrick 
2849a0747c9fSpatrick   unsigned Index = 0;
2850a0747c9fSpatrick   for (Structor &S : Structors) {
2851a0747c9fSpatrick     if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(S.Func))
2852a0747c9fSpatrick       S.Func = CE->getOperand(0);
2853a0747c9fSpatrick 
2854a0747c9fSpatrick     llvm::GlobalAlias::create(
2855a0747c9fSpatrick         GlobalValue::ExternalLinkage,
2856a0747c9fSpatrick         (IsCtor ? llvm::Twine("__sinit") : llvm::Twine("__sterm")) +
2857a0747c9fSpatrick             llvm::Twine(convertToSinitPriority(S.Priority)) +
2858a0747c9fSpatrick             llvm::Twine("_", FormatIndicatorAndUniqueModId) +
2859a0747c9fSpatrick             llvm::Twine("_", llvm::utostr(Index++)),
2860a0747c9fSpatrick         cast<Function>(S.Func));
2861a0747c9fSpatrick   }
2862a0747c9fSpatrick }
2863a0747c9fSpatrick 
emitTTypeReference(const GlobalValue * GV,unsigned Encoding)2864a0747c9fSpatrick void PPCAIXAsmPrinter::emitTTypeReference(const GlobalValue *GV,
2865a0747c9fSpatrick                                           unsigned Encoding) {
2866a0747c9fSpatrick   if (GV) {
2867a0747c9fSpatrick     MCSymbol *TypeInfoSym = TM.getSymbol(GV);
2868a0747c9fSpatrick     MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(TypeInfoSym);
2869a0747c9fSpatrick     const MCSymbol *TOCBaseSym =
2870a0747c9fSpatrick         cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection())
2871a0747c9fSpatrick             ->getQualNameSymbol();
2872a0747c9fSpatrick     auto &Ctx = OutStreamer->getContext();
2873a0747c9fSpatrick     const MCExpr *Exp =
2874a0747c9fSpatrick         MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCEntry, Ctx),
2875a0747c9fSpatrick                                 MCSymbolRefExpr::create(TOCBaseSym, Ctx), Ctx);
2876a0747c9fSpatrick     OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding));
2877a0747c9fSpatrick   } else
2878a0747c9fSpatrick     OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding));
2879a0747c9fSpatrick }
2880a0747c9fSpatrick 
2881a0747c9fSpatrick // Return a pass that prints the PPC assembly code for a MachineFunction to the
2882a0747c9fSpatrick // given output stream.
288309467b48Spatrick static AsmPrinter *
createPPCAsmPrinterPass(TargetMachine & tm,std::unique_ptr<MCStreamer> && Streamer)288409467b48Spatrick createPPCAsmPrinterPass(TargetMachine &tm,
288509467b48Spatrick                         std::unique_ptr<MCStreamer> &&Streamer) {
288609467b48Spatrick   if (tm.getTargetTriple().isOSAIX())
288709467b48Spatrick     return new PPCAIXAsmPrinter(tm, std::move(Streamer));
288809467b48Spatrick 
288909467b48Spatrick   return new PPCLinuxAsmPrinter(tm, std::move(Streamer));
289009467b48Spatrick }
289109467b48Spatrick 
289209467b48Spatrick // Force static initialization.
LLVMInitializePowerPCAsmPrinter()289309467b48Spatrick extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCAsmPrinter() {
289409467b48Spatrick   TargetRegistry::RegisterAsmPrinter(getThePPC32Target(),
289509467b48Spatrick                                      createPPCAsmPrinterPass);
2896a0747c9fSpatrick   TargetRegistry::RegisterAsmPrinter(getThePPC32LETarget(),
2897a0747c9fSpatrick                                      createPPCAsmPrinterPass);
289809467b48Spatrick   TargetRegistry::RegisterAsmPrinter(getThePPC64Target(),
289909467b48Spatrick                                      createPPCAsmPrinterPass);
290009467b48Spatrick   TargetRegistry::RegisterAsmPrinter(getThePPC64LETarget(),
290109467b48Spatrick                                      createPPCAsmPrinterPass);
290209467b48Spatrick }
2903