Coverage Report

Created: 2026-03-31 08:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/keystone/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
Line
Count
Source
1
//===-- HexagonAsmBackend.cpp - Hexagon 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 "Hexagon.h"
11
#include "HexagonFixupKinds.h"
12
#include "HexagonMCTargetDesc.h"
13
#include "MCTargetDesc/HexagonBaseInfo.h"
14
#include "MCTargetDesc/HexagonMCInstrInfo.h"
15
#include "llvm/MC/MCObjectWriter.h"
16
#include "llvm/MC/MCAsmBackend.h"
17
#include "llvm/MC/MCAsmLayout.h"
18
#include "llvm/MC/MCAssembler.h"
19
#include "llvm/MC/MCContext.h"
20
#include "llvm/MC/MCELFObjectWriter.h"
21
#include "llvm/MC/MCFixupKindInfo.h"
22
#include "llvm/MC/MCInstrInfo.h"
23
#include "llvm/Support/Debug.h"
24
#include "llvm/Support/TargetRegistry.h"
25
26
using namespace llvm_ks;
27
using namespace Hexagon;
28
29
#define DEBUG_TYPE "hexagon-asm-backend"
30
31
namespace {
32
33
class HexagonAsmBackend : public MCAsmBackend {
34
  uint8_t OSABI;
35
  StringRef CPU;
36
  mutable uint64_t relaxedCnt;
37
  std::unique_ptr <MCInstrInfo> MCII;
38
  std::unique_ptr <MCInst *> RelaxTarget;
39
  MCInst * Extender;
40
public:
41
  HexagonAsmBackend(Target const &T,  uint8_t OSABI, StringRef CPU) :
42
4.28k
    OSABI(OSABI), MCII (T.createMCInstrInfo()), RelaxTarget(new MCInst *),
43
4.28k
    Extender(nullptr) {}
44
45
4.28k
  MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
46
4.28k
    return createHexagonELFObjectWriter(OS, OSABI, CPU);
47
4.28k
  }
48
49
159
  void setExtender(MCContext &Context) const {
50
159
    if (Extender == nullptr)
51
159
      const_cast<HexagonAsmBackend *>(this)->Extender = new (Context) MCInst;
52
159
  }
53
54
159
  MCInst *takeExtender() const {
55
159
    assert(Extender != nullptr);
56
159
    MCInst * Result = Extender;
57
159
    const_cast<HexagonAsmBackend *>(this)->Extender = nullptr;
58
159
    return Result;
59
159
  }
60
61
2.68k
  unsigned getNumFixupKinds() const override {
62
2.68k
    return Hexagon::NumTargetFixupKinds;
63
2.68k
  }
64
65
32.6k
  const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
66
32.6k
    const static MCFixupKindInfo Infos[Hexagon::NumTargetFixupKinds] = {
67
        // This table *must* be in same the order of fixup_* kinds in
68
        // HexagonFixupKinds.h.
69
        //
70
        // namei                          offset  bits    flags
71
32.6k
        {"fixup_Hexagon_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
72
32.6k
        {"fixup_Hexagon_B15_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
73
32.6k
        {"fixup_Hexagon_B7_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
74
32.6k
        {"fixup_Hexagon_LO16", 0, 32, 0},
75
32.6k
        {"fixup_Hexagon_HI16", 0, 32, 0},
76
32.6k
        {"fixup_Hexagon_32", 0, 32, 0},
77
32.6k
        {"fixup_Hexagon_16", 0, 32, 0},
78
32.6k
        {"fixup_Hexagon_8", 0, 32, 0},
79
32.6k
        {"fixup_Hexagon_GPREL16_0", 0, 32, 0},
80
32.6k
        {"fixup_Hexagon_GPREL16_1", 0, 32, 0},
81
32.6k
        {"fixup_Hexagon_GPREL16_2", 0, 32, 0},
82
32.6k
        {"fixup_Hexagon_GPREL16_3", 0, 32, 0},
83
32.6k
        {"fixup_Hexagon_HL16", 0, 32, 0},
84
32.6k
        {"fixup_Hexagon_B13_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
85
32.6k
        {"fixup_Hexagon_B9_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
86
32.6k
        {"fixup_Hexagon_B32_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
87
32.6k
        {"fixup_Hexagon_32_6_X", 0, 32, 0},
88
32.6k
        {"fixup_Hexagon_B22_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
89
32.6k
        {"fixup_Hexagon_B15_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
90
32.6k
        {"fixup_Hexagon_B13_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
91
32.6k
        {"fixup_Hexagon_B9_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
92
32.6k
        {"fixup_Hexagon_B7_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
93
32.6k
        {"fixup_Hexagon_16_X", 0, 32, 0},
94
32.6k
        {"fixup_Hexagon_12_X", 0, 32, 0},
95
32.6k
        {"fixup_Hexagon_11_X", 0, 32, 0},
96
32.6k
        {"fixup_Hexagon_10_X", 0, 32, 0},
97
32.6k
        {"fixup_Hexagon_9_X", 0, 32, 0},
98
32.6k
        {"fixup_Hexagon_8_X", 0, 32, 0},
99
32.6k
        {"fixup_Hexagon_7_X", 0, 32, 0},
100
32.6k
        {"fixup_Hexagon_6_X", 0, 32, 0},
101
32.6k
        {"fixup_Hexagon_32_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
102
32.6k
        {"fixup_Hexagon_COPY", 0, 32, 0},
103
32.6k
        {"fixup_Hexagon_GLOB_DAT", 0, 32, 0},
104
32.6k
        {"fixup_Hexagon_JMP_SLOT", 0, 32, 0},
105
32.6k
        {"fixup_Hexagon_RELATIVE", 0, 32, 0},
106
32.6k
        {"fixup_Hexagon_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
107
32.6k
        {"fixup_Hexagon_GOTREL_LO16", 0, 32, 0},
108
32.6k
        {"fixup_Hexagon_GOTREL_HI16", 0, 32, 0},
109
32.6k
        {"fixup_Hexagon_GOTREL_32", 0, 32, 0},
110
32.6k
        {"fixup_Hexagon_GOT_LO16", 0, 32, 0},
111
32.6k
        {"fixup_Hexagon_GOT_HI16", 0, 32, 0},
112
32.6k
        {"fixup_Hexagon_GOT_32", 0, 32, 0},
113
32.6k
        {"fixup_Hexagon_GOT_16", 0, 32, 0},
114
32.6k
        {"fixup_Hexagon_DTPMOD_32", 0, 32, 0},
115
32.6k
        {"fixup_Hexagon_DTPREL_LO16", 0, 32, 0},
116
32.6k
        {"fixup_Hexagon_DTPREL_HI16", 0, 32, 0},
117
32.6k
        {"fixup_Hexagon_DTPREL_32", 0, 32, 0},
118
32.6k
        {"fixup_Hexagon_DTPREL_16", 0, 32, 0},
119
32.6k
        {"fixup_Hexagon_GD_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
120
32.6k
        {"fixup_Hexagon_LD_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
121
32.6k
        {"fixup_Hexagon_GD_GOT_LO16", 0, 32, 0},
122
32.6k
        {"fixup_Hexagon_GD_GOT_HI16", 0, 32, 0},
123
32.6k
        {"fixup_Hexagon_GD_GOT_32", 0, 32, 0},
124
32.6k
        {"fixup_Hexagon_GD_GOT_16", 0, 32, 0},
125
32.6k
        {"fixup_Hexagon_LD_GOT_LO16", 0, 32, 0},
126
32.6k
        {"fixup_Hexagon_LD_GOT_HI16", 0, 32, 0},
127
32.6k
        {"fixup_Hexagon_LD_GOT_32", 0, 32, 0},
128
32.6k
        {"fixup_Hexagon_LD_GOT_16", 0, 32, 0},
129
32.6k
        {"fixup_Hexagon_IE_LO16", 0, 32, 0},
130
32.6k
        {"fixup_Hexagon_IE_HI16", 0, 32, 0},
131
32.6k
        {"fixup_Hexagon_IE_32", 0, 32, 0},
132
32.6k
        {"fixup_Hexagon_IE_16", 0, 32, 0},
133
32.6k
        {"fixup_Hexagon_IE_GOT_LO16", 0, 32, 0},
134
32.6k
        {"fixup_Hexagon_IE_GOT_HI16", 0, 32, 0},
135
32.6k
        {"fixup_Hexagon_IE_GOT_32", 0, 32, 0},
136
32.6k
        {"fixup_Hexagon_IE_GOT_16", 0, 32, 0},
137
32.6k
        {"fixup_Hexagon_TPREL_LO16", 0, 32, 0},
138
32.6k
        {"fixup_Hexagon_TPREL_HI16", 0, 32, 0},
139
32.6k
        {"fixup_Hexagon_TPREL_32", 0, 32, 0},
140
32.6k
        {"fixup_Hexagon_TPREL_16", 0, 32, 0},
141
32.6k
        {"fixup_Hexagon_6_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
142
32.6k
        {"fixup_Hexagon_GOTREL_32_6_X", 0, 32, 0},
143
32.6k
        {"fixup_Hexagon_GOTREL_16_X", 0, 32, 0},
144
32.6k
        {"fixup_Hexagon_GOTREL_11_X", 0, 32, 0},
145
32.6k
        {"fixup_Hexagon_GOT_32_6_X", 0, 32, 0},
146
32.6k
        {"fixup_Hexagon_GOT_16_X", 0, 32, 0},
147
32.6k
        {"fixup_Hexagon_GOT_11_X", 0, 32, 0},
148
32.6k
        {"fixup_Hexagon_DTPREL_32_6_X", 0, 32, 0},
149
32.6k
        {"fixup_Hexagon_DTPREL_16_X", 0, 32, 0},
150
32.6k
        {"fixup_Hexagon_DTPREL_11_X", 0, 32, 0},
151
32.6k
        {"fixup_Hexagon_GD_GOT_32_6_X", 0, 32, 0},
152
32.6k
        {"fixup_Hexagon_GD_GOT_16_X", 0, 32, 0},
153
32.6k
        {"fixup_Hexagon_GD_GOT_11_X", 0, 32, 0},
154
32.6k
        {"fixup_Hexagon_LD_GOT_32_6_X", 0, 32, 0},
155
32.6k
        {"fixup_Hexagon_LD_GOT_16_X", 0, 32, 0},
156
32.6k
        {"fixup_Hexagon_LD_GOT_11_X", 0, 32, 0},
157
32.6k
        {"fixup_Hexagon_IE_32_6_X", 0, 32, 0},
158
32.6k
        {"fixup_Hexagon_IE_16_X", 0, 32, 0},
159
32.6k
        {"fixup_Hexagon_IE_GOT_32_6_X", 0, 32, 0},
160
32.6k
        {"fixup_Hexagon_IE_GOT_16_X", 0, 32, 0},
161
32.6k
        {"fixup_Hexagon_IE_GOT_11_X", 0, 32, 0},
162
32.6k
        {"fixup_Hexagon_TPREL_32_6_X", 0, 32, 0},
163
32.6k
        {"fixup_Hexagon_TPREL_16_X", 0, 32, 0},
164
32.6k
        {"fixup_Hexagon_TPREL_11_X", 0, 32, 0}};
165
166
32.6k
    if (Kind < FirstTargetFixupKind) {
167
29.9k
      return MCAsmBackend::getFixupKindInfo(Kind);
168
29.9k
    }
169
170
32.6k
    assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
171
2.68k
           "Invalid kind!");
172
2.68k
    return Infos[Kind - FirstTargetFixupKind];
173
2.68k
  }
174
175
  void applyFixup(MCFixup const & /*Fixup*/, char * /*Data*/,
176
                  unsigned /*DataSize*/, uint64_t /*Value*/,
177
10.3k
                  bool /*IsPCRel*/, unsigned int &KsError) const override {
178
10.3k
    return;
179
10.3k
  }
180
181
5.41k
  bool isInstRelaxable(MCInst const &HMI) const {
182
5.41k
    const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(*MCII, HMI);
183
5.41k
    bool Relaxable = false;
184
    // Branches and loop-setup insns are handled as necessary by relaxation.
185
5.41k
    if (llvm_ks::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeJ ||
186
2.04k
        (llvm_ks::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeNV &&
187
0
         MCID.isBranch()) ||
188
2.04k
        (llvm_ks::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeCR &&
189
80
         HMI.getOpcode() != Hexagon::C4_addipc))
190
3.45k
      if (HexagonMCInstrInfo::isExtendable(*MCII, HMI))
191
3.37k
        Relaxable = true;
192
193
5.41k
    return Relaxable;
194
5.41k
  }
195
196
  /// MayNeedRelaxation - Check whether the given instruction may need
197
  /// relaxation.
198
  ///
199
  /// \param Inst - The instruction to test.
200
5.16k
  bool mayNeedRelaxation(MCInst const &Inst) const override {
201
5.16k
    assert(HexagonMCInstrInfo::isBundle(Inst));
202
5.16k
    bool PreviousIsExtender = false;
203
6.04k
    for (auto const &I : HexagonMCInstrInfo::bundleInstructions(Inst)) {
204
6.04k
      auto const &Inst = *I.getInst();
205
6.04k
      if (!PreviousIsExtender) {
206
5.17k
        if (isInstRelaxable(Inst))
207
3.13k
          return true;
208
5.17k
      }
209
2.91k
      PreviousIsExtender = HexagonMCInstrInfo::isImmext(Inst);
210
2.91k
    }
211
2.02k
    return false;
212
5.16k
  }
213
214
  /// fixupNeedsRelaxation - Target specific predicate for whether a given
215
  /// fixup requires the associated instruction to be relaxed.
216
  bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved,
217
                                    uint64_t Value,
218
                                    const MCRelaxableFragment *DF,
219
476
                                    const MCAsmLayout &Layout) const override {
220
476
    MCInst const &MCB = DF->getInst();
221
476
    assert(HexagonMCInstrInfo::isBundle(MCB));
222
223
476
    *RelaxTarget = nullptr;
224
476
    MCInst &MCI = const_cast<MCInst &>(HexagonMCInstrInfo::instruction(
225
476
        MCB, Fixup.getOffset() / HEXAGON_INSTR_SIZE));
226
    // If we cannot resolve the fixup value, it requires relaxation.
227
476
    if (!Resolved) {
228
231
      switch ((unsigned)Fixup.getKind()) {
229
227
      case fixup_Hexagon_B22_PCREL:
230
      // GetFixupCount assumes B22 won't relax
231
      // Fallthrough
232
227
      default:
233
227
        return false;
234
0
        break;
235
0
      case fixup_Hexagon_B13_PCREL:
236
2
      case fixup_Hexagon_B15_PCREL:
237
2
      case fixup_Hexagon_B9_PCREL:
238
4
      case fixup_Hexagon_B7_PCREL: {
239
4
        if (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_SIZE) {
240
4
          ++relaxedCnt;
241
4
          *RelaxTarget = &MCI;
242
4
          setExtender(Layout.getAssembler().getContext());
243
4
          return true;
244
4
        } else {
245
0
          return false;
246
0
        }
247
0
        break;
248
4
      }
249
231
      }
250
231
    }
251
245
    bool Relaxable = isInstRelaxable(MCI);
252
245
    if (Relaxable == false)
253
0
      return false;
254
255
245
    MCFixupKind Kind = Fixup.getKind();
256
245
    int64_t sValue = Value;
257
245
    int64_t maxValue;
258
259
245
    switch ((unsigned)Kind) {
260
0
    case fixup_Hexagon_B7_PCREL:
261
0
      maxValue = 1 << 8;
262
0
      break;
263
0
    case fixup_Hexagon_B9_PCREL:
264
0
      maxValue = 1 << 10;
265
0
      break;
266
0
    case fixup_Hexagon_B15_PCREL:
267
0
      maxValue = 1 << 16;
268
0
      break;
269
245
    case fixup_Hexagon_B22_PCREL:
270
245
      maxValue = 1 << 23;
271
245
      break;
272
0
    default:
273
0
      maxValue = INT64_MAX;
274
0
      break;
275
245
    }
276
277
245
    bool isFarAway = -maxValue > sValue || sValue > maxValue - 1;
278
279
245
    if (isFarAway) {
280
155
      if (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_SIZE) {
281
155
        ++relaxedCnt;
282
155
        *RelaxTarget = &MCI;
283
155
        setExtender(Layout.getAssembler().getContext());
284
155
        return true;
285
155
      }
286
155
    }
287
288
90
    return false;
289
245
  }
290
291
  /// Simple predicate for targets where !Resolved implies requiring relaxation
292
  bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
293
                            const MCRelaxableFragment *DF,
294
0
                            const MCAsmLayout &Layout, unsigned &KsError) const override {
295
0
    llvm_unreachable("Handled by fixupNeedsRelaxationAdvanced");
296
0
  }
297
298
  void relaxInstruction(MCInst const & Inst,
299
159
                        MCInst & Res) const override {
300
159
    assert(HexagonMCInstrInfo::isBundle(Inst) &&
301
159
           "Hexagon relaxInstruction only works on bundles");
302
303
159
    Res = HexagonMCInstrInfo::createBundle();
304
    // Copy the results into the bundle.
305
159
    bool Update = false;
306
159
    for (auto &I : HexagonMCInstrInfo::bundleInstructions(Inst)) {
307
159
      MCInst &CrntHMI = const_cast<MCInst &>(*I.getInst());
308
309
      // if immediate extender needed, add it in
310
159
      if (*RelaxTarget == &CrntHMI) {
311
159
        Update = true;
312
159
        assert((HexagonMCInstrInfo::bundleSize(Res) < HEXAGON_PACKET_SIZE) &&
313
159
               "No room to insert extender for relaxation");
314
315
159
        MCInst *HMIx = takeExtender();
316
159
        *HMIx = HexagonMCInstrInfo::deriveExtender(
317
159
                *MCII, CrntHMI,
318
159
                HexagonMCInstrInfo::getExtendableOperand(*MCII, CrntHMI));
319
159
        Res.addOperand(MCOperand::createInst(HMIx));
320
159
        *RelaxTarget = nullptr;
321
159
      }
322
      // now copy over the original instruction(the one we may have extended)
323
159
      Res.addOperand(MCOperand::createInst(I.getInst()));
324
159
    }
325
159
    (void)Update;
326
159
    assert(Update && "Didn't find relaxation target");
327
159
  }
328
329
  bool writeNopData(uint64_t Count,
330
826
                    MCObjectWriter * OW) const override {
331
826
    static const uint32_t Nopcode  = 0x7f000000, // Hard-coded NOP.
332
826
                          ParseIn  = 0x00004000, // In packet parse-bits.
333
826
                          ParseEnd = 0x0000c000; // End of packet parse-bits.
334
335
826
    while(Count % HEXAGON_INSTR_SIZE) {
336
0
      DEBUG(dbgs() << "Alignment not a multiple of the instruction size:" <<
337
0
          Count % HEXAGON_INSTR_SIZE << "/" << HEXAGON_INSTR_SIZE << "\n");
338
0
      --Count;
339
0
      OW->write8(0);
340
0
    }
341
342
826
    while(Count) {
343
0
      Count -= HEXAGON_INSTR_SIZE;
344
      // Close the packet whenever a multiple of the maximum packet size remains
345
0
      uint32_t ParseBits = (Count % (HEXAGON_PACKET_SIZE * HEXAGON_INSTR_SIZE))?
346
0
                           ParseIn: ParseEnd;
347
0
      OW->write32(Nopcode | ParseBits);
348
0
    }
349
826
    return true;
350
826
  }
351
};
352
} // end anonymous namespace
353
354
namespace llvm_ks {
355
MCAsmBackend *createHexagonAsmBackend(Target const &T,
356
                                      MCRegisterInfo const & /*MRI*/,
357
4.28k
                                      const Triple &TT, StringRef CPU) {
358
4.28k
  uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
359
4.28k
  return new HexagonAsmBackend(T, OSABI, CPU);
360
4.28k
}
361
}