Coverage Report

Created: 2025-07-15 06:22

/src/keystone/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
Line
Count
Source (jump to first uncovered line)
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
3.45k
    OSABI(OSABI), MCII (T.createMCInstrInfo()), RelaxTarget(new MCInst *),
43
3.45k
    Extender(nullptr) {}
44
45
3.45k
  MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
46
3.45k
    return createHexagonELFObjectWriter(OS, OSABI, CPU);
47
3.45k
  }
48
49
123
  void setExtender(MCContext &Context) const {
50
123
    if (Extender == nullptr)
51
123
      const_cast<HexagonAsmBackend *>(this)->Extender = new (Context) MCInst;
52
123
  }
53
54
123
  MCInst *takeExtender() const {
55
123
    assert(Extender != nullptr);
56
123
    MCInst * Result = Extender;
57
123
    const_cast<HexagonAsmBackend *>(this)->Extender = nullptr;
58
123
    return Result;
59
123
  }
60
61
2.23k
  unsigned getNumFixupKinds() const override {
62
2.23k
    return Hexagon::NumTargetFixupKinds;
63
2.23k
  }
64
65
21.1k
  const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
66
21.1k
    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
21.1k
        {"fixup_Hexagon_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
72
21.1k
        {"fixup_Hexagon_B15_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
73
21.1k
        {"fixup_Hexagon_B7_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
74
21.1k
        {"fixup_Hexagon_LO16", 0, 32, 0},
75
21.1k
        {"fixup_Hexagon_HI16", 0, 32, 0},
76
21.1k
        {"fixup_Hexagon_32", 0, 32, 0},
77
21.1k
        {"fixup_Hexagon_16", 0, 32, 0},
78
21.1k
        {"fixup_Hexagon_8", 0, 32, 0},
79
21.1k
        {"fixup_Hexagon_GPREL16_0", 0, 32, 0},
80
21.1k
        {"fixup_Hexagon_GPREL16_1", 0, 32, 0},
81
21.1k
        {"fixup_Hexagon_GPREL16_2", 0, 32, 0},
82
21.1k
        {"fixup_Hexagon_GPREL16_3", 0, 32, 0},
83
21.1k
        {"fixup_Hexagon_HL16", 0, 32, 0},
84
21.1k
        {"fixup_Hexagon_B13_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
85
21.1k
        {"fixup_Hexagon_B9_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
86
21.1k
        {"fixup_Hexagon_B32_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
87
21.1k
        {"fixup_Hexagon_32_6_X", 0, 32, 0},
88
21.1k
        {"fixup_Hexagon_B22_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
89
21.1k
        {"fixup_Hexagon_B15_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
90
21.1k
        {"fixup_Hexagon_B13_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
91
21.1k
        {"fixup_Hexagon_B9_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
92
21.1k
        {"fixup_Hexagon_B7_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
93
21.1k
        {"fixup_Hexagon_16_X", 0, 32, 0},
94
21.1k
        {"fixup_Hexagon_12_X", 0, 32, 0},
95
21.1k
        {"fixup_Hexagon_11_X", 0, 32, 0},
96
21.1k
        {"fixup_Hexagon_10_X", 0, 32, 0},
97
21.1k
        {"fixup_Hexagon_9_X", 0, 32, 0},
98
21.1k
        {"fixup_Hexagon_8_X", 0, 32, 0},
99
21.1k
        {"fixup_Hexagon_7_X", 0, 32, 0},
100
21.1k
        {"fixup_Hexagon_6_X", 0, 32, 0},
101
21.1k
        {"fixup_Hexagon_32_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
102
21.1k
        {"fixup_Hexagon_COPY", 0, 32, 0},
103
21.1k
        {"fixup_Hexagon_GLOB_DAT", 0, 32, 0},
104
21.1k
        {"fixup_Hexagon_JMP_SLOT", 0, 32, 0},
105
21.1k
        {"fixup_Hexagon_RELATIVE", 0, 32, 0},
106
21.1k
        {"fixup_Hexagon_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
107
21.1k
        {"fixup_Hexagon_GOTREL_LO16", 0, 32, 0},
108
21.1k
        {"fixup_Hexagon_GOTREL_HI16", 0, 32, 0},
109
21.1k
        {"fixup_Hexagon_GOTREL_32", 0, 32, 0},
110
21.1k
        {"fixup_Hexagon_GOT_LO16", 0, 32, 0},
111
21.1k
        {"fixup_Hexagon_GOT_HI16", 0, 32, 0},
112
21.1k
        {"fixup_Hexagon_GOT_32", 0, 32, 0},
113
21.1k
        {"fixup_Hexagon_GOT_16", 0, 32, 0},
114
21.1k
        {"fixup_Hexagon_DTPMOD_32", 0, 32, 0},
115
21.1k
        {"fixup_Hexagon_DTPREL_LO16", 0, 32, 0},
116
21.1k
        {"fixup_Hexagon_DTPREL_HI16", 0, 32, 0},
117
21.1k
        {"fixup_Hexagon_DTPREL_32", 0, 32, 0},
118
21.1k
        {"fixup_Hexagon_DTPREL_16", 0, 32, 0},
119
21.1k
        {"fixup_Hexagon_GD_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
120
21.1k
        {"fixup_Hexagon_LD_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
121
21.1k
        {"fixup_Hexagon_GD_GOT_LO16", 0, 32, 0},
122
21.1k
        {"fixup_Hexagon_GD_GOT_HI16", 0, 32, 0},
123
21.1k
        {"fixup_Hexagon_GD_GOT_32", 0, 32, 0},
124
21.1k
        {"fixup_Hexagon_GD_GOT_16", 0, 32, 0},
125
21.1k
        {"fixup_Hexagon_LD_GOT_LO16", 0, 32, 0},
126
21.1k
        {"fixup_Hexagon_LD_GOT_HI16", 0, 32, 0},
127
21.1k
        {"fixup_Hexagon_LD_GOT_32", 0, 32, 0},
128
21.1k
        {"fixup_Hexagon_LD_GOT_16", 0, 32, 0},
129
21.1k
        {"fixup_Hexagon_IE_LO16", 0, 32, 0},
130
21.1k
        {"fixup_Hexagon_IE_HI16", 0, 32, 0},
131
21.1k
        {"fixup_Hexagon_IE_32", 0, 32, 0},
132
21.1k
        {"fixup_Hexagon_IE_16", 0, 32, 0},
133
21.1k
        {"fixup_Hexagon_IE_GOT_LO16", 0, 32, 0},
134
21.1k
        {"fixup_Hexagon_IE_GOT_HI16", 0, 32, 0},
135
21.1k
        {"fixup_Hexagon_IE_GOT_32", 0, 32, 0},
136
21.1k
        {"fixup_Hexagon_IE_GOT_16", 0, 32, 0},
137
21.1k
        {"fixup_Hexagon_TPREL_LO16", 0, 32, 0},
138
21.1k
        {"fixup_Hexagon_TPREL_HI16", 0, 32, 0},
139
21.1k
        {"fixup_Hexagon_TPREL_32", 0, 32, 0},
140
21.1k
        {"fixup_Hexagon_TPREL_16", 0, 32, 0},
141
21.1k
        {"fixup_Hexagon_6_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
142
21.1k
        {"fixup_Hexagon_GOTREL_32_6_X", 0, 32, 0},
143
21.1k
        {"fixup_Hexagon_GOTREL_16_X", 0, 32, 0},
144
21.1k
        {"fixup_Hexagon_GOTREL_11_X", 0, 32, 0},
145
21.1k
        {"fixup_Hexagon_GOT_32_6_X", 0, 32, 0},
146
21.1k
        {"fixup_Hexagon_GOT_16_X", 0, 32, 0},
147
21.1k
        {"fixup_Hexagon_GOT_11_X", 0, 32, 0},
148
21.1k
        {"fixup_Hexagon_DTPREL_32_6_X", 0, 32, 0},
149
21.1k
        {"fixup_Hexagon_DTPREL_16_X", 0, 32, 0},
150
21.1k
        {"fixup_Hexagon_DTPREL_11_X", 0, 32, 0},
151
21.1k
        {"fixup_Hexagon_GD_GOT_32_6_X", 0, 32, 0},
152
21.1k
        {"fixup_Hexagon_GD_GOT_16_X", 0, 32, 0},
153
21.1k
        {"fixup_Hexagon_GD_GOT_11_X", 0, 32, 0},
154
21.1k
        {"fixup_Hexagon_LD_GOT_32_6_X", 0, 32, 0},
155
21.1k
        {"fixup_Hexagon_LD_GOT_16_X", 0, 32, 0},
156
21.1k
        {"fixup_Hexagon_LD_GOT_11_X", 0, 32, 0},
157
21.1k
        {"fixup_Hexagon_IE_32_6_X", 0, 32, 0},
158
21.1k
        {"fixup_Hexagon_IE_16_X", 0, 32, 0},
159
21.1k
        {"fixup_Hexagon_IE_GOT_32_6_X", 0, 32, 0},
160
21.1k
        {"fixup_Hexagon_IE_GOT_16_X", 0, 32, 0},
161
21.1k
        {"fixup_Hexagon_IE_GOT_11_X", 0, 32, 0},
162
21.1k
        {"fixup_Hexagon_TPREL_32_6_X", 0, 32, 0},
163
21.1k
        {"fixup_Hexagon_TPREL_16_X", 0, 32, 0},
164
21.1k
        {"fixup_Hexagon_TPREL_11_X", 0, 32, 0}};
165
166
21.1k
    if (Kind < FirstTargetFixupKind) {
167
18.8k
      return MCAsmBackend::getFixupKindInfo(Kind);
168
18.8k
    }
169
170
2.23k
    assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
171
2.23k
           "Invalid kind!");
172
2.23k
    return Infos[Kind - FirstTargetFixupKind];
173
2.23k
  }
174
175
  void applyFixup(MCFixup const & /*Fixup*/, char * /*Data*/,
176
                  unsigned /*DataSize*/, uint64_t /*Value*/,
177
6.55k
                  bool /*IsPCRel*/, unsigned int &KsError) const override {
178
6.55k
    return;
179
6.55k
  }
180
181
4.69k
  bool isInstRelaxable(MCInst const &HMI) const {
182
4.69k
    const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(*MCII, HMI);
183
4.69k
    bool Relaxable = false;
184
    // Branches and loop-setup insns are handled as necessary by relaxation.
185
4.69k
    if (llvm_ks::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeJ ||
186
4.69k
        (llvm_ks::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeNV &&
187
1.58k
         MCID.isBranch()) ||
188
4.69k
        (llvm_ks::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeCR &&
189
1.58k
         HMI.getOpcode() != Hexagon::C4_addipc))
190
3.15k
      if (HexagonMCInstrInfo::isExtendable(*MCII, HMI))
191
3.10k
        Relaxable = true;
192
193
4.69k
    return Relaxable;
194
4.69k
  }
195
196
  /// MayNeedRelaxation - Check whether the given instruction may need
197
  /// relaxation.
198
  ///
199
  /// \param Inst - The instruction to test.
200
4.44k
  bool mayNeedRelaxation(MCInst const &Inst) const override {
201
4.44k
    assert(HexagonMCInstrInfo::isBundle(Inst));
202
4.44k
    bool PreviousIsExtender = false;
203
4.98k
    for (auto const &I : HexagonMCInstrInfo::bundleInstructions(Inst)) {
204
4.98k
      auto const &Inst = *I.getInst();
205
4.98k
      if (!PreviousIsExtender) {
206
4.44k
        if (isInstRelaxable(Inst))
207
2.86k
          return true;
208
4.44k
      }
209
2.12k
      PreviousIsExtender = HexagonMCInstrInfo::isImmext(Inst);
210
2.12k
    }
211
1.58k
    return false;
212
4.44k
  }
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
408
                                    const MCAsmLayout &Layout) const override {
220
408
    MCInst const &MCB = DF->getInst();
221
408
    assert(HexagonMCInstrInfo::isBundle(MCB));
222
223
408
    *RelaxTarget = nullptr;
224
408
    MCInst &MCI = const_cast<MCInst &>(HexagonMCInstrInfo::instruction(
225
408
        MCB, Fixup.getOffset() / HEXAGON_INSTR_SIZE));
226
    // If we cannot resolve the fixup value, it requires relaxation.
227
408
    if (!Resolved) {
228
161
      switch ((unsigned)Fixup.getKind()) {
229
161
      case fixup_Hexagon_B22_PCREL:
230
      // GetFixupCount assumes B22 won't relax
231
      // Fallthrough
232
161
      default:
233
161
        return false;
234
0
        break;
235
0
      case fixup_Hexagon_B13_PCREL:
236
0
      case fixup_Hexagon_B15_PCREL:
237
0
      case fixup_Hexagon_B9_PCREL:
238
0
      case fixup_Hexagon_B7_PCREL: {
239
0
        if (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_SIZE) {
240
0
          ++relaxedCnt;
241
0
          *RelaxTarget = &MCI;
242
0
          setExtender(Layout.getAssembler().getContext());
243
0
          return true;
244
0
        } else {
245
0
          return false;
246
0
        }
247
0
        break;
248
0
      }
249
161
      }
250
161
    }
251
247
    bool Relaxable = isInstRelaxable(MCI);
252
247
    if (Relaxable == false)
253
0
      return false;
254
255
247
    MCFixupKind Kind = Fixup.getKind();
256
247
    int64_t sValue = Value;
257
247
    int64_t maxValue;
258
259
247
    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
247
    case fixup_Hexagon_B22_PCREL:
270
247
      maxValue = 1 << 23;
271
247
      break;
272
0
    default:
273
0
      maxValue = INT64_MAX;
274
0
      break;
275
247
    }
276
277
247
    bool isFarAway = -maxValue > sValue || sValue > maxValue - 1;
278
279
247
    if (isFarAway) {
280
123
      if (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_SIZE) {
281
123
        ++relaxedCnt;
282
123
        *RelaxTarget = &MCI;
283
123
        setExtender(Layout.getAssembler().getContext());
284
123
        return true;
285
123
      }
286
123
    }
287
288
124
    return false;
289
247
  }
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
123
                        MCInst & Res) const override {
300
123
    assert(HexagonMCInstrInfo::isBundle(Inst) &&
301
123
           "Hexagon relaxInstruction only works on bundles");
302
303
123
    Res = HexagonMCInstrInfo::createBundle();
304
    // Copy the results into the bundle.
305
123
    bool Update = false;
306
123
    for (auto &I : HexagonMCInstrInfo::bundleInstructions(Inst)) {
307
123
      MCInst &CrntHMI = const_cast<MCInst &>(*I.getInst());
308
309
      // if immediate extender needed, add it in
310
123
      if (*RelaxTarget == &CrntHMI) {
311
123
        Update = true;
312
123
        assert((HexagonMCInstrInfo::bundleSize(Res) < HEXAGON_PACKET_SIZE) &&
313
123
               "No room to insert extender for relaxation");
314
315
123
        MCInst *HMIx = takeExtender();
316
123
        *HMIx = HexagonMCInstrInfo::deriveExtender(
317
123
                *MCII, CrntHMI,
318
123
                HexagonMCInstrInfo::getExtendableOperand(*MCII, CrntHMI));
319
123
        Res.addOperand(MCOperand::createInst(HMIx));
320
123
        *RelaxTarget = nullptr;
321
123
      }
322
      // now copy over the original instruction(the one we may have extended)
323
123
      Res.addOperand(MCOperand::createInst(I.getInst()));
324
123
    }
325
123
    (void)Update;
326
123
    assert(Update && "Didn't find relaxation target");
327
123
  }
328
329
  bool writeNopData(uint64_t Count,
330
185
                    MCObjectWriter * OW) const override {
331
185
    static const uint32_t Nopcode  = 0x7f000000, // Hard-coded NOP.
332
185
                          ParseIn  = 0x00004000, // In packet parse-bits.
333
185
                          ParseEnd = 0x0000c000; // End of packet parse-bits.
334
335
185
    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
185
    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
185
    return true;
350
185
  }
351
};
352
} // end anonymous namespace
353
354
namespace llvm_ks {
355
MCAsmBackend *createHexagonAsmBackend(Target const &T,
356
                                      MCRegisterInfo const & /*MRI*/,
357
3.45k
                                      const Triple &TT, StringRef CPU) {
358
3.45k
  uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
359
3.45k
  return new HexagonAsmBackend(T, OSABI, CPU);
360
3.45k
}
361
}