RISCVAsmBackend.h revision 360784
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
19namespace llvm {
20class MCAssembler;
21class MCObjectTargetWriter;
22class raw_ostream;
23
24class 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
32public:
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