| //===-- AArch64MCTargetDesc.cpp - AArch64 Target Descriptions ---*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file provides AArch64 specific target descriptions. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "AArch64MCTargetDesc.h" |
| #include "AArch64ELFStreamer.h" |
| #include "AArch64MCAsmInfo.h" |
| #include "AArch64WinCOFFStreamer.h" |
| #include "MCTargetDesc/AArch64AddressingModes.h" |
| #include "MCTargetDesc/AArch64InstPrinter.h" |
| #include "TargetInfo/AArch64TargetInfo.h" |
| #include "llvm/DebugInfo/CodeView/CodeView.h" |
| #include "llvm/MC/MCAsmBackend.h" |
| #include "llvm/MC/MCCodeEmitter.h" |
| #include "llvm/MC/MCInstrAnalysis.h" |
| #include "llvm/MC/MCInstrInfo.h" |
| #include "llvm/MC/MCObjectWriter.h" |
| #include "llvm/MC/MCRegisterInfo.h" |
| #include "llvm/MC/MCStreamer.h" |
| #include "llvm/MC/MCSubtargetInfo.h" |
| #include "llvm/Support/Endian.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/TargetRegistry.h" |
| |
| using namespace llvm; |
| |
| #define GET_INSTRINFO_MC_DESC |
| #define GET_INSTRINFO_MC_HELPERS |
| #include "AArch64GenInstrInfo.inc" |
| |
| #define GET_SUBTARGETINFO_MC_DESC |
| #include "AArch64GenSubtargetInfo.inc" |
| |
| #define GET_REGINFO_MC_DESC |
| #include "AArch64GenRegisterInfo.inc" |
| |
| static MCInstrInfo *createAArch64MCInstrInfo() { |
| MCInstrInfo *X = new MCInstrInfo(); |
| InitAArch64MCInstrInfo(X); |
| return X; |
| } |
| |
| static MCSubtargetInfo * |
| createAArch64MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { |
| if (CPU.empty()) |
| CPU = "generic"; |
| |
| return createAArch64MCSubtargetInfoImpl(TT, CPU, FS); |
| } |
| |
| void AArch64_MC::initLLVMToCVRegMapping(MCRegisterInfo *MRI) { |
| // Mapping from CodeView to MC register id. |
| static const struct { |
| codeview::RegisterId CVReg; |
| MCPhysReg Reg; |
| } RegMap[] = { |
| {codeview::RegisterId::ARM64_W0, AArch64::W0}, |
| {codeview::RegisterId::ARM64_W1, AArch64::W1}, |
| {codeview::RegisterId::ARM64_W2, AArch64::W2}, |
| {codeview::RegisterId::ARM64_W3, AArch64::W3}, |
| {codeview::RegisterId::ARM64_W4, AArch64::W4}, |
| {codeview::RegisterId::ARM64_W5, AArch64::W5}, |
| {codeview::RegisterId::ARM64_W6, AArch64::W6}, |
| {codeview::RegisterId::ARM64_W7, AArch64::W7}, |
| {codeview::RegisterId::ARM64_W8, AArch64::W8}, |
| {codeview::RegisterId::ARM64_W9, AArch64::W9}, |
| {codeview::RegisterId::ARM64_W10, AArch64::W10}, |
| {codeview::RegisterId::ARM64_W11, AArch64::W11}, |
| {codeview::RegisterId::ARM64_W12, AArch64::W12}, |
| {codeview::RegisterId::ARM64_W13, AArch64::W13}, |
| {codeview::RegisterId::ARM64_W14, AArch64::W14}, |
| {codeview::RegisterId::ARM64_W15, AArch64::W15}, |
| {codeview::RegisterId::ARM64_W16, AArch64::W16}, |
| {codeview::RegisterId::ARM64_W17, AArch64::W17}, |
| {codeview::RegisterId::ARM64_W18, AArch64::W18}, |
| {codeview::RegisterId::ARM64_W19, AArch64::W19}, |
| {codeview::RegisterId::ARM64_W20, AArch64::W20}, |
| {codeview::RegisterId::ARM64_W21, AArch64::W21}, |
| {codeview::RegisterId::ARM64_W22, AArch64::W22}, |
| {codeview::RegisterId::ARM64_W23, AArch64::W23}, |
| {codeview::RegisterId::ARM64_W24, AArch64::W24}, |
| {codeview::RegisterId::ARM64_W25, AArch64::W25}, |
| {codeview::RegisterId::ARM64_W26, AArch64::W26}, |
| {codeview::RegisterId::ARM64_W27, AArch64::W27}, |
| {codeview::RegisterId::ARM64_W28, AArch64::W28}, |
| {codeview::RegisterId::ARM64_W29, AArch64::W29}, |
| {codeview::RegisterId::ARM64_W30, AArch64::W30}, |
| {codeview::RegisterId::ARM64_WZR, AArch64::WZR}, |
| {codeview::RegisterId::ARM64_X0, AArch64::X0}, |
| {codeview::RegisterId::ARM64_X1, AArch64::X1}, |
| {codeview::RegisterId::ARM64_X2, AArch64::X2}, |
| {codeview::RegisterId::ARM64_X3, AArch64::X3}, |
| {codeview::RegisterId::ARM64_X4, AArch64::X4}, |
| {codeview::RegisterId::ARM64_X5, AArch64::X5}, |
| {codeview::RegisterId::ARM64_X6, AArch64::X6}, |
| {codeview::RegisterId::ARM64_X7, AArch64::X7}, |
| {codeview::RegisterId::ARM64_X8, AArch64::X8}, |
| {codeview::RegisterId::ARM64_X9, AArch64::X9}, |
| {codeview::RegisterId::ARM64_X10, AArch64::X10}, |
| {codeview::RegisterId::ARM64_X11, AArch64::X11}, |
| {codeview::RegisterId::ARM64_X12, AArch64::X12}, |
| {codeview::RegisterId::ARM64_X13, AArch64::X13}, |
| {codeview::RegisterId::ARM64_X14, AArch64::X14}, |
| {codeview::RegisterId::ARM64_X15, AArch64::X15}, |
| {codeview::RegisterId::ARM64_X16, AArch64::X16}, |
| {codeview::RegisterId::ARM64_X17, AArch64::X17}, |
| {codeview::RegisterId::ARM64_X18, AArch64::X18}, |
| {codeview::RegisterId::ARM64_X19, AArch64::X19}, |
| {codeview::RegisterId::ARM64_X20, AArch64::X20}, |
| {codeview::RegisterId::ARM64_X21, AArch64::X21}, |
| {codeview::RegisterId::ARM64_X22, AArch64::X22}, |
| {codeview::RegisterId::ARM64_X23, AArch64::X23}, |
| {codeview::RegisterId::ARM64_X24, AArch64::X24}, |
| {codeview::RegisterId::ARM64_X25, AArch64::X25}, |
| {codeview::RegisterId::ARM64_X26, AArch64::X26}, |
| {codeview::RegisterId::ARM64_X27, AArch64::X27}, |
| {codeview::RegisterId::ARM64_X28, AArch64::X28}, |
| {codeview::RegisterId::ARM64_FP, AArch64::FP}, |
| {codeview::RegisterId::ARM64_LR, AArch64::LR}, |
| {codeview::RegisterId::ARM64_SP, AArch64::SP}, |
| {codeview::RegisterId::ARM64_ZR, AArch64::XZR}, |
| {codeview::RegisterId::ARM64_NZCV, AArch64::NZCV}, |
| {codeview::RegisterId::ARM64_S0, AArch64::S0}, |
| {codeview::RegisterId::ARM64_S1, AArch64::S1}, |
| {codeview::RegisterId::ARM64_S2, AArch64::S2}, |
| {codeview::RegisterId::ARM64_S3, AArch64::S3}, |
| {codeview::RegisterId::ARM64_S4, AArch64::S4}, |
| {codeview::RegisterId::ARM64_S5, AArch64::S5}, |
| {codeview::RegisterId::ARM64_S6, AArch64::S6}, |
| {codeview::RegisterId::ARM64_S7, AArch64::S7}, |
| {codeview::RegisterId::ARM64_S8, AArch64::S8}, |
| {codeview::RegisterId::ARM64_S9, AArch64::S9}, |
| {codeview::RegisterId::ARM64_S10, AArch64::S10}, |
| {codeview::RegisterId::ARM64_S11, AArch64::S11}, |
| {codeview::RegisterId::ARM64_S12, AArch64::S12}, |
| {codeview::RegisterId::ARM64_S13, AArch64::S13}, |
| {codeview::RegisterId::ARM64_S14, AArch64::S14}, |
| {codeview::RegisterId::ARM64_S15, AArch64::S15}, |
| {codeview::RegisterId::ARM64_S16, AArch64::S16}, |
| {codeview::RegisterId::ARM64_S17, AArch64::S17}, |
| {codeview::RegisterId::ARM64_S18, AArch64::S18}, |
| {codeview::RegisterId::ARM64_S19, AArch64::S19}, |
| {codeview::RegisterId::ARM64_S20, AArch64::S20}, |
| {codeview::RegisterId::ARM64_S21, AArch64::S21}, |
| {codeview::RegisterId::ARM64_S22, AArch64::S22}, |
| {codeview::RegisterId::ARM64_S23, AArch64::S23}, |
| {codeview::RegisterId::ARM64_S24, AArch64::S24}, |
| {codeview::RegisterId::ARM64_S25, AArch64::S25}, |
| {codeview::RegisterId::ARM64_S26, AArch64::S26}, |
| {codeview::RegisterId::ARM64_S27, AArch64::S27}, |
| {codeview::RegisterId::ARM64_S28, AArch64::S28}, |
| {codeview::RegisterId::ARM64_S29, AArch64::S29}, |
| {codeview::RegisterId::ARM64_S30, AArch64::S30}, |
| {codeview::RegisterId::ARM64_S31, AArch64::S31}, |
| {codeview::RegisterId::ARM64_D0, AArch64::D0}, |
| {codeview::RegisterId::ARM64_D1, AArch64::D1}, |
| {codeview::RegisterId::ARM64_D2, AArch64::D2}, |
| {codeview::RegisterId::ARM64_D3, AArch64::D3}, |
| {codeview::RegisterId::ARM64_D4, AArch64::D4}, |
| {codeview::RegisterId::ARM64_D5, AArch64::D5}, |
| {codeview::RegisterId::ARM64_D6, AArch64::D6}, |
| {codeview::RegisterId::ARM64_D7, AArch64::D7}, |
| {codeview::RegisterId::ARM64_D8, AArch64::D8}, |
| {codeview::RegisterId::ARM64_D9, AArch64::D9}, |
| {codeview::RegisterId::ARM64_D10, AArch64::D10}, |
| {codeview::RegisterId::ARM64_D11, AArch64::D11}, |
| {codeview::RegisterId::ARM64_D12, AArch64::D12}, |
| {codeview::RegisterId::ARM64_D13, AArch64::D13}, |
| {codeview::RegisterId::ARM64_D14, AArch64::D14}, |
| {codeview::RegisterId::ARM64_D15, AArch64::D15}, |
| {codeview::RegisterId::ARM64_D16, AArch64::D16}, |
| {codeview::RegisterId::ARM64_D17, AArch64::D17}, |
| {codeview::RegisterId::ARM64_D18, AArch64::D18}, |
| {codeview::RegisterId::ARM64_D19, AArch64::D19}, |
| {codeview::RegisterId::ARM64_D20, AArch64::D20}, |
| {codeview::RegisterId::ARM64_D21, AArch64::D21}, |
| {codeview::RegisterId::ARM64_D22, AArch64::D22}, |
| {codeview::RegisterId::ARM64_D23, AArch64::D23}, |
| {codeview::RegisterId::ARM64_D24, AArch64::D24}, |
| {codeview::RegisterId::ARM64_D25, AArch64::D25}, |
| {codeview::RegisterId::ARM64_D26, AArch64::D26}, |
| {codeview::RegisterId::ARM64_D27, AArch64::D27}, |
| {codeview::RegisterId::ARM64_D28, AArch64::D28}, |
| {codeview::RegisterId::ARM64_D29, AArch64::D29}, |
| {codeview::RegisterId::ARM64_D30, AArch64::D30}, |
| {codeview::RegisterId::ARM64_D31, AArch64::D31}, |
| {codeview::RegisterId::ARM64_Q0, AArch64::Q0}, |
| {codeview::RegisterId::ARM64_Q1, AArch64::Q1}, |
| {codeview::RegisterId::ARM64_Q2, AArch64::Q2}, |
| {codeview::RegisterId::ARM64_Q3, AArch64::Q3}, |
| {codeview::RegisterId::ARM64_Q4, AArch64::Q4}, |
| {codeview::RegisterId::ARM64_Q5, AArch64::Q5}, |
| {codeview::RegisterId::ARM64_Q6, AArch64::Q6}, |
| {codeview::RegisterId::ARM64_Q7, AArch64::Q7}, |
| {codeview::RegisterId::ARM64_Q8, AArch64::Q8}, |
| {codeview::RegisterId::ARM64_Q9, AArch64::Q9}, |
| {codeview::RegisterId::ARM64_Q10, AArch64::Q10}, |
| {codeview::RegisterId::ARM64_Q11, AArch64::Q11}, |
| {codeview::RegisterId::ARM64_Q12, AArch64::Q12}, |
| {codeview::RegisterId::ARM64_Q13, AArch64::Q13}, |
| {codeview::RegisterId::ARM64_Q14, AArch64::Q14}, |
| {codeview::RegisterId::ARM64_Q15, AArch64::Q15}, |
| {codeview::RegisterId::ARM64_Q16, AArch64::Q16}, |
| {codeview::RegisterId::ARM64_Q17, AArch64::Q17}, |
| {codeview::RegisterId::ARM64_Q18, AArch64::Q18}, |
| {codeview::RegisterId::ARM64_Q19, AArch64::Q19}, |
| {codeview::RegisterId::ARM64_Q20, AArch64::Q20}, |
| {codeview::RegisterId::ARM64_Q21, AArch64::Q21}, |
| {codeview::RegisterId::ARM64_Q22, AArch64::Q22}, |
| {codeview::RegisterId::ARM64_Q23, AArch64::Q23}, |
| {codeview::RegisterId::ARM64_Q24, AArch64::Q24}, |
| {codeview::RegisterId::ARM64_Q25, AArch64::Q25}, |
| {codeview::RegisterId::ARM64_Q26, AArch64::Q26}, |
| {codeview::RegisterId::ARM64_Q27, AArch64::Q27}, |
| {codeview::RegisterId::ARM64_Q28, AArch64::Q28}, |
| {codeview::RegisterId::ARM64_Q29, AArch64::Q29}, |
| {codeview::RegisterId::ARM64_Q30, AArch64::Q30}, |
| {codeview::RegisterId::ARM64_Q31, AArch64::Q31}, |
| |
| }; |
| for (unsigned I = 0; I < array_lengthof(RegMap); ++I) |
| MRI->mapLLVMRegToCVReg(RegMap[I].Reg, static_cast<int>(RegMap[I].CVReg)); |
| } |
| |
| static MCRegisterInfo *createAArch64MCRegisterInfo(const Triple &Triple) { |
| MCRegisterInfo *X = new MCRegisterInfo(); |
| InitAArch64MCRegisterInfo(X, AArch64::LR); |
| AArch64_MC::initLLVMToCVRegMapping(X); |
| return X; |
| } |
| |
| static MCAsmInfo *createAArch64MCAsmInfo(const MCRegisterInfo &MRI, |
| const Triple &TheTriple, |
| const MCTargetOptions &Options) { |
| MCAsmInfo *MAI; |
| if (TheTriple.isOSBinFormatMachO()) |
| MAI = new AArch64MCAsmInfoDarwin(TheTriple.getArch() == Triple::aarch64_32); |
| else if (TheTriple.isWindowsMSVCEnvironment()) |
| MAI = new AArch64MCAsmInfoMicrosoftCOFF(); |
| else if (TheTriple.isOSBinFormatCOFF()) |
| MAI = new AArch64MCAsmInfoGNUCOFF(); |
| else { |
| assert(TheTriple.isOSBinFormatELF() && "Invalid target"); |
| MAI = new AArch64MCAsmInfoELF(TheTriple); |
| } |
| |
| // Initial state of the frame pointer is SP. |
| unsigned Reg = MRI.getDwarfRegNum(AArch64::SP, true); |
| MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, Reg, 0); |
| MAI->addInitialFrameState(Inst); |
| |
| return MAI; |
| } |
| |
| static MCInstPrinter *createAArch64MCInstPrinter(const Triple &T, |
| unsigned SyntaxVariant, |
| const MCAsmInfo &MAI, |
| const MCInstrInfo &MII, |
| const MCRegisterInfo &MRI) { |
| if (SyntaxVariant == 0) |
| return new AArch64InstPrinter(MAI, MII, MRI); |
| if (SyntaxVariant == 1) |
| return new AArch64AppleInstPrinter(MAI, MII, MRI); |
| |
| return nullptr; |
| } |
| |
| static MCStreamer *createELFStreamer(const Triple &T, MCContext &Ctx, |
| std::unique_ptr<MCAsmBackend> &&TAB, |
| std::unique_ptr<MCObjectWriter> &&OW, |
| std::unique_ptr<MCCodeEmitter> &&Emitter, |
| bool RelaxAll) { |
| return createAArch64ELFStreamer(Ctx, std::move(TAB), std::move(OW), |
| std::move(Emitter), RelaxAll); |
| } |
| |
| static MCStreamer *createMachOStreamer(MCContext &Ctx, |
| std::unique_ptr<MCAsmBackend> &&TAB, |
| std::unique_ptr<MCObjectWriter> &&OW, |
| std::unique_ptr<MCCodeEmitter> &&Emitter, |
| bool RelaxAll, |
| bool DWARFMustBeAtTheEnd) { |
| return createMachOStreamer(Ctx, std::move(TAB), std::move(OW), |
| std::move(Emitter), RelaxAll, DWARFMustBeAtTheEnd, |
| /*LabelSections*/ true); |
| } |
| |
| static MCStreamer * |
| createWinCOFFStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB, |
| std::unique_ptr<MCObjectWriter> &&OW, |
| std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll, |
| bool IncrementalLinkerCompatible) { |
| return createAArch64WinCOFFStreamer(Ctx, std::move(TAB), std::move(OW), |
| std::move(Emitter), RelaxAll, |
| IncrementalLinkerCompatible); |
| } |
| |
| namespace { |
| |
| class AArch64MCInstrAnalysis : public MCInstrAnalysis { |
| public: |
| AArch64MCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} |
| |
| bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, |
| uint64_t &Target) const override { |
| // Search for a PC-relative argument. |
| // This will handle instructions like bcc (where the first argument is the |
| // condition code) and cbz (where it is a register). |
| const auto &Desc = Info->get(Inst.getOpcode()); |
| for (unsigned i = 0, e = Inst.getNumOperands(); i != e; i++) { |
| if (Desc.OpInfo[i].OperandType == MCOI::OPERAND_PCREL) { |
| int64_t Imm = Inst.getOperand(i).getImm() * 4; |
| Target = Addr + Imm; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| std::vector<std::pair<uint64_t, uint64_t>> |
| findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents, |
| uint64_t GotPltSectionVA, |
| const Triple &TargetTriple) const override { |
| // Do a lightweight parsing of PLT entries. |
| std::vector<std::pair<uint64_t, uint64_t>> Result; |
| for (uint64_t Byte = 0, End = PltContents.size(); Byte + 7 < End; |
| Byte += 4) { |
| uint32_t Insn = support::endian::read32le(PltContents.data() + Byte); |
| uint64_t Off = 0; |
| // Check for optional bti c that prefixes adrp in BTI enabled entries |
| if (Insn == 0xd503245f) { |
| Off = 4; |
| Insn = support::endian::read32le(PltContents.data() + Byte + Off); |
| } |
| // Check for adrp. |
| if ((Insn & 0x9f000000) != 0x90000000) |
| continue; |
| Off += 4; |
| uint64_t Imm = (((PltSectionVA + Byte) >> 12) << 12) + |
| (((Insn >> 29) & 3) << 12) + (((Insn >> 5) & 0x3ffff) << 14); |
| uint32_t Insn2 = |
| support::endian::read32le(PltContents.data() + Byte + Off); |
| // Check for: ldr Xt, [Xn, #pimm]. |
| if (Insn2 >> 22 == 0x3e5) { |
| Imm += ((Insn2 >> 10) & 0xfff) << 3; |
| Result.push_back(std::make_pair(PltSectionVA + Byte, Imm)); |
| Byte += 4; |
| } |
| } |
| return Result; |
| } |
| }; |
| |
| } // end anonymous namespace |
| |
| static MCInstrAnalysis *createAArch64InstrAnalysis(const MCInstrInfo *Info) { |
| return new AArch64MCInstrAnalysis(Info); |
| } |
| |
| // Force static initialization. |
| extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAArch64TargetMC() { |
| for (Target *T : {&getTheAArch64leTarget(), &getTheAArch64beTarget(), |
| &getTheAArch64_32Target(), &getTheARM64Target(), |
| &getTheARM64_32Target()}) { |
| // Register the MC asm info. |
| RegisterMCAsmInfoFn X(*T, createAArch64MCAsmInfo); |
| |
| // Register the MC instruction info. |
| TargetRegistry::RegisterMCInstrInfo(*T, createAArch64MCInstrInfo); |
| |
| // Register the MC register info. |
| TargetRegistry::RegisterMCRegInfo(*T, createAArch64MCRegisterInfo); |
| |
| // Register the MC subtarget info. |
| TargetRegistry::RegisterMCSubtargetInfo(*T, createAArch64MCSubtargetInfo); |
| |
| // Register the MC instruction analyzer. |
| TargetRegistry::RegisterMCInstrAnalysis(*T, createAArch64InstrAnalysis); |
| |
| // Register the MC Code Emitter |
| TargetRegistry::RegisterMCCodeEmitter(*T, createAArch64MCCodeEmitter); |
| |
| // Register the obj streamers. |
| TargetRegistry::RegisterELFStreamer(*T, createELFStreamer); |
| TargetRegistry::RegisterMachOStreamer(*T, createMachOStreamer); |
| TargetRegistry::RegisterCOFFStreamer(*T, createWinCOFFStreamer); |
| |
| // Register the obj target streamer. |
| TargetRegistry::RegisterObjectTargetStreamer( |
| *T, createAArch64ObjectTargetStreamer); |
| |
| // Register the asm streamer. |
| TargetRegistry::RegisterAsmTargetStreamer(*T, |
| createAArch64AsmTargetStreamer); |
| // Register the MCInstPrinter. |
| TargetRegistry::RegisterMCInstPrinter(*T, createAArch64MCInstPrinter); |
| } |
| |
| // Register the asm backend. |
| for (Target *T : {&getTheAArch64leTarget(), &getTheAArch64_32Target(), |
| &getTheARM64Target(), &getTheARM64_32Target()}) |
| TargetRegistry::RegisterMCAsmBackend(*T, createAArch64leAsmBackend); |
| TargetRegistry::RegisterMCAsmBackend(getTheAArch64beTarget(), |
| createAArch64beAsmBackend); |
| } |