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_br24: 75 // Branches are 4 byte aligned, so the 24 bits we encode in 76 // the instruction actually represents a 26 bit offset. 77 return {XCOFF::RelocationType::R_RBR, EncodedSignednessIndicator | 25}; 78 case FK_Data_4: 79 return {XCOFF::RelocationType::R_POS, EncodedSignednessIndicator | 31}; 80 } 81 } 82