Home | History | Annotate | Download | only in MCTargetDesc
      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/MC/MCAsmBackend.h"
     12 #include "llvm/MC/MCAssembler.h"
     13 #include "llvm/MC/MCDirectives.h"
     14 #include "llvm/MC/MCELFObjectWriter.h"
     15 #include "llvm/MC/MCFixupKindInfo.h"
     16 #include "llvm/MC/MCObjectWriter.h"
     17 #include "llvm/MC/MCSubtargetInfo.h"
     18 #include "llvm/MC/MCExpr.h"
     19 #include "llvm/MC/MCSymbol.h"
     20 #include "llvm/Support/ErrorHandling.h"
     21 #include "llvm/Support/raw_ostream.h"
     22 
     23 using namespace llvm;
     24 
     25 namespace {
     26 class BPFAsmBackend : public MCAsmBackend {
     27 public:
     28   bool IsLittleEndian;
     29 
     30   BPFAsmBackend(bool IsLittleEndian)
     31     : MCAsmBackend(), IsLittleEndian(IsLittleEndian) {}
     32   ~BPFAsmBackend() override {}
     33 
     34   void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
     35                   uint64_t Value, bool IsPCRel) const override;
     36 
     37   MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
     38 
     39   // No instruction requires relaxation
     40   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
     41                             const MCRelaxableFragment *DF,
     42                             const MCAsmLayout &Layout) const override {
     43     return false;
     44   }
     45 
     46   unsigned getNumFixupKinds() const override { return 1; }
     47 
     48   bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
     49 
     50   void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {}
     51 
     52   bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
     53 };
     54 
     55 bool BPFAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
     56   if ((Count % 8) != 0)
     57     return false;
     58 
     59   for (uint64_t i = 0; i < Count; i += 8)
     60     OW->write64(0x15000000);
     61 
     62   return true;
     63 }
     64 
     65 void BPFAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
     66                                unsigned DataSize, uint64_t Value,
     67                                bool IsPCRel) const {
     68 
     69   if (Fixup.getKind() == FK_SecRel_4 || Fixup.getKind() == FK_SecRel_8) {
     70     assert(Value == 0);
     71   } else if (Fixup.getKind() == FK_Data_4 || Fixup.getKind() == FK_Data_8) {
     72     unsigned Size = Fixup.getKind() == FK_Data_4 ? 4 : 8;
     73 
     74     for (unsigned i = 0; i != Size; ++i) {
     75       unsigned Idx = IsLittleEndian ? i : Size - i;
     76       Data[Fixup.getOffset() + Idx] = uint8_t(Value >> (i * 8));
     77     }
     78   } else {
     79     assert(Fixup.getKind() == FK_PCRel_2);
     80     Value = (uint16_t)((Value - 8) / 8);
     81     if (IsLittleEndian) {
     82       Data[Fixup.getOffset() + 2] = Value & 0xFF;
     83       Data[Fixup.getOffset() + 3] = Value >> 8;
     84     } else {
     85       Data[Fixup.getOffset() + 2] = Value >> 8;
     86       Data[Fixup.getOffset() + 3] = Value & 0xFF;
     87     }
     88   }
     89 }
     90 
     91 MCObjectWriter *BPFAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
     92   return createBPFELFObjectWriter(OS, 0, IsLittleEndian);
     93 }
     94 }
     95 
     96 MCAsmBackend *llvm::createBPFAsmBackend(const Target &T,
     97                                         const MCRegisterInfo &MRI,
     98                                         const Triple &TT, StringRef CPU) {
     99   return new BPFAsmBackend(/*IsLittleEndian=*/true);
    100 }
    101 
    102 MCAsmBackend *llvm::createBPFbeAsmBackend(const Target &T,
    103                                           const MCRegisterInfo &MRI,
    104                                           const Triple &TT, StringRef CPU) {
    105   return new BPFAsmBackend(/*IsLittleEndian=*/false);
    106 }
    107