BPFAsmBackend.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "MCTargetDesc/BPFMCTargetDesc.h"
  9. #include "llvm/ADT/StringRef.h"
  10. #include "llvm/MC/MCAsmBackend.h"
  11. #include "llvm/MC/MCAssembler.h"
  12. #include "llvm/MC/MCContext.h"
  13. #include "llvm/MC/MCFixup.h"
  14. #include "llvm/MC/MCObjectWriter.h"
  15. #include "llvm/Support/EndianStream.h"
  16. #include <cassert>
  17. #include <cstdint>
  18. using namespace llvm;
  19. namespace {
  20. class BPFAsmBackend : public MCAsmBackend {
  21. public:
  22. BPFAsmBackend(support::endianness Endian) : MCAsmBackend(Endian) {}
  23. ~BPFAsmBackend() override = default;
  24. void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
  25. const MCValue &Target, MutableArrayRef<char> Data,
  26. uint64_t Value, bool IsResolved,
  27. const MCSubtargetInfo *STI) const override;
  28. std::unique_ptr<MCObjectTargetWriter>
  29. createObjectTargetWriter() const override;
  30. // No instruction requires relaxation
  31. bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
  32. const MCRelaxableFragment *DF,
  33. const MCAsmLayout &Layout) const override {
  34. return false;
  35. }
  36. unsigned getNumFixupKinds() const override { return 1; }
  37. bool writeNopData(raw_ostream &OS, uint64_t Count,
  38. const MCSubtargetInfo *STI) const override;
  39. };
  40. } // end anonymous namespace
  41. bool BPFAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
  42. const MCSubtargetInfo *STI) const {
  43. if ((Count % 8) != 0)
  44. return false;
  45. for (uint64_t i = 0; i < Count; i += 8)
  46. support::endian::write<uint64_t>(OS, 0x15000000, Endian);
  47. return true;
  48. }
  49. void BPFAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
  50. const MCValue &Target,
  51. MutableArrayRef<char> Data, uint64_t Value,
  52. bool IsResolved,
  53. const MCSubtargetInfo *STI) const {
  54. if (Fixup.getKind() == FK_SecRel_8) {
  55. // The Value is 0 for global variables, and the in-section offset
  56. // for static variables. Write to the immediate field of the inst.
  57. assert(Value <= UINT32_MAX);
  58. support::endian::write<uint32_t>(&Data[Fixup.getOffset() + 4],
  59. static_cast<uint32_t>(Value),
  60. Endian);
  61. } else if (Fixup.getKind() == FK_Data_4) {
  62. support::endian::write<uint32_t>(&Data[Fixup.getOffset()], Value, Endian);
  63. } else if (Fixup.getKind() == FK_Data_8) {
  64. support::endian::write<uint64_t>(&Data[Fixup.getOffset()], Value, Endian);
  65. } else if (Fixup.getKind() == FK_PCRel_4) {
  66. Value = (uint32_t)((Value - 8) / 8);
  67. if (Endian == support::little) {
  68. Data[Fixup.getOffset() + 1] = 0x10;
  69. support::endian::write32le(&Data[Fixup.getOffset() + 4], Value);
  70. } else {
  71. Data[Fixup.getOffset() + 1] = 0x1;
  72. support::endian::write32be(&Data[Fixup.getOffset() + 4], Value);
  73. }
  74. } else {
  75. assert(Fixup.getKind() == FK_PCRel_2);
  76. int64_t ByteOff = (int64_t)Value - 8;
  77. if (ByteOff > INT16_MAX * 8 || ByteOff < INT16_MIN * 8)
  78. report_fatal_error("Branch target out of insn range");
  79. Value = (uint16_t)((Value - 8) / 8);
  80. support::endian::write<uint16_t>(&Data[Fixup.getOffset() + 2], Value,
  81. Endian);
  82. }
  83. }
  84. std::unique_ptr<MCObjectTargetWriter>
  85. BPFAsmBackend::createObjectTargetWriter() const {
  86. return createBPFELFObjectWriter(0);
  87. }
  88. MCAsmBackend *llvm::createBPFAsmBackend(const Target &T,
  89. const MCSubtargetInfo &STI,
  90. const MCRegisterInfo &MRI,
  91. const MCTargetOptions &) {
  92. return new BPFAsmBackend(support::little);
  93. }
  94. MCAsmBackend *llvm::createBPFbeAsmBackend(const Target &T,
  95. const MCSubtargetInfo &STI,
  96. const MCRegisterInfo &MRI,
  97. const MCTargetOptions &) {
  98. return new BPFAsmBackend(support::big);
  99. }