brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.9 KiB · d856c3f Raw
520 lines · cpp
1//===-- PPCMCTargetDesc.cpp - PowerPC Target Descriptions -----------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file provides PowerPC specific target descriptions.10//11//===----------------------------------------------------------------------===//12 13#include "MCTargetDesc/PPCMCTargetDesc.h"14#include "MCTargetDesc/PPCInstPrinter.h"15#include "MCTargetDesc/PPCMCAsmInfo.h"16#include "PPCELFStreamer.h"17#include "PPCMCAsmInfo.h"18#include "PPCTargetStreamer.h"19#include "PPCXCOFFStreamer.h"20#include "TargetInfo/PowerPCTargetInfo.h"21#include "llvm/ADT/SmallPtrSet.h"22#include "llvm/ADT/StringRef.h"23#include "llvm/BinaryFormat/ELF.h"24#include "llvm/MC/MCAsmBackend.h"25#include "llvm/MC/MCAssembler.h"26#include "llvm/MC/MCCodeEmitter.h"27#include "llvm/MC/MCContext.h"28#include "llvm/MC/MCDwarf.h"29#include "llvm/MC/MCELFObjectWriter.h"30#include "llvm/MC/MCELFStreamer.h"31#include "llvm/MC/MCExpr.h"32#include "llvm/MC/MCInstrAnalysis.h"33#include "llvm/MC/MCInstrInfo.h"34#include "llvm/MC/MCRegisterInfo.h"35#include "llvm/MC/MCSectionXCOFF.h"36#include "llvm/MC/MCStreamer.h"37#include "llvm/MC/MCSubtargetInfo.h"38#include "llvm/MC/MCSymbol.h"39#include "llvm/MC/MCSymbolELF.h"40#include "llvm/MC/MCSymbolXCOFF.h"41#include "llvm/MC/MCXCOFFObjectWriter.h"42#include "llvm/MC/TargetRegistry.h"43#include "llvm/Support/Casting.h"44#include "llvm/Support/Compiler.h"45#include "llvm/Support/ErrorHandling.h"46#include "llvm/Support/FormattedStream.h"47#include "llvm/Support/raw_ostream.h"48#include "llvm/TargetParser/Triple.h"49 50using namespace llvm;51 52#define GET_INSTRINFO_MC_DESC53#define ENABLE_INSTR_PREDICATE_VERIFIER54#include "PPCGenInstrInfo.inc"55 56#define GET_SUBTARGETINFO_MC_DESC57#include "PPCGenSubtargetInfo.inc"58 59#define GET_REGINFO_MC_DESC60#include "PPCGenRegisterInfo.inc"61 62/// stripRegisterPrefix - This method strips the character prefix from a63/// register name so that only the number is left.  Used by for linux asm.64const char *PPC::stripRegisterPrefix(const char *RegName) {65  switch (RegName[0]) {66    case 'a':67      if (RegName[1] == 'c' && RegName[2] == 'c')68        return RegName + 3;69      break;70    case 'f':71      if (RegName[1] == 'p')72        return RegName + 2;73      [[fallthrough]];74    case 'r':75    case 'v':76      if (RegName[1] == 's') {77        if (RegName[2] == 'p')78          return RegName + 3;79        return RegName + 2;80      }81      return RegName + 1;82    case 'c':83      if (RegName[1] == 'r')84        return RegName + 2;85      break;86    case 'w':87      // For wacc and wacc_hi88      if (RegName[1] == 'a' && RegName[2] == 'c' && RegName[3] == 'c') {89        if (RegName[4] == '_')90          return RegName + 7;91        else92          return RegName + 4;93      }94      break;95    case 'd':96      // For dmr, dmrp, dmrrow, dmrrowp97      if (RegName[1] == 'm' && RegName[2] == 'r') {98        if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w' &&99            RegName[6] == 'p')100          return RegName + 7;101        else if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w')102          return RegName + 6;103        else if (RegName[3] == 'p')104          return RegName + 4;105        else106          return RegName + 3;107      }108      break;109  }110 111  return RegName;112}113 114/// getRegNumForOperand - some operands use different numbering schemes115/// for the same registers. For example, a VSX instruction may have any of116/// vs0-vs63 allocated whereas an Altivec instruction could only have117/// vs32-vs63 allocated (numbered as v0-v31). This function returns the actual118/// register number needed for the opcode/operand number combination.119/// The operand number argument will be useful when we need to extend this120/// to instructions that use both Altivec and VSX numbering (for different121/// operands).122MCRegister PPC::getRegNumForOperand(const MCInstrDesc &Desc, MCRegister Reg,123                                    unsigned OpNo) {124  int16_t regClass = Desc.operands()[OpNo].RegClass;125  switch (regClass) {126    // We store F0-F31, VF0-VF31 in MCOperand and it should be F0-F31,127    // VSX32-VSX63 during encoding/disassembling128    case PPC::VSSRCRegClassID:129    case PPC::VSFRCRegClassID:130      if (PPC::isVFRegister(Reg))131	return PPC::VSX32 + (Reg - PPC::VF0);132      break;133    // We store VSL0-VSL31, V0-V31 in MCOperand and it should be VSL0-VSL31,134    // VSX32-VSX63 during encoding/disassembling135    case PPC::VSRCRegClassID:136      if (PPC::isVRRegister(Reg))137	return PPC::VSX32 + (Reg - PPC::V0);138      break;139    // Other RegClass doesn't need mapping140    default:141      break;142  }143  return Reg;144}145 146PPCTargetStreamer::PPCTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}147 148// Pin the vtable to this file.149PPCTargetStreamer::~PPCTargetStreamer() = default;150 151static MCInstrInfo *createPPCMCInstrInfo() {152  MCInstrInfo *X = new MCInstrInfo();153  InitPPCMCInstrInfo(X);154  return X;155}156 157static MCRegisterInfo *createPPCMCRegisterInfo(const Triple &TT) {158  bool isPPC64 =159      (TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le);160  unsigned Flavour = isPPC64 ? 0 : 1;161  unsigned RA = isPPC64 ? PPC::LR8 : PPC::LR;162 163  MCRegisterInfo *X = new MCRegisterInfo();164  InitPPCMCRegisterInfo(X, RA, Flavour, Flavour);165  return X;166}167 168static MCSubtargetInfo *createPPCMCSubtargetInfo(const Triple &TT,169                                                 StringRef CPU, StringRef FS) {170  // Set some default feature to MC layer.171  std::string FullFS = std::string(FS);172 173  if (TT.isOSAIX()) {174    if (!FullFS.empty())175      FullFS = "+aix," + FullFS;176    else177      FullFS = "+aix";178  }179 180  return createPPCMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FullFS);181}182 183static MCAsmInfo *createPPCMCAsmInfo(const MCRegisterInfo &MRI,184                                     const Triple &TheTriple,185                                     const MCTargetOptions &Options) {186  bool isPPC64 = (TheTriple.getArch() == Triple::ppc64 ||187                  TheTriple.getArch() == Triple::ppc64le);188 189  MCAsmInfo *MAI;190  if (TheTriple.isOSBinFormatXCOFF())191    MAI = new PPCXCOFFMCAsmInfo(isPPC64, TheTriple);192  else193    MAI = new PPCELFMCAsmInfo(isPPC64, TheTriple);194 195  // Initial state of the frame pointer is R1.196  unsigned Reg = isPPC64 ? PPC::X1 : PPC::R1;197  MCCFIInstruction Inst =198      MCCFIInstruction::cfiDefCfa(nullptr, MRI.getDwarfRegNum(Reg, true), 0);199  MAI->addInitialFrameState(Inst);200 201  return MAI;202}203 204namespace {205 206class PPCTargetAsmStreamer : public PPCTargetStreamer {207  formatted_raw_ostream &OS;208 209public:210  PPCTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS)211      : PPCTargetStreamer(S), OS(OS) {}212 213  void emitTCEntry(const MCSymbol &S, PPCMCExpr::Specifier Kind) override {214    if (getContext().isXCOFF()) {215      MCSymbolXCOFF *TCSym =216          static_cast<const MCSectionXCOFF *>(Streamer.getCurrentSectionOnly())217              ->getQualNameSymbol();218      // On AIX, we have TLS variable offsets (symbol@({gd|ie|le|ld}) depending219      // on the TLS access method (or model). For the general-dynamic access220      // method, we also have region handle (symbol@m) for each variable. For221      // local-dynamic, there is a module handle (_$TLSML[TC]@ml) for all222      // variables. Finally for local-exec and initial-exec, we have a thread223      // pointer, in r13 for 64-bit mode and returned by .__get_tpointer for224      // 32-bit mode.225      if (Kind == PPC::S_AIX_TLSGD || Kind == PPC::S_AIX_TLSGDM ||226          Kind == PPC::S_AIX_TLSIE || Kind == PPC::S_AIX_TLSLE ||227          Kind == PPC::S_AIX_TLSLD || Kind == PPC::S_AIX_TLSML)228        OS << "\t.tc " << TCSym->getName() << "," << S.getName() << "@"229           << getContext().getAsmInfo()->getSpecifierName(Kind) << '\n';230      else231        OS << "\t.tc " << TCSym->getName() << "," << S.getName() << '\n';232 233      if (TCSym->hasRename())234        Streamer.emitXCOFFRenameDirective(TCSym, TCSym->getSymbolTableName());235      return;236    }237 238    OS << "\t.tc " << S.getName() << "[TC]," << S.getName() << '\n';239  }240 241  void emitMachine(StringRef CPU) override {242    const Triple &TT = Streamer.getContext().getTargetTriple();243    if (TT.isOSBinFormatXCOFF())244      OS << "\t.machine\t" << '\"' << CPU << '\"' << '\n';245    else246      OS << "\t.machine " << CPU << '\n';247  }248 249  void emitAbiVersion(int AbiVersion) override {250    OS << "\t.abiversion " << AbiVersion << '\n';251  }252 253  void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {254    const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();255 256    OS << "\t.localentry\t";257    S->print(OS, MAI);258    OS << ", ";259    MAI->printExpr(OS, *LocalOffset);260    OS << '\n';261  }262};263 264class PPCTargetELFStreamer : public PPCTargetStreamer {265public:266  PPCTargetELFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}267 268  MCELFStreamer &getStreamer() {269    return static_cast<MCELFStreamer &>(Streamer);270  }271 272  void emitTCEntry(const MCSymbol &S, PPCMCExpr::Specifier Kind) override {273    // Creates a R_PPC64_TOC relocation274    Streamer.emitValueToAlignment(Align(8));275    Streamer.emitSymbolValue(&S, 8);276  }277 278  void emitMachine(StringRef CPU) override {279    // FIXME: Is there anything to do in here or does this directive only280    // limit the parser?281  }282 283  void emitAbiVersion(int AbiVersion) override {284    ELFObjectWriter &W = getStreamer().getWriter();285    unsigned Flags = W.getELFHeaderEFlags();286    Flags &= ~ELF::EF_PPC64_ABI;287    Flags |= (AbiVersion & ELF::EF_PPC64_ABI);288    W.setELFHeaderEFlags(Flags);289  }290 291  void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {292 293    // encodePPC64LocalEntryOffset will report an error if it cannot294    // encode LocalOffset.295    unsigned Encoded = encodePPC64LocalEntryOffset(LocalOffset);296 297    unsigned Other = S->getOther();298    Other &= ~ELF::STO_PPC64_LOCAL_MASK;299    Other |= Encoded;300    S->setOther(Other);301 302    // For GAS compatibility, unless we already saw a .abiversion directive,303    // set e_flags to indicate ELFv2 ABI.304    ELFObjectWriter &W = getStreamer().getWriter();305    unsigned Flags = W.getELFHeaderEFlags();306    if ((Flags & ELF::EF_PPC64_ABI) == 0)307      W.setELFHeaderEFlags(Flags | 2);308  }309 310  void emitAssignment(MCSymbol *S, const MCExpr *Value) override {311    auto *Symbol = static_cast<MCSymbolELF *>(S);312 313    // When encoding an assignment to set symbol A to symbol B, also copy314    // the st_other bits encoding the local entry point offset.315    if (copyLocalEntry(Symbol, Value))316      UpdateOther.insert(Symbol);317    else318      UpdateOther.erase(Symbol);319  }320 321  void finish() override {322    for (auto *Sym : UpdateOther)323      if (Sym->isVariable())324        copyLocalEntry(Sym, Sym->getVariableValue());325 326    // Clear the set of symbols that needs to be updated so the streamer can327    // be reused without issues.328    UpdateOther.clear();329  }330 331private:332  SmallPtrSet<MCSymbolELF *, 32> UpdateOther;333 334  bool copyLocalEntry(MCSymbolELF *D, const MCExpr *S) {335    auto *Ref = dyn_cast<const MCSymbolRefExpr>(S);336    if (!Ref)337      return false;338    auto &RhsSym = static_cast<const MCSymbolELF &>(Ref->getSymbol());339    unsigned Other = D->getOther();340    Other &= ~ELF::STO_PPC64_LOCAL_MASK;341    Other |= RhsSym.getOther() & ELF::STO_PPC64_LOCAL_MASK;342    D->setOther(Other);343    return true;344  }345 346  unsigned encodePPC64LocalEntryOffset(const MCExpr *LocalOffset) {347    MCAssembler &MCA = getStreamer().getAssembler();348    int64_t Offset;349    if (!LocalOffset->evaluateAsAbsolute(Offset, MCA))350      MCA.getContext().reportError(LocalOffset->getLoc(),351                                   ".localentry expression must be absolute");352 353    switch (Offset) {354    default:355      MCA.getContext().reportError(356          LocalOffset->getLoc(), ".localentry expression must be a power of 2");357      return 0;358    case 0:359      return 0;360    case 1:361      return 1 << ELF::STO_PPC64_LOCAL_BIT;362    case 4:363    case 8:364    case 16:365    case 32:366    case 64:367      return Log2_32(Offset) << ELF::STO_PPC64_LOCAL_BIT;368    }369  }370};371 372class PPCTargetMachOStreamer : public PPCTargetStreamer {373public:374  PPCTargetMachOStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}375 376  void emitTCEntry(const MCSymbol &S, PPCMCExpr::Specifier Kind) override {377    llvm_unreachable("Unknown pseudo-op: .tc");378  }379 380  void emitMachine(StringRef CPU) override {381    // FIXME: We should update the CPUType, CPUSubType in the Object file if382    // the new values are different from the defaults.383  }384 385  void emitAbiVersion(int AbiVersion) override {386    llvm_unreachable("Unknown pseudo-op: .abiversion");387  }388 389  void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {390    llvm_unreachable("Unknown pseudo-op: .localentry");391  }392};393 394class PPCTargetXCOFFStreamer : public PPCTargetStreamer {395public:396  PPCTargetXCOFFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}397 398  void emitTCEntry(const MCSymbol &S, PPCMCExpr::Specifier Kind) override {399    const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();400    const unsigned PointerSize = MAI->getCodePointerSize();401    Streamer.emitValueToAlignment(Align(PointerSize));402    Streamer.emitValue(MCSymbolRefExpr::create(&S, Kind, Streamer.getContext()),403                       PointerSize);404  }405 406  void emitMachine(StringRef CPU) override {407    static_cast<XCOFFObjectWriter &>(Streamer.getAssemblerPtr()->getWriter())408        .setCPU(CPU);409  }410 411  void emitAbiVersion(int AbiVersion) override {412    llvm_unreachable("ABI-version pseudo-ops are invalid for XCOFF.");413  }414 415  void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {416    llvm_unreachable("Local-entry pseudo-ops are invalid for XCOFF.");417  }418};419 420} // end anonymous namespace421 422static MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S,423                                                 formatted_raw_ostream &OS,424                                                 MCInstPrinter *InstPrint) {425  return new PPCTargetAsmStreamer(S, OS);426}427 428static MCTargetStreamer *createNullTargetStreamer(MCStreamer &S) {429  return new PPCTargetStreamer(S);430}431 432static MCTargetStreamer *433createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {434  const Triple &TT = STI.getTargetTriple();435  if (TT.isOSBinFormatELF())436    return new PPCTargetELFStreamer(S);437  if (TT.isOSBinFormatXCOFF())438    return new PPCTargetXCOFFStreamer(S);439  return new PPCTargetMachOStreamer(S);440}441 442static MCInstPrinter *createPPCMCInstPrinter(const Triple &T,443                                             unsigned SyntaxVariant,444                                             const MCAsmInfo &MAI,445                                             const MCInstrInfo &MII,446                                             const MCRegisterInfo &MRI) {447  return new PPCInstPrinter(MAI, MII, MRI, T);448}449 450namespace {451 452class PPCMCInstrAnalysis : public MCInstrAnalysis {453public:454  explicit PPCMCInstrAnalysis(const MCInstrInfo *Info)455      : MCInstrAnalysis(Info) {}456 457  bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,458                      uint64_t &Target) const override {459    unsigned NumOps = Inst.getNumOperands();460    if (NumOps == 0 ||461        Info->get(Inst.getOpcode()).operands()[NumOps - 1].OperandType !=462            MCOI::OPERAND_PCREL)463      return false;464    Target = Addr + Inst.getOperand(NumOps - 1).getImm() * Size;465    return true;466  }467};468 469} // end anonymous namespace470 471static MCInstrAnalysis *createPPCMCInstrAnalysis(const MCInstrInfo *Info) {472  return new PPCMCInstrAnalysis(Info);473}474 475extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void476LLVMInitializePowerPCTargetMC() {477  for (Target *T : {&getThePPC32Target(), &getThePPC32LETarget(),478                    &getThePPC64Target(), &getThePPC64LETarget()}) {479    // Register the MC asm info.480    RegisterMCAsmInfoFn C(*T, createPPCMCAsmInfo);481 482    // Register the MC instruction info.483    TargetRegistry::RegisterMCInstrInfo(*T, createPPCMCInstrInfo);484 485    // Register the MC register info.486    TargetRegistry::RegisterMCRegInfo(*T, createPPCMCRegisterInfo);487 488    // Register the MC subtarget info.489    TargetRegistry::RegisterMCSubtargetInfo(*T, createPPCMCSubtargetInfo);490 491    // Register the MC instruction analyzer.492    TargetRegistry::RegisterMCInstrAnalysis(*T, createPPCMCInstrAnalysis);493 494    // Register the MC Code Emitter495    TargetRegistry::RegisterMCCodeEmitter(*T, createPPCMCCodeEmitter);496 497    // Register the asm backend.498    TargetRegistry::RegisterMCAsmBackend(*T, createPPCAsmBackend);499 500    // Register the elf streamer.501    TargetRegistry::RegisterELFStreamer(*T, createPPCELFStreamer);502 503    // Register the XCOFF streamer.504    TargetRegistry::RegisterXCOFFStreamer(*T, createPPCXCOFFStreamer);505 506    // Register the object target streamer.507    TargetRegistry::RegisterObjectTargetStreamer(*T,508                                                 createObjectTargetStreamer);509 510    // Register the asm target streamer.511    TargetRegistry::RegisterAsmTargetStreamer(*T, createAsmTargetStreamer);512 513    // Register the null target streamer.514    TargetRegistry::RegisterNullTargetStreamer(*T, createNullTargetStreamer);515 516    // Register the MCInstPrinter.517    TargetRegistry::RegisterMCInstPrinter(*T, createPPCMCInstPrinter);518  }519}520