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 } 73 } break; 74 case PPC::fixup_ppc_half16ds: 75 case PPC::fixup_ppc_half16dq: { 76 if (IsPCRel) 77 report_fatal_error("Invalid PC-relative relocation."); 78 switch (Modifier) { 79 default: 80 llvm_unreachable("Unsupported Modifier"); 81 case MCSymbolRefExpr::VK_None: 82 return {XCOFF::RelocationType::R_TOC, 15}; 83 case MCSymbolRefExpr::VK_PPC_L: 84 return {XCOFF::RelocationType::R_TOCL, 15}; 85 } 86 } break; 87 case PPC::fixup_ppc_br24: 88 // Branches are 4 byte aligned, so the 24 bits we encode in 89 // the instruction actually represents a 26 bit offset. 90 return {XCOFF::RelocationType::R_RBR, EncodedSignednessIndicator | 25}; 91 case PPC::fixup_ppc_br24abs: 92 return {XCOFF::RelocationType::R_RBA, EncodedSignednessIndicator | 25}; 93 case PPC::fixup_ppc_nofixup: { 94 if (Modifier == MCSymbolRefExpr::VK_None) 95 return {XCOFF::RelocationType::R_REF, 0}; 96 else 97 llvm_unreachable("Unsupported Modifier"); 98 } break; 99 case FK_Data_4: 100 case FK_Data_8: 101 const uint8_t SignAndSizeForFKData = 102 EncodedSignednessIndicator | 103 ((unsigned)Fixup.getKind() == FK_Data_4 ? 31 : 63); 104 switch (Modifier) { 105 default: 106 report_fatal_error("Unsupported modifier"); 107 case MCSymbolRefExpr::VK_PPC_AIX_TLSGD: 108 return {XCOFF::RelocationType::R_TLS, SignAndSizeForFKData}; 109 case MCSymbolRefExpr::VK_PPC_AIX_TLSGDM: 110 return {XCOFF::RelocationType::R_TLSM, SignAndSizeForFKData}; 111 case MCSymbolRefExpr::VK_PPC_AIX_TLSLE: 112 return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForFKData}; 113 case MCSymbolRefExpr::VK_None: 114 return {XCOFF::RelocationType::R_POS, SignAndSizeForFKData}; 115 } 116 } 117 } 118