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 18using namespace llvm; 19 20namespace { 21class PPCXCOFFObjectWriter : public MCXCOFFObjectTargetWriter { 22 static constexpr uint8_t SignBitMask = 0x80; 23 24public: 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 33PPCXCOFFObjectWriter::PPCXCOFFObjectWriter(bool Is64Bit) 34 : MCXCOFFObjectTargetWriter(Is64Bit) {} 35 36std::unique_ptr<MCObjectTargetWriter> 37llvm::createPPCXCOFFObjectWriter(bool Is64Bit) { 38 return std::make_unique<PPCXCOFFObjectWriter>(Is64Bit); 39} 40 41std::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 switch (Modifier) { 63 default: 64 report_fatal_error("Unsupported modifier for half16 fixup."); 65 case MCSymbolRefExpr::VK_None: 66 return {XCOFF::RelocationType::R_TOC, EncodedSignednessIndicator | 15}; 67 } 68 break; 69 case PPC::fixup_ppc_br24: 70 // Branches are 4 byte aligned, so the 24 bits we encode in 71 // the instruction actually represents a 26 bit offset. 72 return {XCOFF::RelocationType::R_RBR, EncodedSignednessIndicator | 25}; 73 case FK_Data_4: 74 return {XCOFF::RelocationType::R_POS, EncodedSignednessIndicator | 31}; 75 } 76} 77