Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- AsmPrinterInlineAsm.cpp - AsmPrinter Inline Asm Handling ----------===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This file implements the inline assembler pieces of the AsmPrinter class.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "llvm/ADT/SmallString.h"
15
#include "llvm/ADT/Twine.h"
16
#include "llvm/CodeGen/AsmPrinter.h"
17
#include "llvm/CodeGen/MachineBasicBlock.h"
18
#include "llvm/CodeGen/MachineFunction.h"
19
#include "llvm/CodeGen/MachineModuleInfo.h"
20
#include "llvm/IR/Constants.h"
21
#include "llvm/IR/DataLayout.h"
22
#include "llvm/IR/InlineAsm.h"
23
#include "llvm/IR/LLVMContext.h"
24
#include "llvm/IR/Module.h"
25
#include "llvm/MC/MCAsmInfo.h"
26
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
27
#include "llvm/MC/MCStreamer.h"
28
#include "llvm/MC/MCSubtargetInfo.h"
29
#include "llvm/MC/MCSymbol.h"
30
#include "llvm/Support/ErrorHandling.h"
31
#include "llvm/Support/MemoryBuffer.h"
32
#include "llvm/Support/SourceMgr.h"
33
#include "llvm/Support/TargetRegistry.h"
34
#include "llvm/Support/raw_ostream.h"
35
#include "llvm/Target/TargetInstrInfo.h"
36
#include "llvm/Target/TargetMachine.h"
37
#include "llvm/Target/TargetRegisterInfo.h"
38
#include "llvm/Target/TargetSubtargetInfo.h"
39
using namespace llvm;
40
41
#define DEBUG_TYPE "asm-printer"
42
43
/// srcMgrDiagHandler - This callback is invoked when the SourceMgr for an
44
/// inline asm has an error in it.  diagInfo is a pointer to the SrcMgrDiagInfo
45
/// struct above.
46
158
static void srcMgrDiagHandler(const SMDiagnostic &Diag, void *diagInfo) {
47
158
  AsmPrinter::SrcMgrDiagInfo *DiagInfo =
48
158
      static_cast<AsmPrinter::SrcMgrDiagInfo *>(diagInfo);
49
158
  assert(DiagInfo && "Diagnostic context not passed down?");
50
158
51
158
  // Look up a LocInfo for the buffer this diagnostic is coming from.
52
158
  unsigned BufNum = DiagInfo->SrcMgr.FindBufferContainingLoc(Diag.getLoc());
53
158
  const MDNode *LocInfo = nullptr;
54
158
  if (
BufNum > 0 && 158
BufNum <= DiagInfo->LocInfos.size()158
)
55
9
    LocInfo = DiagInfo->LocInfos[BufNum-1];
56
158
57
158
  // If the inline asm had metadata associated with it, pull out a location
58
158
  // cookie corresponding to which line the error occurred on.
59
158
  unsigned LocCookie = 0;
60
158
  if (
LocInfo158
) {
61
9
    unsigned ErrorLine = Diag.getLineNo()-1;
62
9
    if (ErrorLine >= LocInfo->getNumOperands())
63
0
      ErrorLine = 0;
64
9
65
9
    if (LocInfo->getNumOperands() != 0)
66
9
      
if (const ConstantInt *9
CI9
=
67
9
              mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine)))
68
9
        LocCookie = CI->getZExtValue();
69
9
  }
70
158
71
158
  DiagInfo->DiagHandler(Diag, DiagInfo->DiagContext, LocCookie);
72
158
}
73
74
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
75
void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
76
                               const MCTargetOptions &MCOptions,
77
                               const MDNode *LocMDNode,
78
5.68k
                               InlineAsm::AsmDialect Dialect) const {
79
5.68k
  assert(!Str.empty() && "Can't emit empty inline asm block");
80
5.68k
81
5.68k
  // Remember if the buffer is nul terminated or not so we can avoid a copy.
82
5.68k
  bool isNullTerminated = Str.back() == 0;
83
5.68k
  if (isNullTerminated)
84
5.33k
    Str = Str.substr(0, Str.size()-1);
85
5.68k
86
5.68k
  // If the output streamer does not have mature MC support or the integrated
87
5.68k
  // assembler has been disabled, just emit the blob textually.
88
5.68k
  // Otherwise parse the asm and emit it via MC support.
89
5.68k
  // This is useful in case the asm parser doesn't handle something but the
90
5.68k
  // system assembler does.
91
5.68k
  const MCAsmInfo *MCAI = TM.getMCAsmInfo();
92
5.68k
  assert(MCAI && "No MCAsmInfo");
93
5.68k
  if (!MCAI->useIntegratedAssembler() &&
94
5.68k
      
!OutStreamer->isIntegratedAssemblerRequired()1.71k
) {
95
1.70k
    emitInlineAsmStart();
96
1.70k
    OutStreamer->EmitRawText(Str);
97
1.70k
    emitInlineAsmEnd(STI, nullptr);
98
1.70k
    return;
99
1.70k
  }
100
3.98k
101
3.98k
  
if (3.98k
!DiagInfo3.98k
) {
102
767
    DiagInfo = make_unique<SrcMgrDiagInfo>();
103
767
104
767
    MCContext &Context = MMI->getContext();
105
767
    Context.setInlineSourceManager(&DiagInfo->SrcMgr);
106
767
107
767
    LLVMContext &LLVMCtx = MMI->getModule()->getContext();
108
767
    if (
LLVMCtx.getInlineAsmDiagnosticHandler()767
) {
109
745
      DiagInfo->DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler();
110
745
      DiagInfo->DiagContext = LLVMCtx.getInlineAsmDiagnosticContext();
111
745
      DiagInfo->SrcMgr.setDiagHandler(srcMgrDiagHandler, DiagInfo.get());
112
745
    }
113
767
  }
114
3.98k
115
3.98k
  SourceMgr &SrcMgr = DiagInfo->SrcMgr;
116
3.98k
  SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths);
117
3.98k
118
3.98k
  std::unique_ptr<MemoryBuffer> Buffer;
119
3.98k
  // The inline asm source manager will outlive Str, so make a copy of the
120
3.98k
  // string for SourceMgr to own.
121
3.98k
  Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>");
122
3.98k
123
3.98k
  // Tell SrcMgr about this buffer, it takes ownership of the buffer.
124
3.98k
  unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
125
3.98k
126
3.98k
  // Store LocMDNode in DiagInfo, using BufNum as an identifier.
127
3.98k
  if (
LocMDNode3.98k
) {
128
1.02k
    DiagInfo->LocInfos.resize(BufNum);
129
1.02k
    DiagInfo->LocInfos[BufNum-1] = LocMDNode;
130
1.02k
  }
131
3.98k
132
3.98k
  std::unique_ptr<MCAsmParser> Parser(
133
3.98k
      createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum));
134
3.98k
135
3.98k
  // We create a new MCInstrInfo here since we might be at the module level
136
3.98k
  // and not have a MachineFunction to initialize the TargetInstrInfo from and
137
3.98k
  // we only need MCInstrInfo for asm parsing. We create one unconditionally
138
3.98k
  // because it's not subtarget dependent.
139
3.98k
  std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo());
140
3.98k
  std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser(
141
3.98k
      STI, *Parser, *MII, MCOptions));
142
3.98k
  if (!TAP)
143
0
    report_fatal_error("Inline asm not supported by this streamer because"
144
0
                       " we don't have an asm parser for this target\n");
145
3.98k
  Parser->setAssemblerDialect(Dialect);
146
3.98k
  Parser->setTargetParser(*TAP.get());
147
3.98k
  if (Dialect == InlineAsm::AD_Intel)
148
3.98k
    // We need this flag to be able to parse numbers like "0bH"
149
17
    Parser->setParsingInlineAsm(true);
150
3.98k
  if (
MF3.98k
) {
151
3.63k
    const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
152
3.63k
    TAP->SetFrameRegister(TRI->getFrameRegister(*MF));
153
3.63k
  }
154
3.98k
155
3.98k
  emitInlineAsmStart();
156
3.98k
  // Don't implicitly switch to the text section before the asm.
157
3.98k
  int Res = Parser->Run(/*NoInitialTextSection*/ true,
158
3.98k
                        /*NoFinalize*/ true);
159
3.98k
  emitInlineAsmEnd(STI, &TAP->getSTI());
160
3.98k
161
3.98k
  if (
Res && 3.98k
!DiagInfo->DiagHandler32
)
162
0
    report_fatal_error("Error parsing inline asm\n");
163
3.98k
}
164
165
static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
166
                               MachineModuleInfo *MMI, int InlineAsmVariant,
167
                               AsmPrinter *AP, unsigned LocCookie,
168
27
                               raw_ostream &OS) {
169
27
  // Switch to the inline assembly variant.
170
27
  OS << "\t.intel_syntax\n\t";
171
27
172
27
  const char *LastEmitted = AsmStr; // One past the last character emitted.
173
27
  unsigned NumOperands = MI->getNumOperands();
174
27
175
180
  while (
*LastEmitted180
) {
176
153
    switch (*LastEmitted) {
177
83
    default: {
178
83
      // Not a special case, emit the string section literally.
179
83
      const char *LiteralEnd = LastEmitted+1;
180
866
      while (
*LiteralEnd && 866
*LiteralEnd != '{'845
&&
*LiteralEnd != '|'845
&&
181
866
             
*LiteralEnd != '}'845
&&
*LiteralEnd != '$'844
&&
*LiteralEnd != '\n'811
)
182
783
        ++LiteralEnd;
183
83
184
83
      OS.write(LastEmitted, LiteralEnd-LastEmitted);
185
83
      LastEmitted = LiteralEnd;
186
83
      break;
187
153
    }
188
37
    case '\n':
189
37
      ++LastEmitted;   // Consume newline character.
190
37
      OS << '\n';      // Indent code with newline.
191
37
      break;
192
33
    case '$': {
193
33
      ++LastEmitted;   // Consume '$' character.
194
33
      bool Done = true;
195
33
196
33
      // Handle escapes.
197
33
      switch (*LastEmitted) {
198
30
      default: Done = false; break;
199
3
      case '$':
200
3
        ++LastEmitted;  // Consume second '$' character.
201
3
        break;
202
33
      }
203
33
      
if (33
Done33
)
break3
;
204
30
205
30
      // If we have ${:foo}, then this is not a real operand reference, it is a
206
30
      // "magic" string reference, just like in .td files.  Arrange to call
207
30
      // PrintSpecial.
208
30
      
if (30
LastEmitted[0] == '{' && 30
LastEmitted[1] == ':'2
) {
209
2
        LastEmitted += 2;
210
2
        const char *StrStart = LastEmitted;
211
2
        const char *StrEnd = strchr(StrStart, '}');
212
2
        if (!StrEnd)
213
0
          report_fatal_error("Unterminated ${:foo} operand in inline asm"
214
0
                             " string: '" + Twine(AsmStr) + "'");
215
2
216
2
        std::string Val(StrStart, StrEnd);
217
2
        AP->PrintSpecial(MI, OS, Val.c_str());
218
2
        LastEmitted = StrEnd+1;
219
2
        break;
220
2
      }
221
28
222
28
      const char *IDStart = LastEmitted;
223
28
      const char *IDEnd = IDStart;
224
56
      while (
*IDEnd >= '0' && 56
*IDEnd <= '9'30
)
++IDEnd28
;
225
28
226
28
      unsigned Val;
227
28
      if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val))
228
0
        report_fatal_error("Bad $ operand number in inline asm string: '" +
229
0
                           Twine(AsmStr) + "'");
230
28
      LastEmitted = IDEnd;
231
28
232
28
      if (Val >= NumOperands-1)
233
0
        report_fatal_error("Invalid $ operand number in inline asm string: '" +
234
0
                           Twine(AsmStr) + "'");
235
28
236
28
      // Okay, we finally have a value number.  Ask the target to print this
237
28
      // operand!
238
28
      unsigned OpNo = InlineAsm::MIOp_FirstOperand;
239
28
240
28
      bool Error = false;
241
28
242
28
      // Scan to find the machine operand number for the operand.
243
59
      for (; 
Val59
;
--Val31
) {
244
31
        if (
OpNo >= MI->getNumOperands()31
)
break0
;
245
31
        unsigned OpFlags = MI->getOperand(OpNo).getImm();
246
31
        OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
247
31
      }
248
28
249
28
      // We may have a location metadata attached to the end of the
250
28
      // instruction, and at no point should see metadata at any
251
28
      // other point while processing. It's an error if so.
252
28
      if (OpNo >= MI->getNumOperands() ||
253
28
          
MI->getOperand(OpNo).isMetadata()28
) {
254
0
        Error = true;
255
28
      } else {
256
28
        unsigned OpFlags = MI->getOperand(OpNo).getImm();
257
28
        ++OpNo;  // Skip over the ID number.
258
28
259
28
        if (
InlineAsm::isMemKind(OpFlags)28
) {
260
25
          Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant,
261
25
                                            /*Modifier*/ nullptr, OS);
262
28
        } else {
263
3
          Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant,
264
3
                                      /*Modifier*/ nullptr, OS);
265
3
        }
266
28
      }
267
28
      if (
Error28
) {
268
0
        std::string msg;
269
0
        raw_string_ostream Msg(msg);
270
0
        Msg << "invalid operand in inline asm: '" << AsmStr << "'";
271
0
        MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
272
0
      }
273
33
      break;
274
33
    }
275
153
    }
276
153
  }
277
27
  OS << "\n\t.att_syntax\n" << (char)0;  // null terminate string.
278
27
}
279
280
static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
281
                                MachineModuleInfo *MMI, int InlineAsmVariant,
282
                                int AsmPrinterVariant, AsmPrinter *AP,
283
5.30k
                                unsigned LocCookie, raw_ostream &OS) {
284
5.30k
  int CurVariant = -1;            // The number of the {.|.|.} region we are in.
285
5.30k
  const char *LastEmitted = AsmStr; // One past the last character emitted.
286
5.30k
  unsigned NumOperands = MI->getNumOperands();
287
5.30k
288
5.30k
  OS << '\t';
289
5.30k
290
21.1k
  while (
*LastEmitted21.1k
) {
291
15.8k
    switch (*LastEmitted) {
292
9.61k
    default: {
293
9.61k
      // Not a special case, emit the string section literally.
294
9.61k
      const char *LiteralEnd = LastEmitted+1;
295
55.5k
      while (
*LiteralEnd && 55.5k
*LiteralEnd != '{'51.9k
&&
*LiteralEnd != '|'51.8k
&&
296
55.5k
             
*LiteralEnd != '}'51.8k
&&
*LiteralEnd != '$'51.8k
&&
*LiteralEnd != '\n'47.3k
)
297
45.9k
        ++LiteralEnd;
298
9.61k
      if (
CurVariant == -1 || 9.61k
CurVariant == AsmPrinterVariant10
)
299
9.60k
        OS.write(LastEmitted, LiteralEnd-LastEmitted);
300
9.61k
      LastEmitted = LiteralEnd;
301
9.61k
      break;
302
15.8k
    }
303
1.57k
    case '\n':
304
1.57k
      ++LastEmitted;   // Consume newline character.
305
1.57k
      OS << '\n';      // Indent code with newline.
306
1.57k
      break;
307
4.62k
    case '$': {
308
4.62k
      ++LastEmitted;   // Consume '$' character.
309
4.62k
      bool Done = true;
310
4.62k
311
4.62k
      // Handle escapes.
312
4.62k
      switch (*LastEmitted) {
313
3.87k
      default: Done = false; break;
314
716
      case '$':     // $$ -> $
315
716
        if (
CurVariant == -1 || 716
CurVariant == AsmPrinterVariant0
)
316
716
          OS << '$';
317
716
        ++LastEmitted;  // Consume second '$' character.
318
716
        break;
319
5
      case '(':             // $( -> same as GCC's { character.
320
5
        ++LastEmitted;      // Consume '(' character.
321
5
        if (CurVariant != -1)
322
0
          report_fatal_error("Nested variants found in inline asm string: '" +
323
0
                             Twine(AsmStr) + "'");
324
5
        CurVariant = 0;     // We're in the first variant now.
325
5
        break;
326
21
      case '|':
327
21
        ++LastEmitted;  // consume '|' character.
328
21
        if (CurVariant == -1)
329
16
          OS << '|';       // this is gcc's behavior for | outside a variant
330
21
        else
331
5
          ++CurVariant;   // We're in the next variant.
332
21
        break;
333
5
      case ')':         // $) -> same as GCC's } char.
334
5
        ++LastEmitted;  // consume ')' character.
335
5
        if (CurVariant == -1)
336
0
          OS << '}';     // this is gcc's behavior for } outside a variant
337
5
        else
338
5
          CurVariant = -1;
339
5
        break;
340
4.62k
      }
341
4.62k
      
if (4.62k
Done4.62k
)
break747
;
342
3.87k
343
3.87k
      bool HasCurlyBraces = false;
344
3.87k
      if (
*LastEmitted == '{'3.87k
) { // ${variable}
345
287
        ++LastEmitted;               // Consume '{' character.
346
287
        HasCurlyBraces = true;
347
287
      }
348
3.87k
349
3.87k
      // If we have ${:foo}, then this is not a real operand reference, it is a
350
3.87k
      // "magic" string reference, just like in .td files.  Arrange to call
351
3.87k
      // PrintSpecial.
352
3.87k
      if (
HasCurlyBraces && 3.87k
*LastEmitted == ':'287
) {
353
4
        ++LastEmitted;
354
4
        const char *StrStart = LastEmitted;
355
4
        const char *StrEnd = strchr(StrStart, '}');
356
4
        if (!StrEnd)
357
0
          report_fatal_error("Unterminated ${:foo} operand in inline asm"
358
0
                             " string: '" + Twine(AsmStr) + "'");
359
4
360
4
        std::string Val(StrStart, StrEnd);
361
4
        AP->PrintSpecial(MI, OS, Val.c_str());
362
4
        LastEmitted = StrEnd+1;
363
4
        break;
364
4
      }
365
3.87k
366
3.87k
      const char *IDStart = LastEmitted;
367
3.87k
      const char *IDEnd = IDStart;
368
7.74k
      while (
*IDEnd >= '0' && 7.74k
*IDEnd <= '9'4.26k
)
++IDEnd3.87k
;
369
3.87k
370
3.87k
      unsigned Val;
371
3.87k
      if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val))
372
0
        report_fatal_error("Bad $ operand number in inline asm string: '" +
373
0
                           Twine(AsmStr) + "'");
374
3.87k
      LastEmitted = IDEnd;
375
3.87k
376
3.87k
      char Modifier[2] = { 0, 0 };
377
3.87k
378
3.87k
      if (
HasCurlyBraces3.87k
) {
379
283
        // If we have curly braces, check for a modifier character.  This
380
283
        // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm.
381
283
        if (
*LastEmitted == ':'283
) {
382
276
          ++LastEmitted;    // Consume ':' character.
383
276
          if (*LastEmitted == 0)
384
0
            report_fatal_error("Bad ${:} expression in inline asm string: '" +
385
0
                               Twine(AsmStr) + "'");
386
276
387
276
          Modifier[0] = *LastEmitted;
388
276
          ++LastEmitted;    // Consume modifier character.
389
276
        }
390
283
391
283
        
if (283
*LastEmitted != '}'283
)
392
0
          report_fatal_error("Bad ${} expression in inline asm string: '" +
393
0
                             Twine(AsmStr) + "'");
394
283
        ++LastEmitted;    // Consume '}' character.
395
283
      }
396
3.87k
397
3.87k
      
if (3.87k
Val >= NumOperands-13.87k
)
398
0
        report_fatal_error("Invalid $ operand number in inline asm string: '" +
399
0
                           Twine(AsmStr) + "'");
400
3.87k
401
3.87k
      // Okay, we finally have a value number.  Ask the target to print this
402
3.87k
      // operand!
403
3.87k
      
if (3.87k
CurVariant == -1 || 3.87k
CurVariant == AsmPrinterVariant0
) {
404
3.87k
        unsigned OpNo = InlineAsm::MIOp_FirstOperand;
405
3.87k
406
3.87k
        bool Error = false;
407
3.87k
408
3.87k
        // Scan to find the machine operand number for the operand.
409
6.74k
        for (; 
Val6.74k
;
--Val2.87k
) {
410
2.87k
          if (
OpNo >= MI->getNumOperands()2.87k
)
break0
;
411
2.87k
          unsigned OpFlags = MI->getOperand(OpNo).getImm();
412
2.87k
          OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
413
2.87k
        }
414
3.87k
415
3.87k
        // We may have a location metadata attached to the end of the
416
3.87k
        // instruction, and at no point should see metadata at any
417
3.87k
        // other point while processing. It's an error if so.
418
3.87k
        if (OpNo >= MI->getNumOperands() ||
419
3.87k
            
MI->getOperand(OpNo).isMetadata()3.87k
) {
420
0
          Error = true;
421
3.87k
        } else {
422
3.87k
          unsigned OpFlags = MI->getOperand(OpNo).getImm();
423
3.87k
          ++OpNo;  // Skip over the ID number.
424
3.87k
425
3.87k
          if (
Modifier[0] == 'l'3.87k
) { // Labels are target independent.
426
2
            // FIXME: What if the operand isn't an MBB, report error?
427
2
            const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol();
428
2
            Sym->print(OS, AP->MAI);
429
3.87k
          } else {
430
3.87k
            if (
InlineAsm::isMemKind(OpFlags)3.87k
) {
431
326
              Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant,
432
326
                                                Modifier[0] ? 
Modifier10
:
nullptr316
,
433
326
                                                OS);
434
3.87k
            } else {
435
3.54k
              Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant,
436
3.54k
                                          Modifier[0] ? 
Modifier264
:
nullptr3.28k
, OS);
437
3.54k
            }
438
3.87k
          }
439
3.87k
        }
440
3.87k
        if (
Error3.87k
) {
441
0
          std::string msg;
442
0
          raw_string_ostream Msg(msg);
443
0
          Msg << "invalid operand in inline asm: '" << AsmStr << "'";
444
0
          MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
445
0
        }
446
3.87k
      }
447
4.62k
      break;
448
4.62k
    }
449
15.8k
    }
450
15.8k
  }
451
5.30k
  OS << '\n' << (char)0;  // null terminate string.
452
5.30k
}
453
454
/// EmitInlineAsm - This method formats and emits the specified machine
455
/// instruction that is an inline asm.
456
11.2k
void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
457
11.2k
  assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms");
458
11.2k
459
11.2k
  // Count the number of register definitions to find the asm string.
460
11.2k
  unsigned NumDefs = 0;
461
11.2k
  for (; 
MI->getOperand(NumDefs).isReg() && 11.2k
MI->getOperand(NumDefs).isDef()0
;
462
0
       ++NumDefs)
463
11.2k
    assert(NumDefs != MI->getNumOperands()-2 && "No asm string?");
464
11.2k
465
11.2k
  assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?");
466
11.2k
467
11.2k
  // Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
468
11.2k
  const char *AsmStr = MI->getOperand(NumDefs).getSymbolName();
469
11.2k
470
11.2k
  // If this asmstr is empty, just print the #APP/#NOAPP markers.
471
11.2k
  // These are useful to see where empty asm's wound up.
472
11.2k
  if (
AsmStr[0] == 011.2k
) {
473
5.87k
    OutStreamer->emitRawComment(MAI->getInlineAsmStart());
474
5.87k
    OutStreamer->emitRawComment(MAI->getInlineAsmEnd());
475
5.87k
    return;
476
5.87k
  }
477
5.33k
478
5.33k
  // Emit the #APP start marker.  This has to happen even if verbose-asm isn't
479
5.33k
  // enabled, so we use emitRawComment.
480
5.33k
  OutStreamer->emitRawComment(MAI->getInlineAsmStart());
481
5.33k
482
5.33k
  // Get the !srcloc metadata node if we have it, and decode the loc cookie from
483
5.33k
  // it.
484
5.33k
  unsigned LocCookie = 0;
485
5.33k
  const MDNode *LocMD = nullptr;
486
102k
  for (unsigned i = MI->getNumOperands(); 
i != 0102k
;
--i97.1k
) {
487
98.2k
    if (MI->getOperand(i-1).isMetadata() &&
488
1.04k
        (LocMD = MI->getOperand(i-1).getMetadata()) &&
489
98.2k
        
LocMD->getNumOperands() != 01.04k
) {
490
1.04k
      if (const ConstantInt *CI =
491
1.04k
              mdconst::dyn_extract<ConstantInt>(LocMD->getOperand(0))) {
492
1.04k
        LocCookie = CI->getZExtValue();
493
1.04k
        break;
494
1.04k
      }
495
1.04k
    }
496
98.2k
  }
497
5.33k
498
5.33k
  // Emit the inline asm to a temporary string so we can emit it through
499
5.33k
  // EmitInlineAsm.
500
5.33k
  SmallString<256> StringData;
501
5.33k
  raw_svector_ostream OS(StringData);
502
5.33k
503
5.33k
  // The variant of the current asmprinter.
504
5.33k
  int AsmPrinterVariant = MAI->getAssemblerDialect();
505
5.33k
  InlineAsm::AsmDialect InlineAsmVariant = MI->getInlineAsmDialect();
506
5.33k
  AsmPrinter *AP = const_cast<AsmPrinter*>(this);
507
5.33k
  if (InlineAsmVariant == InlineAsm::AD_ATT)
508
5.30k
    EmitGCCInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AsmPrinterVariant,
509
5.30k
                        AP, LocCookie, OS);
510
5.33k
  else
511
27
    EmitMSInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AP, LocCookie, OS);
512
11.2k
513
11.2k
  // Reset SanitizeAddress based on the function's attribute.
514
11.2k
  MCTargetOptions MCOptions = TM.Options.MCOptions;
515
11.2k
  MCOptions.SanitizeAddress =
516
11.2k
      MF->getFunction()->hasFnAttribute(Attribute::SanitizeAddress);
517
11.2k
518
11.2k
  EmitInlineAsm(OS.str(), getSubtargetInfo(), MCOptions, LocMD,
519
11.2k
                MI->getInlineAsmDialect());
520
11.2k
521
11.2k
  // Emit the #NOAPP end marker.  This has to happen even if verbose-asm isn't
522
11.2k
  // enabled, so we use emitRawComment.
523
11.2k
  OutStreamer->emitRawComment(MAI->getInlineAsmEnd());
524
11.2k
}
525
526
527
/// PrintSpecial - Print information related to the specified machine instr
528
/// that is independent of the operand, and may be independent of the instr
529
/// itself.  This can be useful for portably encoding the comment character
530
/// or other bits of target-specific knowledge into the asmstrings.  The
531
/// syntax used is ${:comment}.  Targets can override this to add support
532
/// for their own strange codes.
533
void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
534
6
                              const char *Code) const {
535
6
  if (
!strcmp(Code, "private")6
) {
536
0
    const DataLayout &DL = MF->getDataLayout();
537
0
    OS << DL.getPrivateGlobalPrefix();
538
6
  } else 
if (6
!strcmp(Code, "comment")6
) {
539
0
    OS << MAI->getCommentString();
540
6
  } else 
if (6
!strcmp(Code, "uid")6
) {
541
6
    // Comparing the address of MI isn't sufficient, because machineinstrs may
542
6
    // be allocated to the same address across functions.
543
6
544
6
    // If this is a new LastFn instruction, bump the counter.
545
6
    if (
LastMI != MI || 6
LastFn != getFunctionNumber()3
) {
546
3
      ++Counter;
547
3
      LastMI = MI;
548
3
      LastFn = getFunctionNumber();
549
3
    }
550
6
    OS << Counter;
551
0
  } else {
552
0
    std::string msg;
553
0
    raw_string_ostream Msg(msg);
554
0
    Msg << "Unknown special formatter '" << Code
555
0
         << "' for machine instr: " << *MI;
556
0
    report_fatal_error(Msg.str());
557
0
  }
558
6
}
559
560
/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
561
/// instruction, using the specified assembler variant.  Targets should
562
/// override this to format as appropriate.
563
bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
564
                                 unsigned AsmVariant, const char *ExtraCode,
565
694
                                 raw_ostream &O) {
566
694
  // Does this asm operand have a single letter operand modifier?
567
694
  if (
ExtraCode && 694
ExtraCode[0]53
) {
568
53
    if (
ExtraCode[1] != 053
)
return true0
; // Unknown modifier.
569
53
570
53
    const MachineOperand &MO = MI->getOperand(OpNo);
571
53
    switch (ExtraCode[0]) {
572
37
    default:
573
37
      return true;  // Unknown modifier.
574
5
    case 'c': // Substitute immediate value without immediate syntax
575
5
      if (MO.getType() != MachineOperand::MO_Immediate)
576
0
        return true;
577
5
      O << MO.getImm();
578
5
      return false;
579
5
    case 'n':  // Negate the immediate constant.
580
5
      if (MO.getType() != MachineOperand::MO_Immediate)
581
0
        return true;
582
5
      O << -MO.getImm();
583
5
      return false;
584
6
    case 's':  // The GCC deprecated s modifier
585
6
      if (MO.getType() != MachineOperand::MO_Immediate)
586
5
        return true;
587
1
      O << ((32 - MO.getImm()) & 31);
588
1
      return false;
589
53
    }
590
53
  }
591
641
  return true;
592
641
}
593
594
bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
595
                                       unsigned AsmVariant,
596
0
                                       const char *ExtraCode, raw_ostream &O) {
597
0
  // Target doesn't support this yet!
598
0
  return true;
599
0
}
600
601
5.27k
void AsmPrinter::emitInlineAsmStart() const {}
602
603
void AsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
604
4.84k
                                  const MCSubtargetInfo *EndInfo) const {}