10b57cec5SDimitry Andric //===-- PPCXCOFFObjectWriter.cpp - PowerPC XCOFF Writer -------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // 40b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 50b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 60b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70b57cec5SDimitry Andric // 80b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 90b57cec5SDimitry Andric 105ffd83dbSDimitry Andric #include "MCTargetDesc/PPCFixupKinds.h" 115ffd83dbSDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h" 125ffd83dbSDimitry Andric #include "llvm/BinaryFormat/XCOFF.h" 135ffd83dbSDimitry Andric #include "llvm/MC/MCFixup.h" 145ffd83dbSDimitry Andric #include "llvm/MC/MCFixupKindInfo.h" 155ffd83dbSDimitry Andric #include "llvm/MC/MCValue.h" 160b57cec5SDimitry Andric #include "llvm/MC/MCXCOFFObjectWriter.h" 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric using namespace llvm; 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric namespace { 210b57cec5SDimitry Andric class PPCXCOFFObjectWriter : public MCXCOFFObjectTargetWriter { 225ffd83dbSDimitry Andric static constexpr uint8_t SignBitMask = 0x80; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric public: 250b57cec5SDimitry Andric PPCXCOFFObjectWriter(bool Is64Bit); 265ffd83dbSDimitry Andric 275ffd83dbSDimitry Andric std::pair<uint8_t, uint8_t> 285ffd83dbSDimitry Andric getRelocTypeAndSignSize(const MCValue &Target, const MCFixup &Fixup, 295ffd83dbSDimitry Andric bool IsPCRel) const override; 300b57cec5SDimitry Andric }; 310b57cec5SDimitry Andric } // end anonymous namespace 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric PPCXCOFFObjectWriter::PPCXCOFFObjectWriter(bool Is64Bit) 340b57cec5SDimitry Andric : MCXCOFFObjectTargetWriter(Is64Bit) {} 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric std::unique_ptr<MCObjectTargetWriter> 370b57cec5SDimitry Andric llvm::createPPCXCOFFObjectWriter(bool Is64Bit) { 388bcb0991SDimitry Andric return std::make_unique<PPCXCOFFObjectWriter>(Is64Bit); 390b57cec5SDimitry Andric } 405ffd83dbSDimitry Andric 415ffd83dbSDimitry Andric std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize( 425ffd83dbSDimitry Andric const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { 435ffd83dbSDimitry Andric const MCSymbolRefExpr::VariantKind Modifier = 445ffd83dbSDimitry Andric Target.isAbsolute() ? MCSymbolRefExpr::VK_None 455ffd83dbSDimitry Andric : Target.getSymA()->getKind(); 465ffd83dbSDimitry Andric // People from AIX OS team says AIX link editor does not care about 475ffd83dbSDimitry Andric // the sign bit in the relocation entry "most" of the time. 485ffd83dbSDimitry Andric // The system assembler seems to set the sign bit on relocation entry 495ffd83dbSDimitry Andric // based on similar property of IsPCRel. So we will do the same here. 505ffd83dbSDimitry Andric // TODO: More investigation on how assembler decides to set the sign 515ffd83dbSDimitry Andric // bit, and we might want to match that. 525ffd83dbSDimitry Andric const uint8_t EncodedSignednessIndicator = IsPCRel ? SignBitMask : 0u; 535ffd83dbSDimitry Andric 545ffd83dbSDimitry Andric // The magic number we use in SignAndSize has a strong relationship with 555ffd83dbSDimitry Andric // the corresponding MCFixupKind. In most cases, it's the MCFixupKind 565ffd83dbSDimitry Andric // number - 1, because SignAndSize encodes the bit length being 575ffd83dbSDimitry Andric // relocated minus 1. 585ffd83dbSDimitry Andric switch ((unsigned)Fixup.getKind()) { 595ffd83dbSDimitry Andric default: 605ffd83dbSDimitry Andric report_fatal_error("Unimplemented fixup kind."); 61e8d8bef9SDimitry Andric case PPC::fixup_ppc_half16: { 62e8d8bef9SDimitry Andric const uint8_t SignAndSizeForHalf16 = EncodedSignednessIndicator | 15; 635ffd83dbSDimitry Andric switch (Modifier) { 645ffd83dbSDimitry Andric default: 655ffd83dbSDimitry Andric report_fatal_error("Unsupported modifier for half16 fixup."); 665ffd83dbSDimitry Andric case MCSymbolRefExpr::VK_None: 67e8d8bef9SDimitry Andric return {XCOFF::RelocationType::R_TOC, SignAndSizeForHalf16}; 68e8d8bef9SDimitry Andric case MCSymbolRefExpr::VK_PPC_U: 69e8d8bef9SDimitry Andric return {XCOFF::RelocationType::R_TOCU, SignAndSizeForHalf16}; 70e8d8bef9SDimitry Andric case MCSymbolRefExpr::VK_PPC_L: 71e8d8bef9SDimitry Andric return {XCOFF::RelocationType::R_TOCL, SignAndSizeForHalf16}; 725f757f3fSDimitry Andric case MCSymbolRefExpr::VK_PPC_AIX_TLSLE: 735f757f3fSDimitry Andric return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForHalf16}; 74*0fca6ea1SDimitry Andric case MCSymbolRefExpr::VK_PPC_AIX_TLSLD: 75*0fca6ea1SDimitry Andric return {XCOFF::RelocationType::R_TLS_LD, SignAndSizeForHalf16}; 765ffd83dbSDimitry Andric } 77e8d8bef9SDimitry Andric } break; 7881ad6265SDimitry Andric case PPC::fixup_ppc_half16ds: 7981ad6265SDimitry Andric case PPC::fixup_ppc_half16dq: { 8081ad6265SDimitry Andric if (IsPCRel) 8181ad6265SDimitry Andric report_fatal_error("Invalid PC-relative relocation."); 8281ad6265SDimitry Andric switch (Modifier) { 8381ad6265SDimitry Andric default: 8481ad6265SDimitry Andric llvm_unreachable("Unsupported Modifier"); 8581ad6265SDimitry Andric case MCSymbolRefExpr::VK_None: 8681ad6265SDimitry Andric return {XCOFF::RelocationType::R_TOC, 15}; 8781ad6265SDimitry Andric case MCSymbolRefExpr::VK_PPC_L: 8881ad6265SDimitry Andric return {XCOFF::RelocationType::R_TOCL, 15}; 895f757f3fSDimitry Andric case MCSymbolRefExpr::VK_PPC_AIX_TLSLE: 905f757f3fSDimitry Andric return {XCOFF::RelocationType::R_TLS_LE, 15}; 91*0fca6ea1SDimitry Andric case MCSymbolRefExpr::VK_PPC_AIX_TLSLD: 92*0fca6ea1SDimitry Andric return {XCOFF::RelocationType::R_TLS_LD, 15}; 9381ad6265SDimitry Andric } 9481ad6265SDimitry Andric } break; 955ffd83dbSDimitry Andric case PPC::fixup_ppc_br24: 965ffd83dbSDimitry Andric // Branches are 4 byte aligned, so the 24 bits we encode in 975ffd83dbSDimitry Andric // the instruction actually represents a 26 bit offset. 985ffd83dbSDimitry Andric return {XCOFF::RelocationType::R_RBR, EncodedSignednessIndicator | 25}; 99fe6060f1SDimitry Andric case PPC::fixup_ppc_br24abs: 100fe6060f1SDimitry Andric return {XCOFF::RelocationType::R_RBA, EncodedSignednessIndicator | 25}; 10106c3fb27SDimitry Andric case PPC::fixup_ppc_nofixup: { 10206c3fb27SDimitry Andric if (Modifier == MCSymbolRefExpr::VK_None) 10306c3fb27SDimitry Andric return {XCOFF::RelocationType::R_REF, 0}; 10406c3fb27SDimitry Andric else 10506c3fb27SDimitry Andric llvm_unreachable("Unsupported Modifier"); 10606c3fb27SDimitry Andric } break; 1075ffd83dbSDimitry Andric case FK_Data_4: 10881ad6265SDimitry Andric case FK_Data_8: 10981ad6265SDimitry Andric const uint8_t SignAndSizeForFKData = 11081ad6265SDimitry Andric EncodedSignednessIndicator | 11181ad6265SDimitry Andric ((unsigned)Fixup.getKind() == FK_Data_4 ? 31 : 63); 112fe6060f1SDimitry Andric switch (Modifier) { 113fe6060f1SDimitry Andric default: 114fe6060f1SDimitry Andric report_fatal_error("Unsupported modifier"); 115fe6060f1SDimitry Andric case MCSymbolRefExpr::VK_PPC_AIX_TLSGD: 11681ad6265SDimitry Andric return {XCOFF::RelocationType::R_TLS, SignAndSizeForFKData}; 117fe6060f1SDimitry Andric case MCSymbolRefExpr::VK_PPC_AIX_TLSGDM: 11881ad6265SDimitry Andric return {XCOFF::RelocationType::R_TLSM, SignAndSizeForFKData}; 1195f757f3fSDimitry Andric case MCSymbolRefExpr::VK_PPC_AIX_TLSIE: 1205f757f3fSDimitry Andric return {XCOFF::RelocationType::R_TLS_IE, SignAndSizeForFKData}; 12106c3fb27SDimitry Andric case MCSymbolRefExpr::VK_PPC_AIX_TLSLE: 12206c3fb27SDimitry Andric return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForFKData}; 123*0fca6ea1SDimitry Andric case MCSymbolRefExpr::VK_PPC_AIX_TLSLD: 124*0fca6ea1SDimitry Andric return {XCOFF::RelocationType::R_TLS_LD, SignAndSizeForFKData}; 125*0fca6ea1SDimitry Andric case MCSymbolRefExpr::VK_PPC_AIX_TLSML: 126*0fca6ea1SDimitry Andric return {XCOFF::RelocationType::R_TLSML, SignAndSizeForFKData}; 127fe6060f1SDimitry Andric case MCSymbolRefExpr::VK_None: 12881ad6265SDimitry Andric return {XCOFF::RelocationType::R_POS, SignAndSizeForFKData}; 1295ffd83dbSDimitry Andric } 1305ffd83dbSDimitry Andric } 131fe6060f1SDimitry Andric } 132