Path: blob/main/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
35269 views
//===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly ------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains a printer that converts from our internal representation9// of machine-dependent LLVM code to PowerPC assembly language. This printer is10// the output mechanism used by `llc'.11//12// Documentation at http://developer.apple.com/documentation/DeveloperTools/13// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html14//15//===----------------------------------------------------------------------===//1617#include "MCTargetDesc/PPCInstPrinter.h"18#include "MCTargetDesc/PPCMCExpr.h"19#include "MCTargetDesc/PPCMCTargetDesc.h"20#include "MCTargetDesc/PPCPredicates.h"21#include "PPC.h"22#include "PPCInstrInfo.h"23#include "PPCMachineFunctionInfo.h"24#include "PPCSubtarget.h"25#include "PPCTargetMachine.h"26#include "PPCTargetStreamer.h"27#include "TargetInfo/PowerPCTargetInfo.h"28#include "llvm/ADT/MapVector.h"29#include "llvm/ADT/SetVector.h"30#include "llvm/ADT/Statistic.h"31#include "llvm/ADT/StringExtras.h"32#include "llvm/ADT/StringRef.h"33#include "llvm/ADT/Twine.h"34#include "llvm/BinaryFormat/ELF.h"35#include "llvm/CodeGen/AsmPrinter.h"36#include "llvm/CodeGen/MachineBasicBlock.h"37#include "llvm/CodeGen/MachineFrameInfo.h"38#include "llvm/CodeGen/MachineFunction.h"39#include "llvm/CodeGen/MachineInstr.h"40#include "llvm/CodeGen/MachineModuleInfoImpls.h"41#include "llvm/CodeGen/MachineOperand.h"42#include "llvm/CodeGen/MachineRegisterInfo.h"43#include "llvm/CodeGen/StackMaps.h"44#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"45#include "llvm/IR/DataLayout.h"46#include "llvm/IR/GlobalValue.h"47#include "llvm/IR/GlobalVariable.h"48#include "llvm/IR/Module.h"49#include "llvm/MC/MCAsmInfo.h"50#include "llvm/MC/MCContext.h"51#include "llvm/MC/MCDirectives.h"52#include "llvm/MC/MCExpr.h"53#include "llvm/MC/MCInst.h"54#include "llvm/MC/MCInstBuilder.h"55#include "llvm/MC/MCSectionELF.h"56#include "llvm/MC/MCSectionXCOFF.h"57#include "llvm/MC/MCStreamer.h"58#include "llvm/MC/MCSymbol.h"59#include "llvm/MC/MCSymbolELF.h"60#include "llvm/MC/MCSymbolXCOFF.h"61#include "llvm/MC/SectionKind.h"62#include "llvm/MC/TargetRegistry.h"63#include "llvm/Support/Casting.h"64#include "llvm/Support/CodeGen.h"65#include "llvm/Support/Debug.h"66#include "llvm/Support/Error.h"67#include "llvm/Support/ErrorHandling.h"68#include "llvm/Support/MathExtras.h"69#include "llvm/Support/Process.h"70#include "llvm/Support/Threading.h"71#include "llvm/Support/raw_ostream.h"72#include "llvm/Target/TargetMachine.h"73#include "llvm/TargetParser/Triple.h"74#include "llvm/Transforms/Utils/ModuleUtils.h"75#include <algorithm>76#include <cassert>77#include <cstdint>78#include <memory>79#include <new>8081using namespace llvm;82using namespace llvm::XCOFF;8384#define DEBUG_TYPE "asmprinter"8586STATISTIC(NumTOCEntries, "Number of Total TOC Entries Emitted.");87STATISTIC(NumTOCConstPool, "Number of Constant Pool TOC Entries.");88STATISTIC(NumTOCGlobalInternal,89"Number of Internal Linkage Global TOC Entries.");90STATISTIC(NumTOCGlobalExternal,91"Number of External Linkage Global TOC Entries.");92STATISTIC(NumTOCJumpTable, "Number of Jump Table TOC Entries.");93STATISTIC(NumTOCThreadLocal, "Number of Thread Local TOC Entries.");94STATISTIC(NumTOCBlockAddress, "Number of Block Address TOC Entries.");95STATISTIC(NumTOCEHBlock, "Number of EH Block TOC Entries.");9697static cl::opt<bool> EnableSSPCanaryBitInTB(98"aix-ssp-tb-bit", cl::init(false),99cl::desc("Enable Passing SSP Canary info in Trackback on AIX"), cl::Hidden);100101// Specialize DenseMapInfo to allow102// std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind> in DenseMap.103// This specialization is needed here because that type is used as keys in the104// map representing TOC entries.105namespace llvm {106template <>107struct DenseMapInfo<std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>> {108using TOCKey = std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>;109110static inline TOCKey getEmptyKey() {111return {nullptr, MCSymbolRefExpr::VariantKind::VK_None};112}113static inline TOCKey getTombstoneKey() {114return {nullptr, MCSymbolRefExpr::VariantKind::VK_Invalid};115}116static unsigned getHashValue(const TOCKey &PairVal) {117return detail::combineHashValue(118DenseMapInfo<const MCSymbol *>::getHashValue(PairVal.first),119DenseMapInfo<int>::getHashValue(PairVal.second));120}121static bool isEqual(const TOCKey &A, const TOCKey &B) { return A == B; }122};123} // end namespace llvm124125namespace {126127enum {128// GNU attribute tags for PowerPC ABI129Tag_GNU_Power_ABI_FP = 4,130Tag_GNU_Power_ABI_Vector = 8,131Tag_GNU_Power_ABI_Struct_Return = 12,132133// GNU attribute values for PowerPC float ABI, as combination of two parts134Val_GNU_Power_ABI_NoFloat = 0b00,135Val_GNU_Power_ABI_HardFloat_DP = 0b01,136Val_GNU_Power_ABI_SoftFloat_DP = 0b10,137Val_GNU_Power_ABI_HardFloat_SP = 0b11,138139Val_GNU_Power_ABI_LDBL_IBM128 = 0b0100,140Val_GNU_Power_ABI_LDBL_64 = 0b1000,141Val_GNU_Power_ABI_LDBL_IEEE128 = 0b1100,142};143144class PPCAsmPrinter : public AsmPrinter {145protected:146// For TLS on AIX, we need to be able to identify TOC entries of specific147// VariantKind so we can add the right relocations when we generate the148// entries. So each entry is represented by a pair of MCSymbol and149// VariantKind. For example, we need to be able to identify the following150// entry as a TLSGD entry so we can add the @m relocation:151// .tc .i[TC],i[TL]@m152// By default, VK_None is used for the VariantKind.153MapVector<std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>,154MCSymbol *>155TOC;156const PPCSubtarget *Subtarget = nullptr;157158// Keep track of the number of TLS variables and their corresponding159// addresses, which is then used for the assembly printing of160// non-TOC-based local-exec variables.161MapVector<const GlobalValue *, uint64_t> TLSVarsToAddressMapping;162163public:164explicit PPCAsmPrinter(TargetMachine &TM,165std::unique_ptr<MCStreamer> Streamer)166: AsmPrinter(TM, std::move(Streamer)) {}167168StringRef getPassName() const override { return "PowerPC Assembly Printer"; }169170enum TOCEntryType {171TOCType_ConstantPool,172TOCType_GlobalExternal,173TOCType_GlobalInternal,174TOCType_JumpTable,175TOCType_ThreadLocal,176TOCType_BlockAddress,177TOCType_EHBlock178};179180MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym, TOCEntryType Type,181MCSymbolRefExpr::VariantKind Kind =182MCSymbolRefExpr::VariantKind::VK_None);183184bool doInitialization(Module &M) override {185if (!TOC.empty())186TOC.clear();187return AsmPrinter::doInitialization(M);188}189190void emitInstruction(const MachineInstr *MI) override;191192/// This function is for PrintAsmOperand and PrintAsmMemoryOperand,193/// invoked by EmitMSInlineAsmStr and EmitGCCInlineAsmStr only.194/// The \p MI would be INLINEASM ONLY.195void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);196197void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;198bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,199const char *ExtraCode, raw_ostream &O) override;200bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,201const char *ExtraCode, raw_ostream &O) override;202203void LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI);204void LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI);205void EmitTlsCall(const MachineInstr *MI, MCSymbolRefExpr::VariantKind VK);206void EmitAIXTlsCallHelper(const MachineInstr *MI);207const MCExpr *getAdjustedFasterLocalExpr(const MachineOperand &MO,208int64_t Offset);209bool runOnMachineFunction(MachineFunction &MF) override {210Subtarget = &MF.getSubtarget<PPCSubtarget>();211bool Changed = AsmPrinter::runOnMachineFunction(MF);212emitXRayTable();213return Changed;214}215};216217/// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux218class PPCLinuxAsmPrinter : public PPCAsmPrinter {219public:220explicit PPCLinuxAsmPrinter(TargetMachine &TM,221std::unique_ptr<MCStreamer> Streamer)222: PPCAsmPrinter(TM, std::move(Streamer)) {}223224StringRef getPassName() const override {225return "Linux PPC Assembly Printer";226}227228void emitGNUAttributes(Module &M);229230void emitStartOfAsmFile(Module &M) override;231void emitEndOfAsmFile(Module &) override;232233void emitFunctionEntryLabel() override;234235void emitFunctionBodyStart() override;236void emitFunctionBodyEnd() override;237void emitInstruction(const MachineInstr *MI) override;238};239240class PPCAIXAsmPrinter : public PPCAsmPrinter {241private:242/// Symbols lowered from ExternalSymbolSDNodes, we will need to emit extern243/// linkage for them in AIX.244SmallSetVector<MCSymbol *, 8> ExtSymSDNodeSymbols;245246/// A format indicator and unique trailing identifier to form part of the247/// sinit/sterm function names.248std::string FormatIndicatorAndUniqueModId;249250// Record a list of GlobalAlias associated with a GlobalObject.251// This is used for AIX's extra-label-at-definition aliasing strategy.252DenseMap<const GlobalObject *, SmallVector<const GlobalAlias *, 1>>253GOAliasMap;254255uint16_t getNumberOfVRSaved();256void emitTracebackTable();257258SmallVector<const GlobalVariable *, 8> TOCDataGlobalVars;259260void emitGlobalVariableHelper(const GlobalVariable *);261262// Get the offset of an alias based on its AliaseeObject.263uint64_t getAliasOffset(const Constant *C);264265public:266PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)267: PPCAsmPrinter(TM, std::move(Streamer)) {268if (MAI->isLittleEndian())269report_fatal_error(270"cannot create AIX PPC Assembly Printer for a little-endian target");271}272273StringRef getPassName() const override { return "AIX PPC Assembly Printer"; }274275bool doInitialization(Module &M) override;276277void emitXXStructorList(const DataLayout &DL, const Constant *List,278bool IsCtor) override;279280void SetupMachineFunction(MachineFunction &MF) override;281282void emitGlobalVariable(const GlobalVariable *GV) override;283284void emitFunctionDescriptor() override;285286void emitFunctionEntryLabel() override;287288void emitFunctionBodyEnd() override;289290void emitPGORefs(Module &M);291292void emitEndOfAsmFile(Module &) override;293294void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override;295296void emitInstruction(const MachineInstr *MI) override;297298bool doFinalization(Module &M) override;299300void emitTTypeReference(const GlobalValue *GV, unsigned Encoding) override;301302void emitModuleCommandLines(Module &M) override;303};304305} // end anonymous namespace306307void PPCAsmPrinter::PrintSymbolOperand(const MachineOperand &MO,308raw_ostream &O) {309// Computing the address of a global symbol, not calling it.310const GlobalValue *GV = MO.getGlobal();311getSymbol(GV)->print(O, MAI);312printOffset(MO.getOffset(), O);313}314315void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,316raw_ostream &O) {317const DataLayout &DL = getDataLayout();318const MachineOperand &MO = MI->getOperand(OpNo);319320switch (MO.getType()) {321case MachineOperand::MO_Register: {322// The MI is INLINEASM ONLY and UseVSXReg is always false.323const char *RegName = PPCInstPrinter::getRegisterName(MO.getReg());324325// Linux assembler (Others?) does not take register mnemonics.326// FIXME - What about special registers used in mfspr/mtspr?327O << PPC::stripRegisterPrefix(RegName);328return;329}330case MachineOperand::MO_Immediate:331O << MO.getImm();332return;333334case MachineOperand::MO_MachineBasicBlock:335MO.getMBB()->getSymbol()->print(O, MAI);336return;337case MachineOperand::MO_ConstantPoolIndex:338O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'339<< MO.getIndex();340return;341case MachineOperand::MO_BlockAddress:342GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);343return;344case MachineOperand::MO_GlobalAddress: {345PrintSymbolOperand(MO, O);346return;347}348349default:350O << "<unknown operand type: " << (unsigned)MO.getType() << ">";351return;352}353}354355/// PrintAsmOperand - Print out an operand for an inline asm expression.356///357bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,358const char *ExtraCode, raw_ostream &O) {359// Does this asm operand have a single letter operand modifier?360if (ExtraCode && ExtraCode[0]) {361if (ExtraCode[1] != 0) return true; // Unknown modifier.362363switch (ExtraCode[0]) {364default:365// See if this is a generic print operand366return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);367case 'L': // Write second word of DImode reference.368// Verify that this operand has two consecutive registers.369if (!MI->getOperand(OpNo).isReg() ||370OpNo+1 == MI->getNumOperands() ||371!MI->getOperand(OpNo+1).isReg())372return true;373++OpNo; // Return the high-part.374break;375case 'I':376// Write 'i' if an integer constant, otherwise nothing. Used to print377// addi vs add, etc.378if (MI->getOperand(OpNo).isImm())379O << "i";380return false;381case 'x':382if(!MI->getOperand(OpNo).isReg())383return true;384// This operand uses VSX numbering.385// If the operand is a VMX register, convert it to a VSX register.386Register Reg = MI->getOperand(OpNo).getReg();387if (PPC::isVRRegister(Reg))388Reg = PPC::VSX32 + (Reg - PPC::V0);389else if (PPC::isVFRegister(Reg))390Reg = PPC::VSX32 + (Reg - PPC::VF0);391const char *RegName;392RegName = PPCInstPrinter::getRegisterName(Reg);393RegName = PPC::stripRegisterPrefix(RegName);394O << RegName;395return false;396}397}398399printOperand(MI, OpNo, O);400return false;401}402403// At the moment, all inline asm memory operands are a single register.404// In any case, the output of this routine should always be just one405// assembler operand.406bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,407const char *ExtraCode,408raw_ostream &O) {409if (ExtraCode && ExtraCode[0]) {410if (ExtraCode[1] != 0) return true; // Unknown modifier.411412switch (ExtraCode[0]) {413default: return true; // Unknown modifier.414case 'L': // A memory reference to the upper word of a double word op.415O << getDataLayout().getPointerSize() << "(";416printOperand(MI, OpNo, O);417O << ")";418return false;419case 'y': // A memory reference for an X-form instruction420O << "0, ";421printOperand(MI, OpNo, O);422return false;423case 'I':424// Write 'i' if an integer constant, otherwise nothing. Used to print425// addi vs add, etc.426if (MI->getOperand(OpNo).isImm())427O << "i";428return false;429case 'U': // Print 'u' for update form.430case 'X': // Print 'x' for indexed form.431// FIXME: Currently for PowerPC memory operands are always loaded432// into a register, so we never get an update or indexed form.433// This is bad even for offset forms, since even if we know we434// have a value in -16(r1), we will generate a load into r<n>435// and then load from 0(r<n>). Until that issue is fixed,436// tolerate 'U' and 'X' but don't output anything.437assert(MI->getOperand(OpNo).isReg());438return false;439}440}441442assert(MI->getOperand(OpNo).isReg());443O << "0(";444printOperand(MI, OpNo, O);445O << ")";446return false;447}448449static void collectTOCStats(PPCAsmPrinter::TOCEntryType Type) {450++NumTOCEntries;451switch (Type) {452case PPCAsmPrinter::TOCType_ConstantPool:453++NumTOCConstPool;454break;455case PPCAsmPrinter::TOCType_GlobalInternal:456++NumTOCGlobalInternal;457break;458case PPCAsmPrinter::TOCType_GlobalExternal:459++NumTOCGlobalExternal;460break;461case PPCAsmPrinter::TOCType_JumpTable:462++NumTOCJumpTable;463break;464case PPCAsmPrinter::TOCType_ThreadLocal:465++NumTOCThreadLocal;466break;467case PPCAsmPrinter::TOCType_BlockAddress:468++NumTOCBlockAddress;469break;470case PPCAsmPrinter::TOCType_EHBlock:471++NumTOCEHBlock;472break;473}474}475476static CodeModel::Model getCodeModel(const PPCSubtarget &S,477const TargetMachine &TM,478const MachineOperand &MO) {479CodeModel::Model ModuleModel = TM.getCodeModel();480481// If the operand is not a global address then there is no482// global variable to carry an attribute.483if (!(MO.getType() == MachineOperand::MO_GlobalAddress))484return ModuleModel;485486const GlobalValue *GV = MO.getGlobal();487assert(GV && "expected global for MO_GlobalAddress");488489return S.getCodeModel(TM, GV);490}491492static void setOptionalCodeModel(MCSymbolXCOFF *XSym, CodeModel::Model CM) {493switch (CM) {494case CodeModel::Large:495XSym->setPerSymbolCodeModel(MCSymbolXCOFF::CM_Large);496return;497case CodeModel::Small:498XSym->setPerSymbolCodeModel(MCSymbolXCOFF::CM_Small);499return;500default:501report_fatal_error("Invalid code model for AIX");502}503}504505/// lookUpOrCreateTOCEntry -- Given a symbol, look up whether a TOC entry506/// exists for it. If not, create one. Then return a symbol that references507/// the TOC entry.508MCSymbol *509PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym, TOCEntryType Type,510MCSymbolRefExpr::VariantKind Kind) {511// If this is a new TOC entry add statistics about it.512if (!TOC.contains({Sym, Kind}))513collectTOCStats(Type);514515MCSymbol *&TOCEntry = TOC[{Sym, Kind}];516if (!TOCEntry)517TOCEntry = createTempSymbol("C");518return TOCEntry;519}520521void PPCAsmPrinter::LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI) {522unsigned NumNOPBytes = MI.getOperand(1).getImm();523524auto &Ctx = OutStreamer->getContext();525MCSymbol *MILabel = Ctx.createTempSymbol();526OutStreamer->emitLabel(MILabel);527528SM.recordStackMap(*MILabel, MI);529assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");530531// Scan ahead to trim the shadow.532const MachineBasicBlock &MBB = *MI.getParent();533MachineBasicBlock::const_iterator MII(MI);534++MII;535while (NumNOPBytes > 0) {536if (MII == MBB.end() || MII->isCall() ||537MII->getOpcode() == PPC::DBG_VALUE ||538MII->getOpcode() == TargetOpcode::PATCHPOINT ||539MII->getOpcode() == TargetOpcode::STACKMAP)540break;541++MII;542NumNOPBytes -= 4;543}544545// Emit nops.546for (unsigned i = 0; i < NumNOPBytes; i += 4)547EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));548}549550// Lower a patchpoint of the form:551// [<def>], <id>, <numBytes>, <target>, <numArgs>552void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI) {553auto &Ctx = OutStreamer->getContext();554MCSymbol *MILabel = Ctx.createTempSymbol();555OutStreamer->emitLabel(MILabel);556557SM.recordPatchPoint(*MILabel, MI);558PatchPointOpers Opers(&MI);559560unsigned EncodedBytes = 0;561const MachineOperand &CalleeMO = Opers.getCallTarget();562563if (CalleeMO.isImm()) {564int64_t CallTarget = CalleeMO.getImm();565if (CallTarget) {566assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&567"High 16 bits of call target should be zero.");568Register ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();569EncodedBytes = 0;570// Materialize the jump address:571EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI8)572.addReg(ScratchReg)573.addImm((CallTarget >> 32) & 0xFFFF));574++EncodedBytes;575EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::RLDIC)576.addReg(ScratchReg)577.addReg(ScratchReg)578.addImm(32).addImm(16));579++EncodedBytes;580EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORIS8)581.addReg(ScratchReg)582.addReg(ScratchReg)583.addImm((CallTarget >> 16) & 0xFFFF));584++EncodedBytes;585EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORI8)586.addReg(ScratchReg)587.addReg(ScratchReg)588.addImm(CallTarget & 0xFFFF));589590// Save the current TOC pointer before the remote call.591int TOCSaveOffset = Subtarget->getFrameLowering()->getTOCSaveOffset();592EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::STD)593.addReg(PPC::X2)594.addImm(TOCSaveOffset)595.addReg(PPC::X1));596++EncodedBytes;597598// If we're on ELFv1, then we need to load the actual function pointer599// from the function descriptor.600if (!Subtarget->isELFv2ABI()) {601// Load the new TOC pointer and the function address, but not r11602// (needing this is rare, and loading it here would prevent passing it603// via a 'nest' parameter.604EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)605.addReg(PPC::X2)606.addImm(8)607.addReg(ScratchReg));608++EncodedBytes;609EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)610.addReg(ScratchReg)611.addImm(0)612.addReg(ScratchReg));613++EncodedBytes;614}615616EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTCTR8)617.addReg(ScratchReg));618++EncodedBytes;619EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BCTRL8));620++EncodedBytes;621622// Restore the TOC pointer after the call.623EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)624.addReg(PPC::X2)625.addImm(TOCSaveOffset)626.addReg(PPC::X1));627++EncodedBytes;628}629} else if (CalleeMO.isGlobal()) {630const GlobalValue *GValue = CalleeMO.getGlobal();631MCSymbol *MOSymbol = getSymbol(GValue);632const MCExpr *SymVar = MCSymbolRefExpr::create(MOSymbol, OutContext);633634EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL8_NOP)635.addExpr(SymVar));636EncodedBytes += 2;637}638639// Each instruction is 4 bytes.640EncodedBytes *= 4;641642// Emit padding.643unsigned NumBytes = Opers.getNumPatchBytes();644assert(NumBytes >= EncodedBytes &&645"Patchpoint can't request size less than the length of a call.");646assert((NumBytes - EncodedBytes) % 4 == 0 &&647"Invalid number of NOP bytes requested!");648for (unsigned i = EncodedBytes; i < NumBytes; i += 4)649EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));650}651652/// This helper function creates the TlsGetAddr/TlsGetMod MCSymbol for AIX. We653/// will create the csect and use the qual-name symbol instead of creating just654/// the external symbol.655static MCSymbol *createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc) {656StringRef SymName;657switch (MIOpc) {658default:659SymName = ".__tls_get_addr";660break;661case PPC::GETtlsTpointer32AIX:662SymName = ".__get_tpointer";663break;664case PPC::GETtlsMOD32AIX:665case PPC::GETtlsMOD64AIX:666SymName = ".__tls_get_mod";667break;668}669return Ctx670.getXCOFFSection(SymName, SectionKind::getText(),671XCOFF::CsectProperties(XCOFF::XMC_PR, XCOFF::XTY_ER))672->getQualNameSymbol();673}674675void PPCAsmPrinter::EmitAIXTlsCallHelper(const MachineInstr *MI) {676assert(Subtarget->isAIXABI() &&677"Only expecting to emit calls to get the thread pointer on AIX!");678679MCSymbol *TlsCall = createMCSymbolForTlsGetAddr(OutContext, MI->getOpcode());680const MCExpr *TlsRef =681MCSymbolRefExpr::create(TlsCall, MCSymbolRefExpr::VK_None, OutContext);682EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BLA).addExpr(TlsRef));683}684685/// EmitTlsCall -- Given a GETtls[ld]ADDR[32] instruction, print a686/// call to __tls_get_addr to the current output stream.687void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,688MCSymbolRefExpr::VariantKind VK) {689MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;690unsigned Opcode = PPC::BL8_NOP_TLS;691692assert(MI->getNumOperands() >= 3 && "Expecting at least 3 operands from MI");693if (MI->getOperand(2).getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG ||694MI->getOperand(2).getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) {695Kind = MCSymbolRefExpr::VK_PPC_NOTOC;696Opcode = PPC::BL8_NOTOC_TLS;697}698const Module *M = MF->getFunction().getParent();699700assert(MI->getOperand(0).isReg() &&701((Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::X3) ||702(!Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::R3)) &&703"GETtls[ld]ADDR[32] must define GPR3");704assert(MI->getOperand(1).isReg() &&705((Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::X3) ||706(!Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::R3)) &&707"GETtls[ld]ADDR[32] must read GPR3");708709if (Subtarget->isAIXABI()) {710// For TLSGD, the variable offset should already be in R4 and the region711// handle should already be in R3. We generate an absolute branch to712// .__tls_get_addr. For TLSLD, the module handle should already be in R3.713// We generate an absolute branch to .__tls_get_mod.714Register VarOffsetReg = Subtarget->isPPC64() ? PPC::X4 : PPC::R4;715(void)VarOffsetReg;716assert((MI->getOpcode() == PPC::GETtlsMOD32AIX ||717MI->getOpcode() == PPC::GETtlsMOD64AIX ||718(MI->getOperand(2).isReg() &&719MI->getOperand(2).getReg() == VarOffsetReg)) &&720"GETtls[ld]ADDR[32] must read GPR4");721EmitAIXTlsCallHelper(MI);722return;723}724725MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol("__tls_get_addr");726727if (Subtarget->is32BitELFABI() && isPositionIndependent())728Kind = MCSymbolRefExpr::VK_PLT;729730const MCExpr *TlsRef =731MCSymbolRefExpr::create(TlsGetAddr, Kind, OutContext);732733// Add 32768 offset to the symbol so we follow up the latest GOT/PLT ABI.734if (Kind == MCSymbolRefExpr::VK_PLT && Subtarget->isSecurePlt() &&735M->getPICLevel() == PICLevel::BigPIC)736TlsRef = MCBinaryExpr::createAdd(737TlsRef, MCConstantExpr::create(32768, OutContext), OutContext);738const MachineOperand &MO = MI->getOperand(2);739const GlobalValue *GValue = MO.getGlobal();740MCSymbol *MOSymbol = getSymbol(GValue);741const MCExpr *SymVar = MCSymbolRefExpr::create(MOSymbol, VK, OutContext);742EmitToStreamer(*OutStreamer,743MCInstBuilder(Subtarget->isPPC64() ? Opcode744: (unsigned)PPC::BL_TLS)745.addExpr(TlsRef)746.addExpr(SymVar));747}748749/// Map a machine operand for a TOC pseudo-machine instruction to its750/// corresponding MCSymbol.751static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO,752AsmPrinter &AP) {753switch (MO.getType()) {754case MachineOperand::MO_GlobalAddress:755return AP.getSymbol(MO.getGlobal());756case MachineOperand::MO_ConstantPoolIndex:757return AP.GetCPISymbol(MO.getIndex());758case MachineOperand::MO_JumpTableIndex:759return AP.GetJTISymbol(MO.getIndex());760case MachineOperand::MO_BlockAddress:761return AP.GetBlockAddressSymbol(MO.getBlockAddress());762default:763llvm_unreachable("Unexpected operand type to get symbol.");764}765}766767static PPCAsmPrinter::TOCEntryType768getTOCEntryTypeForMO(const MachineOperand &MO) {769// Use the target flags to determine if this MO is Thread Local.770// If we don't do this it comes out as Global.771if (PPCInstrInfo::hasTLSFlag(MO.getTargetFlags()))772return PPCAsmPrinter::TOCType_ThreadLocal;773774switch (MO.getType()) {775case MachineOperand::MO_GlobalAddress: {776const GlobalValue *GlobalV = MO.getGlobal();777GlobalValue::LinkageTypes Linkage = GlobalV->getLinkage();778if (Linkage == GlobalValue::ExternalLinkage ||779Linkage == GlobalValue::AvailableExternallyLinkage ||780Linkage == GlobalValue::ExternalWeakLinkage)781return PPCAsmPrinter::TOCType_GlobalExternal;782783return PPCAsmPrinter::TOCType_GlobalInternal;784}785case MachineOperand::MO_ConstantPoolIndex:786return PPCAsmPrinter::TOCType_ConstantPool;787case MachineOperand::MO_JumpTableIndex:788return PPCAsmPrinter::TOCType_JumpTable;789case MachineOperand::MO_BlockAddress:790return PPCAsmPrinter::TOCType_BlockAddress;791default:792llvm_unreachable("Unexpected operand type to get TOC type.");793}794}795/// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to796/// the current output stream.797///798void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {799PPC_MC::verifyInstructionPredicates(MI->getOpcode(),800getSubtargetInfo().getFeatureBits());801802MCInst TmpInst;803const bool IsPPC64 = Subtarget->isPPC64();804const bool IsAIX = Subtarget->isAIXABI();805const bool HasAIXSmallLocalTLS = Subtarget->hasAIXSmallLocalExecTLS() ||806Subtarget->hasAIXSmallLocalDynamicTLS();807const Module *M = MF->getFunction().getParent();808PICLevel::Level PL = M->getPICLevel();809810#ifndef NDEBUG811// Validate that SPE and FPU are mutually exclusive in codegen812if (!MI->isInlineAsm()) {813for (const MachineOperand &MO: MI->operands()) {814if (MO.isReg()) {815Register Reg = MO.getReg();816if (Subtarget->hasSPE()) {817if (PPC::F4RCRegClass.contains(Reg) ||818PPC::F8RCRegClass.contains(Reg) ||819PPC::VFRCRegClass.contains(Reg) ||820PPC::VRRCRegClass.contains(Reg) ||821PPC::VSFRCRegClass.contains(Reg) ||822PPC::VSSRCRegClass.contains(Reg)823)824llvm_unreachable("SPE targets cannot have FPRegs!");825} else {826if (PPC::SPERCRegClass.contains(Reg))827llvm_unreachable("SPE register found in FPU-targeted code!");828}829}830}831}832#endif833834auto getTOCRelocAdjustedExprForXCOFF = [this](const MCExpr *Expr,835ptrdiff_t OriginalOffset) {836// Apply an offset to the TOC-based expression such that the adjusted837// notional offset from the TOC base (to be encoded into the instruction's D838// or DS field) is the signed 16-bit truncation of the original notional839// offset from the TOC base.840// This is consistent with the treatment used both by XL C/C++ and841// by AIX ld -r.842ptrdiff_t Adjustment =843OriginalOffset - llvm::SignExtend32<16>(OriginalOffset);844return MCBinaryExpr::createAdd(845Expr, MCConstantExpr::create(-Adjustment, OutContext), OutContext);846};847848auto getTOCEntryLoadingExprForXCOFF =849[IsPPC64, getTOCRelocAdjustedExprForXCOFF,850this](const MCSymbol *MOSymbol, const MCExpr *Expr,851MCSymbolRefExpr::VariantKind VK =852MCSymbolRefExpr::VariantKind::VK_None) -> const MCExpr * {853const unsigned EntryByteSize = IsPPC64 ? 8 : 4;854const auto TOCEntryIter = TOC.find({MOSymbol, VK});855assert(TOCEntryIter != TOC.end() &&856"Could not find the TOC entry for this symbol.");857const ptrdiff_t EntryDistanceFromTOCBase =858(TOCEntryIter - TOC.begin()) * EntryByteSize;859constexpr int16_t PositiveTOCRange = INT16_MAX;860861if (EntryDistanceFromTOCBase > PositiveTOCRange)862return getTOCRelocAdjustedExprForXCOFF(Expr, EntryDistanceFromTOCBase);863864return Expr;865};866auto GetVKForMO = [&](const MachineOperand &MO) {867// For TLS initial-exec and local-exec accesses on AIX, we have one TOC868// entry for the symbol (with the variable offset), which is differentiated869// by MO_TPREL_FLAG.870unsigned Flag = MO.getTargetFlags();871if (Flag == PPCII::MO_TPREL_FLAG ||872Flag == PPCII::MO_GOT_TPREL_PCREL_FLAG ||873Flag == PPCII::MO_TPREL_PCREL_FLAG) {874assert(MO.isGlobal() && "Only expecting a global MachineOperand here!\n");875TLSModel::Model Model = TM.getTLSModel(MO.getGlobal());876if (Model == TLSModel::LocalExec)877return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE;878if (Model == TLSModel::InitialExec)879return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;880// On AIX, TLS model opt may have turned local-dynamic accesses into881// initial-exec accesses.882PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();883if (Model == TLSModel::LocalDynamic &&884FuncInfo->isAIXFuncUseTLSIEForLD()) {885LLVM_DEBUG(886dbgs() << "Current function uses IE access for default LD vars.\n");887return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;888}889llvm_unreachable("Only expecting local-exec or initial-exec accesses!");890}891// For GD TLS access on AIX, we have two TOC entries for the symbol (one for892// the variable offset and the other for the region handle). They are893// differentiated by MO_TLSGD_FLAG and MO_TLSGDM_FLAG.894if (Flag == PPCII::MO_TLSGDM_FLAG)895return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM;896if (Flag == PPCII::MO_TLSGD_FLAG || Flag == PPCII::MO_GOT_TLSGD_PCREL_FLAG)897return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD;898// For local-dynamic TLS access on AIX, we have one TOC entry for the symbol899// (the variable offset) and one shared TOC entry for the module handle.900// They are differentiated by MO_TLSLD_FLAG and MO_TLSLDM_FLAG.901if (Flag == PPCII::MO_TLSLD_FLAG && IsAIX)902return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD;903if (Flag == PPCII::MO_TLSLDM_FLAG && IsAIX)904return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSML;905return MCSymbolRefExpr::VariantKind::VK_None;906};907908// Lower multi-instruction pseudo operations.909switch (MI->getOpcode()) {910default: break;911case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {912assert(!Subtarget->isAIXABI() &&913"AIX does not support patchable function entry!");914// PATCHABLE_FUNCTION_ENTER on little endian is for XRAY support which is915// handled in PPCLinuxAsmPrinter.916if (MAI->isLittleEndian())917return;918const Function &F = MF->getFunction();919unsigned Num = 0;920(void)F.getFnAttribute("patchable-function-entry")921.getValueAsString()922.getAsInteger(10, Num);923if (!Num)924return;925emitNops(Num);926return;927}928case TargetOpcode::DBG_VALUE:929llvm_unreachable("Should be handled target independently");930case TargetOpcode::STACKMAP:931return LowerSTACKMAP(SM, *MI);932case TargetOpcode::PATCHPOINT:933return LowerPATCHPOINT(SM, *MI);934935case PPC::MoveGOTtoLR: {936// Transform %lr = MoveGOTtoLR937// Into this: bl _GLOBAL_OFFSET_TABLE_@local-4938// _GLOBAL_OFFSET_TABLE_@local-4 (instruction preceding939// _GLOBAL_OFFSET_TABLE_) has exactly one instruction:940// blrl941// This will return the pointer to _GLOBAL_OFFSET_TABLE_@local942MCSymbol *GOTSymbol =943OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));944const MCExpr *OffsExpr =945MCBinaryExpr::createSub(MCSymbolRefExpr::create(GOTSymbol,946MCSymbolRefExpr::VK_PPC_LOCAL,947OutContext),948MCConstantExpr::create(4, OutContext),949OutContext);950951// Emit the 'bl'.952EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL).addExpr(OffsExpr));953return;954}955case PPC::MovePCtoLR:956case PPC::MovePCtoLR8: {957// Transform %lr = MovePCtoLR958// Into this, where the label is the PIC base:959// bl L1$pb960// L1$pb:961MCSymbol *PICBase = MF->getPICBaseSymbol();962963// Emit the 'bl'.964EmitToStreamer(*OutStreamer,965MCInstBuilder(PPC::BL)966// FIXME: We would like an efficient form for this, so we967// don't have to do a lot of extra uniquing.968.addExpr(MCSymbolRefExpr::create(PICBase, OutContext)));969970// Emit the label.971OutStreamer->emitLabel(PICBase);972return;973}974case PPC::UpdateGBR: {975// Transform %rd = UpdateGBR(%rt, %ri)976// Into: lwz %rt, .L0$poff - .L0$pb(%ri)977// add %rd, %rt, %ri978// or into (if secure plt mode is on):979// addis r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@ha980// addi r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@l981// Get the offset from the GOT Base Register to the GOT982LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);983if (Subtarget->isSecurePlt() && isPositionIndependent() ) {984unsigned PICR = TmpInst.getOperand(0).getReg();985MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol(986M->getPICLevel() == PICLevel::SmallPIC ? "_GLOBAL_OFFSET_TABLE_"987: ".LTOC");988const MCExpr *PB =989MCSymbolRefExpr::create(MF->getPICBaseSymbol(), OutContext);990991const MCExpr *DeltaExpr = MCBinaryExpr::createSub(992MCSymbolRefExpr::create(BaseSymbol, OutContext), PB, OutContext);993994const MCExpr *DeltaHi = PPCMCExpr::createHa(DeltaExpr, OutContext);995EmitToStreamer(996*OutStreamer,997MCInstBuilder(PPC::ADDIS).addReg(PICR).addReg(PICR).addExpr(DeltaHi));998999const MCExpr *DeltaLo = PPCMCExpr::createLo(DeltaExpr, OutContext);1000EmitToStreamer(1001*OutStreamer,1002MCInstBuilder(PPC::ADDI).addReg(PICR).addReg(PICR).addExpr(DeltaLo));1003return;1004} else {1005MCSymbol *PICOffset =1006MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol(*MF);1007TmpInst.setOpcode(PPC::LWZ);1008const MCExpr *Exp =1009MCSymbolRefExpr::create(PICOffset, MCSymbolRefExpr::VK_None, OutContext);1010const MCExpr *PB =1011MCSymbolRefExpr::create(MF->getPICBaseSymbol(),1012MCSymbolRefExpr::VK_None,1013OutContext);1014const MCOperand TR = TmpInst.getOperand(1);1015const MCOperand PICR = TmpInst.getOperand(0);10161017// Step 1: lwz %rt, .L$poff - .L$pb(%ri)1018TmpInst.getOperand(1) =1019MCOperand::createExpr(MCBinaryExpr::createSub(Exp, PB, OutContext));1020TmpInst.getOperand(0) = TR;1021TmpInst.getOperand(2) = PICR;1022EmitToStreamer(*OutStreamer, TmpInst);10231024TmpInst.setOpcode(PPC::ADD4);1025TmpInst.getOperand(0) = PICR;1026TmpInst.getOperand(1) = TR;1027TmpInst.getOperand(2) = PICR;1028EmitToStreamer(*OutStreamer, TmpInst);1029return;1030}1031}1032case PPC::LWZtoc: {1033// Transform %rN = LWZtoc @op1, %r21034LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);10351036// Change the opcode to LWZ.1037TmpInst.setOpcode(PPC::LWZ);10381039const MachineOperand &MO = MI->getOperand(1);1040assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&1041"Invalid operand for LWZtoc.");10421043// Map the operand to its corresponding MCSymbol.1044const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);10451046// Create a reference to the GOT entry for the symbol. The GOT entry will be1047// synthesized later.1048if (PL == PICLevel::SmallPIC && !IsAIX) {1049const MCExpr *Exp =1050MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_GOT,1051OutContext);1052TmpInst.getOperand(1) = MCOperand::createExpr(Exp);1053EmitToStreamer(*OutStreamer, TmpInst);1054return;1055}10561057MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);10581059// Otherwise, use the TOC. 'TOCEntry' is a label used to reference the1060// storage allocated in the TOC which contains the address of1061// 'MOSymbol'. Said TOC entry will be synthesized later.1062MCSymbol *TOCEntry =1063lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);1064const MCExpr *Exp =1065MCSymbolRefExpr::create(TOCEntry, MCSymbolRefExpr::VK_None, OutContext);10661067// AIX uses the label directly as the lwz displacement operand for1068// references into the toc section. The displacement value will be generated1069// relative to the toc-base.1070if (IsAIX) {1071assert(1072getCodeModel(*Subtarget, TM, MO) == CodeModel::Small &&1073"This pseudo should only be selected for 32-bit small code model.");1074Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);1075TmpInst.getOperand(1) = MCOperand::createExpr(Exp);10761077// Print MO for better readability1078if (isVerbose())1079OutStreamer->getCommentOS() << MO << '\n';1080EmitToStreamer(*OutStreamer, TmpInst);1081return;1082}10831084// Create an explicit subtract expression between the local symbol and1085// '.LTOC' to manifest the toc-relative offset.1086const MCExpr *PB = MCSymbolRefExpr::create(1087OutContext.getOrCreateSymbol(Twine(".LTOC")), OutContext);1088Exp = MCBinaryExpr::createSub(Exp, PB, OutContext);1089TmpInst.getOperand(1) = MCOperand::createExpr(Exp);1090EmitToStreamer(*OutStreamer, TmpInst);1091return;1092}1093case PPC::ADDItoc:1094case PPC::ADDItoc8: {1095assert(IsAIX && TM.getCodeModel() == CodeModel::Small &&1096"PseudoOp only valid for small code model AIX");10971098// Transform %rN = ADDItoc/8 %r2, @op1.1099LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);11001101// Change the opcode to load address.1102TmpInst.setOpcode((!IsPPC64) ? (PPC::LA) : (PPC::LA8));11031104const MachineOperand &MO = MI->getOperand(2);1105assert(MO.isGlobal() && "Invalid operand for ADDItoc[8].");11061107// Map the operand to its corresponding MCSymbol.1108const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);11091110const MCExpr *Exp =1111MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_None, OutContext);11121113TmpInst.getOperand(2) = MCOperand::createExpr(Exp);1114EmitToStreamer(*OutStreamer, TmpInst);1115return;1116}1117case PPC::LDtocJTI:1118case PPC::LDtocCPT:1119case PPC::LDtocBA:1120case PPC::LDtoc: {1121// Transform %x3 = LDtoc @min1, %x21122LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);11231124// Change the opcode to LD.1125TmpInst.setOpcode(PPC::LD);11261127const MachineOperand &MO = MI->getOperand(1);1128assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&1129"Invalid operand!");11301131// Map the operand to its corresponding MCSymbol.1132const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);11331134MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);11351136// Map the machine operand to its corresponding MCSymbol, then map the1137// global address operand to be a reference to the TOC entry we will1138// synthesize later.1139MCSymbol *TOCEntry =1140lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);11411142MCSymbolRefExpr::VariantKind VKExpr =1143IsAIX ? MCSymbolRefExpr::VK_None : MCSymbolRefExpr::VK_PPC_TOC;1144const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry, VKExpr, OutContext);1145TmpInst.getOperand(1) = MCOperand::createExpr(1146IsAIX ? getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK) : Exp);11471148// Print MO for better readability1149if (isVerbose() && IsAIX)1150OutStreamer->getCommentOS() << MO << '\n';1151EmitToStreamer(*OutStreamer, TmpInst);1152return;1153}1154case PPC::ADDIStocHA: {1155const MachineOperand &MO = MI->getOperand(2);11561157assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&1158"Invalid operand for ADDIStocHA.");1159assert((IsAIX && !IsPPC64 &&1160getCodeModel(*Subtarget, TM, MO) == CodeModel::Large) &&1161"This pseudo should only be selected for 32-bit large code model on"1162" AIX.");11631164// Transform %rd = ADDIStocHA %rA, @sym(%r2)1165LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);11661167// Change the opcode to ADDIS.1168TmpInst.setOpcode(PPC::ADDIS);11691170// Map the machine operand to its corresponding MCSymbol.1171MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);11721173MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);11741175// Map the global address operand to be a reference to the TOC entry we1176// will synthesize later. 'TOCEntry' is a label used to reference the1177// storage allocated in the TOC which contains the address of 'MOSymbol'.1178// If the symbol does not have the toc-data attribute, then we create the1179// TOC entry on AIX. If the toc-data attribute is used, the TOC entry1180// contains the data rather than the address of the MOSymbol.1181if ( {1182if (!MO.isGlobal())1183return false;11841185const GlobalVariable *GV = dyn_cast<GlobalVariable>(MO.getGlobal());1186if (!GV)1187return false;1188return GV->hasAttribute("toc-data");1189}(MO)) {1190MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);1191}11921193const MCExpr *Exp = MCSymbolRefExpr::create(1194MOSymbol, MCSymbolRefExpr::VK_PPC_U, OutContext);1195TmpInst.getOperand(2) = MCOperand::createExpr(Exp);1196EmitToStreamer(*OutStreamer, TmpInst);1197return;1198}1199case PPC::LWZtocL: {1200const MachineOperand &MO = MI->getOperand(1);12011202assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&1203"Invalid operand for LWZtocL.");1204assert(IsAIX && !IsPPC64 &&1205getCodeModel(*Subtarget, TM, MO) == CodeModel::Large &&1206"This pseudo should only be selected for 32-bit large code model on"1207" AIX.");12081209// Transform %rd = LWZtocL @sym, %rs.1210LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);12111212// Change the opcode to lwz.1213TmpInst.setOpcode(PPC::LWZ);12141215// Map the machine operand to its corresponding MCSymbol.1216MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);12171218MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);12191220// Always use TOC on AIX. Map the global address operand to be a reference1221// to the TOC entry we will synthesize later. 'TOCEntry' is a label used to1222// reference the storage allocated in the TOC which contains the address of1223// 'MOSymbol'.1224MCSymbol *TOCEntry =1225lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);1226const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry,1227MCSymbolRefExpr::VK_PPC_L,1228OutContext);1229TmpInst.getOperand(1) = MCOperand::createExpr(Exp);1230EmitToStreamer(*OutStreamer, TmpInst);1231return;1232}1233case PPC::ADDIStocHA8: {1234// Transform %xd = ADDIStocHA8 %x2, @sym1235LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);12361237// Change the opcode to ADDIS8. If the global address is the address of1238// an external symbol, is a jump table address, is a block address, or is a1239// constant pool index with large code model enabled, then generate a TOC1240// entry and reference that. Otherwise, reference the symbol directly.1241TmpInst.setOpcode(PPC::ADDIS8);12421243const MachineOperand &MO = MI->getOperand(2);1244assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&1245"Invalid operand for ADDIStocHA8!");12461247const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);12481249MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);12501251const bool GlobalToc =1252MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal());12531254const CodeModel::Model CM =1255IsAIX ? getCodeModel(*Subtarget, TM, MO) : TM.getCodeModel();12561257if (GlobalToc || MO.isJTI() || MO.isBlockAddress() ||1258(MO.isCPI() && CM == CodeModel::Large))1259MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);12601261VK = IsAIX ? MCSymbolRefExpr::VK_PPC_U : MCSymbolRefExpr::VK_PPC_TOC_HA;12621263const MCExpr *Exp =1264MCSymbolRefExpr::create(MOSymbol, VK, OutContext);12651266if (!MO.isJTI() && MO.getOffset())1267Exp = MCBinaryExpr::createAdd(Exp,1268MCConstantExpr::create(MO.getOffset(),1269OutContext),1270OutContext);12711272TmpInst.getOperand(2) = MCOperand::createExpr(Exp);1273EmitToStreamer(*OutStreamer, TmpInst);1274return;1275}1276case PPC::LDtocL: {1277// Transform %xd = LDtocL @sym, %xs1278LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);12791280// Change the opcode to LD. If the global address is the address of1281// an external symbol, is a jump table address, is a block address, or is1282// a constant pool index with large code model enabled, then generate a1283// TOC entry and reference that. Otherwise, reference the symbol directly.1284TmpInst.setOpcode(PPC::LD);12851286const MachineOperand &MO = MI->getOperand(1);1287assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() ||1288MO.isBlockAddress()) &&1289"Invalid operand for LDtocL!");12901291LLVM_DEBUG(assert(1292(!MO.isGlobal() || Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&1293"LDtocL used on symbol that could be accessed directly is "1294"invalid. Must match ADDIStocHA8."));12951296const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);12971298MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);1299CodeModel::Model CM =1300IsAIX ? getCodeModel(*Subtarget, TM, MO) : TM.getCodeModel();1301if (!MO.isCPI() || CM == CodeModel::Large)1302MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);13031304VK = IsAIX ? MCSymbolRefExpr::VK_PPC_L : MCSymbolRefExpr::VK_PPC_TOC_LO;1305const MCExpr *Exp =1306MCSymbolRefExpr::create(MOSymbol, VK, OutContext);1307TmpInst.getOperand(1) = MCOperand::createExpr(Exp);1308EmitToStreamer(*OutStreamer, TmpInst);1309return;1310}1311case PPC::ADDItocL:1312case PPC::ADDItocL8: {1313// Transform %xd = ADDItocL %xs, @sym1314LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);13151316unsigned Op = MI->getOpcode();13171318// Change the opcode to load address for toc-data.1319// ADDItocL is only used for 32-bit toc-data on AIX and will always use LA.1320TmpInst.setOpcode(Op == PPC::ADDItocL8 ? (IsAIX ? PPC::LA8 : PPC::ADDI8)1321: PPC::LA);13221323const MachineOperand &MO = MI->getOperand(2);1324assert((Op == PPC::ADDItocL8)1325? (MO.isGlobal() || MO.isCPI())1326: MO.isGlobal() && "Invalid operand for ADDItocL8.");1327assert(!(MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&1328"Interposable definitions must use indirect accesses.");13291330// Map the operand to its corresponding MCSymbol.1331const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);13321333const MCExpr *Exp = MCSymbolRefExpr::create(1334MOSymbol,1335IsAIX ? MCSymbolRefExpr::VK_PPC_L : MCSymbolRefExpr::VK_PPC_TOC_LO,1336OutContext);13371338TmpInst.getOperand(2) = MCOperand::createExpr(Exp);1339EmitToStreamer(*OutStreamer, TmpInst);1340return;1341}1342case PPC::ADDISgotTprelHA: {1343// Transform: %xd = ADDISgotTprelHA %x2, @sym1344// Into: %xd = ADDIS8 %x2, sym@got@tlsgd@ha1345assert(IsPPC64 && "Not supported for 32-bit PowerPC");1346const MachineOperand &MO = MI->getOperand(2);1347const GlobalValue *GValue = MO.getGlobal();1348MCSymbol *MOSymbol = getSymbol(GValue);1349const MCExpr *SymGotTprel =1350MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA,1351OutContext);1352EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)1353.addReg(MI->getOperand(0).getReg())1354.addReg(MI->getOperand(1).getReg())1355.addExpr(SymGotTprel));1356return;1357}1358case PPC::LDgotTprelL:1359case PPC::LDgotTprelL32: {1360// Transform %xd = LDgotTprelL @sym, %xs1361LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);13621363// Change the opcode to LD.1364TmpInst.setOpcode(IsPPC64 ? PPC::LD : PPC::LWZ);1365const MachineOperand &MO = MI->getOperand(1);1366const GlobalValue *GValue = MO.getGlobal();1367MCSymbol *MOSymbol = getSymbol(GValue);1368const MCExpr *Exp = MCSymbolRefExpr::create(1369MOSymbol, IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO1370: MCSymbolRefExpr::VK_PPC_GOT_TPREL,1371OutContext);1372TmpInst.getOperand(1) = MCOperand::createExpr(Exp);1373EmitToStreamer(*OutStreamer, TmpInst);1374return;1375}13761377case PPC::PPC32PICGOT: {1378MCSymbol *GOTSymbol = OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));1379MCSymbol *GOTRef = OutContext.createTempSymbol();1380MCSymbol *NextInstr = OutContext.createTempSymbol();13811382EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL)1383// FIXME: We would like an efficient form for this, so we don't have to do1384// a lot of extra uniquing.1385.addExpr(MCSymbolRefExpr::create(NextInstr, OutContext)));1386const MCExpr *OffsExpr =1387MCBinaryExpr::createSub(MCSymbolRefExpr::create(GOTSymbol, OutContext),1388MCSymbolRefExpr::create(GOTRef, OutContext),1389OutContext);1390OutStreamer->emitLabel(GOTRef);1391OutStreamer->emitValue(OffsExpr, 4);1392OutStreamer->emitLabel(NextInstr);1393EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR)1394.addReg(MI->getOperand(0).getReg()));1395EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LWZ)1396.addReg(MI->getOperand(1).getReg())1397.addImm(0)1398.addReg(MI->getOperand(0).getReg()));1399EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD4)1400.addReg(MI->getOperand(0).getReg())1401.addReg(MI->getOperand(1).getReg())1402.addReg(MI->getOperand(0).getReg()));1403return;1404}1405case PPC::PPC32GOT: {1406MCSymbol *GOTSymbol =1407OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));1408const MCExpr *SymGotTlsL = MCSymbolRefExpr::create(1409GOTSymbol, MCSymbolRefExpr::VK_PPC_LO, OutContext);1410const MCExpr *SymGotTlsHA = MCSymbolRefExpr::create(1411GOTSymbol, MCSymbolRefExpr::VK_PPC_HA, OutContext);1412EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI)1413.addReg(MI->getOperand(0).getReg())1414.addExpr(SymGotTlsL));1415EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)1416.addReg(MI->getOperand(0).getReg())1417.addReg(MI->getOperand(0).getReg())1418.addExpr(SymGotTlsHA));1419return;1420}1421case PPC::ADDIStlsgdHA: {1422// Transform: %xd = ADDIStlsgdHA %x2, @sym1423// Into: %xd = ADDIS8 %x2, sym@got@tlsgd@ha1424assert(IsPPC64 && "Not supported for 32-bit PowerPC");1425const MachineOperand &MO = MI->getOperand(2);1426const GlobalValue *GValue = MO.getGlobal();1427MCSymbol *MOSymbol = getSymbol(GValue);1428const MCExpr *SymGotTlsGD =1429MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA,1430OutContext);1431EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)1432.addReg(MI->getOperand(0).getReg())1433.addReg(MI->getOperand(1).getReg())1434.addExpr(SymGotTlsGD));1435return;1436}1437case PPC::ADDItlsgdL:1438// Transform: %xd = ADDItlsgdL %xs, @sym1439// Into: %xd = ADDI8 %xs, sym@got@tlsgd@l1440case PPC::ADDItlsgdL32: {1441// Transform: %rd = ADDItlsgdL32 %rs, @sym1442// Into: %rd = ADDI %rs, sym@got@tlsgd1443const MachineOperand &MO = MI->getOperand(2);1444const GlobalValue *GValue = MO.getGlobal();1445MCSymbol *MOSymbol = getSymbol(GValue);1446const MCExpr *SymGotTlsGD = MCSymbolRefExpr::create(1447MOSymbol, IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO1448: MCSymbolRefExpr::VK_PPC_GOT_TLSGD,1449OutContext);1450EmitToStreamer(*OutStreamer,1451MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)1452.addReg(MI->getOperand(0).getReg())1453.addReg(MI->getOperand(1).getReg())1454.addExpr(SymGotTlsGD));1455return;1456}1457case PPC::GETtlsMOD32AIX:1458case PPC::GETtlsMOD64AIX:1459// Transform: %r3 = GETtlsMODNNAIX %r3 (for NN == 32/64).1460// Into: BLA .__tls_get_mod()1461// Input parameter is a module handle (_$TLSML[TC]@ml) for all variables.1462case PPC::GETtlsADDR:1463// Transform: %x3 = GETtlsADDR %x3, @sym1464// Into: BL8_NOP_TLS __tls_get_addr(sym at tlsgd)1465case PPC::GETtlsADDRPCREL:1466case PPC::GETtlsADDR32AIX:1467case PPC::GETtlsADDR64AIX:1468// Transform: %r3 = GETtlsADDRNNAIX %r3, %r4 (for NN == 32/64).1469// Into: BLA .__tls_get_addr()1470// Unlike on Linux, there is no symbol or relocation needed for this call.1471case PPC::GETtlsADDR32: {1472// Transform: %r3 = GETtlsADDR32 %r3, @sym1473// Into: BL_TLS __tls_get_addr(sym at tlsgd)@PLT1474EmitTlsCall(MI, MCSymbolRefExpr::VK_PPC_TLSGD);1475return;1476}1477case PPC::GETtlsTpointer32AIX: {1478// Transform: %r3 = GETtlsTpointer32AIX1479// Into: BLA .__get_tpointer()1480EmitAIXTlsCallHelper(MI);1481return;1482}1483case PPC::ADDIStlsldHA: {1484// Transform: %xd = ADDIStlsldHA %x2, @sym1485// Into: %xd = ADDIS8 %x2, sym@got@tlsld@ha1486assert(IsPPC64 && "Not supported for 32-bit PowerPC");1487const MachineOperand &MO = MI->getOperand(2);1488const GlobalValue *GValue = MO.getGlobal();1489MCSymbol *MOSymbol = getSymbol(GValue);1490const MCExpr *SymGotTlsLD =1491MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA,1492OutContext);1493EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)1494.addReg(MI->getOperand(0).getReg())1495.addReg(MI->getOperand(1).getReg())1496.addExpr(SymGotTlsLD));1497return;1498}1499case PPC::ADDItlsldL:1500// Transform: %xd = ADDItlsldL %xs, @sym1501// Into: %xd = ADDI8 %xs, sym@got@tlsld@l1502case PPC::ADDItlsldL32: {1503// Transform: %rd = ADDItlsldL32 %rs, @sym1504// Into: %rd = ADDI %rs, sym@got@tlsld1505const MachineOperand &MO = MI->getOperand(2);1506const GlobalValue *GValue = MO.getGlobal();1507MCSymbol *MOSymbol = getSymbol(GValue);1508const MCExpr *SymGotTlsLD = MCSymbolRefExpr::create(1509MOSymbol, IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO1510: MCSymbolRefExpr::VK_PPC_GOT_TLSLD,1511OutContext);1512EmitToStreamer(*OutStreamer,1513MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)1514.addReg(MI->getOperand(0).getReg())1515.addReg(MI->getOperand(1).getReg())1516.addExpr(SymGotTlsLD));1517return;1518}1519case PPC::GETtlsldADDR:1520// Transform: %x3 = GETtlsldADDR %x3, @sym1521// Into: BL8_NOP_TLS __tls_get_addr(sym at tlsld)1522case PPC::GETtlsldADDRPCREL:1523case PPC::GETtlsldADDR32: {1524// Transform: %r3 = GETtlsldADDR32 %r3, @sym1525// Into: BL_TLS __tls_get_addr(sym at tlsld)@PLT1526EmitTlsCall(MI, MCSymbolRefExpr::VK_PPC_TLSLD);1527return;1528}1529case PPC::ADDISdtprelHA:1530// Transform: %xd = ADDISdtprelHA %xs, @sym1531// Into: %xd = ADDIS8 %xs, sym@dtprel@ha1532case PPC::ADDISdtprelHA32: {1533// Transform: %rd = ADDISdtprelHA32 %rs, @sym1534// Into: %rd = ADDIS %rs, sym@dtprel@ha1535const MachineOperand &MO = MI->getOperand(2);1536const GlobalValue *GValue = MO.getGlobal();1537MCSymbol *MOSymbol = getSymbol(GValue);1538const MCExpr *SymDtprel =1539MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_HA,1540OutContext);1541EmitToStreamer(1542*OutStreamer,1543MCInstBuilder(IsPPC64 ? PPC::ADDIS8 : PPC::ADDIS)1544.addReg(MI->getOperand(0).getReg())1545.addReg(MI->getOperand(1).getReg())1546.addExpr(SymDtprel));1547return;1548}1549case PPC::PADDIdtprel: {1550// Transform: %rd = PADDIdtprel %rs, @sym1551// Into: %rd = PADDI8 %rs, sym@dtprel1552const MachineOperand &MO = MI->getOperand(2);1553const GlobalValue *GValue = MO.getGlobal();1554MCSymbol *MOSymbol = getSymbol(GValue);1555const MCExpr *SymDtprel = MCSymbolRefExpr::create(1556MOSymbol, MCSymbolRefExpr::VK_DTPREL, OutContext);1557EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::PADDI8)1558.addReg(MI->getOperand(0).getReg())1559.addReg(MI->getOperand(1).getReg())1560.addExpr(SymDtprel));1561return;1562}15631564case PPC::ADDIdtprelL:1565// Transform: %xd = ADDIdtprelL %xs, @sym1566// Into: %xd = ADDI8 %xs, sym@dtprel@l1567case PPC::ADDIdtprelL32: {1568// Transform: %rd = ADDIdtprelL32 %rs, @sym1569// Into: %rd = ADDI %rs, sym@dtprel@l1570const MachineOperand &MO = MI->getOperand(2);1571const GlobalValue *GValue = MO.getGlobal();1572MCSymbol *MOSymbol = getSymbol(GValue);1573const MCExpr *SymDtprel =1574MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_LO,1575OutContext);1576EmitToStreamer(*OutStreamer,1577MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)1578.addReg(MI->getOperand(0).getReg())1579.addReg(MI->getOperand(1).getReg())1580.addExpr(SymDtprel));1581return;1582}1583case PPC::MFOCRF:1584case PPC::MFOCRF8:1585if (!Subtarget->hasMFOCRF()) {1586// Transform: %r3 = MFOCRF %cr71587// Into: %r3 = MFCR ;; cr71588unsigned NewOpcode =1589MI->getOpcode() == PPC::MFOCRF ? PPC::MFCR : PPC::MFCR8;1590OutStreamer->AddComment(PPCInstPrinter::1591getRegisterName(MI->getOperand(1).getReg()));1592EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)1593.addReg(MI->getOperand(0).getReg()));1594return;1595}1596break;1597case PPC::MTOCRF:1598case PPC::MTOCRF8:1599if (!Subtarget->hasMFOCRF()) {1600// Transform: %cr7 = MTOCRF %r31601// Into: MTCRF mask, %r3 ;; cr71602unsigned NewOpcode =1603MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8;1604unsigned Mask = 0x80 >> OutContext.getRegisterInfo()1605->getEncodingValue(MI->getOperand(0).getReg());1606OutStreamer->AddComment(PPCInstPrinter::1607getRegisterName(MI->getOperand(0).getReg()));1608EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)1609.addImm(Mask)1610.addReg(MI->getOperand(1).getReg()));1611return;1612}1613break;1614case PPC::LD:1615case PPC::STD:1616case PPC::LWA_32:1617case PPC::LWA: {1618// Verify alignment is legal, so we don't create relocations1619// that can't be supported.1620unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1;1621// For non-TOC-based local-exec TLS accesses with non-zero offsets, the1622// machine operand (which is a TargetGlobalTLSAddress) is expected to be1623// the same operand for both loads and stores.1624for (const MachineOperand &TempMO : MI->operands()) {1625if (((TempMO.getTargetFlags() == PPCII::MO_TPREL_FLAG ||1626TempMO.getTargetFlags() == PPCII::MO_TLSLD_FLAG)) &&1627TempMO.getOperandNo() == 1)1628OpNum = 1;1629}1630const MachineOperand &MO = MI->getOperand(OpNum);1631if (MO.isGlobal()) {1632const DataLayout &DL = MO.getGlobal()->getDataLayout();1633if (MO.getGlobal()->getPointerAlignment(DL) < 4)1634llvm_unreachable("Global must be word-aligned for LD, STD, LWA!");1635}1636// As these load/stores share common code with the following load/stores,1637// fall through to the subsequent cases in order to either process the1638// non-TOC-based local-exec sequence or to process the instruction normally.1639[[fallthrough]];1640}1641case PPC::LBZ:1642case PPC::LBZ8:1643case PPC::LHA:1644case PPC::LHA8:1645case PPC::LHZ:1646case PPC::LHZ8:1647case PPC::LWZ:1648case PPC::LWZ8:1649case PPC::STB:1650case PPC::STB8:1651case PPC::STH:1652case PPC::STH8:1653case PPC::STW:1654case PPC::STW8:1655case PPC::LFS:1656case PPC::STFS:1657case PPC::LFD:1658case PPC::STFD:1659case PPC::ADDI8: {1660// A faster non-TOC-based local-[exec|dynamic] sequence is represented by1661// `addi` or a load/store instruction (that directly loads or stores off of1662// the thread pointer) with an immediate operand having the1663// [MO_TPREL_FLAG|MO_TLSLD_FLAG]. Such instructions do not otherwise arise.1664if (!HasAIXSmallLocalTLS)1665break;1666bool IsMIADDI8 = MI->getOpcode() == PPC::ADDI8;1667unsigned OpNum = IsMIADDI8 ? 2 : 1;1668const MachineOperand &MO = MI->getOperand(OpNum);1669unsigned Flag = MO.getTargetFlags();1670if (Flag == PPCII::MO_TPREL_FLAG ||1671Flag == PPCII::MO_GOT_TPREL_PCREL_FLAG ||1672Flag == PPCII::MO_TPREL_PCREL_FLAG || Flag == PPCII::MO_TLSLD_FLAG) {1673LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);16741675const MCExpr *Expr = getAdjustedFasterLocalExpr(MO, MO.getOffset());1676if (Expr)1677TmpInst.getOperand(OpNum) = MCOperand::createExpr(Expr);16781679// Change the opcode to load address if the original opcode is an `addi`.1680if (IsMIADDI8)1681TmpInst.setOpcode(PPC::LA8);16821683EmitToStreamer(*OutStreamer, TmpInst);1684return;1685}1686// Now process the instruction normally.1687break;1688}1689case PPC::PseudoEIEIO: {1690EmitToStreamer(1691*OutStreamer,1692MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));1693EmitToStreamer(1694*OutStreamer,1695MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));1696EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::EnforceIEIO));1697return;1698}1699}17001701LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);1702EmitToStreamer(*OutStreamer, TmpInst);1703}17041705// For non-TOC-based local-[exec|dynamic] variables that have a non-zero offset,1706// we need to create a new MCExpr that adds the non-zero offset to the address1707// of the local-[exec|dynamic] variable that will be used in either an addi,1708// load or store. However, the final displacement for these instructions must be1709// between [-32768, 32768), so if the TLS address + its non-zero offset is1710// greater than 32KB, a new MCExpr is produced to accommodate this situation.1711const MCExpr *1712PPCAsmPrinter::getAdjustedFasterLocalExpr(const MachineOperand &MO,1713int64_t Offset) {1714// Non-zero offsets (for loads, stores or `addi`) require additional handling.1715// When the offset is zero, there is no need to create an adjusted MCExpr.1716if (!Offset)1717return nullptr;17181719assert(MO.isGlobal() && "Only expecting a global MachineOperand here!");1720const GlobalValue *GValue = MO.getGlobal();1721TLSModel::Model Model = TM.getTLSModel(GValue);1722assert((Model == TLSModel::LocalExec || Model == TLSModel::LocalDynamic) &&1723"Only local-[exec|dynamic] accesses are handled!");17241725bool IsGlobalADeclaration = GValue->isDeclarationForLinker();1726// Find the GlobalVariable that corresponds to the particular TLS variable1727// in the TLS variable-to-address mapping. All TLS variables should exist1728// within this map, with the exception of TLS variables marked as extern.1729const auto TLSVarsMapEntryIter = TLSVarsToAddressMapping.find(GValue);1730if (TLSVarsMapEntryIter == TLSVarsToAddressMapping.end())1731assert(IsGlobalADeclaration &&1732"Only expecting to find extern TLS variables not present in the TLS "1733"variable-to-address map!");17341735unsigned TLSVarAddress =1736IsGlobalADeclaration ? 0 : TLSVarsMapEntryIter->second;1737ptrdiff_t FinalAddress = (TLSVarAddress + Offset);1738// If the address of the TLS variable + the offset is less than 32KB,1739// or if the TLS variable is extern, we simply produce an MCExpr to add the1740// non-zero offset to the TLS variable address.1741// For when TLS variables are extern, this is safe to do because we can1742// assume that the address of extern TLS variables are zero.1743const MCExpr *Expr = MCSymbolRefExpr::create(1744getSymbol(GValue),1745Model == TLSModel::LocalExec ? MCSymbolRefExpr::VK_PPC_AIX_TLSLE1746: MCSymbolRefExpr::VK_PPC_AIX_TLSLD,1747OutContext);1748Expr = MCBinaryExpr::createAdd(1749Expr, MCConstantExpr::create(Offset, OutContext), OutContext);1750if (FinalAddress >= 32768) {1751// Handle the written offset for cases where:1752// TLS variable address + Offset > 32KB.17531754// The assembly that is printed will look like:1755// TLSVar@le + Offset - Delta1756// where Delta is a multiple of 64KB: ((FinalAddress + 32768) & ~0xFFFF).1757ptrdiff_t Delta = ((FinalAddress + 32768) & ~0xFFFF);1758// Check that the total instruction displacement fits within [-32768,32768).1759[[maybe_unused]] ptrdiff_t InstDisp = TLSVarAddress + Offset - Delta;1760assert(1761((InstDisp < 32768) && (InstDisp >= -32768)) &&1762"Expecting the instruction displacement for local-[exec|dynamic] TLS "1763"variables to be between [-32768, 32768)!");1764Expr = MCBinaryExpr::createAdd(1765Expr, MCConstantExpr::create(-Delta, OutContext), OutContext);1766}17671768return Expr;1769}17701771void PPCLinuxAsmPrinter::emitGNUAttributes(Module &M) {1772// Emit float ABI into GNU attribute1773Metadata *MD = M.getModuleFlag("float-abi");1774MDString *FloatABI = dyn_cast_or_null<MDString>(MD);1775if (!FloatABI)1776return;1777StringRef flt = FloatABI->getString();1778// TODO: Support emitting soft-fp and hard double/single attributes.1779if (flt == "doubledouble")1780OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,1781Val_GNU_Power_ABI_HardFloat_DP |1782Val_GNU_Power_ABI_LDBL_IBM128);1783else if (flt == "ieeequad")1784OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,1785Val_GNU_Power_ABI_HardFloat_DP |1786Val_GNU_Power_ABI_LDBL_IEEE128);1787else if (flt == "ieeedouble")1788OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,1789Val_GNU_Power_ABI_HardFloat_DP |1790Val_GNU_Power_ABI_LDBL_64);1791}17921793void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {1794if (!Subtarget->isPPC64())1795return PPCAsmPrinter::emitInstruction(MI);17961797switch (MI->getOpcode()) {1798default:1799break;1800case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {1801// .begin:1802// b .end # lis 0, FuncId[16..32]1803// nop # li 0, FuncId[0..15]1804// std 0, -8(1)1805// mflr 01806// bl __xray_FunctionEntry1807// mtlr 01808// .end:1809//1810// Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number1811// of instructions change.1812// XRAY is only supported on PPC Linux little endian.1813if (!MAI->isLittleEndian())1814break;1815MCSymbol *BeginOfSled = OutContext.createTempSymbol();1816MCSymbol *EndOfSled = OutContext.createTempSymbol();1817OutStreamer->emitLabel(BeginOfSled);1818EmitToStreamer(*OutStreamer,1819MCInstBuilder(PPC::B).addExpr(1820MCSymbolRefExpr::create(EndOfSled, OutContext)));1821EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));1822EmitToStreamer(1823*OutStreamer,1824MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));1825EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));1826EmitToStreamer(*OutStreamer,1827MCInstBuilder(PPC::BL8_NOP)1828.addExpr(MCSymbolRefExpr::create(1829OutContext.getOrCreateSymbol("__xray_FunctionEntry"),1830OutContext)));1831EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));1832OutStreamer->emitLabel(EndOfSled);1833recordSled(BeginOfSled, *MI, SledKind::FUNCTION_ENTER, 2);1834break;1835}1836case TargetOpcode::PATCHABLE_RET: {1837unsigned RetOpcode = MI->getOperand(0).getImm();1838MCInst RetInst;1839RetInst.setOpcode(RetOpcode);1840for (const auto &MO : llvm::drop_begin(MI->operands())) {1841MCOperand MCOp;1842if (LowerPPCMachineOperandToMCOperand(MO, MCOp, *this))1843RetInst.addOperand(MCOp);1844}18451846bool IsConditional;1847if (RetOpcode == PPC::BCCLR) {1848IsConditional = true;1849} else if (RetOpcode == PPC::TCRETURNdi8 || RetOpcode == PPC::TCRETURNri8 ||1850RetOpcode == PPC::TCRETURNai8) {1851break;1852} else if (RetOpcode == PPC::BLR8 || RetOpcode == PPC::TAILB8) {1853IsConditional = false;1854} else {1855EmitToStreamer(*OutStreamer, RetInst);1856return;1857}18581859MCSymbol *FallthroughLabel;1860if (IsConditional) {1861// Before:1862// bgtlr cr01863//1864// After:1865// ble cr0, .end1866// .p2align 31867// .begin:1868// blr # lis 0, FuncId[16..32]1869// nop # li 0, FuncId[0..15]1870// std 0, -8(1)1871// mflr 01872// bl __xray_FunctionExit1873// mtlr 01874// blr1875// .end:1876//1877// Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number1878// of instructions change.1879FallthroughLabel = OutContext.createTempSymbol();1880EmitToStreamer(1881*OutStreamer,1882MCInstBuilder(PPC::BCC)1883.addImm(PPC::InvertPredicate(1884static_cast<PPC::Predicate>(MI->getOperand(1).getImm())))1885.addReg(MI->getOperand(2).getReg())1886.addExpr(MCSymbolRefExpr::create(FallthroughLabel, OutContext)));1887RetInst = MCInst();1888RetInst.setOpcode(PPC::BLR8);1889}1890// .p2align 31891// .begin:1892// b(lr)? # lis 0, FuncId[16..32]1893// nop # li 0, FuncId[0..15]1894// std 0, -8(1)1895// mflr 01896// bl __xray_FunctionExit1897// mtlr 01898// b(lr)?1899//1900// Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number1901// of instructions change.1902OutStreamer->emitCodeAlignment(Align(8), &getSubtargetInfo());1903MCSymbol *BeginOfSled = OutContext.createTempSymbol();1904OutStreamer->emitLabel(BeginOfSled);1905EmitToStreamer(*OutStreamer, RetInst);1906EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));1907EmitToStreamer(1908*OutStreamer,1909MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));1910EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));1911EmitToStreamer(*OutStreamer,1912MCInstBuilder(PPC::BL8_NOP)1913.addExpr(MCSymbolRefExpr::create(1914OutContext.getOrCreateSymbol("__xray_FunctionExit"),1915OutContext)));1916EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));1917EmitToStreamer(*OutStreamer, RetInst);1918if (IsConditional)1919OutStreamer->emitLabel(FallthroughLabel);1920recordSled(BeginOfSled, *MI, SledKind::FUNCTION_EXIT, 2);1921return;1922}1923case TargetOpcode::PATCHABLE_FUNCTION_EXIT:1924llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");1925case TargetOpcode::PATCHABLE_TAIL_CALL:1926// TODO: Define a trampoline `__xray_FunctionTailExit` and differentiate a1927// normal function exit from a tail exit.1928llvm_unreachable("Tail call is handled in the normal case. See comments "1929"around this assert.");1930}1931return PPCAsmPrinter::emitInstruction(MI);1932}19331934void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) {1935if (static_cast<const PPCTargetMachine &>(TM).isELFv2ABI()) {1936PPCTargetStreamer *TS =1937static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());1938TS->emitAbiVersion(2);1939}19401941if (static_cast<const PPCTargetMachine &>(TM).isPPC64() ||1942!isPositionIndependent())1943return AsmPrinter::emitStartOfAsmFile(M);19441945if (M.getPICLevel() == PICLevel::SmallPIC)1946return AsmPrinter::emitStartOfAsmFile(M);19471948OutStreamer->switchSection(OutContext.getELFSection(1949".got2", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC));19501951MCSymbol *TOCSym = OutContext.getOrCreateSymbol(Twine(".LTOC"));1952MCSymbol *CurrentPos = OutContext.createTempSymbol();19531954OutStreamer->emitLabel(CurrentPos);19551956// The GOT pointer points to the middle of the GOT, in order to reference the1957// entire 64kB range. 0x8000 is the midpoint.1958const MCExpr *tocExpr =1959MCBinaryExpr::createAdd(MCSymbolRefExpr::create(CurrentPos, OutContext),1960MCConstantExpr::create(0x8000, OutContext),1961OutContext);19621963OutStreamer->emitAssignment(TOCSym, tocExpr);19641965OutStreamer->switchSection(getObjFileLowering().getTextSection());1966}19671968void PPCLinuxAsmPrinter::emitFunctionEntryLabel() {1969// linux/ppc32 - Normal entry label.1970if (!Subtarget->isPPC64() &&1971(!isPositionIndependent() ||1972MF->getFunction().getParent()->getPICLevel() == PICLevel::SmallPIC))1973return AsmPrinter::emitFunctionEntryLabel();19741975if (!Subtarget->isPPC64()) {1976const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();1977if (PPCFI->usesPICBase() && !Subtarget->isSecurePlt()) {1978MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol(*MF);1979MCSymbol *PICBase = MF->getPICBaseSymbol();1980OutStreamer->emitLabel(RelocSymbol);19811982const MCExpr *OffsExpr =1983MCBinaryExpr::createSub(1984MCSymbolRefExpr::create(OutContext.getOrCreateSymbol(Twine(".LTOC")),1985OutContext),1986MCSymbolRefExpr::create(PICBase, OutContext),1987OutContext);1988OutStreamer->emitValue(OffsExpr, 4);1989OutStreamer->emitLabel(CurrentFnSym);1990return;1991} else1992return AsmPrinter::emitFunctionEntryLabel();1993}19941995// ELFv2 ABI - Normal entry label.1996if (Subtarget->isELFv2ABI()) {1997// In the Large code model, we allow arbitrary displacements between1998// the text section and its associated TOC section. We place the1999// full 8-byte offset to the TOC in memory immediately preceding2000// the function global entry point.2001if (TM.getCodeModel() == CodeModel::Large2002&& !MF->getRegInfo().use_empty(PPC::X2)) {2003const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();20042005MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));2006MCSymbol *GlobalEPSymbol = PPCFI->getGlobalEPSymbol(*MF);2007const MCExpr *TOCDeltaExpr =2008MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext),2009MCSymbolRefExpr::create(GlobalEPSymbol,2010OutContext),2011OutContext);20122013OutStreamer->emitLabel(PPCFI->getTOCOffsetSymbol(*MF));2014OutStreamer->emitValue(TOCDeltaExpr, 8);2015}2016return AsmPrinter::emitFunctionEntryLabel();2017}20182019// Emit an official procedure descriptor.2020MCSectionSubPair Current = OutStreamer->getCurrentSection();2021MCSectionELF *Section = OutStreamer->getContext().getELFSection(2022".opd", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);2023OutStreamer->switchSection(Section);2024OutStreamer->emitLabel(CurrentFnSym);2025OutStreamer->emitValueToAlignment(Align(8));2026MCSymbol *Symbol1 = CurrentFnSymForSize;2027// Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function2028// entry point.2029OutStreamer->emitValue(MCSymbolRefExpr::create(Symbol1, OutContext),20308 /*size*/);2031MCSymbol *Symbol2 = OutContext.getOrCreateSymbol(StringRef(".TOC."));2032// Generates a R_PPC64_TOC relocation for TOC base insertion.2033OutStreamer->emitValue(2034MCSymbolRefExpr::create(Symbol2, MCSymbolRefExpr::VK_PPC_TOCBASE, OutContext),20358/*size*/);2036// Emit a null environment pointer.2037OutStreamer->emitIntValue(0, 8 /* size */);2038OutStreamer->switchSection(Current.first, Current.second);2039}20402041void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) {2042const DataLayout &DL = getDataLayout();20432044bool isPPC64 = DL.getPointerSizeInBits() == 64;20452046PPCTargetStreamer *TS =2047static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());20482049// If we are using any values provided by Glibc at fixed addresses,2050// we need to ensure that the Glibc used at link time actually provides2051// those values. All versions of Glibc that do will define the symbol2052// named "__parse_hwcap_and_convert_at_platform".2053if (static_cast<const PPCTargetMachine &>(TM).hasGlibcHWCAPAccess())2054OutStreamer->emitSymbolValue(2055GetExternalSymbolSymbol("__parse_hwcap_and_convert_at_platform"),2056MAI->getCodePointerSize());2057emitGNUAttributes(M);20582059if (!TOC.empty()) {2060const char *Name = isPPC64 ? ".toc" : ".got2";2061MCSectionELF *Section = OutContext.getELFSection(2062Name, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);2063OutStreamer->switchSection(Section);2064if (!isPPC64)2065OutStreamer->emitValueToAlignment(Align(4));20662067for (const auto &TOCMapPair : TOC) {2068const MCSymbol *const TOCEntryTarget = TOCMapPair.first.first;2069MCSymbol *const TOCEntryLabel = TOCMapPair.second;20702071OutStreamer->emitLabel(TOCEntryLabel);2072if (isPPC64)2073TS->emitTCEntry(*TOCEntryTarget, TOCMapPair.first.second);2074else2075OutStreamer->emitSymbolValue(TOCEntryTarget, 4);2076}2077}20782079PPCAsmPrinter::emitEndOfAsmFile(M);2080}20812082/// EmitFunctionBodyStart - Emit a global entry point prefix for ELFv2.2083void PPCLinuxAsmPrinter::emitFunctionBodyStart() {2084// In the ELFv2 ABI, in functions that use the TOC register, we need to2085// provide two entry points. The ABI guarantees that when calling the2086// local entry point, r2 is set up by the caller to contain the TOC base2087// for this function, and when calling the global entry point, r12 is set2088// up by the caller to hold the address of the global entry point. We2089// thus emit a prefix sequence along the following lines:2090//2091// func:2092// .Lfunc_gepNN:2093// # global entry point2094// addis r2,r12,(.TOC.-.Lfunc_gepNN)@ha2095// addi r2,r2,(.TOC.-.Lfunc_gepNN)@l2096// .Lfunc_lepNN:2097// .localentry func, .Lfunc_lepNN-.Lfunc_gepNN2098// # local entry point, followed by function body2099//2100// For the Large code model, we create2101//2102// .Lfunc_tocNN:2103// .quad .TOC.-.Lfunc_gepNN # done by EmitFunctionEntryLabel2104// func:2105// .Lfunc_gepNN:2106// # global entry point2107// ld r2,.Lfunc_tocNN-.Lfunc_gepNN(r12)2108// add r2,r2,r122109// .Lfunc_lepNN:2110// .localentry func, .Lfunc_lepNN-.Lfunc_gepNN2111// # local entry point, followed by function body2112//2113// This ensures we have r2 set up correctly while executing the function2114// body, no matter which entry point is called.2115const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();2116const bool UsesX2OrR2 = !MF->getRegInfo().use_empty(PPC::X2) ||2117!MF->getRegInfo().use_empty(PPC::R2);2118const bool PCrelGEPRequired = Subtarget->isUsingPCRelativeCalls() &&2119UsesX2OrR2 && PPCFI->usesTOCBasePtr();2120const bool NonPCrelGEPRequired = !Subtarget->isUsingPCRelativeCalls() &&2121Subtarget->isELFv2ABI() && UsesX2OrR2;21222123// Only do all that if the function uses R2 as the TOC pointer2124// in the first place. We don't need the global entry point if the2125// function uses R2 as an allocatable register.2126if (NonPCrelGEPRequired || PCrelGEPRequired) {2127// Note: The logic here must be synchronized with the code in the2128// branch-selection pass which sets the offset of the first block in the2129// function. This matters because it affects the alignment.2130MCSymbol *GlobalEntryLabel = PPCFI->getGlobalEPSymbol(*MF);2131OutStreamer->emitLabel(GlobalEntryLabel);2132const MCSymbolRefExpr *GlobalEntryLabelExp =2133MCSymbolRefExpr::create(GlobalEntryLabel, OutContext);21342135if (TM.getCodeModel() != CodeModel::Large) {2136MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));2137const MCExpr *TOCDeltaExpr =2138MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext),2139GlobalEntryLabelExp, OutContext);21402141const MCExpr *TOCDeltaHi = PPCMCExpr::createHa(TOCDeltaExpr, OutContext);2142EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)2143.addReg(PPC::X2)2144.addReg(PPC::X12)2145.addExpr(TOCDeltaHi));21462147const MCExpr *TOCDeltaLo = PPCMCExpr::createLo(TOCDeltaExpr, OutContext);2148EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI)2149.addReg(PPC::X2)2150.addReg(PPC::X2)2151.addExpr(TOCDeltaLo));2152} else {2153MCSymbol *TOCOffset = PPCFI->getTOCOffsetSymbol(*MF);2154const MCExpr *TOCOffsetDeltaExpr =2155MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCOffset, OutContext),2156GlobalEntryLabelExp, OutContext);21572158EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)2159.addReg(PPC::X2)2160.addExpr(TOCOffsetDeltaExpr)2161.addReg(PPC::X12));2162EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD8)2163.addReg(PPC::X2)2164.addReg(PPC::X2)2165.addReg(PPC::X12));2166}21672168MCSymbol *LocalEntryLabel = PPCFI->getLocalEPSymbol(*MF);2169OutStreamer->emitLabel(LocalEntryLabel);2170const MCSymbolRefExpr *LocalEntryLabelExp =2171MCSymbolRefExpr::create(LocalEntryLabel, OutContext);2172const MCExpr *LocalOffsetExp =2173MCBinaryExpr::createSub(LocalEntryLabelExp,2174GlobalEntryLabelExp, OutContext);21752176PPCTargetStreamer *TS =2177static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());2178TS->emitLocalEntry(cast<MCSymbolELF>(CurrentFnSym), LocalOffsetExp);2179} else if (Subtarget->isUsingPCRelativeCalls()) {2180// When generating the entry point for a function we have a few scenarios2181// based on whether or not that function uses R2 and whether or not that2182// function makes calls (or is a leaf function).2183// 1) A leaf function that does not use R2 (or treats it as callee-saved2184// and preserves it). In this case st_other=0 and both2185// the local and global entry points for the function are the same.2186// No special entry point code is required.2187// 2) A function uses the TOC pointer R2. This function may or may not have2188// calls. In this case st_other=[2,6] and the global and local entry2189// points are different. Code to correctly setup the TOC pointer in R22190// is put between the global and local entry points. This case is2191// covered by the if statatement above.2192// 3) A function does not use the TOC pointer R2 but does have calls.2193// In this case st_other=1 since we do not know whether or not any2194// of the callees clobber R2. This case is dealt with in this else if2195// block. Tail calls are considered calls and the st_other should also2196// be set to 1 in that case as well.2197// 4) The function does not use the TOC pointer but R2 is used inside2198// the function. In this case st_other=1 once again.2199// 5) This function uses inline asm. We mark R2 as reserved if the function2200// has inline asm as we have to assume that it may be used.2201if (MF->getFrameInfo().hasCalls() || MF->getFrameInfo().hasTailCall() ||2202MF->hasInlineAsm() || (!PPCFI->usesTOCBasePtr() && UsesX2OrR2)) {2203PPCTargetStreamer *TS =2204static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());2205TS->emitLocalEntry(cast<MCSymbolELF>(CurrentFnSym),2206MCConstantExpr::create(1, OutContext));2207}2208}2209}22102211/// EmitFunctionBodyEnd - Print the traceback table before the .size2212/// directive.2213///2214void PPCLinuxAsmPrinter::emitFunctionBodyEnd() {2215// Only the 64-bit target requires a traceback table. For now,2216// we only emit the word of zeroes that GDB requires to find2217// the end of the function, and zeroes for the eight-byte2218// mandatory fields.2219// FIXME: We should fill in the eight-byte mandatory fields as described in2220// the PPC64 ELF ABI (this is a low-priority item because GDB does not2221// currently make use of these fields).2222if (Subtarget->isPPC64()) {2223OutStreamer->emitIntValue(0, 4/*size*/);2224OutStreamer->emitIntValue(0, 8/*size*/);2225}2226}22272228void PPCAIXAsmPrinter::emitLinkage(const GlobalValue *GV,2229MCSymbol *GVSym) const {22302231assert(MAI->hasVisibilityOnlyWithLinkage() &&2232"AIX's linkage directives take a visibility setting.");22332234MCSymbolAttr LinkageAttr = MCSA_Invalid;2235switch (GV->getLinkage()) {2236case GlobalValue::ExternalLinkage:2237LinkageAttr = GV->isDeclaration() ? MCSA_Extern : MCSA_Global;2238break;2239case GlobalValue::LinkOnceAnyLinkage:2240case GlobalValue::LinkOnceODRLinkage:2241case GlobalValue::WeakAnyLinkage:2242case GlobalValue::WeakODRLinkage:2243case GlobalValue::ExternalWeakLinkage:2244LinkageAttr = MCSA_Weak;2245break;2246case GlobalValue::AvailableExternallyLinkage:2247LinkageAttr = MCSA_Extern;2248break;2249case GlobalValue::PrivateLinkage:2250return;2251case GlobalValue::InternalLinkage:2252assert(GV->getVisibility() == GlobalValue::DefaultVisibility &&2253"InternalLinkage should not have other visibility setting.");2254LinkageAttr = MCSA_LGlobal;2255break;2256case GlobalValue::AppendingLinkage:2257llvm_unreachable("Should never emit this");2258case GlobalValue::CommonLinkage:2259llvm_unreachable("CommonLinkage of XCOFF should not come to this path");2260}22612262assert(LinkageAttr != MCSA_Invalid && "LinkageAttr should not MCSA_Invalid.");22632264MCSymbolAttr VisibilityAttr = MCSA_Invalid;2265if (!TM.getIgnoreXCOFFVisibility()) {2266if (GV->hasDLLExportStorageClass() && !GV->hasDefaultVisibility())2267report_fatal_error(2268"Cannot not be both dllexport and non-default visibility");2269switch (GV->getVisibility()) {22702271// TODO: "internal" Visibility needs to go here.2272case GlobalValue::DefaultVisibility:2273if (GV->hasDLLExportStorageClass())2274VisibilityAttr = MAI->getExportedVisibilityAttr();2275break;2276case GlobalValue::HiddenVisibility:2277VisibilityAttr = MAI->getHiddenVisibilityAttr();2278break;2279case GlobalValue::ProtectedVisibility:2280VisibilityAttr = MAI->getProtectedVisibilityAttr();2281break;2282}2283}22842285// Do not emit the _$TLSML symbol.2286if (GV->getThreadLocalMode() == GlobalVariable::LocalDynamicTLSModel &&2287GV->hasName() && GV->getName() == "_$TLSML")2288return;22892290OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr,2291VisibilityAttr);2292}22932294void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {2295// Setup CurrentFnDescSym and its containing csect.2296MCSectionXCOFF *FnDescSec =2297cast<MCSectionXCOFF>(getObjFileLowering().getSectionForFunctionDescriptor(2298&MF.getFunction(), TM));2299FnDescSec->setAlignment(Align(Subtarget->isPPC64() ? 8 : 4));23002301CurrentFnDescSym = FnDescSec->getQualNameSymbol();23022303return AsmPrinter::SetupMachineFunction(MF);2304}23052306uint16_t PPCAIXAsmPrinter::getNumberOfVRSaved() {2307// Calculate the number of VRs be saved.2308// Vector registers 20 through 31 are marked as reserved and cannot be used2309// in the default ABI.2310const PPCSubtarget &Subtarget = MF->getSubtarget<PPCSubtarget>();2311if (Subtarget.isAIXABI() && Subtarget.hasAltivec() &&2312TM.getAIXExtendedAltivecABI()) {2313const MachineRegisterInfo &MRI = MF->getRegInfo();2314for (unsigned Reg = PPC::V20; Reg <= PPC::V31; ++Reg)2315if (MRI.isPhysRegModified(Reg))2316// Number of VRs saved.2317return PPC::V31 - Reg + 1;2318}2319return 0;2320}23212322void PPCAIXAsmPrinter::emitFunctionBodyEnd() {23232324if (!TM.getXCOFFTracebackTable())2325return;23262327emitTracebackTable();23282329// If ShouldEmitEHBlock returns true, then the eh info table2330// will be emitted via `AIXException::endFunction`. Otherwise, we2331// need to emit a dumy eh info table when VRs are saved. We could not2332// consolidate these two places into one because there is no easy way2333// to access register information in `AIXException` class.2334if (!TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF) &&2335(getNumberOfVRSaved() > 0)) {2336// Emit dummy EH Info Table.2337OutStreamer->switchSection(getObjFileLowering().getCompactUnwindSection());2338MCSymbol *EHInfoLabel =2339TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(MF);2340OutStreamer->emitLabel(EHInfoLabel);23412342// Version number.2343OutStreamer->emitInt32(0);23442345const DataLayout &DL = MMI->getModule()->getDataLayout();2346const unsigned PointerSize = DL.getPointerSize();2347// Add necessary paddings in 64 bit mode.2348OutStreamer->emitValueToAlignment(Align(PointerSize));23492350OutStreamer->emitIntValue(0, PointerSize);2351OutStreamer->emitIntValue(0, PointerSize);2352OutStreamer->switchSection(MF->getSection());2353}2354}23552356void PPCAIXAsmPrinter::emitTracebackTable() {23572358// Create a symbol for the end of function.2359MCSymbol *FuncEnd = createTempSymbol(MF->getName());2360OutStreamer->emitLabel(FuncEnd);23612362OutStreamer->AddComment("Traceback table begin");2363// Begin with a fullword of zero.2364OutStreamer->emitIntValueInHexWithPadding(0, 4 /*size*/);23652366SmallString<128> CommentString;2367raw_svector_ostream CommentOS(CommentString);23682369auto EmitComment = [&]() {2370OutStreamer->AddComment(CommentOS.str());2371CommentString.clear();2372};23732374auto EmitCommentAndValue = [&](uint64_t Value, int Size) {2375EmitComment();2376OutStreamer->emitIntValueInHexWithPadding(Value, Size);2377};23782379unsigned int Version = 0;2380CommentOS << "Version = " << Version;2381EmitCommentAndValue(Version, 1);23822383// There is a lack of information in the IR to assist with determining the2384// source language. AIX exception handling mechanism would only search for2385// personality routine and LSDA area when such language supports exception2386// handling. So to be conservatively correct and allow runtime to do its job,2387// we need to set it to C++ for now.2388TracebackTable::LanguageID LanguageIdentifier =2389TracebackTable::CPlusPlus; // C++23902391CommentOS << "Language = "2392<< getNameForTracebackTableLanguageId(LanguageIdentifier);2393EmitCommentAndValue(LanguageIdentifier, 1);23942395// This is only populated for the third and fourth bytes.2396uint32_t FirstHalfOfMandatoryField = 0;23972398// Emit the 3rd byte of the mandatory field.23992400// We always set traceback offset bit to true.2401FirstHalfOfMandatoryField |= TracebackTable::HasTraceBackTableOffsetMask;24022403const PPCFunctionInfo *FI = MF->getInfo<PPCFunctionInfo>();2404const MachineRegisterInfo &MRI = MF->getRegInfo();24052406// Check the function uses floating-point processor instructions or not2407for (unsigned Reg = PPC::F0; Reg <= PPC::F31; ++Reg) {2408if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {2409FirstHalfOfMandatoryField |= TracebackTable::IsFloatingPointPresentMask;2410break;2411}2412}24132414#define GENBOOLCOMMENT(Prefix, V, Field) \2415CommentOS << (Prefix) << ((V) & (TracebackTable::Field##Mask) ? "+" : "-") \2416<< #Field24172418#define GENVALUECOMMENT(PrefixAndName, V, Field) \2419CommentOS << (PrefixAndName) << " = " \2420<< static_cast<unsigned>(((V) & (TracebackTable::Field##Mask)) >> \2421(TracebackTable::Field##Shift))24222423GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsGlobaLinkage);2424GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsOutOfLineEpilogOrPrologue);2425EmitComment();24262427GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasTraceBackTableOffset);2428GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsInternalProcedure);2429EmitComment();24302431GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasControlledStorage);2432GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsTOCless);2433EmitComment();24342435GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsFloatingPointPresent);2436EmitComment();2437GENBOOLCOMMENT("", FirstHalfOfMandatoryField,2438IsFloatingPointOperationLogOrAbortEnabled);2439EmitComment();24402441OutStreamer->emitIntValueInHexWithPadding(2442(FirstHalfOfMandatoryField & 0x0000ff00) >> 8, 1);24432444// Set the 4th byte of the mandatory field.2445FirstHalfOfMandatoryField |= TracebackTable::IsFunctionNamePresentMask;24462447const PPCRegisterInfo *RegInfo =2448static_cast<const PPCRegisterInfo *>(Subtarget->getRegisterInfo());2449Register FrameReg = RegInfo->getFrameRegister(*MF);2450if (FrameReg == (Subtarget->isPPC64() ? PPC::X31 : PPC::R31))2451FirstHalfOfMandatoryField |= TracebackTable::IsAllocaUsedMask;24522453const SmallVectorImpl<Register> &MustSaveCRs = FI->getMustSaveCRs();2454if (!MustSaveCRs.empty())2455FirstHalfOfMandatoryField |= TracebackTable::IsCRSavedMask;24562457if (FI->mustSaveLR())2458FirstHalfOfMandatoryField |= TracebackTable::IsLRSavedMask;24592460GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsInterruptHandler);2461GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsFunctionNamePresent);2462GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsAllocaUsed);2463EmitComment();2464GENVALUECOMMENT("OnConditionDirective", FirstHalfOfMandatoryField,2465OnConditionDirective);2466GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsCRSaved);2467GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsLRSaved);2468EmitComment();2469OutStreamer->emitIntValueInHexWithPadding((FirstHalfOfMandatoryField & 0xff),24701);24712472// Set the 5th byte of mandatory field.2473uint32_t SecondHalfOfMandatoryField = 0;24742475SecondHalfOfMandatoryField |= MF->getFrameInfo().getStackSize()2476? TracebackTable::IsBackChainStoredMask2477: 0;24782479uint32_t FPRSaved = 0;2480for (unsigned Reg = PPC::F14; Reg <= PPC::F31; ++Reg) {2481if (MRI.isPhysRegModified(Reg)) {2482FPRSaved = PPC::F31 - Reg + 1;2483break;2484}2485}2486SecondHalfOfMandatoryField |= (FPRSaved << TracebackTable::FPRSavedShift) &2487TracebackTable::FPRSavedMask;2488GENBOOLCOMMENT("", SecondHalfOfMandatoryField, IsBackChainStored);2489GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, IsFixup);2490GENVALUECOMMENT(", NumOfFPRsSaved", SecondHalfOfMandatoryField, FPRSaved);2491EmitComment();2492OutStreamer->emitIntValueInHexWithPadding(2493(SecondHalfOfMandatoryField & 0xff000000) >> 24, 1);24942495// Set the 6th byte of mandatory field.24962497// Check whether has Vector Instruction,We only treat instructions uses vector2498// register as vector instructions.2499bool HasVectorInst = false;2500for (unsigned Reg = PPC::V0; Reg <= PPC::V31; ++Reg)2501if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {2502// Has VMX instruction.2503HasVectorInst = true;2504break;2505}25062507if (FI->hasVectorParms() || HasVectorInst)2508SecondHalfOfMandatoryField |= TracebackTable::HasVectorInfoMask;25092510uint16_t NumOfVRSaved = getNumberOfVRSaved();2511bool ShouldEmitEHBlock =2512TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF) || NumOfVRSaved > 0;25132514if (ShouldEmitEHBlock)2515SecondHalfOfMandatoryField |= TracebackTable::HasExtensionTableMask;25162517uint32_t GPRSaved = 0;25182519// X13 is reserved under 64-bit environment.2520unsigned GPRBegin = Subtarget->isPPC64() ? PPC::X14 : PPC::R13;2521unsigned GPREnd = Subtarget->isPPC64() ? PPC::X31 : PPC::R31;25222523for (unsigned Reg = GPRBegin; Reg <= GPREnd; ++Reg) {2524if (MRI.isPhysRegModified(Reg)) {2525GPRSaved = GPREnd - Reg + 1;2526break;2527}2528}25292530SecondHalfOfMandatoryField |= (GPRSaved << TracebackTable::GPRSavedShift) &2531TracebackTable::GPRSavedMask;25322533GENBOOLCOMMENT("", SecondHalfOfMandatoryField, HasExtensionTable);2534GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasVectorInfo);2535GENVALUECOMMENT(", NumOfGPRsSaved", SecondHalfOfMandatoryField, GPRSaved);2536EmitComment();2537OutStreamer->emitIntValueInHexWithPadding(2538(SecondHalfOfMandatoryField & 0x00ff0000) >> 16, 1);25392540// Set the 7th byte of mandatory field.2541uint32_t NumberOfFixedParms = FI->getFixedParmsNum();2542SecondHalfOfMandatoryField |=2543(NumberOfFixedParms << TracebackTable::NumberOfFixedParmsShift) &2544TracebackTable::NumberOfFixedParmsMask;2545GENVALUECOMMENT("NumberOfFixedParms", SecondHalfOfMandatoryField,2546NumberOfFixedParms);2547EmitComment();2548OutStreamer->emitIntValueInHexWithPadding(2549(SecondHalfOfMandatoryField & 0x0000ff00) >> 8, 1);25502551// Set the 8th byte of mandatory field.25522553// Always set parameter on stack.2554SecondHalfOfMandatoryField |= TracebackTable::HasParmsOnStackMask;25552556uint32_t NumberOfFPParms = FI->getFloatingPointParmsNum();2557SecondHalfOfMandatoryField |=2558(NumberOfFPParms << TracebackTable::NumberOfFloatingPointParmsShift) &2559TracebackTable::NumberOfFloatingPointParmsMask;25602561GENVALUECOMMENT("NumberOfFPParms", SecondHalfOfMandatoryField,2562NumberOfFloatingPointParms);2563GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasParmsOnStack);2564EmitComment();2565OutStreamer->emitIntValueInHexWithPadding(SecondHalfOfMandatoryField & 0xff,25661);25672568// Generate the optional fields of traceback table.25692570// Parameter type.2571if (NumberOfFixedParms || NumberOfFPParms) {2572uint32_t ParmsTypeValue = FI->getParmsType();25732574Expected<SmallString<32>> ParmsType =2575FI->hasVectorParms()2576? XCOFF::parseParmsTypeWithVecInfo(2577ParmsTypeValue, NumberOfFixedParms, NumberOfFPParms,2578FI->getVectorParmsNum())2579: XCOFF::parseParmsType(ParmsTypeValue, NumberOfFixedParms,2580NumberOfFPParms);25812582assert(ParmsType && toString(ParmsType.takeError()).c_str());2583if (ParmsType) {2584CommentOS << "Parameter type = " << ParmsType.get();2585EmitComment();2586}2587OutStreamer->emitIntValueInHexWithPadding(ParmsTypeValue,2588sizeof(ParmsTypeValue));2589}2590// Traceback table offset.2591OutStreamer->AddComment("Function size");2592if (FirstHalfOfMandatoryField & TracebackTable::HasTraceBackTableOffsetMask) {2593MCSymbol *FuncSectSym = getObjFileLowering().getFunctionEntryPointSymbol(2594&(MF->getFunction()), TM);2595OutStreamer->emitAbsoluteSymbolDiff(FuncEnd, FuncSectSym, 4);2596}25972598// Since we unset the Int_Handler.2599if (FirstHalfOfMandatoryField & TracebackTable::IsInterruptHandlerMask)2600report_fatal_error("Hand_Mask not implement yet");26012602if (FirstHalfOfMandatoryField & TracebackTable::HasControlledStorageMask)2603report_fatal_error("Ctl_Info not implement yet");26042605if (FirstHalfOfMandatoryField & TracebackTable::IsFunctionNamePresentMask) {2606StringRef Name = MF->getName().substr(0, INT16_MAX);2607int16_t NameLength = Name.size();2608CommentOS << "Function name len = "2609<< static_cast<unsigned int>(NameLength);2610EmitCommentAndValue(NameLength, 2);2611OutStreamer->AddComment("Function Name");2612OutStreamer->emitBytes(Name);2613}26142615if (FirstHalfOfMandatoryField & TracebackTable::IsAllocaUsedMask) {2616uint8_t AllocReg = XCOFF::AllocRegNo;2617OutStreamer->AddComment("AllocaUsed");2618OutStreamer->emitIntValueInHex(AllocReg, sizeof(AllocReg));2619}26202621if (SecondHalfOfMandatoryField & TracebackTable::HasVectorInfoMask) {2622uint16_t VRData = 0;2623if (NumOfVRSaved) {2624// Number of VRs saved.2625VRData |= (NumOfVRSaved << TracebackTable::NumberOfVRSavedShift) &2626TracebackTable::NumberOfVRSavedMask;2627// This bit is supposed to set only when the special register2628// VRSAVE is saved on stack.2629// However, IBM XL compiler sets the bit when any vector registers2630// are saved on the stack. We will follow XL's behavior on AIX2631// so that we don't get surprise behavior change for C code.2632VRData |= TracebackTable::IsVRSavedOnStackMask;2633}26342635// Set has_varargs.2636if (FI->getVarArgsFrameIndex())2637VRData |= TracebackTable::HasVarArgsMask;26382639// Vector parameters number.2640unsigned VectorParmsNum = FI->getVectorParmsNum();2641VRData |= (VectorParmsNum << TracebackTable::NumberOfVectorParmsShift) &2642TracebackTable::NumberOfVectorParmsMask;26432644if (HasVectorInst)2645VRData |= TracebackTable::HasVMXInstructionMask;26462647GENVALUECOMMENT("NumOfVRsSaved", VRData, NumberOfVRSaved);2648GENBOOLCOMMENT(", ", VRData, IsVRSavedOnStack);2649GENBOOLCOMMENT(", ", VRData, HasVarArgs);2650EmitComment();2651OutStreamer->emitIntValueInHexWithPadding((VRData & 0xff00) >> 8, 1);26522653GENVALUECOMMENT("NumOfVectorParams", VRData, NumberOfVectorParms);2654GENBOOLCOMMENT(", ", VRData, HasVMXInstruction);2655EmitComment();2656OutStreamer->emitIntValueInHexWithPadding(VRData & 0x00ff, 1);26572658uint32_t VecParmTypeValue = FI->getVecExtParmsType();26592660Expected<SmallString<32>> VecParmsType =2661XCOFF::parseVectorParmsType(VecParmTypeValue, VectorParmsNum);2662assert(VecParmsType && toString(VecParmsType.takeError()).c_str());2663if (VecParmsType) {2664CommentOS << "Vector Parameter type = " << VecParmsType.get();2665EmitComment();2666}2667OutStreamer->emitIntValueInHexWithPadding(VecParmTypeValue,2668sizeof(VecParmTypeValue));2669// Padding 2 bytes.2670CommentOS << "Padding";2671EmitCommentAndValue(0, 2);2672}26732674uint8_t ExtensionTableFlag = 0;2675if (SecondHalfOfMandatoryField & TracebackTable::HasExtensionTableMask) {2676if (ShouldEmitEHBlock)2677ExtensionTableFlag |= ExtendedTBTableFlag::TB_EH_INFO;2678if (EnableSSPCanaryBitInTB &&2679TargetLoweringObjectFileXCOFF::ShouldSetSSPCanaryBitInTB(MF))2680ExtensionTableFlag |= ExtendedTBTableFlag::TB_SSP_CANARY;26812682CommentOS << "ExtensionTableFlag = "2683<< getExtendedTBTableFlagString(ExtensionTableFlag);2684EmitCommentAndValue(ExtensionTableFlag, sizeof(ExtensionTableFlag));2685}26862687if (ExtensionTableFlag & ExtendedTBTableFlag::TB_EH_INFO) {2688auto &Ctx = OutStreamer->getContext();2689MCSymbol *EHInfoSym =2690TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(MF);2691MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(EHInfoSym, TOCType_EHBlock);2692const MCSymbol *TOCBaseSym =2693cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection())2694->getQualNameSymbol();2695const MCExpr *Exp =2696MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCEntry, Ctx),2697MCSymbolRefExpr::create(TOCBaseSym, Ctx), Ctx);26982699const DataLayout &DL = getDataLayout();2700OutStreamer->emitValueToAlignment(Align(4));2701OutStreamer->AddComment("EHInfo Table");2702OutStreamer->emitValue(Exp, DL.getPointerSize());2703}2704#undef GENBOOLCOMMENT2705#undef GENVALUECOMMENT2706}27072708static bool isSpecialLLVMGlobalArrayToSkip(const GlobalVariable *GV) {2709return GV->hasAppendingLinkage() &&2710StringSwitch<bool>(GV->getName())2711// TODO: Linker could still eliminate the GV if we just skip2712// handling llvm.used array. Skipping them for now until we or the2713// AIX OS team come up with a good solution.2714.Case("llvm.used", true)2715// It's correct to just skip llvm.compiler.used array here.2716.Case("llvm.compiler.used", true)2717.Default(false);2718}27192720static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV) {2721return StringSwitch<bool>(GV->getName())2722.Cases("llvm.global_ctors", "llvm.global_dtors", true)2723.Default(false);2724}27252726uint64_t PPCAIXAsmPrinter::getAliasOffset(const Constant *C) {2727if (auto *GA = dyn_cast<GlobalAlias>(C))2728return getAliasOffset(GA->getAliasee());2729if (auto *CE = dyn_cast<ConstantExpr>(C)) {2730const MCExpr *LowC = lowerConstant(CE);2731const MCBinaryExpr *CBE = dyn_cast<MCBinaryExpr>(LowC);2732if (!CBE)2733return 0;2734if (CBE->getOpcode() != MCBinaryExpr::Add)2735report_fatal_error("Only adding an offset is supported now.");2736auto *RHS = dyn_cast<MCConstantExpr>(CBE->getRHS());2737if (!RHS)2738report_fatal_error("Unable to get the offset of alias.");2739return RHS->getValue();2740}2741return 0;2742}27432744static void tocDataChecks(unsigned PointerSize, const GlobalVariable *GV) {2745// TODO: These asserts should be updated as more support for the toc data2746// transformation is added (struct support, etc.).2747assert(2748PointerSize >= GV->getAlign().valueOrOne().value() &&2749"GlobalVariables with an alignment requirement stricter than TOC entry "2750"size not supported by the toc data transformation.");27512752Type *GVType = GV->getValueType();2753assert(GVType->isSized() && "A GlobalVariable's size must be known to be "2754"supported by the toc data transformation.");2755if (GV->getDataLayout().getTypeSizeInBits(GVType) >2756PointerSize * 8)2757report_fatal_error(2758"A GlobalVariable with size larger than a TOC entry is not currently "2759"supported by the toc data transformation.");2760if (GV->hasPrivateLinkage())2761report_fatal_error("A GlobalVariable with private linkage is not "2762"currently supported by the toc data transformation.");2763}27642765void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {2766// Special LLVM global arrays have been handled at the initialization.2767if (isSpecialLLVMGlobalArrayToSkip(GV) || isSpecialLLVMGlobalArrayForStaticInit(GV))2768return;27692770// If the Global Variable has the toc-data attribute, it needs to be emitted2771// when we emit the .toc section.2772if (GV->hasAttribute("toc-data")) {2773unsigned PointerSize = GV->getDataLayout().getPointerSize();2774tocDataChecks(PointerSize, GV);2775TOCDataGlobalVars.push_back(GV);2776return;2777}27782779emitGlobalVariableHelper(GV);2780}27812782void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {2783assert(!GV->getName().starts_with("llvm.") &&2784"Unhandled intrinsic global variable.");27852786if (GV->hasComdat())2787report_fatal_error("COMDAT not yet supported by AIX.");27882789MCSymbolXCOFF *GVSym = cast<MCSymbolXCOFF>(getSymbol(GV));27902791if (GV->isDeclarationForLinker()) {2792emitLinkage(GV, GVSym);2793return;2794}27952796SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);2797if (!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly() &&2798!GVKind.isThreadLocal()) // Checks for both ThreadData and ThreadBSS.2799report_fatal_error("Encountered a global variable kind that is "2800"not supported yet.");28012802// Print GV in verbose mode2803if (isVerbose()) {2804if (GV->hasInitializer()) {2805GV->printAsOperand(OutStreamer->getCommentOS(),2806/*PrintType=*/false, GV->getParent());2807OutStreamer->getCommentOS() << '\n';2808}2809}28102811MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(2812getObjFileLowering().SectionForGlobal(GV, GVKind, TM));28132814// Switch to the containing csect.2815OutStreamer->switchSection(Csect);28162817const DataLayout &DL = GV->getDataLayout();28182819// Handle common and zero-initialized local symbols.2820if (GV->hasCommonLinkage() || GVKind.isBSSLocal() ||2821GVKind.isThreadBSSLocal()) {2822Align Alignment = GV->getAlign().value_or(DL.getPreferredAlign(GV));2823uint64_t Size = DL.getTypeAllocSize(GV->getValueType());2824GVSym->setStorageClass(2825TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV));28262827if (GVKind.isBSSLocal() && Csect->getMappingClass() == XCOFF::XMC_TD) {2828OutStreamer->emitZeros(Size);2829} else if (GVKind.isBSSLocal() || GVKind.isThreadBSSLocal()) {2830assert(Csect->getMappingClass() != XCOFF::XMC_TD &&2831"BSS local toc-data already handled and TLS variables "2832"incompatible with XMC_TD");2833OutStreamer->emitXCOFFLocalCommonSymbol(2834OutContext.getOrCreateSymbol(GVSym->getSymbolTableName()), Size,2835GVSym, Alignment);2836} else {2837OutStreamer->emitCommonSymbol(GVSym, Size, Alignment);2838}2839return;2840}28412842MCSymbol *EmittedInitSym = GVSym;28432844// Emit linkage for the global variable and its aliases.2845emitLinkage(GV, EmittedInitSym);2846for (const GlobalAlias *GA : GOAliasMap[GV])2847emitLinkage(GA, getSymbol(GA));28482849emitAlignment(getGVAlignment(GV, DL), GV);28502851// When -fdata-sections is enabled, every GlobalVariable will2852// be put into its own csect; therefore, label is not necessary here.2853if (!TM.getDataSections() || GV->hasSection()) {2854if (Csect->getMappingClass() != XCOFF::XMC_TD)2855OutStreamer->emitLabel(EmittedInitSym);2856}28572858// No alias to emit.2859if (!GOAliasMap[GV].size()) {2860emitGlobalConstant(GV->getDataLayout(), GV->getInitializer());2861return;2862}28632864// Aliases with the same offset should be aligned. Record the list of aliases2865// associated with the offset.2866AliasMapTy AliasList;2867for (const GlobalAlias *GA : GOAliasMap[GV])2868AliasList[getAliasOffset(GA->getAliasee())].push_back(GA);28692870// Emit alias label and element value for global variable.2871emitGlobalConstant(GV->getDataLayout(), GV->getInitializer(),2872&AliasList);2873}28742875void PPCAIXAsmPrinter::emitFunctionDescriptor() {2876const DataLayout &DL = getDataLayout();2877const unsigned PointerSize = DL.getPointerSizeInBits() == 64 ? 8 : 4;28782879MCSectionSubPair Current = OutStreamer->getCurrentSection();2880// Emit function descriptor.2881OutStreamer->switchSection(2882cast<MCSymbolXCOFF>(CurrentFnDescSym)->getRepresentedCsect());28832884// Emit aliasing label for function descriptor csect.2885for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])2886OutStreamer->emitLabel(getSymbol(Alias));28872888// Emit function entry point address.2889OutStreamer->emitValue(MCSymbolRefExpr::create(CurrentFnSym, OutContext),2890PointerSize);2891// Emit TOC base address.2892const MCSymbol *TOCBaseSym =2893cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection())2894->getQualNameSymbol();2895OutStreamer->emitValue(MCSymbolRefExpr::create(TOCBaseSym, OutContext),2896PointerSize);2897// Emit a null environment pointer.2898OutStreamer->emitIntValue(0, PointerSize);28992900OutStreamer->switchSection(Current.first, Current.second);2901}29022903void PPCAIXAsmPrinter::emitFunctionEntryLabel() {2904// For functions without user defined section, it's not necessary to emit the2905// label when we have individual function in its own csect.2906if (!TM.getFunctionSections() || MF->getFunction().hasSection())2907PPCAsmPrinter::emitFunctionEntryLabel();29082909// Emit aliasing label for function entry point label.2910for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])2911OutStreamer->emitLabel(2912getObjFileLowering().getFunctionEntryPointSymbol(Alias, TM));2913}29142915void PPCAIXAsmPrinter::emitPGORefs(Module &M) {2916if (!OutContext.hasXCOFFSection(2917"__llvm_prf_cnts",2918XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))2919return;29202921// When inside a csect `foo`, a .ref directive referring to a csect `bar`2922// translates into a relocation entry from `foo` to` bar`. The referring2923// csect, `foo`, is identified by its address. If multiple csects have the2924// same address (because one or more of them are zero-length), the referring2925// csect cannot be determined. Hence, we don't generate the .ref directives2926// if `__llvm_prf_cnts` is an empty section.2927bool HasNonZeroLengthPrfCntsSection = false;2928const DataLayout &DL = M.getDataLayout();2929for (GlobalVariable &GV : M.globals())2930if (GV.hasSection() && GV.getSection() == "__llvm_prf_cnts" &&2931DL.getTypeAllocSize(GV.getValueType()) > 0) {2932HasNonZeroLengthPrfCntsSection = true;2933break;2934}29352936if (HasNonZeroLengthPrfCntsSection) {2937MCSection *CntsSection = OutContext.getXCOFFSection(2938"__llvm_prf_cnts", SectionKind::getData(),2939XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD),2940/*MultiSymbolsAllowed*/ true);29412942OutStreamer->switchSection(CntsSection);2943if (OutContext.hasXCOFFSection(2944"__llvm_prf_data",2945XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {2946MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_data[RW]");2947OutStreamer->emitXCOFFRefDirective(S);2948}2949if (OutContext.hasXCOFFSection(2950"__llvm_prf_names",2951XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD))) {2952MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_names[RO]");2953OutStreamer->emitXCOFFRefDirective(S);2954}2955if (OutContext.hasXCOFFSection(2956"__llvm_prf_vnds",2957XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {2958MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_vnds[RW]");2959OutStreamer->emitXCOFFRefDirective(S);2960}2961}2962}29632964void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {2965// If there are no functions and there are no toc-data definitions in this2966// module, we will never need to reference the TOC base.2967if (M.empty() && TOCDataGlobalVars.empty())2968return;29692970emitPGORefs(M);29712972// Switch to section to emit TOC base.2973OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());29742975PPCTargetStreamer *TS =2976static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());29772978for (auto &I : TOC) {2979MCSectionXCOFF *TCEntry;2980// Setup the csect for the current TC entry. If the variant kind is2981// VK_PPC_AIX_TLSGDM the entry represents the region handle, we create a2982// new symbol to prefix the name with a dot.2983// If TLS model opt is turned on, create a new symbol to prefix the name2984// with a dot.2985if (I.first.second == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM ||2986(Subtarget->hasAIXShLibTLSModelOpt() &&2987I.first.second == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD)) {2988SmallString<128> Name;2989StringRef Prefix = ".";2990Name += Prefix;2991Name += cast<MCSymbolXCOFF>(I.first.first)->getSymbolTableName();2992MCSymbol *S = OutContext.getOrCreateSymbol(Name);2993TCEntry = cast<MCSectionXCOFF>(2994getObjFileLowering().getSectionForTOCEntry(S, TM));2995} else {2996TCEntry = cast<MCSectionXCOFF>(2997getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));2998}2999OutStreamer->switchSection(TCEntry);30003001OutStreamer->emitLabel(I.second);3002TS->emitTCEntry(*I.first.first, I.first.second);3003}30043005// Traverse the list of global variables twice, emitting all of the3006// non-common global variables before the common ones, as emitting a3007// .comm directive changes the scope from .toc to the common symbol.3008for (const auto *GV : TOCDataGlobalVars) {3009if (!GV->hasCommonLinkage())3010emitGlobalVariableHelper(GV);3011}3012for (const auto *GV : TOCDataGlobalVars) {3013if (GV->hasCommonLinkage())3014emitGlobalVariableHelper(GV);3015}3016}30173018bool PPCAIXAsmPrinter::doInitialization(Module &M) {3019const bool Result = PPCAsmPrinter::doInitialization(M);30203021auto setCsectAlignment = [this](const GlobalObject *GO) {3022// Declarations have 0 alignment which is set by default.3023if (GO->isDeclarationForLinker())3024return;30253026SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM);3027MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(3028getObjFileLowering().SectionForGlobal(GO, GOKind, TM));30293030Align GOAlign = getGVAlignment(GO, GO->getDataLayout());3031Csect->ensureMinAlignment(GOAlign);3032};30333034// For all TLS variables, calculate their corresponding addresses and store3035// them into TLSVarsToAddressMapping, which will be used to determine whether3036// or not local-exec TLS variables require special assembly printing.3037uint64_t TLSVarAddress = 0;3038auto DL = M.getDataLayout();3039for (const auto &G : M.globals()) {3040if (G.isThreadLocal() && !G.isDeclaration()) {3041TLSVarAddress = alignTo(TLSVarAddress, getGVAlignment(&G, DL));3042TLSVarsToAddressMapping[&G] = TLSVarAddress;3043TLSVarAddress += DL.getTypeAllocSize(G.getValueType());3044}3045}30463047// We need to know, up front, the alignment of csects for the assembly path,3048// because once a .csect directive gets emitted, we could not change the3049// alignment value on it.3050for (const auto &G : M.globals()) {3051if (isSpecialLLVMGlobalArrayToSkip(&G))3052continue;30533054if (isSpecialLLVMGlobalArrayForStaticInit(&G)) {3055// Generate a format indicator and a unique module id to be a part of3056// the sinit and sterm function names.3057if (FormatIndicatorAndUniqueModId.empty()) {3058std::string UniqueModuleId = getUniqueModuleId(&M);3059if (UniqueModuleId != "")3060// TODO: Use source file full path to generate the unique module id3061// and add a format indicator as a part of function name in case we3062// will support more than one format.3063FormatIndicatorAndUniqueModId = "clang_" + UniqueModuleId.substr(1);3064else {3065// Use threadId, Pid, and current time as the unique module id when we3066// cannot generate one based on a module's strong external symbols.3067auto CurTime =3068std::chrono::duration_cast<std::chrono::nanoseconds>(3069std::chrono::steady_clock::now().time_since_epoch())3070.count();3071FormatIndicatorAndUniqueModId =3072"clangPidTidTime_" + llvm::itostr(sys::Process::getProcessId()) +3073"_" + llvm::itostr(llvm::get_threadid()) + "_" +3074llvm::itostr(CurTime);3075}3076}30773078emitSpecialLLVMGlobal(&G);3079continue;3080}30813082setCsectAlignment(&G);3083std::optional<CodeModel::Model> OptionalCodeModel = G.getCodeModel();3084if (OptionalCodeModel)3085setOptionalCodeModel(cast<MCSymbolXCOFF>(getSymbol(&G)),3086*OptionalCodeModel);3087}30883089for (const auto &F : M)3090setCsectAlignment(&F);30913092// Construct an aliasing list for each GlobalObject.3093for (const auto &Alias : M.aliases()) {3094const GlobalObject *Aliasee = Alias.getAliaseeObject();3095if (!Aliasee)3096report_fatal_error(3097"alias without a base object is not yet supported on AIX");30983099if (Aliasee->hasCommonLinkage()) {3100report_fatal_error("Aliases to common variables are not allowed on AIX:"3101"\n\tAlias attribute for " +3102Alias.getGlobalIdentifier() +3103" is invalid because " + Aliasee->getName() +3104" is common.",3105false);3106}31073108const GlobalVariable *GVar =3109dyn_cast_or_null<GlobalVariable>(Alias.getAliaseeObject());3110if (GVar) {3111std::optional<CodeModel::Model> OptionalCodeModel = GVar->getCodeModel();3112if (OptionalCodeModel)3113setOptionalCodeModel(cast<MCSymbolXCOFF>(getSymbol(&Alias)),3114*OptionalCodeModel);3115}31163117GOAliasMap[Aliasee].push_back(&Alias);3118}31193120return Result;3121}31223123void PPCAIXAsmPrinter::emitInstruction(const MachineInstr *MI) {3124switch (MI->getOpcode()) {3125default:3126break;3127case PPC::TW:3128case PPC::TWI:3129case PPC::TD:3130case PPC::TDI: {3131if (MI->getNumOperands() < 5)3132break;3133const MachineOperand &LangMO = MI->getOperand(3);3134const MachineOperand &ReasonMO = MI->getOperand(4);3135if (!LangMO.isImm() || !ReasonMO.isImm())3136break;3137MCSymbol *TempSym = OutContext.createNamedTempSymbol();3138OutStreamer->emitLabel(TempSym);3139OutStreamer->emitXCOFFExceptDirective(CurrentFnSym, TempSym,3140LangMO.getImm(), ReasonMO.getImm(),3141Subtarget->isPPC64() ? MI->getMF()->getInstructionCount() * 8 :3142MI->getMF()->getInstructionCount() * 4,3143MMI->hasDebugInfo());3144break;3145}3146case PPC::GETtlsMOD32AIX:3147case PPC::GETtlsMOD64AIX:3148case PPC::GETtlsTpointer32AIX:3149case PPC::GETtlsADDR64AIX:3150case PPC::GETtlsADDR32AIX: {3151// A reference to .__tls_get_mod/.__tls_get_addr/.__get_tpointer is unknown3152// to the assembler so we need to emit an external symbol reference.3153MCSymbol *TlsGetAddr =3154createMCSymbolForTlsGetAddr(OutContext, MI->getOpcode());3155ExtSymSDNodeSymbols.insert(TlsGetAddr);3156break;3157}3158case PPC::BL8:3159case PPC::BL:3160case PPC::BL8_NOP:3161case PPC::BL_NOP: {3162const MachineOperand &MO = MI->getOperand(0);3163if (MO.isSymbol()) {3164MCSymbolXCOFF *S =3165cast<MCSymbolXCOFF>(OutContext.getOrCreateSymbol(MO.getSymbolName()));3166ExtSymSDNodeSymbols.insert(S);3167}3168} break;3169case PPC::BL_TLS:3170case PPC::BL8_TLS:3171case PPC::BL8_TLS_:3172case PPC::BL8_NOP_TLS:3173report_fatal_error("TLS call not yet implemented");3174case PPC::TAILB:3175case PPC::TAILB8:3176case PPC::TAILBA:3177case PPC::TAILBA8:3178case PPC::TAILBCTR:3179case PPC::TAILBCTR8:3180if (MI->getOperand(0).isSymbol())3181report_fatal_error("Tail call for extern symbol not yet supported.");3182break;3183case PPC::DST:3184case PPC::DST64:3185case PPC::DSTT:3186case PPC::DSTT64:3187case PPC::DSTST:3188case PPC::DSTST64:3189case PPC::DSTSTT:3190case PPC::DSTSTT64:3191EmitToStreamer(3192*OutStreamer,3193MCInstBuilder(PPC::ORI).addReg(PPC::R0).addReg(PPC::R0).addImm(0));3194return;3195}3196return PPCAsmPrinter::emitInstruction(MI);3197}31983199bool PPCAIXAsmPrinter::doFinalization(Module &M) {3200// Do streamer related finalization for DWARF.3201if (!MAI->usesDwarfFileAndLocDirectives() && MMI->hasDebugInfo())3202OutStreamer->doFinalizationAtSectionEnd(3203OutStreamer->getContext().getObjectFileInfo()->getTextSection());32043205for (MCSymbol *Sym : ExtSymSDNodeSymbols)3206OutStreamer->emitSymbolAttribute(Sym, MCSA_Extern);3207return PPCAsmPrinter::doFinalization(M);3208}32093210static unsigned mapToSinitPriority(int P) {3211if (P < 0 || P > 65535)3212report_fatal_error("invalid init priority");32133214if (P <= 20)3215return P;32163217if (P < 81)3218return 20 + (P - 20) * 16;32193220if (P <= 1124)3221return 1004 + (P - 81);32223223if (P < 64512)3224return 2047 + (P - 1124) * 33878;32253226return 2147482625u + (P - 64512);3227}32283229static std::string convertToSinitPriority(int Priority) {3230// This helper function converts clang init priority to values used in sinit3231// and sterm functions.3232//3233// The conversion strategies are:3234// We map the reserved clang/gnu priority range [0, 100] into the sinit/sterm3235// reserved priority range [0, 1023] by3236// - directly mapping the first 21 and the last 20 elements of the ranges3237// - linear interpolating the intermediate values with a step size of 16.3238//3239// We map the non reserved clang/gnu priority range of [101, 65535] into the3240// sinit/sterm priority range [1024, 2147483648] by:3241// - directly mapping the first and the last 1024 elements of the ranges3242// - linear interpolating the intermediate values with a step size of 33878.3243unsigned int P = mapToSinitPriority(Priority);32443245std::string PrioritySuffix;3246llvm::raw_string_ostream os(PrioritySuffix);3247os << llvm::format_hex_no_prefix(P, 8);3248os.flush();3249return PrioritySuffix;3250}32513252void PPCAIXAsmPrinter::emitXXStructorList(const DataLayout &DL,3253const Constant *List, bool IsCtor) {3254SmallVector<Structor, 8> Structors;3255preprocessXXStructorList(DL, List, Structors);3256if (Structors.empty())3257return;32583259unsigned Index = 0;3260for (Structor &S : Structors) {3261if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(S.Func))3262S.Func = CE->getOperand(0);32633264llvm::GlobalAlias::create(3265GlobalValue::ExternalLinkage,3266(IsCtor ? llvm::Twine("__sinit") : llvm::Twine("__sterm")) +3267llvm::Twine(convertToSinitPriority(S.Priority)) +3268llvm::Twine("_", FormatIndicatorAndUniqueModId) +3269llvm::Twine("_", llvm::utostr(Index++)),3270cast<Function>(S.Func));3271}3272}32733274void PPCAIXAsmPrinter::emitTTypeReference(const GlobalValue *GV,3275unsigned Encoding) {3276if (GV) {3277TOCEntryType GlobalType = TOCType_GlobalInternal;3278GlobalValue::LinkageTypes Linkage = GV->getLinkage();3279if (Linkage == GlobalValue::ExternalLinkage ||3280Linkage == GlobalValue::AvailableExternallyLinkage ||3281Linkage == GlobalValue::ExternalWeakLinkage)3282GlobalType = TOCType_GlobalExternal;3283MCSymbol *TypeInfoSym = TM.getSymbol(GV);3284MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(TypeInfoSym, GlobalType);3285const MCSymbol *TOCBaseSym =3286cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection())3287->getQualNameSymbol();3288auto &Ctx = OutStreamer->getContext();3289const MCExpr *Exp =3290MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCEntry, Ctx),3291MCSymbolRefExpr::create(TOCBaseSym, Ctx), Ctx);3292OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding));3293} else3294OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding));3295}32963297// Return a pass that prints the PPC assembly code for a MachineFunction to the3298// given output stream.3299static AsmPrinter *3300createPPCAsmPrinterPass(TargetMachine &tm,3301std::unique_ptr<MCStreamer> &&Streamer) {3302if (tm.getTargetTriple().isOSAIX())3303return new PPCAIXAsmPrinter(tm, std::move(Streamer));33043305return new PPCLinuxAsmPrinter(tm, std::move(Streamer));3306}33073308void PPCAIXAsmPrinter::emitModuleCommandLines(Module &M) {3309const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline");3310if (!NMD || !NMD->getNumOperands())3311return;33123313std::string S;3314raw_string_ostream RSOS(S);3315for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {3316const MDNode *N = NMD->getOperand(i);3317assert(N->getNumOperands() == 1 &&3318"llvm.commandline metadata entry can have only one operand");3319const MDString *MDS = cast<MDString>(N->getOperand(0));3320// Add "@(#)" to support retrieving the command line information with the3321// AIX "what" command3322RSOS << "@(#)opt " << MDS->getString() << "\n";3323RSOS.write('\0');3324}3325OutStreamer->emitXCOFFCInfoSym(".GCC.command.line", RSOS.str());3326}33273328// Force static initialization.3329extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCAsmPrinter() {3330TargetRegistry::RegisterAsmPrinter(getThePPC32Target(),3331createPPCAsmPrinterPass);3332TargetRegistry::RegisterAsmPrinter(getThePPC32LETarget(),3333createPPCAsmPrinterPass);3334TargetRegistry::RegisterAsmPrinter(getThePPC64Target(),3335createPPCAsmPrinterPass);3336TargetRegistry::RegisterAsmPrinter(getThePPC64LETarget(),3337createPPCAsmPrinterPass);3338}333933403341