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