1 //===-- RISCVAsmBackend.h - RISCV 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 #ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVASMBACKEND_H
11 #define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVASMBACKEND_H
12 
13 #include "MCTargetDesc/RISCVFixupKinds.h"
14 #include "MCTargetDesc/RISCVMCTargetDesc.h"
15 #include "llvm/MC/MCAsmBackend.h"
16 #include "llvm/MC/MCFixupKindInfo.h"
17 #include "llvm/MC/MCSubtargetInfo.h"
18 
19 namespace llvm {
20 class MCAssembler;
21 class MCObjectTargetWriter;
22 class raw_ostream;
23 
24 class RISCVAsmBackend : public MCAsmBackend {
25   const MCSubtargetInfo &STI;
26   uint8_t OSABI;
27   bool Is64Bit;
28   bool ForceRelocs = false;
29 
30 public:
RISCVAsmBackend(const MCSubtargetInfo & STI,uint8_t OSABI,bool Is64Bit)31   RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit)
32       : MCAsmBackend(support::little), STI(STI), OSABI(OSABI),
33         Is64Bit(Is64Bit) {}
~RISCVAsmBackend()34   ~RISCVAsmBackend() override {}
35 
setForceRelocs()36   void setForceRelocs() { ForceRelocs = true; }
37 
38   // Generate diff expression relocations if the relax feature is enabled or had
39   // previously been enabled, otherwise it is safe for the assembler to
40   // calculate these internally.
requiresDiffExpressionRelocations()41   bool requiresDiffExpressionRelocations() const override {
42     return STI.getFeatureBits()[RISCV::FeatureRelax] || ForceRelocs;
43   }
44   void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
45                   const MCValue &Target, MutableArrayRef<char> Data,
46                   uint64_t Value, bool IsResolved,
47                   const MCSubtargetInfo *STI) const override;
48 
49   std::unique_ptr<MCObjectTargetWriter>
50   createObjectTargetWriter() const override;
51 
52   bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
53                              const MCValue &Target) override;
54 
fixupNeedsRelaxation(const MCFixup & Fixup,uint64_t Value,const MCRelaxableFragment * DF,const MCAsmLayout & Layout)55   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
56                             const MCRelaxableFragment *DF,
57                             const MCAsmLayout &Layout) const override {
58     llvm_unreachable("Handled by fixupNeedsRelaxationAdvanced");
59   }
60 
61   bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved,
62                                     uint64_t Value,
63                                     const MCRelaxableFragment *DF,
64                                     const MCAsmLayout &Layout,
65                                     const bool WasForced) const override;
66 
getNumFixupKinds()67   unsigned getNumFixupKinds() const override {
68     return RISCV::NumTargetFixupKinds;
69   }
70 
getFixupKindInfo(MCFixupKind Kind)71   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
72     const static MCFixupKindInfo Infos[] = {
73       // This table *must* be in the order that the fixup_* kinds are defined in
74       // RISCVFixupKinds.h.
75       //
76       // name                      offset bits  flags
77       { "fixup_riscv_hi20",         12,     20,  0 },
78       { "fixup_riscv_lo12_i",       20,     12,  0 },
79       { "fixup_riscv_lo12_s",        0,     32,  0 },
80       { "fixup_riscv_pcrel_hi20",   12,     20,  MCFixupKindInfo::FKF_IsPCRel },
81       { "fixup_riscv_pcrel_lo12_i", 20,     12,  MCFixupKindInfo::FKF_IsPCRel },
82       { "fixup_riscv_pcrel_lo12_s",  0,     32,  MCFixupKindInfo::FKF_IsPCRel },
83       { "fixup_riscv_jal",          12,     20,  MCFixupKindInfo::FKF_IsPCRel },
84       { "fixup_riscv_branch",        0,     32,  MCFixupKindInfo::FKF_IsPCRel },
85       { "fixup_riscv_rvc_jump",      2,     11,  MCFixupKindInfo::FKF_IsPCRel },
86       { "fixup_riscv_rvc_branch",    0,     16,  MCFixupKindInfo::FKF_IsPCRel },
87       { "fixup_riscv_call",          0,     64,  MCFixupKindInfo::FKF_IsPCRel },
88       { "fixup_riscv_relax",         0,      0,  0 }
89     };
90     static_assert((array_lengthof(Infos)) == RISCV::NumTargetFixupKinds,
91                   "Not all fixup kinds added to Infos array");
92 
93     if (Kind < FirstTargetFixupKind)
94       return MCAsmBackend::getFixupKindInfo(Kind);
95 
96     assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
97            "Invalid kind!");
98     return Infos[Kind - FirstTargetFixupKind];
99   }
100 
101   bool mayNeedRelaxation(const MCInst &Inst,
102                          const MCSubtargetInfo &STI) const override;
103   unsigned getRelaxedOpcode(unsigned Op) const;
104 
105   void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
106                         MCInst &Res) const override;
107 
108 
109   bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
110 };
111 }
112 
113 #endif
114