Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- MSP430AsmBackend.cpp - MSP430 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
#include "MCTargetDesc/MSP430FixupKinds.h"
10
#include "MCTargetDesc/MSP430MCTargetDesc.h"
11
#include "llvm/ADT/APInt.h"
12
#include "llvm/MC/MCAsmBackend.h"
13
#include "llvm/MC/MCAssembler.h"
14
#include "llvm/MC/MCContext.h"
15
#include "llvm/MC/MCDirectives.h"
16
#include "llvm/MC/MCELFObjectWriter.h"
17
#include "llvm/MC/MCExpr.h"
18
#include "llvm/MC/MCFixupKindInfo.h"
19
#include "llvm/MC/MCObjectWriter.h"
20
#include "llvm/MC/MCSubtargetInfo.h"
21
#include "llvm/MC/MCSymbol.h"
22
#include "llvm/MC/MCTargetOptions.h"
23
#include "llvm/Support/ErrorHandling.h"
24
#include "llvm/Support/raw_ostream.h"
25
26
using namespace llvm;
27
28
namespace {
29
class MSP430AsmBackend : public MCAsmBackend {
30
  uint8_t OSABI;
31
32
  uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
33
                            MCContext &Ctx) const;
34
35
public:
36
  MSP430AsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI)
37
86
      : MCAsmBackend(support::little), OSABI(OSABI) {}
38
86
  ~MSP430AsmBackend() override {}
39
40
  void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
41
                  const MCValue &Target, MutableArrayRef<char> Data,
42
                  uint64_t Value, bool IsResolved,
43
                  const MCSubtargetInfo *STI) const override;
44
45
  std::unique_ptr<MCObjectTargetWriter>
46
86
  createObjectTargetWriter() const override {
47
86
    return createMSP430ELFObjectWriter(OSABI);
48
86
  }
49
50
  bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
51
                            const MCRelaxableFragment *DF,
52
0
                            const MCAsmLayout &Layout) const override {
53
0
    return false;
54
0
  }
55
56
  bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved,
57
                                    uint64_t Value,
58
                                    const MCRelaxableFragment *DF,
59
                                    const MCAsmLayout &Layout,
60
0
                                    const bool WasForced) const override {
61
0
    return false;
62
0
  }
63
64
0
  unsigned getNumFixupKinds() const override {
65
0
    return MSP430::NumTargetFixupKinds;
66
0
  }
67
68
130
  const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
69
130
    const static MCFixupKindInfo Infos[MSP430::NumTargetFixupKinds] = {
70
130
      // This table must be in the same order of enum in MSP430FixupKinds.h.
71
130
      //
72
130
      // name            offset bits flags
73
130
      {"fixup_32",            0, 32, 0},
74
130
      {"fixup_10_pcrel",      0, 10, MCFixupKindInfo::FKF_IsPCRel},
75
130
      {"fixup_16",            0, 16, 0},
76
130
      {"fixup_16_pcrel",      0, 16, MCFixupKindInfo::FKF_IsPCRel},
77
130
      {"fixup_16_byte",       0, 16, 0},
78
130
      {"fixup_16_pcrel_byte", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
79
130
      {"fixup_2x_pcrel",      0, 10, MCFixupKindInfo::FKF_IsPCRel},
80
130
      {"fixup_rl_pcrel",      0, 16, MCFixupKindInfo::FKF_IsPCRel},
81
130
      {"fixup_8",             0,  8, 0},
82
130
      {"fixup_sym_diff",      0, 32, 0},
83
130
    };
84
130
    static_assert((array_lengthof(Infos)) == MSP430::NumTargetFixupKinds,
85
130
                  "Not all fixup kinds added to Infos array");
86
130
  
87
130
    if (Kind < FirstTargetFixupKind)
88
16
      return MCAsmBackend::getFixupKindInfo(Kind);
89
114
  
90
114
    return Infos[Kind - FirstTargetFixupKind];
91
114
  }
92
93
  bool mayNeedRelaxation(const MCInst &Inst,
94
79
                         const MCSubtargetInfo &STI) const override {
95
79
    return false;
96
79
  }
97
98
  void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
99
0
                        MCInst &Res) const override {}
100
101
  bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
102
};
103
104
uint64_t MSP430AsmBackend::adjustFixupValue(const MCFixup &Fixup,
105
                                            uint64_t Value,
106
13
                                            MCContext &Ctx) const {
107
13
  unsigned Kind = Fixup.getKind();
108
13
  switch (Kind) {
109
13
  case MSP430::fixup_10_pcrel: {
110
2
    if (Value & 0x1)
111
0
      Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");
112
2
113
2
    // Offset is signed
114
2
    int16_t Offset = Value;
115
2
    // Jumps are in words
116
2
    Offset >>= 1;
117
2
    // PC points to the next instruction so decrement by one
118
2
    --Offset;
119
2
120
2
    if (Offset < -512 || Offset > 511)
121
0
      Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
122
2
123
2
    // Mask 10 bits
124
2
    Offset &= 0x3ff;
125
2
126
2
    return Offset;
127
13
  }
128
13
  default:
129
11
    return Value;
130
13
  }
131
13
}
132
133
void MSP430AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
134
                                  const MCValue &Target,
135
                                  MutableArrayRef<char> Data,
136
                                  uint64_t Value, bool IsResolved,
137
13
                                  const MCSubtargetInfo *STI) const {
138
13
  Value = adjustFixupValue(Fixup, Value, Asm.getContext());
139
13
  MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
140
13
  if (!Value)
141
11
    return; // Doesn't change encoding.
142
2
143
2
  // Shift the value into position.
144
2
  Value <<= Info.TargetOffset;
145
2
146
2
  unsigned Offset = Fixup.getOffset();
147
2
  unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;
148
2
149
2
  assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
150
2
151
2
  // For each byte of the fragment that the fixup touches, mask in the
152
2
  // bits from the fixup value.
153
6
  for (unsigned i = 0; i != NumBytes; 
++i4
) {
154
4
    Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
155
4
  }
156
2
}
157
158
5
bool MSP430AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const {
159
5
  if ((Count % 2) != 0)
160
0
    return false;
161
5
162
5
  // The canonical nop on MSP430 is mov #0, r3
163
5
  uint64_t NopCount = Count / 2;
164
5
  while (NopCount--)
165
0
    OS.write("\x03\x43", 2);
166
5
167
5
  return true;
168
5
}
169
170
} // end anonymous namespace
171
172
MCAsmBackend *llvm::createMSP430MCAsmBackend(const Target &T,
173
                                             const MCSubtargetInfo &STI,
174
                                             const MCRegisterInfo &MRI,
175
86
                                             const MCTargetOptions &Options) {
176
86
  return new MSP430AsmBackend(STI, ELF::ELFOSABI_STANDALONE);
177
86
}