Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/ARM/ARMMCInstLower.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- ARMMCInstLower.cpp - Convert ARM 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 ARM MachineInstrs to their corresponding
10
// MCInst records.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "ARM.h"
15
#include "ARMAsmPrinter.h"
16
#include "ARMBaseInstrInfo.h"
17
#include "ARMMachineFunctionInfo.h"
18
#include "ARMSubtarget.h"
19
#include "MCTargetDesc/ARMAddressingModes.h"
20
#include "MCTargetDesc/ARMBaseInfo.h"
21
#include "MCTargetDesc/ARMMCExpr.h"
22
#include "llvm/ADT/APFloat.h"
23
#include "llvm/CodeGen/MachineBasicBlock.h"
24
#include "llvm/CodeGen/MachineInstr.h"
25
#include "llvm/CodeGen/MachineOperand.h"
26
#include "llvm/IR/Constants.h"
27
#include "llvm/MC/MCContext.h"
28
#include "llvm/MC/MCExpr.h"
29
#include "llvm/MC/MCInst.h"
30
#include "llvm/MC/MCInstBuilder.h"
31
#include "llvm/MC/MCStreamer.h"
32
#include "llvm/Support/ErrorHandling.h"
33
#include <cassert>
34
#include <cstdint>
35
36
using namespace llvm;
37
38
MCOperand ARMAsmPrinter::GetSymbolRef(const MachineOperand &MO,
39
63.6k
                                      const MCSymbol *Symbol) {
40
63.6k
  MCSymbolRefExpr::VariantKind SymbolVariant = MCSymbolRefExpr::VK_None;
41
63.6k
  if (MO.getTargetFlags() & ARMII::MO_SBREL)
42
40
    SymbolVariant = MCSymbolRefExpr::VK_ARM_SBREL;
43
63.6k
44
63.6k
  const MCExpr *Expr =
45
63.6k
      MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
46
63.6k
  switch (MO.getTargetFlags() & ARMII::MO_OPTION_MASK) {
47
63.6k
  default:
48
0
    llvm_unreachable("Unknown target flag on symbol operand");
49
63.6k
  case ARMII::MO_NO_FLAG:
50
61.4k
    break;
51
63.6k
  case ARMII::MO_LO16:
52
1.10k
    Expr =
53
1.10k
        MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
54
1.10k
    Expr = ARMMCExpr::createLower16(Expr, OutContext);
55
1.10k
    break;
56
63.6k
  case ARMII::MO_HI16:
57
1.10k
    Expr =
58
1.10k
        MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
59
1.10k
    Expr = ARMMCExpr::createUpper16(Expr, OutContext);
60
1.10k
    break;
61
63.6k
  }
62
63.6k
63
63.6k
  if (!MO.isJTI() && MO.getOffset())
64
0
    Expr = MCBinaryExpr::createAdd(Expr,
65
0
                                   MCConstantExpr::create(MO.getOffset(),
66
0
                                                          OutContext),
67
0
                                   OutContext);
68
63.6k
  return MCOperand::createExpr(Expr);
69
63.6k
70
63.6k
}
71
72
bool ARMAsmPrinter::lowerOperand(const MachineOperand &MO,
73
3.48M
                                 MCOperand &MCOp) {
74
3.48M
  switch (MO.getType()) {
75
3.48M
  
default: 0
llvm_unreachable0
("unknown operand type");
76
3.48M
  case MachineOperand::MO_Register:
77
2.34M
    // Ignore all non-CPSR implicit register operands.
78
2.34M
    if (MO.isImplicit() && 
MO.getReg() != ARM::CPSR438k
)
79
393k
      return false;
80
1.94M
    assert(!MO.getSubReg() && "Subregs should be eliminated!");
81
1.94M
    MCOp = MCOperand::createReg(MO.getReg());
82
1.94M
    break;
83
1.94M
  case MachineOperand::MO_Immediate:
84
974k
    MCOp = MCOperand::createImm(MO.getImm());
85
974k
    break;
86
1.94M
  case MachineOperand::MO_MachineBasicBlock:
87
56.2k
    MCOp = MCOperand::createExpr(MCSymbolRefExpr::create(
88
56.2k
        MO.getMBB()->getSymbol(), OutContext));
89
56.2k
    break;
90
1.94M
  case MachineOperand::MO_GlobalAddress:
91
51.5k
    MCOp = GetSymbolRef(MO,
92
51.5k
                        GetARMGVSymbol(MO.getGlobal(), MO.getTargetFlags()));
93
51.5k
    break;
94
1.94M
  case MachineOperand::MO_ExternalSymbol:
95
6.92k
    MCOp = GetSymbolRef(MO,
96
6.92k
                        GetExternalSymbolSymbol(MO.getSymbolName()));
97
6.92k
    break;
98
1.94M
  case MachineOperand::MO_JumpTableIndex:
99
0
    MCOp = GetSymbolRef(MO, GetJTISymbol(MO.getIndex()));
100
0
    break;
101
1.94M
  case MachineOperand::MO_ConstantPoolIndex:
102
5.25k
    if (Subtarget->genExecuteOnly())
103
5.25k
      
llvm_unreachable0
("execute-only should not generate constant pools");
104
5.25k
    MCOp = GetSymbolRef(MO, GetCPISymbol(MO.getIndex()));
105
5.25k
    break;
106
5.25k
  case MachineOperand::MO_BlockAddress:
107
0
    MCOp = GetSymbolRef(MO, GetBlockAddressSymbol(MO.getBlockAddress()));
108
0
    break;
109
5.25k
  case MachineOperand::MO_FPImmediate: {
110
0
    APFloat Val = MO.getFPImm()->getValueAPF();
111
0
    bool ignored;
112
0
    Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &ignored);
113
0
    MCOp = MCOperand::createFPImm(Val.convertToDouble());
114
0
    break;
115
5.25k
  }
116
54.1k
  case MachineOperand::MO_RegisterMask:
117
54.1k
    // Ignore call clobbers.
118
54.1k
    return false;
119
3.04M
  }
120
3.04M
  return true;
121
3.04M
}
122
123
void llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
124
636k
                                        ARMAsmPrinter &AP) {
125
636k
  OutMI.setOpcode(MI->getOpcode());
126
636k
127
636k
  // In the MC layer, we keep modified immediates in their encoded form
128
636k
  bool EncodeImms = false;
129
636k
  switch (MI->getOpcode()) {
130
636k
  
default: break625k
;
131
636k
  case ARM::MOVi:
132
10.3k
  case ARM::MVNi:
133
10.3k
  case ARM::CMPri:
134
10.3k
  case ARM::CMNri:
135
10.3k
  case ARM::TSTri:
136
10.3k
  case ARM::TEQri:
137
10.3k
  case ARM::MSRi:
138
10.3k
  case ARM::ADCri:
139
10.3k
  case ARM::ADDri:
140
10.3k
  case ARM::ADDSri:
141
10.3k
  case ARM::SBCri:
142
10.3k
  case ARM::SUBri:
143
10.3k
  case ARM::SUBSri:
144
10.3k
  case ARM::ANDri:
145
10.3k
  case ARM::ORRri:
146
10.3k
  case ARM::EORri:
147
10.3k
  case ARM::BICri:
148
10.3k
  case ARM::RSBri:
149
10.3k
  case ARM::RSBSri:
150
10.3k
  case ARM::RSCri:
151
10.3k
    EncodeImms = true;
152
10.3k
    break;
153
636k
  }
154
636k
155
3.37M
  
for (const MachineOperand &MO : MI->operands())636k
{
156
3.37M
    MCOperand MCOp;
157
3.37M
    if (AP.lowerOperand(MO, MCOp)) {
158
2.93M
      if (MCOp.isImm() && 
EncodeImms950k
) {
159
20.6k
        int32_t Enc = ARM_AM::getSOImmVal(MCOp.getImm());
160
20.6k
        if (Enc != -1)
161
20.6k
          MCOp.setImm(Enc);
162
20.6k
      }
163
2.93M
      OutMI.addOperand(MCOp);
164
2.93M
    }
165
3.37M
  }
166
636k
}
167
168
void ARMAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)
169
16
{
170
16
  if (MI.getParent()->getParent()->getInfo<ARMFunctionInfo>()
171
16
    ->isThumbFunction())
172
0
  {
173
0
    MI.emitError("An attempt to perform XRay instrumentation for a"
174
0
      " Thumb function (not supported). Detected when emitting a sled.");
175
0
    return;
176
0
  }
177
16
  static const int8_t NoopsInSledCount = 6;
178
16
  // We want to emit the following pattern:
179
16
  //
180
16
  // .Lxray_sled_N:
181
16
  //   ALIGN
182
16
  //   B #20
183
16
  //   ; 6 NOP instructions (24 bytes)
184
16
  // .tmpN
185
16
  //
186
16
  // We need the 24 bytes (6 instructions) because at runtime, we'd be patching
187
16
  // over the full 28 bytes (7 instructions) with the following pattern:
188
16
  //
189
16
  //   PUSH{ r0, lr }
190
16
  //   MOVW r0, #<lower 16 bits of function ID>
191
16
  //   MOVT r0, #<higher 16 bits of function ID>
192
16
  //   MOVW ip, #<lower 16 bits of address of __xray_FunctionEntry/Exit>
193
16
  //   MOVT ip, #<higher 16 bits of address of __xray_FunctionEntry/Exit>
194
16
  //   BLX ip
195
16
  //   POP{ r0, lr }
196
16
  //
197
16
  OutStreamer->EmitCodeAlignment(4);
198
16
  auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
199
16
  OutStreamer->EmitLabel(CurSled);
200
16
  auto Target = OutContext.createTempSymbol();
201
16
202
16
  // Emit "B #20" instruction, which jumps over the next 24 bytes (because
203
16
  // register pc is 8 bytes ahead of the jump instruction by the moment CPU
204
16
  // is executing it).
205
16
  // By analogy to ARMAsmPrinter::emitPseudoExpansionLowering() |case ARM::B|.
206
16
  // It is not clear why |addReg(0)| is needed (the last operand).
207
16
  EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::Bcc).addImm(20)
208
16
    .addImm(ARMCC::AL).addReg(0));
209
16
210
16
  MCInst Noop;
211
16
  Subtarget->getInstrInfo()->getNoop(Noop);
212
112
  for (int8_t I = 0; I < NoopsInSledCount; 
I++96
)
213
96
    OutStreamer->EmitInstruction(Noop, getSubtargetInfo());
214
16
215
16
  OutStreamer->EmitLabel(Target);
216
16
  recordSled(CurSled, MI, Kind);
217
16
}
218
219
void ARMAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)
220
8
{
221
8
  EmitSled(MI, SledKind::FUNCTION_ENTER);
222
8
}
223
224
void ARMAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI)
225
8
{
226
8
  EmitSled(MI, SledKind::FUNCTION_EXIT);
227
8
}
228
229
void ARMAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
230
0
{
231
0
  EmitSled(MI, SledKind::TAIL_CALL);
232
0
}