Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===//
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 a printer that converts from our internal representation
10
// of machine-dependent LLVM code to GAS-format SPARC assembly language.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "MCTargetDesc/SparcInstPrinter.h"
15
#include "MCTargetDesc/SparcMCExpr.h"
16
#include "MCTargetDesc/SparcTargetStreamer.h"
17
#include "Sparc.h"
18
#include "SparcInstrInfo.h"
19
#include "SparcTargetMachine.h"
20
#include "TargetInfo/SparcTargetInfo.h"
21
#include "llvm/CodeGen/AsmPrinter.h"
22
#include "llvm/CodeGen/MachineInstr.h"
23
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
24
#include "llvm/CodeGen/MachineRegisterInfo.h"
25
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
26
#include "llvm/IR/Mangler.h"
27
#include "llvm/MC/MCAsmInfo.h"
28
#include "llvm/MC/MCContext.h"
29
#include "llvm/MC/MCInst.h"
30
#include "llvm/MC/MCStreamer.h"
31
#include "llvm/MC/MCSymbol.h"
32
#include "llvm/Support/TargetRegistry.h"
33
#include "llvm/Support/raw_ostream.h"
34
using namespace llvm;
35
36
#define DEBUG_TYPE "asm-printer"
37
38
namespace {
39
  class SparcAsmPrinter : public AsmPrinter {
40
33
    SparcTargetStreamer &getTargetStreamer() {
41
33
      return static_cast<SparcTargetStreamer &>(
42
33
          *OutStreamer->getTargetStreamer());
43
33
    }
44
  public:
45
    explicit SparcAsmPrinter(TargetMachine &TM,
46
                             std::unique_ptr<MCStreamer> Streamer)
47
198
        : AsmPrinter(TM, std::move(Streamer)) {}
48
49
691
    StringRef getPassName() const override { return "Sparc Assembly Printer"; }
50
51
    void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
52
    void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS,
53
                         const char *Modifier = nullptr);
54
55
    void EmitFunctionBodyStart() override;
56
    void EmitInstruction(const MachineInstr *MI) override;
57
58
158
    static const char *getRegisterName(unsigned RegNo) {
59
158
      return SparcInstPrinter::getRegisterName(RegNo);
60
158
    }
61
62
    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
63
                         const char *ExtraCode, raw_ostream &O) override;
64
    bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
65
                               const char *ExtraCode, raw_ostream &O) override;
66
67
    void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
68
                                   const MCSubtargetInfo &STI);
69
70
  };
71
} // end of anonymous namespace
72
73
static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind,
74
38
                                      MCSymbol *Sym, MCContext &OutContext) {
75
38
  const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym,
76
38
                                                         OutContext);
77
38
  const SparcMCExpr *expr = SparcMCExpr::create(Kind, MCSym, OutContext);
78
38
  return MCOperand::createExpr(expr);
79
38
80
38
}
81
static MCOperand createPCXCallOP(MCSymbol *Label,
82
28
                                 MCContext &OutContext) {
83
28
  return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext);
84
28
}
85
86
static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind,
87
                                    MCSymbol *GOTLabel, MCSymbol *StartLabel,
88
                                    MCSymbol *CurLabel,
89
                                    MCContext &OutContext)
90
56
{
91
56
  const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
92
56
  const MCSymbolRefExpr *Start = MCSymbolRefExpr::create(StartLabel,
93
56
                                                         OutContext);
94
56
  const MCSymbolRefExpr *Cur = MCSymbolRefExpr::create(CurLabel,
95
56
                                                       OutContext);
96
56
97
56
  const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Cur, Start, OutContext);
98
56
  const MCBinaryExpr *Add = MCBinaryExpr::createAdd(GOT, Sub, OutContext);
99
56
  const SparcMCExpr *expr = SparcMCExpr::create(Kind,
100
56
                                                Add, OutContext);
101
56
  return MCOperand::createExpr(expr);
102
56
}
103
104
static void EmitCall(MCStreamer &OutStreamer,
105
                     MCOperand &Callee,
106
                     const MCSubtargetInfo &STI)
107
28
{
108
28
  MCInst CallInst;
109
28
  CallInst.setOpcode(SP::CALL);
110
28
  CallInst.addOperand(Callee);
111
28
  OutStreamer.EmitInstruction(CallInst, STI);
112
28
}
113
114
static void EmitSETHI(MCStreamer &OutStreamer,
115
                      MCOperand &Imm, MCOperand &RD,
116
                      const MCSubtargetInfo &STI)
117
32
{
118
32
  MCInst SETHIInst;
119
32
  SETHIInst.setOpcode(SP::SETHIi);
120
32
  SETHIInst.addOperand(RD);
121
32
  SETHIInst.addOperand(Imm);
122
32
  OutStreamer.EmitInstruction(SETHIInst, STI);
123
32
}
124
125
static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode,
126
                       MCOperand &RS1, MCOperand &Src2, MCOperand &RD,
127
                       const MCSubtargetInfo &STI)
128
64
{
129
64
  MCInst Inst;
130
64
  Inst.setOpcode(Opcode);
131
64
  Inst.addOperand(RD);
132
64
  Inst.addOperand(RS1);
133
64
  Inst.addOperand(Src2);
134
64
  OutStreamer.EmitInstruction(Inst, STI);
135
64
}
136
137
static void EmitOR(MCStreamer &OutStreamer,
138
                   MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
139
34
                   const MCSubtargetInfo &STI) {
140
34
  EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD, STI);
141
34
}
142
143
static void EmitADD(MCStreamer &OutStreamer,
144
                    MCOperand &RS1, MCOperand &RS2, MCOperand &RD,
145
28
                    const MCSubtargetInfo &STI) {
146
28
  EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD, STI);
147
28
}
148
149
static void EmitSHL(MCStreamer &OutStreamer,
150
                    MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
151
2
                    const MCSubtargetInfo &STI) {
152
2
  EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD, STI);
153
2
}
154
155
156
static void EmitHiLo(MCStreamer &OutStreamer,  MCSymbol *GOTSym,
157
                     SparcMCExpr::VariantKind HiKind,
158
                     SparcMCExpr::VariantKind LoKind,
159
                     MCOperand &RD,
160
                     MCContext &OutContext,
161
4
                     const MCSubtargetInfo &STI) {
162
4
163
4
  MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext);
164
4
  MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext);
165
4
  EmitSETHI(OutStreamer, hi, RD, STI);
166
4
  EmitOR(OutStreamer, RD, lo, RD, STI);
167
4
}
168
169
void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
170
                                                const MCSubtargetInfo &STI)
171
32
{
172
32
  MCSymbol *GOTLabel   =
173
32
    OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
174
32
175
32
  const MachineOperand &MO = MI->getOperand(0);
176
32
  assert(MO.getReg() != SP::O7 &&
177
32
         "%o7 is assigned as destination for getpcx!");
178
32
179
32
  MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
180
32
181
32
182
32
  if (!isPositionIndependent()) {
183
4
    // Just load the address of GOT to MCRegOP.
184
4
    switch(TM.getCodeModel()) {
185
4
    default:
186
0
      llvm_unreachable("Unsupported absolute code model");
187
4
    case CodeModel::Small:
188
2
      EmitHiLo(*OutStreamer, GOTLabel,
189
2
               SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
190
2
               MCRegOP, OutContext, STI);
191
2
      break;
192
4
    case CodeModel::Medium: {
193
2
      EmitHiLo(*OutStreamer, GOTLabel,
194
2
               SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44,
195
2
               MCRegOP, OutContext, STI);
196
2
      MCOperand imm = MCOperand::createExpr(MCConstantExpr::create(12,
197
2
                                                                   OutContext));
198
2
      EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
199
2
      MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44,
200
2
                                          GOTLabel, OutContext);
201
2
      EmitOR(*OutStreamer, MCRegOP, lo, MCRegOP, STI);
202
2
      break;
203
4
    }
204
4
    case CodeModel::Large: {
205
0
      EmitHiLo(*OutStreamer, GOTLabel,
206
0
               SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM,
207
0
               MCRegOP, OutContext, STI);
208
0
      MCOperand imm = MCOperand::createExpr(MCConstantExpr::create(32,
209
0
                                                                   OutContext));
210
0
      EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
211
0
      // Use register %o7 to load the lower 32 bits.
212
0
      MCOperand RegO7 = MCOperand::createReg(SP::O7);
213
0
      EmitHiLo(*OutStreamer, GOTLabel,
214
0
               SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
215
0
               RegO7, OutContext, STI);
216
0
      EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
217
0
    }
218
4
    }
219
4
    return;
220
28
  }
221
28
222
28
  MCSymbol *StartLabel = OutContext.createTempSymbol();
223
28
  MCSymbol *EndLabel   = OutContext.createTempSymbol();
224
28
  MCSymbol *SethiLabel = OutContext.createTempSymbol();
225
28
226
28
  MCOperand RegO7   = MCOperand::createReg(SP::O7);
227
28
228
28
  // <StartLabel>:
229
28
  //   call <EndLabel>
230
28
  // <SethiLabel>:
231
28
  //     sethi %hi(_GLOBAL_OFFSET_TABLE_+(<SethiLabel>-<StartLabel>)), <MO>
232
28
  // <EndLabel>:
233
28
  //   or  <MO>, %lo(_GLOBAL_OFFSET_TABLE_+(<EndLabel>-<StartLabel>))), <MO>
234
28
  //   add <MO>, %o7, <MO>
235
28
236
28
  OutStreamer->EmitLabel(StartLabel);
237
28
  MCOperand Callee =  createPCXCallOP(EndLabel, OutContext);
238
28
  EmitCall(*OutStreamer, Callee, STI);
239
28
  OutStreamer->EmitLabel(SethiLabel);
240
28
  MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC22,
241
28
                                       GOTLabel, StartLabel, SethiLabel,
242
28
                                       OutContext);
243
28
  EmitSETHI(*OutStreamer, hiImm, MCRegOP, STI);
244
28
  OutStreamer->EmitLabel(EndLabel);
245
28
  MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC10,
246
28
                                       GOTLabel, StartLabel, EndLabel,
247
28
                                       OutContext);
248
28
  EmitOR(*OutStreamer, MCRegOP, loImm, MCRegOP, STI);
249
28
  EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
250
28
}
251
252
void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
253
15.4k
{
254
15.4k
255
15.4k
  switch (MI->getOpcode()) {
256
15.4k
  
default: break15.4k
;
257
15.4k
  case TargetOpcode::DBG_VALUE:
258
0
    // FIXME: Debug Value.
259
0
    return;
260
15.4k
  case SP::GETPCX:
261
32
    LowerGETPCXAndEmitMCInsts(MI, getSubtargetInfo());
262
32
    return;
263
15.4k
  }
264
15.4k
  MachineBasicBlock::const_instr_iterator I = MI->getIterator();
265
15.4k
  MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
266
16.6k
  do {
267
16.6k
    MCInst TmpInst;
268
16.6k
    LowerSparcMachineInstrToMCInst(&*I, TmpInst, *this);
269
16.6k
    EmitToStreamer(*OutStreamer, TmpInst);
270
16.6k
  } while ((++I != E) && 
I->isInsideBundle()15.7k
); // Delay slot check.
271
15.4k
}
272
273
691
void SparcAsmPrinter::EmitFunctionBodyStart() {
274
691
  if (!MF->getSubtarget<SparcSubtarget>().is64Bit())
275
442
    return;
276
249
277
249
  const MachineRegisterInfo &MRI = MF->getRegInfo();
278
249
  const unsigned globalRegs[] = { SP::G2, SP::G3, SP::G6, SP::G7, 0 };
279
1.24k
  for (unsigned i = 0; globalRegs[i] != 0; 
++i996
) {
280
996
    unsigned reg = globalRegs[i];
281
996
    if (MRI.use_empty(reg))
282
963
      continue;
283
33
284
33
    if  (reg == SP::G6 || reg == SP::G7)
285
6
      getTargetStreamer().emitSparcRegisterIgnore(reg);
286
27
    else
287
27
      getTargetStreamer().emitSparcRegisterScratch(reg);
288
33
  }
289
249
}
290
291
void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
292
183
                                   raw_ostream &O) {
293
183
  const DataLayout &DL = getDataLayout();
294
183
  const MachineOperand &MO = MI->getOperand (opNum);
295
183
  SparcMCExpr::VariantKind TF = (SparcMCExpr::VariantKind) MO.getTargetFlags();
296
183
297
#ifndef NDEBUG
298
  // Verify the target flags.
299
  if (MO.isGlobal() || MO.isSymbol() || MO.isCPI()) {
300
    if (MI->getOpcode() == SP::CALL)
301
      assert(TF == SparcMCExpr::VK_Sparc_None &&
302
             "Cannot handle target flags on call address");
303
    else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi)
304
      assert((TF == SparcMCExpr::VK_Sparc_HI
305
              || TF == SparcMCExpr::VK_Sparc_H44
306
              || TF == SparcMCExpr::VK_Sparc_HH
307
              || TF == SparcMCExpr::VK_Sparc_TLS_GD_HI22
308
              || TF == SparcMCExpr::VK_Sparc_TLS_LDM_HI22
309
              || TF == SparcMCExpr::VK_Sparc_TLS_LDO_HIX22
310
              || TF == SparcMCExpr::VK_Sparc_TLS_IE_HI22
311
              || TF == SparcMCExpr::VK_Sparc_TLS_LE_HIX22) &&
312
             "Invalid target flags for address operand on sethi");
313
    else if (MI->getOpcode() == SP::TLS_CALL)
314
      assert((TF == SparcMCExpr::VK_Sparc_None
315
              || TF == SparcMCExpr::VK_Sparc_TLS_GD_CALL
316
              || TF == SparcMCExpr::VK_Sparc_TLS_LDM_CALL) &&
317
             "Cannot handle target flags on tls call address");
318
    else if (MI->getOpcode() == SP::TLS_ADDrr)
319
      assert((TF == SparcMCExpr::VK_Sparc_TLS_GD_ADD
320
              || TF == SparcMCExpr::VK_Sparc_TLS_LDM_ADD
321
              || TF == SparcMCExpr::VK_Sparc_TLS_LDO_ADD
322
              || TF == SparcMCExpr::VK_Sparc_TLS_IE_ADD) &&
323
             "Cannot handle target flags on add for TLS");
324
    else if (MI->getOpcode() == SP::TLS_LDrr)
325
      assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LD &&
326
             "Cannot handle target flags on ld for TLS");
327
    else if (MI->getOpcode() == SP::TLS_LDXrr)
328
      assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LDX &&
329
             "Cannot handle target flags on ldx for TLS");
330
    else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri)
331
      assert((TF == SparcMCExpr::VK_Sparc_TLS_LDO_LOX10
332
              || TF == SparcMCExpr::VK_Sparc_TLS_LE_LOX10) &&
333
             "Cannot handle target flags on xor for TLS");
334
    else
335
      assert((TF == SparcMCExpr::VK_Sparc_LO
336
              || TF == SparcMCExpr::VK_Sparc_M44
337
              || TF == SparcMCExpr::VK_Sparc_L44
338
              || TF == SparcMCExpr::VK_Sparc_HM
339
              || TF == SparcMCExpr::VK_Sparc_TLS_GD_LO10
340
              || TF == SparcMCExpr::VK_Sparc_TLS_LDM_LO10
341
              || TF == SparcMCExpr::VK_Sparc_TLS_IE_LO10 ) &&
342
             "Invalid target flags for small address operand");
343
  }
344
#endif
345
346
183
347
183
  bool CloseParen = SparcMCExpr::printVariantKind(O, TF);
348
183
349
183
  switch (MO.getType()) {
350
183
  case MachineOperand::MO_Register:
351
158
    O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
352
158
    break;
353
183
354
183
  case MachineOperand::MO_Immediate:
355
22
    O << (int)MO.getImm();
356
22
    break;
357
183
  case MachineOperand::MO_MachineBasicBlock:
358
0
    MO.getMBB()->getSymbol()->print(O, MAI);
359
0
    return;
360
183
  case MachineOperand::MO_GlobalAddress:
361
3
    PrintSymbolOperand(MO, O);
362
3
    break;
363
183
  case MachineOperand::MO_BlockAddress:
364
0
    O <<  GetBlockAddressSymbol(MO.getBlockAddress())->getName();
365
0
    break;
366
183
  case MachineOperand::MO_ExternalSymbol:
367
0
    O << MO.getSymbolName();
368
0
    break;
369
183
  case MachineOperand::MO_ConstantPoolIndex:
370
0
    O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
371
0
      << MO.getIndex();
372
0
    break;
373
183
  case MachineOperand::MO_Metadata:
374
0
    MO.getMetadata()->printAsOperand(O, MMI->getModule());
375
0
    break;
376
183
  default:
377
0
    llvm_unreachable("<unknown operand type>");
378
183
  }
379
183
  if (CloseParen) 
O << ")"3
;
380
183
}
381
382
void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
383
12
                                      raw_ostream &O, const char *Modifier) {
384
12
  printOperand(MI, opNum, O);
385
12
386
12
  // If this is an ADD operand, emit it like normal operands.
387
12
  if (Modifier && 
!strcmp(Modifier, "arith")0
) {
388
0
    O << ", ";
389
0
    printOperand(MI, opNum+1, O);
390
0
    return;
391
0
  }
392
12
393
12
  if (MI->getOperand(opNum+1).isReg() &&
394
12
      
MI->getOperand(opNum+1).getReg() == SP::G01
)
395
1
    return;   // don't print "+%g0"
396
11
  if (MI->getOperand(opNum+1).isImm() &&
397
11
      
MI->getOperand(opNum+1).getImm() == 08
)
398
0
    return;   // don't print "+0"
399
11
400
11
  O << "+";
401
11
  printOperand(MI, opNum+1, O);
402
11
}
403
404
/// PrintAsmOperand - Print out an operand for an inline asm expression.
405
///
406
bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
407
                                      const char *ExtraCode,
408
164
                                      raw_ostream &O) {
409
164
  if (ExtraCode && 
ExtraCode[0]4
) {
410
4
    if (ExtraCode[1] != 0) 
return true0
; // Unknown modifier.
411
4
412
4
    switch (ExtraCode[0]) {
413
4
    default:
414
4
      // See if this is a generic print operand
415
4
      return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
416
4
    case 'f':
417
0
    case 'r':
418
0
     break;
419
160
    }
420
160
  }
421
160
422
160
  printOperand(MI, OpNo, O);
423
160
424
160
  return false;
425
160
}
426
427
bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
428
                                            unsigned OpNo,
429
                                            const char *ExtraCode,
430
12
                                            raw_ostream &O) {
431
12
  if (ExtraCode && 
ExtraCode[0]0
)
432
0
    return true;  // Unknown modifier
433
12
434
12
  O << '[';
435
12
  printMemOperand(MI, OpNo, O);
436
12
  O << ']';
437
12
438
12
  return false;
439
12
}
440
441
// Force static initialization.
442
78.9k
extern "C" void LLVMInitializeSparcAsmPrinter() {
443
78.9k
  RegisterAsmPrinter<SparcAsmPrinter> X(getTheSparcTarget());
444
78.9k
  RegisterAsmPrinter<SparcAsmPrinter> Y(getTheSparcV9Target());
445
78.9k
  RegisterAsmPrinter<SparcAsmPrinter> Z(getTheSparcelTarget());
446
78.9k
}