Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
Line
Count
Source (jump to first uncovered line)
1
//==-- AArch64MCInstLower.cpp - Convert AArch64 MachineInstr to an MCInst --==//
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
// This file contains code to lower AArch64 MachineInstrs to their corresponding
10
// MCInst records.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "AArch64MCInstLower.h"
15
#include "MCTargetDesc/AArch64MCExpr.h"
16
#include "Utils/AArch64BaseInfo.h"
17
#include "llvm/CodeGen/AsmPrinter.h"
18
#include "llvm/CodeGen/MachineBasicBlock.h"
19
#include "llvm/CodeGen/MachineInstr.h"
20
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
21
#include "llvm/IR/Mangler.h"
22
#include "llvm/MC/MCContext.h"
23
#include "llvm/MC/MCExpr.h"
24
#include "llvm/MC/MCInst.h"
25
#include "llvm/Support/CodeGen.h"
26
#include "llvm/Support/CommandLine.h"
27
#include "llvm/Target/TargetLoweringObjectFile.h"
28
#include "llvm/Target/TargetMachine.h"
29
using namespace llvm;
30
31
extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration;
32
33
AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
34
8.72k
    : Ctx(ctx), Printer(printer) {}
35
36
MCSymbol *
37
2.36M
AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
38
2.36M
  const GlobalValue *GV = MO.getGlobal();
39
2.36M
  unsigned TargetFlags = MO.getTargetFlags();
40
2.36M
  const Triple &TheTriple = Printer.TM.getTargetTriple();
41
2.36M
  if (!TheTriple.isOSBinFormatCOFF())
42
2.36M
    return Printer.getSymbol(GV);
43
209
44
209
  assert(TheTriple.isOSWindows() &&
45
209
         "Windows is the only supported COFF target");
46
209
47
209
  bool IsIndirect = (TargetFlags & (AArch64II::MO_DLLIMPORT | AArch64II::MO_COFFSTUB));
48
209
  if (!IsIndirect)
49
165
    return Printer.getSymbol(GV);
50
44
51
44
  SmallString<128> Name;
52
44
  if (TargetFlags & AArch64II::MO_DLLIMPORT)
53
30
    Name = "__imp_";
54
14
  else if (TargetFlags & AArch64II::MO_COFFSTUB)
55
14
    Name = ".refptr.";
56
44
  Printer.TM.getNameWithPrefix(Name, GV,
57
44
                               Printer.getObjFileLowering().getMangler());
58
44
59
44
  MCSymbol *MCSym = Ctx.getOrCreateSymbol(Name);
60
44
61
44
  if (TargetFlags & AArch64II::MO_COFFSTUB) {
62
14
    MachineModuleInfoCOFF &MMICOFF =
63
14
        Printer.MMI->getObjFileInfo<MachineModuleInfoCOFF>();
64
14
    MachineModuleInfoImpl::StubValueTy &StubSym =
65
14
        MMICOFF.getGVStubEntry(MCSym);
66
14
67
14
    if (!StubSym.getPointer())
68
5
      StubSym = MachineModuleInfoImpl::StubValueTy(Printer.getSymbol(GV), true);
69
14
  }
70
44
71
44
  return MCSym;
72
44
}
73
74
MCSymbol *
75
35.1k
AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
76
35.1k
  return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
77
35.1k
}
78
79
MCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO,
80
2.44M
                                                       MCSymbol *Sym) const {
81
2.44M
  // FIXME: We would like an efficient form for this, so we don't have to do a
82
2.44M
  // lot of extra uniquing.
83
2.44M
  MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
84
2.44M
  if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
85
317k
    if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
86
158k
      RefKind = MCSymbolRefExpr::VK_GOTPAGE;
87
158k
    else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
88
158k
             AArch64II::MO_PAGEOFF)
89
158k
      RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
90
158k
    else
91
158k
      
llvm_unreachable0
("Unexpected target flags with MO_GOT on GV operand");
92
2.13M
  } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
93
64
    if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
94
32
      RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
95
32
    else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
96
32
             AArch64II::MO_PAGEOFF)
97
32
      RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
98
32
    else
99
32
      
llvm_unreachable0
("Unexpected target flags with MO_TLS on GV operand");
100
2.13M
  } else {
101
2.13M
    if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
102
477k
      RefKind = MCSymbolRefExpr::VK_PAGE;
103
1.65M
    else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
104
1.65M
             AArch64II::MO_PAGEOFF)
105
495k
      RefKind = MCSymbolRefExpr::VK_PAGEOFF;
106
2.13M
  }
107
2.44M
  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
108
2.44M
  if (!MO.isJTI() && 
MO.getOffset()2.44M
)
109
7.42k
    Expr = MCBinaryExpr::createAdd(
110
7.42k
        Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
111
2.44M
  return MCOperand::createExpr(Expr);
112
2.44M
}
113
114
MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
115
9.44k
                                                    MCSymbol *Sym) const {
116
9.44k
  uint32_t RefFlags = 0;
117
9.44k
118
9.44k
  if (MO.getTargetFlags() & AArch64II::MO_GOT)
119
164
    RefFlags |= AArch64MCExpr::VK_GOT;
120
9.28k
  else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
121
141
    TLSModel::Model Model;
122
141
    if (MO.isGlobal()) {
123
114
      const GlobalValue *GV = MO.getGlobal();
124
114
      Model = Printer.TM.getTLSModel(GV);
125
114
      if (!EnableAArch64ELFLocalDynamicTLSGeneration &&
126
114
          
Model == TLSModel::LocalDynamic72
)
127
24
        Model = TLSModel::GeneralDynamic;
128
114
129
114
    } else {
130
27
      assert(MO.isSymbol() &&
131
27
             StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
132
27
             "unexpected external TLS symbol");
133
27
      // The general dynamic access sequence is used to get the
134
27
      // address of _TLS_MODULE_BASE_.
135
27
      Model = TLSModel::GeneralDynamic;
136
27
    }
137
141
    switch (Model) {
138
141
    case TLSModel::InitialExec:
139
12
      RefFlags |= AArch64MCExpr::VK_GOTTPREL;
140
12
      break;
141
141
    case TLSModel::LocalExec:
142
18
      RefFlags |= AArch64MCExpr::VK_TPREL;
143
18
      break;
144
141
    case TLSModel::LocalDynamic:
145
24
      RefFlags |= AArch64MCExpr::VK_DTPREL;
146
24
      break;
147
141
    case TLSModel::GeneralDynamic:
148
87
      RefFlags |= AArch64MCExpr::VK_TLSDESC;
149
87
      break;
150
9.14k
    }
151
9.14k
  } else {
152
9.14k
    // No modifier means this is a generic reference, classified as absolute for
153
9.14k
    // the cases where it matters (:abs_g0: etc).
154
9.14k
    RefFlags |= AArch64MCExpr::VK_ABS;
155
9.14k
  }
156
9.44k
157
9.44k
  if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
158
3.17k
    RefFlags |= AArch64MCExpr::VK_PAGE;
159
6.27k
  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
160
6.27k
           AArch64II::MO_PAGEOFF)
161
3.48k
    RefFlags |= AArch64MCExpr::VK_PAGEOFF;
162
2.78k
  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
163
32
    RefFlags |= AArch64MCExpr::VK_G3;
164
2.75k
  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
165
32
    RefFlags |= AArch64MCExpr::VK_G2;
166
2.72k
  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
167
32
    RefFlags |= AArch64MCExpr::VK_G1;
168
2.69k
  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
169
32
    RefFlags |= AArch64MCExpr::VK_G0;
170
2.66k
  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12)
171
21
    RefFlags |= AArch64MCExpr::VK_HI12;
172
9.44k
173
9.44k
  if (MO.getTargetFlags() & AArch64II::MO_NC)
174
3.55k
    RefFlags |= AArch64MCExpr::VK_NC;
175
9.44k
176
9.44k
  const MCExpr *Expr =
177
9.44k
      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
178
9.44k
  if (!MO.isJTI() && 
MO.getOffset()9.31k
)
179
92
    Expr = MCBinaryExpr::createAdd(
180
92
        Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
181
9.44k
182
9.44k
  AArch64MCExpr::VariantKind RefKind;
183
9.44k
  RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
184
9.44k
  Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
185
9.44k
186
9.44k
  return MCOperand::createExpr(Expr);
187
9.44k
}
188
189
MCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO,
190
257
                                                     MCSymbol *Sym) const {
191
257
  uint32_t RefFlags = 0;
192
257
193
257
  if (MO.getTargetFlags() & AArch64II::MO_TLS) {
194
10
    if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGEOFF)
195
5
      RefFlags |= AArch64MCExpr::VK_SECREL_LO12;
196
5
    else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
197
5
             AArch64II::MO_HI12)
198
5
      RefFlags |= AArch64MCExpr::VK_SECREL_HI12;
199
10
200
247
  } else if (MO.getTargetFlags() & AArch64II::MO_S) {
201
7
    RefFlags |= AArch64MCExpr::VK_SABS;
202
240
  } else {
203
240
    RefFlags |= AArch64MCExpr::VK_ABS;
204
240
  }
205
257
206
257
  if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
207
0
    RefFlags |= AArch64MCExpr::VK_G3;
208
257
  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
209
0
    RefFlags |= AArch64MCExpr::VK_G2;
210
257
  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
211
7
    RefFlags |= AArch64MCExpr::VK_G1;
212
250
  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
213
7
    RefFlags |= AArch64MCExpr::VK_G0;
214
257
215
257
  // FIXME: Currently we only set VK_NC for MO_G3/MO_G2/MO_G1/MO_G0. This is
216
257
  // because setting VK_NC for others would mean setting their respective
217
257
  // RefFlags correctly.  We should do this in a separate patch.
218
257
  if (MO.getTargetFlags() & AArch64II::MO_NC) {
219
72
    auto MOFrag = (MO.getTargetFlags() & AArch64II::MO_FRAGMENT);
220
72
    if (MOFrag == AArch64II::MO_G3 || MOFrag == AArch64II::MO_G2 ||
221
72
        MOFrag == AArch64II::MO_G1 || MOFrag == AArch64II::MO_G0)
222
7
      RefFlags |= AArch64MCExpr::VK_NC;
223
72
  }
224
257
225
257
  const MCExpr *Expr =
226
257
      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
227
257
  if (!MO.isJTI() && 
MO.getOffset()253
)
228
0
    Expr = MCBinaryExpr::createAdd(
229
0
        Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
230
257
231
257
  auto RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
232
257
  assert(RefKind != AArch64MCExpr::VK_INVALID &&
233
257
         "Invalid relocation requested");
234
257
  Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
235
257
236
257
  return MCOperand::createExpr(Expr);
237
257
}
238
239
MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
240
2.45M
                                                 MCSymbol *Sym) const {
241
2.45M
  if (Printer.TM.getTargetTriple().isOSDarwin())
242
2.44M
    return lowerSymbolOperandDarwin(MO, Sym);
243
9.70k
  if (Printer.TM.getTargetTriple().isOSBinFormatCOFF())
244
257
    return lowerSymbolOperandCOFF(MO, Sym);
245
9.44k
246
9.44k
  assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target");
247
9.44k
  return lowerSymbolOperandELF(MO, Sym);
248
9.44k
}
249
250
bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
251
55.2M
                                      MCOperand &MCOp) const {
252
55.2M
  switch (MO.getType()) {
253
55.2M
  default:
254
0
    llvm_unreachable("unknown operand type");
255
55.2M
  case MachineOperand::MO_Register:
256
36.5M
    // Ignore all implicit register operands.
257
36.5M
    if (MO.isImplicit())
258
8.71M
      return false;
259
27.8M
    MCOp = MCOperand::createReg(MO.getReg());
260
27.8M
    break;
261
27.8M
  case MachineOperand::MO_RegisterMask:
262
1.17M
    // Regmasks are like implicit defs.
263
1.17M
    return false;
264
27.8M
  case MachineOperand::MO_Immediate:
265
13.6M
    MCOp = MCOperand::createImm(MO.getImm());
266
13.6M
    break;
267
27.8M
  case MachineOperand::MO_MachineBasicBlock:
268
1.41M
    MCOp = MCOperand::createExpr(
269
1.41M
        MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
270
1.41M
    break;
271
27.8M
  case MachineOperand::MO_GlobalAddress:
272
2.36M
    MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
273
2.36M
    break;
274
27.8M
  case MachineOperand::MO_ExternalSymbol:
275
35.1k
    MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
276
35.1k
    break;
277
27.8M
  case MachineOperand::MO_MCSymbol:
278
46
    MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
279
46
    break;
280
27.8M
  case MachineOperand::MO_JumpTableIndex:
281
5.05k
    MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
282
5.05k
    break;
283
27.8M
  case MachineOperand::MO_ConstantPoolIndex:
284
54.8k
    MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
285
54.8k
    break;
286
27.8M
  case MachineOperand::MO_BlockAddress:
287
17
    MCOp = LowerSymbolOperand(
288
17
        MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
289
17
    break;
290
45.3M
  }
291
45.3M
  return true;
292
45.3M
}
293
294
14.5M
void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
295
14.5M
  OutMI.setOpcode(MI->getOpcode());
296
14.5M
297
55.1M
  for (const MachineOperand &MO : MI->operands()) {
298
55.1M
    MCOperand MCOp;
299
55.1M
    if (lowerOperand(MO, MCOp))
300
45.2M
      OutMI.addOperand(MCOp);
301
55.1M
  }
302
14.5M
303
14.5M
  switch (OutMI.getOpcode()) {
304
14.5M
  case AArch64::CATCHRET:
305
7
    OutMI = MCInst();
306
7
    OutMI.setOpcode(AArch64::RET);
307
7
    OutMI.addOperand(MCOperand::createReg(AArch64::LR));
308
7
    break;
309
14.5M
  case AArch64::CLEANUPRET:
310
5
    OutMI = MCInst();
311
5
    OutMI.setOpcode(AArch64::RET);
312
5
    OutMI.addOperand(MCOperand::createReg(AArch64::LR));
313
5
    break;
314
14.5M
  }
315
14.5M
}