1 //===-- BPFAsmBackend.cpp - BPF Assembler Backend -------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "MCTargetDesc/BPFMCTargetDesc.h" 11 #include "llvm/ADT/StringRef.h" 12 #include "llvm/MC/MCAsmBackend.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 19 using namespace llvm; 20 21 namespace { 22 23 class BPFAsmBackend : public MCAsmBackend { 24 public: 25 BPFAsmBackend(support::endianness Endian) : MCAsmBackend(Endian) {} 26 ~BPFAsmBackend() override = default; 27 28 void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, 29 const MCValue &Target, MutableArrayRef<char> Data, 30 uint64_t Value, bool IsResolved, 31 const MCSubtargetInfo *STI) const override; 32 33 std::unique_ptr<MCObjectTargetWriter> 34 createObjectTargetWriter() const override; 35 36 // No instruction requires relaxation 37 bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, 38 const MCRelaxableFragment *DF, 39 const MCAsmLayout &Layout) const override { 40 return false; 41 } 42 43 unsigned getNumFixupKinds() const override { return 1; } 44 45 bool mayNeedRelaxation(const MCInst &Inst, 46 const MCSubtargetInfo &STI) const override { 47 return false; 48 } 49 50 void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, 51 MCInst &Res) const override {} 52 53 bool writeNopData(raw_ostream &OS, uint64_t Count) const override; 54 }; 55 56 } // end anonymous namespace 57 58 bool BPFAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { 59 if ((Count % 8) != 0) 60 return false; 61 62 for (uint64_t i = 0; i < Count; i += 8) 63 support::endian::write<uint64_t>(OS, 0x15000000, Endian); 64 65 return true; 66 } 67 68 void BPFAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, 69 const MCValue &Target, 70 MutableArrayRef<char> Data, uint64_t Value, 71 bool IsResolved, 72 const MCSubtargetInfo *STI) const { 73 if (Fixup.getKind() == FK_SecRel_4 || Fixup.getKind() == FK_SecRel_8) { 74 assert(Value == 0); 75 } else if (Fixup.getKind() == FK_Data_4) { 76 support::endian::write<uint32_t>(&Data[Fixup.getOffset()], Value, Endian); 77 } else if (Fixup.getKind() == FK_Data_8) { 78 support::endian::write<uint64_t>(&Data[Fixup.getOffset()], Value, Endian); 79 } else if (Fixup.getKind() == FK_PCRel_4) { 80 Value = (uint32_t)((Value - 8) / 8); 81 if (Endian == support::little) { 82 Data[Fixup.getOffset() + 1] = 0x10; 83 support::endian::write32le(&Data[Fixup.getOffset() + 4], Value); 84 } else { 85 Data[Fixup.getOffset() + 1] = 0x1; 86 support::endian::write32be(&Data[Fixup.getOffset() + 4], Value); 87 } 88 } else { 89 assert(Fixup.getKind() == FK_PCRel_2); 90 Value = (uint16_t)((Value - 8) / 8); 91 support::endian::write<uint16_t>(&Data[Fixup.getOffset() + 2], Value, 92 Endian); 93 } 94 } 95 96 std::unique_ptr<MCObjectTargetWriter> 97 BPFAsmBackend::createObjectTargetWriter() const { 98 return createBPFELFObjectWriter(0); 99 } 100 101 MCAsmBackend *llvm::createBPFAsmBackend(const Target &T, 102 const MCSubtargetInfo &STI, 103 const MCRegisterInfo &MRI, 104 const MCTargetOptions &) { 105 return new BPFAsmBackend(support::little); 106 } 107 108 MCAsmBackend *llvm::createBPFbeAsmBackend(const Target &T, 109 const MCSubtargetInfo &STI, 110 const MCRegisterInfo &MRI, 111 const MCTargetOptions &) { 112 return new BPFAsmBackend(support::big); 113 } 114