1 //===-- RISCVAsmBackend.h - RISCV Assembler Backend -----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVASMBACKEND_H
10 #define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVASMBACKEND_H
11 
12 #include "MCTargetDesc/RISCVFixupKinds.h"
13 #include "MCTargetDesc/RISCVMCTargetDesc.h"
14 #include "Utils/RISCVBaseInfo.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   const MCTargetOptions &TargetOptions;
30   RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
31 
32 public:
33   RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit,
34                   const MCTargetOptions &Options)
35       : MCAsmBackend(support::little), STI(STI), OSABI(OSABI), Is64Bit(Is64Bit),
36         TargetOptions(Options) {
37     TargetABI = RISCVABI::computeTargetABI(
38         STI.getTargetTriple(), STI.getFeatureBits(), Options.getABIName());
39     RISCVFeatures::validate(STI.getTargetTriple(), STI.getFeatureBits());
40   }
41   ~RISCVAsmBackend() override {}
42 
43   void setForceRelocs() { ForceRelocs = true; }
44 
45   // Returns true if relocations will be forced for shouldForceRelocation by
46   // default. This will be true if relaxation is enabled or had previously
47   // been enabled.
48   bool willForceRelocations() const {
49     return ForceRelocs || STI.getFeatureBits()[RISCV::FeatureRelax];
50   }
51 
52   // Generate diff expression relocations if the relax feature is enabled or had
53   // previously been enabled, otherwise it is safe for the assembler to
54   // calculate these internally.
55   bool requiresDiffExpressionRelocations() const override {
56     return willForceRelocations();
57   }
58 
59   // Return Size with extra Nop Bytes for alignment directive in code section.
60   bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF,
61                                              unsigned &Size) override;
62 
63   // Insert target specific fixup type for alignment directive in code section.
64   bool shouldInsertFixupForCodeAlign(MCAssembler &Asm,
65                                      const MCAsmLayout &Layout,
66                                      MCAlignFragment &AF) override;
67 
68   bool evaluateTargetFixup(const MCAssembler &Asm, const MCAsmLayout &Layout,
69                            const MCFixup &Fixup, const MCFragment *DF,
70                            const MCValue &Target, uint64_t &Value,
71                            bool &WasForced) override;
72 
73   void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
74                   const MCValue &Target, MutableArrayRef<char> Data,
75                   uint64_t Value, bool IsResolved,
76                   const MCSubtargetInfo *STI) const override;
77 
78   std::unique_ptr<MCObjectTargetWriter>
79   createObjectTargetWriter() const override;
80 
81   bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
82                              const MCValue &Target) override;
83 
84   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
85                             const MCRelaxableFragment *DF,
86                             const MCAsmLayout &Layout) const override {
87     llvm_unreachable("Handled by fixupNeedsRelaxationAdvanced");
88   }
89 
90   bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved,
91                                     uint64_t Value,
92                                     const MCRelaxableFragment *DF,
93                                     const MCAsmLayout &Layout,
94                                     const bool WasForced) const override;
95 
96   unsigned getNumFixupKinds() const override {
97     return RISCV::NumTargetFixupKinds;
98   }
99 
100   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
101     const static MCFixupKindInfo Infos[] = {
102       // This table *must* be in the order that the fixup_* kinds are defined in
103       // RISCVFixupKinds.h.
104       //
105       // name                      offset bits  flags
106       { "fixup_riscv_hi20",         12,     20,  0 },
107       { "fixup_riscv_lo12_i",       20,     12,  0 },
108       { "fixup_riscv_lo12_s",        0,     32,  0 },
109       { "fixup_riscv_pcrel_hi20",   12,     20,
110         MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget },
111       { "fixup_riscv_pcrel_lo12_i", 20,     12,
112         MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget },
113       { "fixup_riscv_pcrel_lo12_s",  0,     32,
114         MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget },
115       { "fixup_riscv_got_hi20",     12,     20,  MCFixupKindInfo::FKF_IsPCRel },
116       { "fixup_riscv_tprel_hi20",   12,     20,  0 },
117       { "fixup_riscv_tprel_lo12_i", 20,     12,  0 },
118       { "fixup_riscv_tprel_lo12_s",  0,     32,  0 },
119       { "fixup_riscv_tprel_add",     0,      0,  0 },
120       { "fixup_riscv_tls_got_hi20", 12,     20,  MCFixupKindInfo::FKF_IsPCRel },
121       { "fixup_riscv_tls_gd_hi20",  12,     20,  MCFixupKindInfo::FKF_IsPCRel },
122       { "fixup_riscv_jal",          12,     20,  MCFixupKindInfo::FKF_IsPCRel },
123       { "fixup_riscv_branch",        0,     32,  MCFixupKindInfo::FKF_IsPCRel },
124       { "fixup_riscv_rvc_jump",      2,     11,  MCFixupKindInfo::FKF_IsPCRel },
125       { "fixup_riscv_rvc_branch",    0,     16,  MCFixupKindInfo::FKF_IsPCRel },
126       { "fixup_riscv_call",          0,     64,  MCFixupKindInfo::FKF_IsPCRel },
127       { "fixup_riscv_call_plt",      0,     64,  MCFixupKindInfo::FKF_IsPCRel },
128       { "fixup_riscv_relax",         0,      0,  0 },
129       { "fixup_riscv_align",         0,      0,  0 }
130     };
131     static_assert((array_lengthof(Infos)) == RISCV::NumTargetFixupKinds,
132                   "Not all fixup kinds added to Infos array");
133 
134     if (Kind < FirstTargetFixupKind)
135       return MCAsmBackend::getFixupKindInfo(Kind);
136 
137     assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
138            "Invalid kind!");
139     return Infos[Kind - FirstTargetFixupKind];
140   }
141 
142   bool mayNeedRelaxation(const MCInst &Inst,
143                          const MCSubtargetInfo &STI) const override;
144   unsigned getRelaxedOpcode(unsigned Op) const;
145 
146   void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
147                         MCInst &Res) const override;
148 
149 
150   bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
151 
152   const MCTargetOptions &getTargetOptions() const { return TargetOptions; }
153   RISCVABI::ABI getTargetABI() const { return TargetABI; }
154 };
155 }
156 
157 #endif
158