Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- PPCAsmBackend.cpp - PPC 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/PPCFixupKinds.h"
10
#include "MCTargetDesc/PPCMCTargetDesc.h"
11
#include "llvm/BinaryFormat/ELF.h"
12
#include "llvm/BinaryFormat/MachO.h"
13
#include "llvm/MC/MCAsmBackend.h"
14
#include "llvm/MC/MCAssembler.h"
15
#include "llvm/MC/MCELFObjectWriter.h"
16
#include "llvm/MC/MCFixupKindInfo.h"
17
#include "llvm/MC/MCMachObjectWriter.h"
18
#include "llvm/MC/MCObjectWriter.h"
19
#include "llvm/MC/MCSectionMachO.h"
20
#include "llvm/MC/MCSubtargetInfo.h"
21
#include "llvm/MC/MCSymbolELF.h"
22
#include "llvm/MC/MCValue.h"
23
#include "llvm/Support/ErrorHandling.h"
24
#include "llvm/Support/TargetRegistry.h"
25
using namespace llvm;
26
27
1.56k
static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
28
1.56k
  switch (Kind) {
29
1.56k
  default:
30
0
    llvm_unreachable("Unknown fixup kind!");
31
1.56k
  case FK_NONE:
32
374
  case FK_Data_1:
33
374
  case FK_Data_2:
34
374
  case FK_Data_4:
35
374
  case FK_Data_8:
36
374
  case PPC::fixup_ppc_nofixup:
37
374
    return Value;
38
374
  case PPC::fixup_ppc_brcond14:
39
36
  case PPC::fixup_ppc_brcond14abs:
40
36
    return Value & 0xfffc;
41
225
  case PPC::fixup_ppc_br24:
42
225
  case PPC::fixup_ppc_br24abs:
43
225
    return Value & 0x3fffffc;
44
770
  case PPC::fixup_ppc_half16:
45
770
    return Value & 0xffff;
46
225
  case PPC::fixup_ppc_half16ds:
47
162
    return Value & 0xfffc;
48
1.56k
  }
49
1.56k
}
50
51
198
static unsigned getFixupKindNumBytes(unsigned Kind) {
52
198
  switch (Kind) {
53
198
  default:
54
0
    llvm_unreachable("Unknown fixup kind!");
55
198
  case FK_NONE:
56
0
    return 0;
57
198
  case FK_Data_1:
58
2
    return 1;
59
198
  case FK_Data_2:
60
44
  case PPC::fixup_ppc_half16:
61
44
  case PPC::fixup_ppc_half16ds:
62
44
    return 2;
63
150
  case FK_Data_4:
64
150
  case PPC::fixup_ppc_brcond14:
65
150
  case PPC::fixup_ppc_brcond14abs:
66
150
  case PPC::fixup_ppc_br24:
67
150
  case PPC::fixup_ppc_br24abs:
68
150
    return 4;
69
150
  case FK_Data_8:
70
2
    return 8;
71
150
  case PPC::fixup_ppc_nofixup:
72
0
    return 0;
73
198
  }
74
198
}
75
76
namespace {
77
78
class PPCAsmBackend : public MCAsmBackend {
79
protected:
80
  Triple TT;
81
public:
82
  PPCAsmBackend(const Target &T, const Triple &TT)
83
      : MCAsmBackend(TT.isLittleEndian() ? support::little : support::big),
84
2.06k
        TT(TT) {}
85
86
0
  unsigned getNumFixupKinds() const override {
87
0
    return PPC::NumTargetFixupKinds;
88
0
  }
89
90
6.37k
  const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
91
6.37k
    const static MCFixupKindInfo InfosBE[PPC::NumTargetFixupKinds] = {
92
6.37k
      // name                    offset  bits  flags
93
6.37k
      { "fixup_ppc_br24",        6,      24,   MCFixupKindInfo::FKF_IsPCRel },
94
6.37k
      { "fixup_ppc_brcond14",    16,     14,   MCFixupKindInfo::FKF_IsPCRel },
95
6.37k
      { "fixup_ppc_br24abs",     6,      24,   0 },
96
6.37k
      { "fixup_ppc_brcond14abs", 16,     14,   0 },
97
6.37k
      { "fixup_ppc_half16",       0,     16,   0 },
98
6.37k
      { "fixup_ppc_half16ds",     0,     14,   0 },
99
6.37k
      { "fixup_ppc_nofixup",      0,      0,   0 }
100
6.37k
    };
101
6.37k
    const static MCFixupKindInfo InfosLE[PPC::NumTargetFixupKinds] = {
102
6.37k
      // name                    offset  bits  flags
103
6.37k
      { "fixup_ppc_br24",        2,      24,   MCFixupKindInfo::FKF_IsPCRel },
104
6.37k
      { "fixup_ppc_brcond14",    2,      14,   MCFixupKindInfo::FKF_IsPCRel },
105
6.37k
      { "fixup_ppc_br24abs",     2,      24,   0 },
106
6.37k
      { "fixup_ppc_brcond14abs", 2,      14,   0 },
107
6.37k
      { "fixup_ppc_half16",      0,      16,   0 },
108
6.37k
      { "fixup_ppc_half16ds",    2,      14,   0 },
109
6.37k
      { "fixup_ppc_nofixup",     0,       0,   0 }
110
6.37k
    };
111
6.37k
112
6.37k
    if (Kind < FirstTargetFixupKind)
113
841
      return MCAsmBackend::getFixupKindInfo(Kind);
114
5.53k
115
5.53k
    assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
116
5.53k
           "Invalid kind!");
117
5.53k
    return (Endian == support::little
118
5.53k
                ? 
InfosLE2.68k
119
5.53k
                : 
InfosBE2.85k
)[Kind - FirstTargetFixupKind];
120
5.53k
  }
121
122
  void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
123
                  const MCValue &Target, MutableArrayRef<char> Data,
124
                  uint64_t Value, bool IsResolved,
125
1.56k
                  const MCSubtargetInfo *STI) const override {
126
1.56k
    Value = adjustFixupValue(Fixup.getKind(), Value);
127
1.56k
    if (!Value) 
return1.36k
; // Doesn't change encoding.
128
198
129
198
    unsigned Offset = Fixup.getOffset();
130
198
    unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
131
198
132
198
    // For each byte of the fragment that the fixup touches, mask in the bits
133
198
    // from the fixup value. The Value has been "split up" into the appropriate
134
198
    // bitfields above.
135
904
    for (unsigned i = 0; i != NumBytes; 
++i706
) {
136
706
      unsigned Idx = Endian == support::little ? 
i309
:
(NumBytes - 1 - i)397
;
137
706
      Data[Offset + i] |= uint8_t((Value >> (Idx * 8)) & 0xff);
138
706
    }
139
198
  }
140
141
  bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
142
223
                             const MCValue &Target) override {
143
223
    switch ((unsigned)Fixup.getKind()) {
144
223
    default:
145
138
      return false;
146
223
    case FK_NONE:
147
3
      return true;
148
223
    case PPC::fixup_ppc_br24:
149
82
    case PPC::fixup_ppc_br24abs:
150
82
      // If the target symbol has a local entry point we must not attempt
151
82
      // to resolve the fixup directly.  Emit a relocation and leave
152
82
      // resolution of the final target address to the linker.
153
82
      if (const MCSymbolRefExpr *A = Target.getSymA()) {
154
82
        if (const auto *S = dyn_cast<MCSymbolELF>(&A->getSymbol())) {
155
81
          // The "other" values are stored in the last 6 bits of the second
156
81
          // byte. The traditional defines for STO values assume the full byte
157
81
          // and thus the shift to pack it.
158
81
          unsigned Other = S->getOther() << 2;
159
81
          if ((Other & ELF::STO_PPC64_LOCAL_MASK) != 0)
160
21
            return true;
161
61
        }
162
82
      }
163
61
      return false;
164
223
    }
165
223
  }
166
167
  bool mayNeedRelaxation(const MCInst &Inst,
168
2.74k
                         const MCSubtargetInfo &STI) const override {
169
2.74k
    // FIXME.
170
2.74k
    return false;
171
2.74k
  }
172
173
  bool fixupNeedsRelaxation(const MCFixup &Fixup,
174
                            uint64_t Value,
175
                            const MCRelaxableFragment *DF,
176
0
                            const MCAsmLayout &Layout) const override {
177
0
    // FIXME.
178
0
    llvm_unreachable("relaxInstruction() unimplemented");
179
0
  }
180
181
  void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
182
0
                        MCInst &Res) const override {
183
0
    // FIXME.
184
0
    llvm_unreachable("relaxInstruction() unimplemented");
185
0
  }
186
187
426
  bool writeNopData(raw_ostream &OS, uint64_t Count) const override {
188
426
    uint64_t NumNops = Count / 4;
189
524
    for (uint64_t i = 0; i != NumNops; 
++i98
)
190
98
      support::endian::write<uint32_t>(OS, 0x60000000, Endian);
191
426
192
426
    OS.write_zeros(Count % 4);
193
426
194
426
    return true;
195
426
  }
196
};
197
} // end anonymous namespace
198
199
200
// FIXME: This should be in a separate file.
201
namespace {
202
203
class DarwinPPCAsmBackend : public PPCAsmBackend {
204
public:
205
  DarwinPPCAsmBackend(const Target &T, const Triple &TT)
206
4
      : PPCAsmBackend(T, TT) {}
207
208
  std::unique_ptr<MCObjectTargetWriter>
209
4
  createObjectTargetWriter() const override {
210
4
    bool Is64 = TT.isPPC64();
211
4
    return createPPCMachObjectWriter(
212
4
        /*Is64Bit=*/Is64,
213
4
        (Is64 ? 
MachO::CPU_TYPE_POWERPC641
:
MachO::CPU_TYPE_POWERPC3
),
214
4
        MachO::CPU_SUBTYPE_POWERPC_ALL);
215
4
  }
216
};
217
218
class ELFPPCAsmBackend : public PPCAsmBackend {
219
public:
220
2.05k
  ELFPPCAsmBackend(const Target &T, const Triple &TT) : PPCAsmBackend(T, TT) {}
221
222
  std::unique_ptr<MCObjectTargetWriter>
223
2.05k
  createObjectTargetWriter() const override {
224
2.05k
    uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
225
2.05k
    bool Is64 = TT.isPPC64();
226
2.05k
    return createPPCELFObjectWriter(Is64, OSABI);
227
2.05k
  }
228
229
  Optional<MCFixupKind> getFixupKind(StringRef Name) const override;
230
};
231
232
class XCOFFPPCAsmBackend : public PPCAsmBackend {
233
public:
234
  XCOFFPPCAsmBackend(const Target &T, const Triple &TT)
235
5
      : PPCAsmBackend(T, TT) {}
236
237
  std::unique_ptr<MCObjectTargetWriter>
238
5
  createObjectTargetWriter() const override {
239
5
    return createPPCXCOFFObjectWriter(TT.isArch64Bit());
240
5
  }
241
};
242
243
} // end anonymous namespace
244
245
9
Optional<MCFixupKind> ELFPPCAsmBackend::getFixupKind(StringRef Name) const {
246
9
  if (TT.isPPC64()) {
247
6
    if (Name == "R_PPC64_NONE")
248
6
      return FK_NONE;
249
3
  } else {
250
3
    if (Name == "R_PPC_NONE")
251
3
      return FK_NONE;
252
0
  }
253
0
  return MCAsmBackend::getFixupKind(Name);
254
0
}
255
256
MCAsmBackend *llvm::createPPCAsmBackend(const Target &T,
257
                                        const MCSubtargetInfo &STI,
258
                                        const MCRegisterInfo &MRI,
259
2.06k
                                        const MCTargetOptions &Options) {
260
2.06k
  const Triple &TT = STI.getTargetTriple();
261
2.06k
  if (TT.isOSDarwin())
262
4
    return new DarwinPPCAsmBackend(T, TT);
263
2.06k
264
2.06k
  if (TT.isOSBinFormatXCOFF())
265
5
    return new XCOFFPPCAsmBackend(T, TT);
266
2.05k
267
2.05k
  return new ELFPPCAsmBackend(T, TT);
268
2.05k
}