Path: blob/main/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
35294 views
//===-- PPCMCTargetDesc.cpp - PowerPC Target Descriptions -----------------===//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 provides PowerPC specific target descriptions.9//10//===----------------------------------------------------------------------===//1112#include "MCTargetDesc/PPCMCTargetDesc.h"13#include "MCTargetDesc/PPCInstPrinter.h"14#include "MCTargetDesc/PPCMCAsmInfo.h"15#include "PPCELFStreamer.h"16#include "PPCTargetStreamer.h"17#include "PPCXCOFFStreamer.h"18#include "TargetInfo/PowerPCTargetInfo.h"19#include "llvm/ADT/SmallPtrSet.h"20#include "llvm/ADT/StringRef.h"21#include "llvm/BinaryFormat/ELF.h"22#include "llvm/MC/MCAsmBackend.h"23#include "llvm/MC/MCAssembler.h"24#include "llvm/MC/MCCodeEmitter.h"25#include "llvm/MC/MCContext.h"26#include "llvm/MC/MCDwarf.h"27#include "llvm/MC/MCELFStreamer.h"28#include "llvm/MC/MCExpr.h"29#include "llvm/MC/MCInstrAnalysis.h"30#include "llvm/MC/MCInstrInfo.h"31#include "llvm/MC/MCObjectWriter.h"32#include "llvm/MC/MCRegisterInfo.h"33#include "llvm/MC/MCSectionXCOFF.h"34#include "llvm/MC/MCStreamer.h"35#include "llvm/MC/MCSubtargetInfo.h"36#include "llvm/MC/MCSymbol.h"37#include "llvm/MC/MCSymbolELF.h"38#include "llvm/MC/MCSymbolXCOFF.h"39#include "llvm/MC/TargetRegistry.h"40#include "llvm/Support/Casting.h"41#include "llvm/Support/CodeGen.h"42#include "llvm/Support/ErrorHandling.h"43#include "llvm/Support/FormattedStream.h"44#include "llvm/Support/raw_ostream.h"45#include "llvm/TargetParser/Triple.h"4647using namespace llvm;4849#define GET_INSTRINFO_MC_DESC50#define ENABLE_INSTR_PREDICATE_VERIFIER51#include "PPCGenInstrInfo.inc"5253#define GET_SUBTARGETINFO_MC_DESC54#include "PPCGenSubtargetInfo.inc"5556#define GET_REGINFO_MC_DESC57#include "PPCGenRegisterInfo.inc"5859/// stripRegisterPrefix - This method strips the character prefix from a60/// register name so that only the number is left. Used by for linux asm.61const char *PPC::stripRegisterPrefix(const char *RegName) {62switch (RegName[0]) {63case 'a':64if (RegName[1] == 'c' && RegName[2] == 'c')65return RegName + 3;66break;67case 'f':68if (RegName[1] == 'p')69return RegName + 2;70[[fallthrough]];71case 'r':72case 'v':73if (RegName[1] == 's') {74if (RegName[2] == 'p')75return RegName + 3;76return RegName + 2;77}78return RegName + 1;79case 'c':80if (RegName[1] == 'r')81return RegName + 2;82break;83case 'w':84// For wacc and wacc_hi85if (RegName[1] == 'a' && RegName[2] == 'c' && RegName[3] == 'c') {86if (RegName[4] == '_')87return RegName + 7;88else89return RegName + 4;90}91break;92case 'd':93// For dmr, dmrp, dmrrow, dmrrowp94if (RegName[1] == 'm' && RegName[2] == 'r') {95if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w' &&96RegName[6] == 'p')97return RegName + 7;98else if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w')99return RegName + 6;100else if (RegName[3] == 'p')101return RegName + 4;102else103return RegName + 3;104}105break;106}107108return RegName;109}110111/// getRegNumForOperand - some operands use different numbering schemes112/// for the same registers. For example, a VSX instruction may have any of113/// vs0-vs63 allocated whereas an Altivec instruction could only have114/// vs32-vs63 allocated (numbered as v0-v31). This function returns the actual115/// register number needed for the opcode/operand number combination.116/// The operand number argument will be useful when we need to extend this117/// to instructions that use both Altivec and VSX numbering (for different118/// operands).119unsigned PPC::getRegNumForOperand(const MCInstrDesc &Desc, unsigned Reg,120unsigned OpNo) {121int16_t regClass = Desc.operands()[OpNo].RegClass;122switch (regClass) {123// We store F0-F31, VF0-VF31 in MCOperand and it should be F0-F31,124// VSX32-VSX63 during encoding/disassembling125case PPC::VSSRCRegClassID:126case PPC::VSFRCRegClassID:127if (PPC::isVFRegister(Reg))128return PPC::VSX32 + (Reg - PPC::VF0);129break;130// We store VSL0-VSL31, V0-V31 in MCOperand and it should be VSL0-VSL31,131// VSX32-VSX63 during encoding/disassembling132case PPC::VSRCRegClassID:133if (PPC::isVRRegister(Reg))134return PPC::VSX32 + (Reg - PPC::V0);135break;136// Other RegClass doesn't need mapping137default:138break;139}140return Reg;141}142143PPCTargetStreamer::PPCTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}144145// Pin the vtable to this file.146PPCTargetStreamer::~PPCTargetStreamer() = default;147148static MCInstrInfo *createPPCMCInstrInfo() {149MCInstrInfo *X = new MCInstrInfo();150InitPPCMCInstrInfo(X);151return X;152}153154static MCRegisterInfo *createPPCMCRegisterInfo(const Triple &TT) {155bool isPPC64 =156(TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le);157unsigned Flavour = isPPC64 ? 0 : 1;158unsigned RA = isPPC64 ? PPC::LR8 : PPC::LR;159160MCRegisterInfo *X = new MCRegisterInfo();161InitPPCMCRegisterInfo(X, RA, Flavour, Flavour);162return X;163}164165static MCSubtargetInfo *createPPCMCSubtargetInfo(const Triple &TT,166StringRef CPU, StringRef FS) {167// Set some default feature to MC layer.168std::string FullFS = std::string(FS);169170if (TT.isOSAIX()) {171if (!FullFS.empty())172FullFS = "+aix," + FullFS;173else174FullFS = "+aix";175}176177return createPPCMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FullFS);178}179180static MCAsmInfo *createPPCMCAsmInfo(const MCRegisterInfo &MRI,181const Triple &TheTriple,182const MCTargetOptions &Options) {183bool isPPC64 = (TheTriple.getArch() == Triple::ppc64 ||184TheTriple.getArch() == Triple::ppc64le);185186MCAsmInfo *MAI;187if (TheTriple.isOSBinFormatXCOFF())188MAI = new PPCXCOFFMCAsmInfo(isPPC64, TheTriple);189else190MAI = new PPCELFMCAsmInfo(isPPC64, TheTriple);191192// Initial state of the frame pointer is R1.193unsigned Reg = isPPC64 ? PPC::X1 : PPC::R1;194MCCFIInstruction Inst =195MCCFIInstruction::cfiDefCfa(nullptr, MRI.getDwarfRegNum(Reg, true), 0);196MAI->addInitialFrameState(Inst);197198return MAI;199}200201static MCStreamer *202createPPCELFStreamer(const Triple &T, MCContext &Context,203std::unique_ptr<MCAsmBackend> &&MAB,204std::unique_ptr<MCObjectWriter> &&OW,205std::unique_ptr<MCCodeEmitter> &&Emitter) {206return createPPCELFStreamer(Context, std::move(MAB), std::move(OW),207std::move(Emitter));208}209210static MCStreamer *211createPPCXCOFFStreamer(const Triple &T, MCContext &Context,212std::unique_ptr<MCAsmBackend> &&MAB,213std::unique_ptr<MCObjectWriter> &&OW,214std::unique_ptr<MCCodeEmitter> &&Emitter) {215return createPPCXCOFFStreamer(Context, std::move(MAB), std::move(OW),216std::move(Emitter));217}218219namespace {220221class PPCTargetAsmStreamer : public PPCTargetStreamer {222formatted_raw_ostream &OS;223224public:225PPCTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS)226: PPCTargetStreamer(S), OS(OS) {}227228void emitTCEntry(const MCSymbol &S,229MCSymbolRefExpr::VariantKind Kind) override {230if (const MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(&S)) {231MCSymbolXCOFF *TCSym =232cast<MCSectionXCOFF>(Streamer.getCurrentSectionOnly())233->getQualNameSymbol();234// On AIX, we have TLS variable offsets (symbol@({gd|ie|le|ld}) depending235// on the TLS access method (or model). For the general-dynamic access236// method, we also have region handle (symbol@m) for each variable. For237// local-dynamic, there is a module handle (_$TLSML[TC]@ml) for all238// variables. Finally for local-exec and initial-exec, we have a thread239// pointer, in r13 for 64-bit mode and returned by .__get_tpointer for240// 32-bit mode.241if (Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD ||242Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM ||243Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE ||244Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE ||245Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD ||246Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSML)247OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@"248<< MCSymbolRefExpr::getVariantKindName(Kind) << '\n';249else250OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << '\n';251252if (TCSym->hasRename())253Streamer.emitXCOFFRenameDirective(TCSym, TCSym->getSymbolTableName());254return;255}256257OS << "\t.tc " << S.getName() << "[TC]," << S.getName() << '\n';258}259260void emitMachine(StringRef CPU) override {261OS << "\t.machine " << CPU << '\n';262}263264void emitAbiVersion(int AbiVersion) override {265OS << "\t.abiversion " << AbiVersion << '\n';266}267268void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {269const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();270271OS << "\t.localentry\t";272S->print(OS, MAI);273OS << ", ";274LocalOffset->print(OS, MAI);275OS << '\n';276}277};278279class PPCTargetELFStreamer : public PPCTargetStreamer {280public:281PPCTargetELFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}282283MCELFStreamer &getStreamer() {284return static_cast<MCELFStreamer &>(Streamer);285}286287void emitTCEntry(const MCSymbol &S,288MCSymbolRefExpr::VariantKind Kind) override {289// Creates a R_PPC64_TOC relocation290Streamer.emitValueToAlignment(Align(8));291Streamer.emitSymbolValue(&S, 8);292}293294void emitMachine(StringRef CPU) override {295// FIXME: Is there anything to do in here or does this directive only296// limit the parser?297}298299void emitAbiVersion(int AbiVersion) override {300ELFObjectWriter &W = getStreamer().getWriter();301unsigned Flags = W.getELFHeaderEFlags();302Flags &= ~ELF::EF_PPC64_ABI;303Flags |= (AbiVersion & ELF::EF_PPC64_ABI);304W.setELFHeaderEFlags(Flags);305}306307void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {308309// encodePPC64LocalEntryOffset will report an error if it cannot310// encode LocalOffset.311unsigned Encoded = encodePPC64LocalEntryOffset(LocalOffset);312313unsigned Other = S->getOther();314Other &= ~ELF::STO_PPC64_LOCAL_MASK;315Other |= Encoded;316S->setOther(Other);317318// For GAS compatibility, unless we already saw a .abiversion directive,319// set e_flags to indicate ELFv2 ABI.320ELFObjectWriter &W = getStreamer().getWriter();321unsigned Flags = W.getELFHeaderEFlags();322if ((Flags & ELF::EF_PPC64_ABI) == 0)323W.setELFHeaderEFlags(Flags | 2);324}325326void emitAssignment(MCSymbol *S, const MCExpr *Value) override {327auto *Symbol = cast<MCSymbolELF>(S);328329// When encoding an assignment to set symbol A to symbol B, also copy330// the st_other bits encoding the local entry point offset.331if (copyLocalEntry(Symbol, Value))332UpdateOther.insert(Symbol);333else334UpdateOther.erase(Symbol);335}336337void finish() override {338for (auto *Sym : UpdateOther)339if (Sym->isVariable())340copyLocalEntry(Sym, Sym->getVariableValue());341342// Clear the set of symbols that needs to be updated so the streamer can343// be reused without issues.344UpdateOther.clear();345}346347private:348SmallPtrSet<MCSymbolELF *, 32> UpdateOther;349350bool copyLocalEntry(MCSymbolELF *D, const MCExpr *S) {351auto *Ref = dyn_cast<const MCSymbolRefExpr>(S);352if (!Ref)353return false;354const auto &RhsSym = cast<MCSymbolELF>(Ref->getSymbol());355unsigned Other = D->getOther();356Other &= ~ELF::STO_PPC64_LOCAL_MASK;357Other |= RhsSym.getOther() & ELF::STO_PPC64_LOCAL_MASK;358D->setOther(Other);359return true;360}361362unsigned encodePPC64LocalEntryOffset(const MCExpr *LocalOffset) {363MCAssembler &MCA = getStreamer().getAssembler();364int64_t Offset;365if (!LocalOffset->evaluateAsAbsolute(Offset, MCA))366MCA.getContext().reportError(LocalOffset->getLoc(),367".localentry expression must be absolute");368369switch (Offset) {370default:371MCA.getContext().reportError(372LocalOffset->getLoc(), ".localentry expression must be a power of 2");373return 0;374case 0:375return 0;376case 1:377return 1 << ELF::STO_PPC64_LOCAL_BIT;378case 4:379case 8:380case 16:381case 32:382case 64:383return Log2_32(Offset) << ELF::STO_PPC64_LOCAL_BIT;384}385}386};387388class PPCTargetMachOStreamer : public PPCTargetStreamer {389public:390PPCTargetMachOStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}391392void emitTCEntry(const MCSymbol &S,393MCSymbolRefExpr::VariantKind Kind) override {394llvm_unreachable("Unknown pseudo-op: .tc");395}396397void emitMachine(StringRef CPU) override {398// FIXME: We should update the CPUType, CPUSubType in the Object file if399// the new values are different from the defaults.400}401402void emitAbiVersion(int AbiVersion) override {403llvm_unreachable("Unknown pseudo-op: .abiversion");404}405406void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {407llvm_unreachable("Unknown pseudo-op: .localentry");408}409};410411class PPCTargetXCOFFStreamer : public PPCTargetStreamer {412public:413PPCTargetXCOFFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}414415void emitTCEntry(const MCSymbol &S,416MCSymbolRefExpr::VariantKind Kind) override {417const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();418const unsigned PointerSize = MAI->getCodePointerSize();419Streamer.emitValueToAlignment(Align(PointerSize));420Streamer.emitValue(MCSymbolRefExpr::create(&S, Kind, Streamer.getContext()),421PointerSize);422}423424void emitMachine(StringRef CPU) override {425llvm_unreachable("Machine pseudo-ops are invalid for XCOFF.");426}427428void emitAbiVersion(int AbiVersion) override {429llvm_unreachable("ABI-version pseudo-ops are invalid for XCOFF.");430}431432void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {433llvm_unreachable("Local-entry pseudo-ops are invalid for XCOFF.");434}435};436437} // end anonymous namespace438439static MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S,440formatted_raw_ostream &OS,441MCInstPrinter *InstPrint) {442return new PPCTargetAsmStreamer(S, OS);443}444445static MCTargetStreamer *createNullTargetStreamer(MCStreamer &S) {446return new PPCTargetStreamer(S);447}448449static MCTargetStreamer *450createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {451const Triple &TT = STI.getTargetTriple();452if (TT.isOSBinFormatELF())453return new PPCTargetELFStreamer(S);454if (TT.isOSBinFormatXCOFF())455return new PPCTargetXCOFFStreamer(S);456return new PPCTargetMachOStreamer(S);457}458459static MCInstPrinter *createPPCMCInstPrinter(const Triple &T,460unsigned SyntaxVariant,461const MCAsmInfo &MAI,462const MCInstrInfo &MII,463const MCRegisterInfo &MRI) {464return new PPCInstPrinter(MAI, MII, MRI, T);465}466467namespace {468469class PPCMCInstrAnalysis : public MCInstrAnalysis {470public:471explicit PPCMCInstrAnalysis(const MCInstrInfo *Info)472: MCInstrAnalysis(Info) {}473474bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,475uint64_t &Target) const override {476unsigned NumOps = Inst.getNumOperands();477if (NumOps == 0 ||478Info->get(Inst.getOpcode()).operands()[NumOps - 1].OperandType !=479MCOI::OPERAND_PCREL)480return false;481Target = Addr + Inst.getOperand(NumOps - 1).getImm() * Size;482return true;483}484};485486} // end anonymous namespace487488static MCInstrAnalysis *createPPCMCInstrAnalysis(const MCInstrInfo *Info) {489return new PPCMCInstrAnalysis(Info);490}491492extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetMC() {493for (Target *T : {&getThePPC32Target(), &getThePPC32LETarget(),494&getThePPC64Target(), &getThePPC64LETarget()}) {495// Register the MC asm info.496RegisterMCAsmInfoFn C(*T, createPPCMCAsmInfo);497498// Register the MC instruction info.499TargetRegistry::RegisterMCInstrInfo(*T, createPPCMCInstrInfo);500501// Register the MC register info.502TargetRegistry::RegisterMCRegInfo(*T, createPPCMCRegisterInfo);503504// Register the MC subtarget info.505TargetRegistry::RegisterMCSubtargetInfo(*T, createPPCMCSubtargetInfo);506507// Register the MC instruction analyzer.508TargetRegistry::RegisterMCInstrAnalysis(*T, createPPCMCInstrAnalysis);509510// Register the MC Code Emitter511TargetRegistry::RegisterMCCodeEmitter(*T, createPPCMCCodeEmitter);512513// Register the asm backend.514TargetRegistry::RegisterMCAsmBackend(*T, createPPCAsmBackend);515516// Register the elf streamer.517TargetRegistry::RegisterELFStreamer(*T, createPPCELFStreamer);518519// Register the XCOFF streamer.520TargetRegistry::RegisterXCOFFStreamer(*T, createPPCXCOFFStreamer);521522// Register the object target streamer.523TargetRegistry::RegisterObjectTargetStreamer(*T,524createObjectTargetStreamer);525526// Register the asm target streamer.527TargetRegistry::RegisterAsmTargetStreamer(*T, createAsmTargetStreamer);528529// Register the null target streamer.530TargetRegistry::RegisterNullTargetStreamer(*T, createNullTargetStreamer);531532// Register the MCInstPrinter.533TargetRegistry::RegisterMCInstPrinter(*T, createPPCMCInstPrinter);534}535}536537538