10b57cec5SDimitry Andric //===-- PPCAsmBackend.cpp - PPC Assembler Backend -------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "MCTargetDesc/PPCFixupKinds.h" 100b57cec5SDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h" 110b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 120b57cec5SDimitry Andric #include "llvm/BinaryFormat/MachO.h" 130b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h" 140b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h" 150b57cec5SDimitry Andric #include "llvm/MC/MCELFObjectWriter.h" 160b57cec5SDimitry Andric #include "llvm/MC/MCFixupKindInfo.h" 170b57cec5SDimitry Andric #include "llvm/MC/MCMachObjectWriter.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCSectionMachO.h" 200b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h" 2206c3fb27SDimitry Andric #include "llvm/MC/MCSymbolXCOFF.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCValue.h" 24349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 250b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 260b57cec5SDimitry Andric using namespace llvm; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) { 290b57cec5SDimitry Andric switch (Kind) { 300b57cec5SDimitry Andric default: 310b57cec5SDimitry Andric llvm_unreachable("Unknown fixup kind!"); 320b57cec5SDimitry Andric case FK_Data_1: 330b57cec5SDimitry Andric case FK_Data_2: 340b57cec5SDimitry Andric case FK_Data_4: 350b57cec5SDimitry Andric case FK_Data_8: 360b57cec5SDimitry Andric case PPC::fixup_ppc_nofixup: 370b57cec5SDimitry Andric return Value; 380b57cec5SDimitry Andric case PPC::fixup_ppc_brcond14: 390b57cec5SDimitry Andric case PPC::fixup_ppc_brcond14abs: 400b57cec5SDimitry Andric return Value & 0xfffc; 410b57cec5SDimitry Andric case PPC::fixup_ppc_br24: 420b57cec5SDimitry Andric case PPC::fixup_ppc_br24abs: 435ffd83dbSDimitry Andric case PPC::fixup_ppc_br24_notoc: 440b57cec5SDimitry Andric return Value & 0x3fffffc; 450b57cec5SDimitry Andric case PPC::fixup_ppc_half16: 460b57cec5SDimitry Andric return Value & 0xffff; 470b57cec5SDimitry Andric case PPC::fixup_ppc_half16ds: 483a9a9c0cSDimitry Andric case PPC::fixup_ppc_half16dq: 490b57cec5SDimitry Andric return Value & 0xfffc; 505ffd83dbSDimitry Andric case PPC::fixup_ppc_pcrel34: 51e8d8bef9SDimitry Andric case PPC::fixup_ppc_imm34: 525ffd83dbSDimitry Andric return Value & 0x3ffffffff; 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric static unsigned getFixupKindNumBytes(unsigned Kind) { 570b57cec5SDimitry Andric switch (Kind) { 580b57cec5SDimitry Andric default: 590b57cec5SDimitry Andric llvm_unreachable("Unknown fixup kind!"); 600b57cec5SDimitry Andric case FK_Data_1: 610b57cec5SDimitry Andric return 1; 620b57cec5SDimitry Andric case FK_Data_2: 630b57cec5SDimitry Andric case PPC::fixup_ppc_half16: 640b57cec5SDimitry Andric case PPC::fixup_ppc_half16ds: 653a9a9c0cSDimitry Andric case PPC::fixup_ppc_half16dq: 660b57cec5SDimitry Andric return 2; 670b57cec5SDimitry Andric case FK_Data_4: 680b57cec5SDimitry Andric case PPC::fixup_ppc_brcond14: 690b57cec5SDimitry Andric case PPC::fixup_ppc_brcond14abs: 700b57cec5SDimitry Andric case PPC::fixup_ppc_br24: 710b57cec5SDimitry Andric case PPC::fixup_ppc_br24abs: 725ffd83dbSDimitry Andric case PPC::fixup_ppc_br24_notoc: 730b57cec5SDimitry Andric return 4; 745ffd83dbSDimitry Andric case PPC::fixup_ppc_pcrel34: 75e8d8bef9SDimitry Andric case PPC::fixup_ppc_imm34: 760b57cec5SDimitry Andric case FK_Data_8: 770b57cec5SDimitry Andric return 8; 780b57cec5SDimitry Andric case PPC::fixup_ppc_nofixup: 790b57cec5SDimitry Andric return 0; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric namespace { 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric class PPCAsmBackend : public MCAsmBackend { 860b57cec5SDimitry Andric protected: 870b57cec5SDimitry Andric Triple TT; 880b57cec5SDimitry Andric public: 890b57cec5SDimitry Andric PPCAsmBackend(const Target &T, const Triple &TT) 90*5f757f3fSDimitry Andric : MCAsmBackend(TT.isLittleEndian() ? llvm::endianness::little 91*5f757f3fSDimitry Andric : llvm::endianness::big), 920b57cec5SDimitry Andric TT(TT) {} 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric unsigned getNumFixupKinds() const override { 950b57cec5SDimitry Andric return PPC::NumTargetFixupKinds; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { 990b57cec5SDimitry Andric const static MCFixupKindInfo InfosBE[PPC::NumTargetFixupKinds] = { 1000b57cec5SDimitry Andric // name offset bits flags 1010b57cec5SDimitry Andric { "fixup_ppc_br24", 6, 24, MCFixupKindInfo::FKF_IsPCRel }, 1025ffd83dbSDimitry Andric { "fixup_ppc_br24_notoc", 6, 24, MCFixupKindInfo::FKF_IsPCRel }, 1030b57cec5SDimitry Andric { "fixup_ppc_brcond14", 16, 14, MCFixupKindInfo::FKF_IsPCRel }, 1040b57cec5SDimitry Andric { "fixup_ppc_br24abs", 6, 24, 0 }, 1050b57cec5SDimitry Andric { "fixup_ppc_brcond14abs", 16, 14, 0 }, 1060b57cec5SDimitry Andric { "fixup_ppc_half16", 0, 16, 0 }, 1070b57cec5SDimitry Andric { "fixup_ppc_half16ds", 0, 14, 0 }, 1085ffd83dbSDimitry Andric { "fixup_ppc_pcrel34", 0, 34, MCFixupKindInfo::FKF_IsPCRel }, 109e8d8bef9SDimitry Andric { "fixup_ppc_imm34", 0, 34, 0 }, 1100b57cec5SDimitry Andric { "fixup_ppc_nofixup", 0, 0, 0 } 1110b57cec5SDimitry Andric }; 1120b57cec5SDimitry Andric const static MCFixupKindInfo InfosLE[PPC::NumTargetFixupKinds] = { 1130b57cec5SDimitry Andric // name offset bits flags 1140b57cec5SDimitry Andric { "fixup_ppc_br24", 2, 24, MCFixupKindInfo::FKF_IsPCRel }, 1155ffd83dbSDimitry Andric { "fixup_ppc_br24_notoc", 2, 24, MCFixupKindInfo::FKF_IsPCRel }, 1160b57cec5SDimitry Andric { "fixup_ppc_brcond14", 2, 14, MCFixupKindInfo::FKF_IsPCRel }, 1170b57cec5SDimitry Andric { "fixup_ppc_br24abs", 2, 24, 0 }, 1180b57cec5SDimitry Andric { "fixup_ppc_brcond14abs", 2, 14, 0 }, 1190b57cec5SDimitry Andric { "fixup_ppc_half16", 0, 16, 0 }, 1200b57cec5SDimitry Andric { "fixup_ppc_half16ds", 2, 14, 0 }, 1215ffd83dbSDimitry Andric { "fixup_ppc_pcrel34", 0, 34, MCFixupKindInfo::FKF_IsPCRel }, 122e8d8bef9SDimitry Andric { "fixup_ppc_imm34", 0, 34, 0 }, 1230b57cec5SDimitry Andric { "fixup_ppc_nofixup", 0, 0, 0 } 1240b57cec5SDimitry Andric }; 1250b57cec5SDimitry Andric 1265ffd83dbSDimitry Andric // Fixup kinds from .reloc directive are like R_PPC_NONE/R_PPC64_NONE. They 1275ffd83dbSDimitry Andric // do not require any extra processing. 1285ffd83dbSDimitry Andric if (Kind >= FirstLiteralRelocationKind) 1295ffd83dbSDimitry Andric return MCAsmBackend::getFixupKindInfo(FK_NONE); 1305ffd83dbSDimitry Andric 1310b57cec5SDimitry Andric if (Kind < FirstTargetFixupKind) 1320b57cec5SDimitry Andric return MCAsmBackend::getFixupKindInfo(Kind); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 1350b57cec5SDimitry Andric "Invalid kind!"); 136*5f757f3fSDimitry Andric return (Endian == llvm::endianness::little 1370b57cec5SDimitry Andric ? InfosLE 1380b57cec5SDimitry Andric : InfosBE)[Kind - FirstTargetFixupKind]; 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, 1420b57cec5SDimitry Andric const MCValue &Target, MutableArrayRef<char> Data, 1430b57cec5SDimitry Andric uint64_t Value, bool IsResolved, 1440b57cec5SDimitry Andric const MCSubtargetInfo *STI) const override { 1455ffd83dbSDimitry Andric MCFixupKind Kind = Fixup.getKind(); 1465ffd83dbSDimitry Andric if (Kind >= FirstLiteralRelocationKind) 1475ffd83dbSDimitry Andric return; 1485ffd83dbSDimitry Andric Value = adjustFixupValue(Kind, Value); 1490b57cec5SDimitry Andric if (!Value) return; // Doesn't change encoding. 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric unsigned Offset = Fixup.getOffset(); 1525ffd83dbSDimitry Andric unsigned NumBytes = getFixupKindNumBytes(Kind); 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric // For each byte of the fragment that the fixup touches, mask in the bits 1550b57cec5SDimitry Andric // from the fixup value. The Value has been "split up" into the appropriate 1560b57cec5SDimitry Andric // bitfields above. 1570b57cec5SDimitry Andric for (unsigned i = 0; i != NumBytes; ++i) { 158*5f757f3fSDimitry Andric unsigned Idx = 159*5f757f3fSDimitry Andric Endian == llvm::endianness::little ? i : (NumBytes - 1 - i); 1600b57cec5SDimitry Andric Data[Offset + i] |= uint8_t((Value >> (Idx * 8)) & 0xff); 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, 165*5f757f3fSDimitry Andric const MCValue &Target, 166*5f757f3fSDimitry Andric const MCSubtargetInfo *STI) override { 1675ffd83dbSDimitry Andric MCFixupKind Kind = Fixup.getKind(); 1685ffd83dbSDimitry Andric switch ((unsigned)Kind) { 1690b57cec5SDimitry Andric default: 1705ffd83dbSDimitry Andric return Kind >= FirstLiteralRelocationKind; 1710b57cec5SDimitry Andric case PPC::fixup_ppc_br24: 1720b57cec5SDimitry Andric case PPC::fixup_ppc_br24abs: 1735ffd83dbSDimitry Andric case PPC::fixup_ppc_br24_notoc: 1740b57cec5SDimitry Andric // If the target symbol has a local entry point we must not attempt 1750b57cec5SDimitry Andric // to resolve the fixup directly. Emit a relocation and leave 1760b57cec5SDimitry Andric // resolution of the final target address to the linker. 1770b57cec5SDimitry Andric if (const MCSymbolRefExpr *A = Target.getSymA()) { 1780b57cec5SDimitry Andric if (const auto *S = dyn_cast<MCSymbolELF>(&A->getSymbol())) { 1790b57cec5SDimitry Andric // The "other" values are stored in the last 6 bits of the second 1800b57cec5SDimitry Andric // byte. The traditional defines for STO values assume the full byte 1810b57cec5SDimitry Andric // and thus the shift to pack it. 1820b57cec5SDimitry Andric unsigned Other = S->getOther() << 2; 1830b57cec5SDimitry Andric if ((Other & ELF::STO_PPC64_LOCAL_MASK) != 0) 1840b57cec5SDimitry Andric return true; 18506c3fb27SDimitry Andric } else if (const auto *S = dyn_cast<MCSymbolXCOFF>(&A->getSymbol())) { 18606c3fb27SDimitry Andric return !Target.isAbsolute() && S->isExternal() && 18706c3fb27SDimitry Andric S->getStorageClass() == XCOFF::C_WEAKEXT; 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric return false; 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1945ffd83dbSDimitry Andric void relaxInstruction(MCInst &Inst, 1955ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const override { 1960b57cec5SDimitry Andric // FIXME. 1970b57cec5SDimitry Andric llvm_unreachable("relaxInstruction() unimplemented"); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 200349cc55cSDimitry Andric bool writeNopData(raw_ostream &OS, uint64_t Count, 201349cc55cSDimitry Andric const MCSubtargetInfo *STI) const override { 2020b57cec5SDimitry Andric uint64_t NumNops = Count / 4; 2030b57cec5SDimitry Andric for (uint64_t i = 0; i != NumNops; ++i) 2040b57cec5SDimitry Andric support::endian::write<uint32_t>(OS, 0x60000000, Endian); 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric OS.write_zeros(Count % 4); 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric return true; 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric }; 2110b57cec5SDimitry Andric } // end anonymous namespace 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric // FIXME: This should be in a separate file. 2150b57cec5SDimitry Andric namespace { 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric class ELFPPCAsmBackend : public PPCAsmBackend { 2180b57cec5SDimitry Andric public: 2190b57cec5SDimitry Andric ELFPPCAsmBackend(const Target &T, const Triple &TT) : PPCAsmBackend(T, TT) {} 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric std::unique_ptr<MCObjectTargetWriter> 2220b57cec5SDimitry Andric createObjectTargetWriter() const override { 2230b57cec5SDimitry Andric uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); 2240b57cec5SDimitry Andric bool Is64 = TT.isPPC64(); 2250b57cec5SDimitry Andric return createPPCELFObjectWriter(Is64, OSABI); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 228bdd1243dSDimitry Andric std::optional<MCFixupKind> getFixupKind(StringRef Name) const override; 2290b57cec5SDimitry Andric }; 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric class XCOFFPPCAsmBackend : public PPCAsmBackend { 2320b57cec5SDimitry Andric public: 2330b57cec5SDimitry Andric XCOFFPPCAsmBackend(const Target &T, const Triple &TT) 2340b57cec5SDimitry Andric : PPCAsmBackend(T, TT) {} 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric std::unique_ptr<MCObjectTargetWriter> 2370b57cec5SDimitry Andric createObjectTargetWriter() const override { 2380b57cec5SDimitry Andric return createPPCXCOFFObjectWriter(TT.isArch64Bit()); 2390b57cec5SDimitry Andric } 24006c3fb27SDimitry Andric 24106c3fb27SDimitry Andric std::optional<MCFixupKind> getFixupKind(StringRef Name) const override; 2420b57cec5SDimitry Andric }; 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric } // end anonymous namespace 2450b57cec5SDimitry Andric 246bdd1243dSDimitry Andric std::optional<MCFixupKind> 247bdd1243dSDimitry Andric ELFPPCAsmBackend::getFixupKind(StringRef Name) const { 2485ffd83dbSDimitry Andric if (TT.isOSBinFormatELF()) { 2495ffd83dbSDimitry Andric unsigned Type; 2500b57cec5SDimitry Andric if (TT.isPPC64()) { 2515ffd83dbSDimitry Andric Type = llvm::StringSwitch<unsigned>(Name) 2525ffd83dbSDimitry Andric #define ELF_RELOC(X, Y) .Case(#X, Y) 2535ffd83dbSDimitry Andric #include "llvm/BinaryFormat/ELFRelocs/PowerPC64.def" 2545ffd83dbSDimitry Andric #undef ELF_RELOC 255fe6060f1SDimitry Andric .Case("BFD_RELOC_NONE", ELF::R_PPC64_NONE) 256fe6060f1SDimitry Andric .Case("BFD_RELOC_16", ELF::R_PPC64_ADDR16) 257fe6060f1SDimitry Andric .Case("BFD_RELOC_32", ELF::R_PPC64_ADDR32) 258fe6060f1SDimitry Andric .Case("BFD_RELOC_64", ELF::R_PPC64_ADDR64) 2595ffd83dbSDimitry Andric .Default(-1u); 2600b57cec5SDimitry Andric } else { 2615ffd83dbSDimitry Andric Type = llvm::StringSwitch<unsigned>(Name) 2625ffd83dbSDimitry Andric #define ELF_RELOC(X, Y) .Case(#X, Y) 2635ffd83dbSDimitry Andric #include "llvm/BinaryFormat/ELFRelocs/PowerPC.def" 2645ffd83dbSDimitry Andric #undef ELF_RELOC 265fe6060f1SDimitry Andric .Case("BFD_RELOC_NONE", ELF::R_PPC_NONE) 266fe6060f1SDimitry Andric .Case("BFD_RELOC_16", ELF::R_PPC_ADDR16) 267fe6060f1SDimitry Andric .Case("BFD_RELOC_32", ELF::R_PPC_ADDR32) 2685ffd83dbSDimitry Andric .Default(-1u); 2690b57cec5SDimitry Andric } 2705ffd83dbSDimitry Andric if (Type != -1u) 2715ffd83dbSDimitry Andric return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type); 2725ffd83dbSDimitry Andric } 273bdd1243dSDimitry Andric return std::nullopt; 2740b57cec5SDimitry Andric } 2750b57cec5SDimitry Andric 27606c3fb27SDimitry Andric std::optional<MCFixupKind> 27706c3fb27SDimitry Andric XCOFFPPCAsmBackend::getFixupKind(StringRef Name) const { 27806c3fb27SDimitry Andric return StringSwitch<std::optional<MCFixupKind>>(Name) 27906c3fb27SDimitry Andric .Case("R_REF", (MCFixupKind)PPC::fixup_ppc_nofixup) 28006c3fb27SDimitry Andric .Default(std::nullopt); 28106c3fb27SDimitry Andric } 28206c3fb27SDimitry Andric 2830b57cec5SDimitry Andric MCAsmBackend *llvm::createPPCAsmBackend(const Target &T, 2840b57cec5SDimitry Andric const MCSubtargetInfo &STI, 2850b57cec5SDimitry Andric const MCRegisterInfo &MRI, 2860b57cec5SDimitry Andric const MCTargetOptions &Options) { 2870b57cec5SDimitry Andric const Triple &TT = STI.getTargetTriple(); 2880b57cec5SDimitry Andric if (TT.isOSBinFormatXCOFF()) 2890b57cec5SDimitry Andric return new XCOFFPPCAsmBackend(T, TT); 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric return new ELFPPCAsmBackend(T, TT); 2920b57cec5SDimitry Andric } 293