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, const MCSubtargetInfo &STI,
     51                         MCInst &Res) const override {}
     52 
     53   bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
     54 };
     55 
     56 bool BPFAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
     57   if ((Count % 8) != 0)
     58     return false;
     59 
     60   for (uint64_t i = 0; i < Count; i += 8)
     61     OW->write64(0x15000000);
     62 
     63   return true;
     64 }
     65 
     66 void BPFAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
     67                                unsigned DataSize, uint64_t Value,
     68                                bool IsPCRel) const {
     69 
     70   if (Fixup.getKind() == FK_SecRel_4 || Fixup.getKind() == FK_SecRel_8) {
     71     assert(Value == 0);
     72   } else if (Fixup.getKind() == FK_Data_4 || Fixup.getKind() == FK_Data_8) {
     73     unsigned Size = Fixup.getKind() == FK_Data_4 ? 4 : 8;
     74 
     75     for (unsigned i = 0; i != Size; ++i) {
     76       unsigned Idx = IsLittleEndian ? i : Size - i;
     77       Data[Fixup.getOffset() + Idx] = uint8_t(Value >> (i * 8));
     78     }
     79   } else {
     80     assert(Fixup.getKind() == FK_PCRel_2);
     81     Value = (uint16_t)((Value - 8) / 8);
     82     if (IsLittleEndian) {
     83       Data[Fixup.getOffset() + 2] = Value & 0xFF;
     84       Data[Fixup.getOffset() + 3] = Value >> 8;
     85     } else {
     86       Data[Fixup.getOffset() + 2] = Value >> 8;
     87       Data[Fixup.getOffset() + 3] = Value & 0xFF;
     88     }
     89   }
     90 }
     91 
     92 MCObjectWriter *BPFAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
     93   return createBPFELFObjectWriter(OS, 0, IsLittleEndian);
     94 }
     95 }
     96 
     97 MCAsmBackend *llvm::createBPFAsmBackend(const Target &T,
     98                                         const MCRegisterInfo &MRI,
     99                                         const Triple &TT, StringRef CPU) {
    100   return new BPFAsmBackend(/*IsLittleEndian=*/true);
    101 }
    102 
    103 MCAsmBackend *llvm::createBPFbeAsmBackend(const Target &T,
    104                                           const MCRegisterInfo &MRI,
    105                                           const Triple &TT, StringRef CPU) {
    106   return new BPFAsmBackend(/*IsLittleEndian=*/false);
    107 }
    108