brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.4 KiB · 53933f9 Raw
124 lines · cpp
1//===-- BPFAsmBackend.cpp - BPF 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/BPFMCFixups.h"10#include "MCTargetDesc/BPFMCTargetDesc.h"11#include "llvm/MC/MCAsmBackend.h"12#include "llvm/MC/MCAssembler.h"13#include "llvm/MC/MCContext.h"14#include "llvm/MC/MCFixup.h"15#include "llvm/MC/MCObjectWriter.h"16#include "llvm/Support/EndianStream.h"17#include <cassert>18#include <cstdint>19 20using namespace llvm;21 22namespace {23 24class BPFAsmBackend : public MCAsmBackend {25public:26  BPFAsmBackend(llvm::endianness Endian) : MCAsmBackend(Endian) {}27  ~BPFAsmBackend() override = default;28 29  void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,30                  uint8_t *Data, uint64_t Value, bool IsResolved) override;31 32  std::unique_ptr<MCObjectTargetWriter>33  createObjectTargetWriter() const override;34 35  MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;36 37  bool writeNopData(raw_ostream &OS, uint64_t Count,38                    const MCSubtargetInfo *STI) const override;39};40 41} // end anonymous namespace42 43MCFixupKindInfo BPFAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {44  const static MCFixupKindInfo Infos[BPF::NumTargetFixupKinds] = {45      {"FK_BPF_PCRel_4", 0, 32, 0},46  };47 48  if (Kind < FirstTargetFixupKind)49    return MCAsmBackend::getFixupKindInfo(Kind);50 51  assert(unsigned(Kind - FirstTargetFixupKind) < BPF::NumTargetFixupKinds &&52         "Invalid kind!");53  return Infos[Kind - FirstTargetFixupKind];54}55 56bool BPFAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,57                                 const MCSubtargetInfo *STI) const {58  if ((Count % 8) != 0)59    return false;60 61  for (uint64_t i = 0; i < Count; i += 8)62    support::endian::write<uint64_t>(OS, 0x15000000, Endian);63 64  return true;65}66 67void BPFAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,68                               const MCValue &Target, uint8_t *Data,69                               uint64_t Value, bool IsResolved) {70  maybeAddReloc(F, Fixup, Target, Value, IsResolved);71  if (Fixup.getKind() == FK_SecRel_8) {72    // The Value is 0 for global variables, and the in-section offset73    // for static variables. Write to the immediate field of the inst.74    assert(Value <= UINT32_MAX);75    support::endian::write<uint32_t>(Data + 4, static_cast<uint32_t>(Value),76                                     Endian);77  } else if (Fixup.getKind() == FK_Data_4 && !Fixup.isPCRel()) {78    support::endian::write<uint32_t>(Data, Value, Endian);79  } else if (Fixup.getKind() == FK_Data_8) {80    support::endian::write<uint64_t>(Data, Value, Endian);81  } else if (Fixup.getKind() == FK_Data_4 && Fixup.isPCRel()) {82    Value = (uint32_t)((Value - 8) / 8);83    if (Endian == llvm::endianness::little) {84      Data[1] = 0x10;85      support::endian::write32le(Data + 4, Value);86    } else {87      Data[1] = 0x1;88      support::endian::write32be(Data + 4, Value);89    }90  } else if (Fixup.getKind() == BPF::FK_BPF_PCRel_4) {91    // The input Value represents the number of bytes.92    Value = (uint32_t)((Value - 8) / 8);93    support::endian::write<uint32_t>(Data + 4, Value, Endian);94  } else {95    assert(Fixup.getKind() == FK_Data_2 && Fixup.isPCRel());96 97    int64_t ByteOff = (int64_t)Value - 8;98    if (ByteOff > INT16_MAX * 8 || ByteOff < INT16_MIN * 8)99      report_fatal_error("Branch target out of insn range");100 101    Value = (uint16_t)((Value - 8) / 8);102    support::endian::write<uint16_t>(Data + 2, Value, Endian);103  }104}105 106std::unique_ptr<MCObjectTargetWriter>107BPFAsmBackend::createObjectTargetWriter() const {108  return createBPFELFObjectWriter(0);109}110 111MCAsmBackend *llvm::createBPFAsmBackend(const Target &T,112                                        const MCSubtargetInfo &STI,113                                        const MCRegisterInfo &MRI,114                                        const MCTargetOptions &) {115  return new BPFAsmBackend(llvm::endianness::little);116}117 118MCAsmBackend *llvm::createBPFbeAsmBackend(const Target &T,119                                          const MCSubtargetInfo &STI,120                                          const MCRegisterInfo &MRI,121                                          const MCTargetOptions &) {122  return new BPFAsmBackend(llvm::endianness::big);123}124