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