192 lines · cpp
1//===-- VEAsmBackend.cpp - VE Assembler Backend ---------------------------===//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//===----------------------------------------------------------------------===//8 9#include "MCTargetDesc/VEFixupKinds.h"10#include "MCTargetDesc/VEMCTargetDesc.h"11#include "llvm/MC/MCAsmBackend.h"12#include "llvm/MC/MCELFObjectWriter.h"13#include "llvm/MC/MCExpr.h"14#include "llvm/MC/MCObjectWriter.h"15#include "llvm/MC/MCSubtargetInfo.h"16#include "llvm/MC/MCValue.h"17#include "llvm/MC/TargetRegistry.h"18#include "llvm/Support/EndianStream.h"19 20using namespace llvm;21 22static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {23 switch (Kind) {24 default:25 llvm_unreachable("Unknown fixup kind!");26 case FK_Data_1:27 case FK_Data_2:28 case FK_Data_4:29 case FK_Data_8:30 return Value;31 case VE::fixup_ve_hi32:32 case VE::fixup_ve_pc_hi32:33 case VE::fixup_ve_got_hi32:34 case VE::fixup_ve_gotoff_hi32:35 case VE::fixup_ve_plt_hi32:36 case VE::fixup_ve_tls_gd_hi32:37 case VE::fixup_ve_tpoff_hi32:38 return (Value >> 32) & 0xffffffff;39 case VE::fixup_ve_reflong:40 case VE::fixup_ve_srel32:41 case VE::fixup_ve_lo32:42 case VE::fixup_ve_pc_lo32:43 case VE::fixup_ve_got_lo32:44 case VE::fixup_ve_gotoff_lo32:45 case VE::fixup_ve_plt_lo32:46 case VE::fixup_ve_tls_gd_lo32:47 case VE::fixup_ve_tpoff_lo32:48 return Value & 0xffffffff;49 }50}51 52/// getFixupKindNumBytes - The number of bytes the fixup may change.53static unsigned getFixupKindNumBytes(unsigned Kind) {54 switch (Kind) {55 default:56 llvm_unreachable("Unknown fixup kind!");57 case FK_Data_1:58 return 1;59 case FK_Data_2:60 return 2;61 case FK_Data_4:62 case VE::fixup_ve_reflong:63 case VE::fixup_ve_srel32:64 case VE::fixup_ve_hi32:65 case VE::fixup_ve_lo32:66 case VE::fixup_ve_pc_hi32:67 case VE::fixup_ve_pc_lo32:68 case VE::fixup_ve_got_hi32:69 case VE::fixup_ve_got_lo32:70 case VE::fixup_ve_gotoff_hi32:71 case VE::fixup_ve_gotoff_lo32:72 case VE::fixup_ve_plt_hi32:73 case VE::fixup_ve_plt_lo32:74 case VE::fixup_ve_tls_gd_hi32:75 case VE::fixup_ve_tls_gd_lo32:76 case VE::fixup_ve_tpoff_hi32:77 case VE::fixup_ve_tpoff_lo32:78 return 4;79 case FK_Data_8:80 return 8;81 }82}83 84namespace {85class VEAsmBackend : public MCAsmBackend {86protected:87 const Target &TheTarget;88 89public:90 VEAsmBackend(const Target &T)91 : MCAsmBackend(llvm::endianness::little), TheTarget(T) {}92 93 MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override {94 const static MCFixupKindInfo Infos[VE::NumTargetFixupKinds] = {95 // name, offset, bits, flags96 {"fixup_ve_reflong", 0, 32, 0}, {"fixup_ve_srel32", 0, 32, 0},97 {"fixup_ve_hi32", 0, 32, 0}, {"fixup_ve_lo32", 0, 32, 0},98 {"fixup_ve_pc_hi32", 0, 32, 0}, {"fixup_ve_pc_lo32", 0, 32, 0},99 {"fixup_ve_got_hi32", 0, 32, 0}, {"fixup_ve_got_lo32", 0, 32, 0},100 {"fixup_ve_gotoff_hi32", 0, 32, 0}, {"fixup_ve_gotoff_lo32", 0, 32, 0},101 {"fixup_ve_plt_hi32", 0, 32, 0}, {"fixup_ve_plt_lo32", 0, 32, 0},102 {"fixup_ve_tls_gd_hi32", 0, 32, 0}, {"fixup_ve_tls_gd_lo32", 0, 32, 0},103 {"fixup_ve_tpoff_hi32", 0, 32, 0}, {"fixup_ve_tpoff_lo32", 0, 32, 0},104 };105 106 if (Kind < FirstTargetFixupKind)107 return MCAsmBackend::getFixupKindInfo(Kind);108 109 assert(unsigned(Kind - FirstTargetFixupKind) < VE::NumTargetFixupKinds &&110 "Invalid kind!");111 return Infos[Kind - FirstTargetFixupKind];112 }113 114 void applyFixup(const MCFragment &, const MCFixup &, const MCValue &,115 uint8_t *, uint64_t Value, bool IsResolved) override;116 117 bool mayNeedRelaxation(unsigned Opcode, ArrayRef<MCOperand> Operands,118 const MCSubtargetInfo &STI) const override {119 // Not implemented yet. For example, if we have a branch with120 // lager than SIMM32 immediate value, we want to relaxation such121 // branch instructions.122 return false;123 }124 125 bool writeNopData(raw_ostream &OS, uint64_t Count,126 const MCSubtargetInfo *STI) const override {127 if ((Count % 8) != 0)128 return false;129 130 for (uint64_t i = 0; i < Count; i += 8)131 support::endian::write<uint64_t>(OS, 0x7900000000000000ULL,132 llvm::endianness::little);133 134 return true;135 }136};137 138class ELFVEAsmBackend : public VEAsmBackend {139 Triple::OSType OSType;140 141public:142 ELFVEAsmBackend(const Target &T, Triple::OSType OSType)143 : VEAsmBackend(T), OSType(OSType) {}144 145 std::unique_ptr<MCObjectTargetWriter>146 createObjectTargetWriter() const override {147 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);148 return createVEELFObjectWriter(OSABI);149 }150};151} // end anonymous namespace152 153void VEAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,154 const MCValue &Target, uint8_t *Data,155 uint64_t Value, bool IsResolved) {156 switch (Fixup.getKind()) {157 case VE::fixup_ve_tls_gd_hi32:158 case VE::fixup_ve_tls_gd_lo32:159 case VE::fixup_ve_tpoff_hi32:160 case VE::fixup_ve_tpoff_lo32:161 IsResolved = false;162 break;163 }164 maybeAddReloc(F, Fixup, Target, Value, IsResolved);165 Value = adjustFixupValue(Fixup.getKind(), Value);166 if (!Value)167 return; // Doesn't change encoding.168 169 MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());170 171 // Shift the value into position.172 Value <<= Info.TargetOffset;173 174 unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());175 assert(Fixup.getOffset() + NumBytes <= F.getSize() &&176 "Invalid fixup offset!");177 // For each byte of the fragment that the fixup touches, mask in the bits178 // from the fixup value. The Value has been "split up" into the179 // appropriate bitfields above.180 for (unsigned i = 0; i != NumBytes; ++i) {181 unsigned Idx = Endian == llvm::endianness::little ? i : (NumBytes - 1) - i;182 Data[Idx] |= static_cast<uint8_t>((Value >> (i * 8)) & 0xff);183 }184}185 186MCAsmBackend *llvm::createVEAsmBackend(const Target &T,187 const MCSubtargetInfo &STI,188 const MCRegisterInfo &MRI,189 const MCTargetOptions &Options) {190 return new ELFVEAsmBackend(T, STI.getTargetTriple().getOS());191}192