1*9880d681SAndroid Build Coastguard Worker //===-- BPFAsmBackend.cpp - BPF Assembler Backend -------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/BPFMCTargetDesc.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmBackend.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAssembler.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCDirectives.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCELFObjectWriter.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCFixupKindInfo.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCObjectWriter.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbol.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
22*9880d681SAndroid Build Coastguard Worker
23*9880d681SAndroid Build Coastguard Worker using namespace llvm;
24*9880d681SAndroid Build Coastguard Worker
25*9880d681SAndroid Build Coastguard Worker namespace {
26*9880d681SAndroid Build Coastguard Worker class BPFAsmBackend : public MCAsmBackend {
27*9880d681SAndroid Build Coastguard Worker public:
28*9880d681SAndroid Build Coastguard Worker bool IsLittleEndian;
29*9880d681SAndroid Build Coastguard Worker
BPFAsmBackend(bool IsLittleEndian)30*9880d681SAndroid Build Coastguard Worker BPFAsmBackend(bool IsLittleEndian)
31*9880d681SAndroid Build Coastguard Worker : MCAsmBackend(), IsLittleEndian(IsLittleEndian) {}
~BPFAsmBackend()32*9880d681SAndroid Build Coastguard Worker ~BPFAsmBackend() override {}
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
35*9880d681SAndroid Build Coastguard Worker uint64_t Value, bool IsPCRel) const override;
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker // No instruction requires relaxation
fixupNeedsRelaxation(const MCFixup & Fixup,uint64_t Value,const MCRelaxableFragment * DF,const MCAsmLayout & Layout) const40*9880d681SAndroid Build Coastguard Worker bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
41*9880d681SAndroid Build Coastguard Worker const MCRelaxableFragment *DF,
42*9880d681SAndroid Build Coastguard Worker const MCAsmLayout &Layout) const override {
43*9880d681SAndroid Build Coastguard Worker return false;
44*9880d681SAndroid Build Coastguard Worker }
45*9880d681SAndroid Build Coastguard Worker
getNumFixupKinds() const46*9880d681SAndroid Build Coastguard Worker unsigned getNumFixupKinds() const override { return 1; }
47*9880d681SAndroid Build Coastguard Worker
mayNeedRelaxation(const MCInst & Inst) const48*9880d681SAndroid Build Coastguard Worker bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
49*9880d681SAndroid Build Coastguard Worker
relaxInstruction(const MCInst & Inst,const MCSubtargetInfo & STI,MCInst & Res) const50*9880d681SAndroid Build Coastguard Worker void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
51*9880d681SAndroid Build Coastguard Worker MCInst &Res) const override {}
52*9880d681SAndroid Build Coastguard Worker
53*9880d681SAndroid Build Coastguard Worker bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
54*9880d681SAndroid Build Coastguard Worker };
55*9880d681SAndroid Build Coastguard Worker
writeNopData(uint64_t Count,MCObjectWriter * OW) const56*9880d681SAndroid Build Coastguard Worker bool BPFAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
57*9880d681SAndroid Build Coastguard Worker if ((Count % 8) != 0)
58*9880d681SAndroid Build Coastguard Worker return false;
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker for (uint64_t i = 0; i < Count; i += 8)
61*9880d681SAndroid Build Coastguard Worker OW->write64(0x15000000);
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Worker return true;
64*9880d681SAndroid Build Coastguard Worker }
65*9880d681SAndroid Build Coastguard Worker
applyFixup(const MCFixup & Fixup,char * Data,unsigned DataSize,uint64_t Value,bool IsPCRel) const66*9880d681SAndroid Build Coastguard Worker void BPFAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
67*9880d681SAndroid Build Coastguard Worker unsigned DataSize, uint64_t Value,
68*9880d681SAndroid Build Coastguard Worker bool IsPCRel) const {
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker if (Fixup.getKind() == FK_SecRel_4 || Fixup.getKind() == FK_SecRel_8) {
71*9880d681SAndroid Build Coastguard Worker assert(Value == 0);
72*9880d681SAndroid Build Coastguard Worker } else if (Fixup.getKind() == FK_Data_4 || Fixup.getKind() == FK_Data_8) {
73*9880d681SAndroid Build Coastguard Worker unsigned Size = Fixup.getKind() == FK_Data_4 ? 4 : 8;
74*9880d681SAndroid Build Coastguard Worker
75*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i != Size; ++i) {
76*9880d681SAndroid Build Coastguard Worker unsigned Idx = IsLittleEndian ? i : Size - i;
77*9880d681SAndroid Build Coastguard Worker Data[Fixup.getOffset() + Idx] = uint8_t(Value >> (i * 8));
78*9880d681SAndroid Build Coastguard Worker }
79*9880d681SAndroid Build Coastguard Worker } else {
80*9880d681SAndroid Build Coastguard Worker assert(Fixup.getKind() == FK_PCRel_2);
81*9880d681SAndroid Build Coastguard Worker Value = (uint16_t)((Value - 8) / 8);
82*9880d681SAndroid Build Coastguard Worker if (IsLittleEndian) {
83*9880d681SAndroid Build Coastguard Worker Data[Fixup.getOffset() + 2] = Value & 0xFF;
84*9880d681SAndroid Build Coastguard Worker Data[Fixup.getOffset() + 3] = Value >> 8;
85*9880d681SAndroid Build Coastguard Worker } else {
86*9880d681SAndroid Build Coastguard Worker Data[Fixup.getOffset() + 2] = Value >> 8;
87*9880d681SAndroid Build Coastguard Worker Data[Fixup.getOffset() + 3] = Value & 0xFF;
88*9880d681SAndroid Build Coastguard Worker }
89*9880d681SAndroid Build Coastguard Worker }
90*9880d681SAndroid Build Coastguard Worker }
91*9880d681SAndroid Build Coastguard Worker
createObjectWriter(raw_pwrite_stream & OS) const92*9880d681SAndroid Build Coastguard Worker MCObjectWriter *BPFAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
93*9880d681SAndroid Build Coastguard Worker return createBPFELFObjectWriter(OS, 0, IsLittleEndian);
94*9880d681SAndroid Build Coastguard Worker }
95*9880d681SAndroid Build Coastguard Worker }
96*9880d681SAndroid Build Coastguard Worker
createBPFAsmBackend(const Target & T,const MCRegisterInfo & MRI,const Triple & TT,StringRef CPU)97*9880d681SAndroid Build Coastguard Worker MCAsmBackend *llvm::createBPFAsmBackend(const Target &T,
98*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo &MRI,
99*9880d681SAndroid Build Coastguard Worker const Triple &TT, StringRef CPU) {
100*9880d681SAndroid Build Coastguard Worker return new BPFAsmBackend(/*IsLittleEndian=*/true);
101*9880d681SAndroid Build Coastguard Worker }
102*9880d681SAndroid Build Coastguard Worker
createBPFbeAsmBackend(const Target & T,const MCRegisterInfo & MRI,const Triple & TT,StringRef CPU)103*9880d681SAndroid Build Coastguard Worker MCAsmBackend *llvm::createBPFbeAsmBackend(const Target &T,
104*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo &MRI,
105*9880d681SAndroid Build Coastguard Worker const Triple &TT, StringRef CPU) {
106*9880d681SAndroid Build Coastguard Worker return new BPFAsmBackend(/*IsLittleEndian=*/false);
107*9880d681SAndroid Build Coastguard Worker }
108