1 //===-- PPCXCOFFObjectWriter.cpp - PowerPC XCOFF Writer -------------------===// 2 // 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "MCTargetDesc/PPCFixupKinds.h" 11 #include "MCTargetDesc/PPCMCTargetDesc.h" 12 #include "llvm/BinaryFormat/XCOFF.h" 13 #include "llvm/MC/MCFixup.h" 14 #include "llvm/MC/MCFixupKindInfo.h" 15 #include "llvm/MC/MCValue.h" 16 #include "llvm/MC/MCXCOFFObjectWriter.h" 17 18 using namespace llvm; 19 20 namespace { 21 class PPCXCOFFObjectWriter : public MCXCOFFObjectTargetWriter { 22 static constexpr uint8_t SignBitMask = 0x80; 23 24 public: 25 PPCXCOFFObjectWriter(bool Is64Bit); 26 27 std::pair<uint8_t, uint8_t> 28 getRelocTypeAndSignSize(const MCValue &Target, const MCFixup &Fixup, 29 bool IsPCRel) const override; 30 }; 31 } // end anonymous namespace 32 33 PPCXCOFFObjectWriter::PPCXCOFFObjectWriter(bool Is64Bit) 34 : MCXCOFFObjectTargetWriter(Is64Bit) {} 35 36 std::unique_ptr<MCObjectTargetWriter> 37 llvm::createPPCXCOFFObjectWriter(bool Is64Bit) { 38 return std::make_unique<PPCXCOFFObjectWriter>(Is64Bit); 39 } 40 41 std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize( 42 const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { 43 const MCSymbolRefExpr::VariantKind Modifier = 44 Target.isAbsolute() ? MCSymbolRefExpr::VK_None 45 : Target.getSymA()->getKind(); 46 // People from AIX OS team says AIX link editor does not care about 47 // the sign bit in the relocation entry "most" of the time. 48 // The system assembler seems to set the sign bit on relocation entry 49 // based on similar property of IsPCRel. So we will do the same here. 50 // TODO: More investigation on how assembler decides to set the sign 51 // bit, and we might want to match that. 52 const uint8_t EncodedSignednessIndicator = IsPCRel ? SignBitMask : 0u; 53 54 // The magic number we use in SignAndSize has a strong relationship with 55 // the corresponding MCFixupKind. In most cases, it's the MCFixupKind 56 // number - 1, because SignAndSize encodes the bit length being 57 // relocated minus 1. 58 switch ((unsigned)Fixup.getKind()) { 59 default: 60 report_fatal_error("Unimplemented fixup kind."); 61 case PPC::fixup_ppc_half16: { 62 const uint8_t SignAndSizeForHalf16 = EncodedSignednessIndicator | 15; 63 switch (Modifier) { 64 default: 65 report_fatal_error("Unsupported modifier for half16 fixup."); 66 case MCSymbolRefExpr::VK_None: 67 return {XCOFF::RelocationType::R_TOC, SignAndSizeForHalf16}; 68 case MCSymbolRefExpr::VK_PPC_U: 69 return {XCOFF::RelocationType::R_TOCU, SignAndSizeForHalf16}; 70 case MCSymbolRefExpr::VK_PPC_L: 71 return {XCOFF::RelocationType::R_TOCL, SignAndSizeForHalf16}; 72 case MCSymbolRefExpr::VK_PPC_AIX_TLSLE: 73 return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForHalf16}; 74 } 75 } break; 76 case PPC::fixup_ppc_half16ds: 77 case PPC::fixup_ppc_half16dq: { 78 if (IsPCRel) 79 report_fatal_error("Invalid PC-relative relocation."); 80 switch (Modifier) { 81 default: 82 llvm_unreachable("Unsupported Modifier"); 83 case MCSymbolRefExpr::VK_None: 84 return {XCOFF::RelocationType::R_TOC, 15}; 85 case MCSymbolRefExpr::VK_PPC_L: 86 return {XCOFF::RelocationType::R_TOCL, 15}; 87 case MCSymbolRefExpr::VK_PPC_AIX_TLSLE: 88 return {XCOFF::RelocationType::R_TLS_LE, 15}; 89 } 90 } break; 91 case PPC::fixup_ppc_br24: 92 // Branches are 4 byte aligned, so the 24 bits we encode in 93 // the instruction actually represents a 26 bit offset. 94 return {XCOFF::RelocationType::R_RBR, EncodedSignednessIndicator | 25}; 95 case PPC::fixup_ppc_br24abs: 96 return {XCOFF::RelocationType::R_RBA, EncodedSignednessIndicator | 25}; 97 case PPC::fixup_ppc_nofixup: { 98 if (Modifier == MCSymbolRefExpr::VK_None) 99 return {XCOFF::RelocationType::R_REF, 0}; 100 else 101 llvm_unreachable("Unsupported Modifier"); 102 } break; 103 case FK_Data_4: 104 case FK_Data_8: 105 const uint8_t SignAndSizeForFKData = 106 EncodedSignednessIndicator | 107 ((unsigned)Fixup.getKind() == FK_Data_4 ? 31 : 63); 108 switch (Modifier) { 109 default: 110 report_fatal_error("Unsupported modifier"); 111 case MCSymbolRefExpr::VK_PPC_AIX_TLSGD: 112 return {XCOFF::RelocationType::R_TLS, SignAndSizeForFKData}; 113 case MCSymbolRefExpr::VK_PPC_AIX_TLSGDM: 114 return {XCOFF::RelocationType::R_TLSM, SignAndSizeForFKData}; 115 case MCSymbolRefExpr::VK_PPC_AIX_TLSIE: 116 return {XCOFF::RelocationType::R_TLS_IE, SignAndSizeForFKData}; 117 case MCSymbolRefExpr::VK_PPC_AIX_TLSLE: 118 return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForFKData}; 119 case MCSymbolRefExpr::VK_None: 120 return {XCOFF::RelocationType::R_POS, SignAndSizeForFKData}; 121 } 122 } 123 } 124