brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.3 KiB · c1b9d9f Raw
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