1 //===-- AsmPrinterInlineAsm.cpp - AsmPrinter Inline Asm Handling ----------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the inline assembler pieces of the AsmPrinter class.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ADT/SmallString.h"
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/CodeGen/AsmPrinter.h"
16 #include "llvm/CodeGen/MachineBasicBlock.h"
17 #include "llvm/CodeGen/MachineFunction.h"
18 #include "llvm/CodeGen/MachineModuleInfo.h"
19 #include "llvm/CodeGen/TargetInstrInfo.h"
20 #include "llvm/CodeGen/TargetRegisterInfo.h"
21 #include "llvm/IR/Constants.h"
22 #include "llvm/IR/DataLayout.h"
23 #include "llvm/IR/InlineAsm.h"
24 #include "llvm/IR/LLVMContext.h"
25 #include "llvm/IR/Module.h"
26 #include "llvm/MC/MCAsmInfo.h"
27 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
28 #include "llvm/MC/MCStreamer.h"
29 #include "llvm/MC/MCSubtargetInfo.h"
30 #include "llvm/MC/MCSymbol.h"
31 #include "llvm/Support/ErrorHandling.h"
32 #include "llvm/Support/MemoryBuffer.h"
33 #include "llvm/Support/SourceMgr.h"
34 #include "llvm/Support/TargetRegistry.h"
35 #include "llvm/Support/raw_ostream.h"
36 #include "llvm/Target/TargetMachine.h"
39 #define DEBUG_TYPE "asm-printer"
41 /// srcMgrDiagHandler - This callback is invoked when the SourceMgr for an
42 /// inline asm has an error in it. diagInfo is a pointer to the SrcMgrDiagInfo
44 static void srcMgrDiagHandler(const SMDiagnostic
&Diag
, void *diagInfo
) {
45 AsmPrinter::SrcMgrDiagInfo
*DiagInfo
=
46 static_cast<AsmPrinter::SrcMgrDiagInfo
*>(diagInfo
);
47 assert(DiagInfo
&& "Diagnostic context not passed down?");
49 // Look up a LocInfo for the buffer this diagnostic is coming from.
50 unsigned BufNum
= DiagInfo
->SrcMgr
.FindBufferContainingLoc(Diag
.getLoc());
51 const MDNode
*LocInfo
= nullptr;
52 if (BufNum
> 0 && BufNum
<= DiagInfo
->LocInfos
.size())
53 LocInfo
= DiagInfo
->LocInfos
[BufNum
-1];
55 // If the inline asm had metadata associated with it, pull out a location
56 // cookie corresponding to which line the error occurred on.
57 unsigned LocCookie
= 0;
59 unsigned ErrorLine
= Diag
.getLineNo()-1;
60 if (ErrorLine
>= LocInfo
->getNumOperands())
63 if (LocInfo
->getNumOperands() != 0)
64 if (const ConstantInt
*CI
=
65 mdconst::dyn_extract
<ConstantInt
>(LocInfo
->getOperand(ErrorLine
)))
66 LocCookie
= CI
->getZExtValue();
69 DiagInfo
->DiagHandler(Diag
, DiagInfo
->DiagContext
, LocCookie
);
72 unsigned AsmPrinter::addInlineAsmDiagBuffer(StringRef AsmStr
,
73 const MDNode
*LocMDNode
) const {
75 DiagInfo
= make_unique
<SrcMgrDiagInfo
>();
77 MCContext
&Context
= MMI
->getContext();
78 Context
.setInlineSourceManager(&DiagInfo
->SrcMgr
);
80 LLVMContext
&LLVMCtx
= MMI
->getModule()->getContext();
81 if (LLVMCtx
.getInlineAsmDiagnosticHandler()) {
82 DiagInfo
->DiagHandler
= LLVMCtx
.getInlineAsmDiagnosticHandler();
83 DiagInfo
->DiagContext
= LLVMCtx
.getInlineAsmDiagnosticContext();
84 DiagInfo
->SrcMgr
.setDiagHandler(srcMgrDiagHandler
, DiagInfo
.get());
88 SourceMgr
&SrcMgr
= DiagInfo
->SrcMgr
;
90 std::unique_ptr
<MemoryBuffer
> Buffer
;
91 // The inline asm source manager will outlive AsmStr, so make a copy of the
92 // string for SourceMgr to own.
93 Buffer
= MemoryBuffer::getMemBufferCopy(AsmStr
, "<inline asm>");
95 // Tell SrcMgr about this buffer, it takes ownership of the buffer.
96 unsigned BufNum
= SrcMgr
.AddNewSourceBuffer(std::move(Buffer
), SMLoc());
98 // Store LocMDNode in DiagInfo, using BufNum as an identifier.
100 DiagInfo
->LocInfos
.resize(BufNum
);
101 DiagInfo
->LocInfos
[BufNum
- 1] = LocMDNode
;
108 /// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
109 void AsmPrinter::EmitInlineAsm(StringRef Str
, const MCSubtargetInfo
&STI
,
110 const MCTargetOptions
&MCOptions
,
111 const MDNode
*LocMDNode
,
112 InlineAsm::AsmDialect Dialect
) const {
113 assert(!Str
.empty() && "Can't emit empty inline asm block");
115 // Remember if the buffer is nul terminated or not so we can avoid a copy.
116 bool isNullTerminated
= Str
.back() == 0;
117 if (isNullTerminated
)
118 Str
= Str
.substr(0, Str
.size()-1);
120 // If the output streamer does not have mature MC support or the integrated
121 // assembler has been disabled, just emit the blob textually.
122 // Otherwise parse the asm and emit it via MC support.
123 // This is useful in case the asm parser doesn't handle something but the
124 // system assembler does.
125 const MCAsmInfo
*MCAI
= TM
.getMCAsmInfo();
126 assert(MCAI
&& "No MCAsmInfo");
127 if (!MCAI
->useIntegratedAssembler() &&
128 !OutStreamer
->isIntegratedAssemblerRequired()) {
129 emitInlineAsmStart();
130 OutStreamer
->EmitRawText(Str
);
131 emitInlineAsmEnd(STI
, nullptr);
135 unsigned BufNum
= addInlineAsmDiagBuffer(Str
, LocMDNode
);
136 DiagInfo
->SrcMgr
.setIncludeDirs(MCOptions
.IASSearchPaths
);
138 std::unique_ptr
<MCAsmParser
> Parser(createMCAsmParser(
139 DiagInfo
->SrcMgr
, OutContext
, *OutStreamer
, *MAI
, BufNum
));
141 // Do not use assembler-level information for parsing inline assembly.
142 OutStreamer
->setUseAssemblerInfoForParsing(false);
144 // We create a new MCInstrInfo here since we might be at the module level
145 // and not have a MachineFunction to initialize the TargetInstrInfo from and
146 // we only need MCInstrInfo for asm parsing. We create one unconditionally
147 // because it's not subtarget dependent.
148 std::unique_ptr
<MCInstrInfo
> MII(TM
.getTarget().createMCInstrInfo());
149 std::unique_ptr
<MCTargetAsmParser
> TAP(TM
.getTarget().createMCAsmParser(
150 STI
, *Parser
, *MII
, MCOptions
));
152 report_fatal_error("Inline asm not supported by this streamer because"
153 " we don't have an asm parser for this target\n");
154 Parser
->setAssemblerDialect(Dialect
);
155 Parser
->setTargetParser(*TAP
.get());
156 // Enable lexing Masm binary and hex integer literals in intel inline
158 if (Dialect
== InlineAsm::AD_Intel
)
159 Parser
->getLexer().setLexMasmIntegers(true);
161 emitInlineAsmStart();
162 // Don't implicitly switch to the text section before the asm.
163 int Res
= Parser
->Run(/*NoInitialTextSection*/ true,
164 /*NoFinalize*/ true);
165 emitInlineAsmEnd(STI
, &TAP
->getSTI());
167 if (Res
&& !DiagInfo
->DiagHandler
)
168 report_fatal_error("Error parsing inline asm\n");
171 static void EmitMSInlineAsmStr(const char *AsmStr
, const MachineInstr
*MI
,
172 MachineModuleInfo
*MMI
, AsmPrinter
*AP
,
173 unsigned LocCookie
, raw_ostream
&OS
) {
174 // Switch to the inline assembly variant.
175 OS
<< "\t.intel_syntax\n\t";
177 const char *LastEmitted
= AsmStr
; // One past the last character emitted.
178 unsigned NumOperands
= MI
->getNumOperands();
180 while (*LastEmitted
) {
181 switch (*LastEmitted
) {
183 // Not a special case, emit the string section literally.
184 const char *LiteralEnd
= LastEmitted
+1;
185 while (*LiteralEnd
&& *LiteralEnd
!= '{' && *LiteralEnd
!= '|' &&
186 *LiteralEnd
!= '}' && *LiteralEnd
!= '$' && *LiteralEnd
!= '\n')
189 OS
.write(LastEmitted
, LiteralEnd
-LastEmitted
);
190 LastEmitted
= LiteralEnd
;
194 ++LastEmitted
; // Consume newline character.
195 OS
<< '\n'; // Indent code with newline.
198 ++LastEmitted
; // Consume '$' character.
202 switch (*LastEmitted
) {
203 default: Done
= false; break;
205 ++LastEmitted
; // Consume second '$' character.
210 // If we have ${:foo}, then this is not a real operand reference, it is a
211 // "magic" string reference, just like in .td files. Arrange to call
213 if (LastEmitted
[0] == '{' && LastEmitted
[1] == ':') {
215 const char *StrStart
= LastEmitted
;
216 const char *StrEnd
= strchr(StrStart
, '}');
218 report_fatal_error("Unterminated ${:foo} operand in inline asm"
219 " string: '" + Twine(AsmStr
) + "'");
221 std::string
Val(StrStart
, StrEnd
);
222 AP
->PrintSpecial(MI
, OS
, Val
.c_str());
223 LastEmitted
= StrEnd
+1;
227 const char *IDStart
= LastEmitted
;
228 const char *IDEnd
= IDStart
;
229 while (*IDEnd
>= '0' && *IDEnd
<= '9') ++IDEnd
;
232 if (StringRef(IDStart
, IDEnd
-IDStart
).getAsInteger(10, Val
))
233 report_fatal_error("Bad $ operand number in inline asm string: '" +
234 Twine(AsmStr
) + "'");
237 if (Val
>= NumOperands
-1)
238 report_fatal_error("Invalid $ operand number in inline asm string: '" +
239 Twine(AsmStr
) + "'");
241 // Okay, we finally have a value number. Ask the target to print this
243 unsigned OpNo
= InlineAsm::MIOp_FirstOperand
;
247 // Scan to find the machine operand number for the operand.
249 if (OpNo
>= MI
->getNumOperands()) break;
250 unsigned OpFlags
= MI
->getOperand(OpNo
).getImm();
251 OpNo
+= InlineAsm::getNumOperandRegisters(OpFlags
) + 1;
254 // We may have a location metadata attached to the end of the
255 // instruction, and at no point should see metadata at any
256 // other point while processing. It's an error if so.
257 if (OpNo
>= MI
->getNumOperands() ||
258 MI
->getOperand(OpNo
).isMetadata()) {
261 unsigned OpFlags
= MI
->getOperand(OpNo
).getImm();
262 ++OpNo
; // Skip over the ID number.
264 if (InlineAsm::isMemKind(OpFlags
)) {
265 Error
= AP
->PrintAsmMemoryOperand(MI
, OpNo
, /*Modifier*/ nullptr, OS
);
267 Error
= AP
->PrintAsmOperand(MI
, OpNo
, /*Modifier*/ nullptr, OS
);
272 raw_string_ostream
Msg(msg
);
273 Msg
<< "invalid operand in inline asm: '" << AsmStr
<< "'";
274 MMI
->getModule()->getContext().emitError(LocCookie
, Msg
.str());
280 OS
<< "\n\t.att_syntax\n" << (char)0; // null terminate string.
283 static void EmitGCCInlineAsmStr(const char *AsmStr
, const MachineInstr
*MI
,
284 MachineModuleInfo
*MMI
, int AsmPrinterVariant
,
285 AsmPrinter
*AP
, unsigned LocCookie
,
287 int CurVariant
= -1; // The number of the {.|.|.} region we are in.
288 const char *LastEmitted
= AsmStr
; // One past the last character emitted.
289 unsigned NumOperands
= MI
->getNumOperands();
293 while (*LastEmitted
) {
294 switch (*LastEmitted
) {
296 // Not a special case, emit the string section literally.
297 const char *LiteralEnd
= LastEmitted
+1;
298 while (*LiteralEnd
&& *LiteralEnd
!= '{' && *LiteralEnd
!= '|' &&
299 *LiteralEnd
!= '}' && *LiteralEnd
!= '$' && *LiteralEnd
!= '\n')
301 if (CurVariant
== -1 || CurVariant
== AsmPrinterVariant
)
302 OS
.write(LastEmitted
, LiteralEnd
-LastEmitted
);
303 LastEmitted
= LiteralEnd
;
307 ++LastEmitted
; // Consume newline character.
308 OS
<< '\n'; // Indent code with newline.
311 ++LastEmitted
; // Consume '$' character.
315 switch (*LastEmitted
) {
316 default: Done
= false; break;
318 if (CurVariant
== -1 || CurVariant
== AsmPrinterVariant
)
320 ++LastEmitted
; // Consume second '$' character.
322 case '(': // $( -> same as GCC's { character.
323 ++LastEmitted
; // Consume '(' character.
324 if (CurVariant
!= -1)
325 report_fatal_error("Nested variants found in inline asm string: '" +
326 Twine(AsmStr
) + "'");
327 CurVariant
= 0; // We're in the first variant now.
330 ++LastEmitted
; // consume '|' character.
331 if (CurVariant
== -1)
332 OS
<< '|'; // this is gcc's behavior for | outside a variant
334 ++CurVariant
; // We're in the next variant.
336 case ')': // $) -> same as GCC's } char.
337 ++LastEmitted
; // consume ')' character.
338 if (CurVariant
== -1)
339 OS
<< '}'; // this is gcc's behavior for } outside a variant
346 bool HasCurlyBraces
= false;
347 if (*LastEmitted
== '{') { // ${variable}
348 ++LastEmitted
; // Consume '{' character.
349 HasCurlyBraces
= true;
352 // If we have ${:foo}, then this is not a real operand reference, it is a
353 // "magic" string reference, just like in .td files. Arrange to call
355 if (HasCurlyBraces
&& *LastEmitted
== ':') {
357 const char *StrStart
= LastEmitted
;
358 const char *StrEnd
= strchr(StrStart
, '}');
360 report_fatal_error("Unterminated ${:foo} operand in inline asm"
361 " string: '" + Twine(AsmStr
) + "'");
363 std::string
Val(StrStart
, StrEnd
);
364 AP
->PrintSpecial(MI
, OS
, Val
.c_str());
365 LastEmitted
= StrEnd
+1;
369 const char *IDStart
= LastEmitted
;
370 const char *IDEnd
= IDStart
;
371 while (*IDEnd
>= '0' && *IDEnd
<= '9') ++IDEnd
;
374 if (StringRef(IDStart
, IDEnd
-IDStart
).getAsInteger(10, Val
))
375 report_fatal_error("Bad $ operand number in inline asm string: '" +
376 Twine(AsmStr
) + "'");
379 char Modifier
[2] = { 0, 0 };
381 if (HasCurlyBraces
) {
382 // If we have curly braces, check for a modifier character. This
383 // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm.
384 if (*LastEmitted
== ':') {
385 ++LastEmitted
; // Consume ':' character.
386 if (*LastEmitted
== 0)
387 report_fatal_error("Bad ${:} expression in inline asm string: '" +
388 Twine(AsmStr
) + "'");
390 Modifier
[0] = *LastEmitted
;
391 ++LastEmitted
; // Consume modifier character.
394 if (*LastEmitted
!= '}')
395 report_fatal_error("Bad ${} expression in inline asm string: '" +
396 Twine(AsmStr
) + "'");
397 ++LastEmitted
; // Consume '}' character.
400 if (Val
>= NumOperands
-1)
401 report_fatal_error("Invalid $ operand number in inline asm string: '" +
402 Twine(AsmStr
) + "'");
404 // Okay, we finally have a value number. Ask the target to print this
406 if (CurVariant
== -1 || CurVariant
== AsmPrinterVariant
) {
407 unsigned OpNo
= InlineAsm::MIOp_FirstOperand
;
411 // Scan to find the machine operand number for the operand.
413 if (OpNo
>= MI
->getNumOperands()) break;
414 unsigned OpFlags
= MI
->getOperand(OpNo
).getImm();
415 OpNo
+= InlineAsm::getNumOperandRegisters(OpFlags
) + 1;
418 // We may have a location metadata attached to the end of the
419 // instruction, and at no point should see metadata at any
420 // other point while processing. It's an error if so.
421 if (OpNo
>= MI
->getNumOperands() ||
422 MI
->getOperand(OpNo
).isMetadata()) {
425 unsigned OpFlags
= MI
->getOperand(OpNo
).getImm();
426 ++OpNo
; // Skip over the ID number.
428 // FIXME: Shouldn't arch-independent output template handling go into
430 if (Modifier
[0] == 'l') { // Labels are target independent.
431 if (MI
->getOperand(OpNo
).isBlockAddress()) {
432 const BlockAddress
*BA
= MI
->getOperand(OpNo
).getBlockAddress();
433 MCSymbol
*Sym
= AP
->GetBlockAddressSymbol(BA
);
434 Sym
->print(OS
, AP
->MAI
);
435 } else if (MI
->getOperand(OpNo
).isMBB()) {
436 const MCSymbol
*Sym
= MI
->getOperand(OpNo
).getMBB()->getSymbol();
437 Sym
->print(OS
, AP
->MAI
);
442 if (InlineAsm::isMemKind(OpFlags
)) {
443 Error
= AP
->PrintAsmMemoryOperand(
444 MI
, OpNo
, Modifier
[0] ? Modifier
: nullptr, OS
);
446 Error
= AP
->PrintAsmOperand(MI
, OpNo
,
447 Modifier
[0] ? Modifier
: nullptr, OS
);
453 raw_string_ostream
Msg(msg
);
454 Msg
<< "invalid operand in inline asm: '" << AsmStr
<< "'";
455 MMI
->getModule()->getContext().emitError(LocCookie
, Msg
.str());
462 OS
<< '\n' << (char)0; // null terminate string.
465 /// EmitInlineAsm - This method formats and emits the specified machine
466 /// instruction that is an inline asm.
467 void AsmPrinter::EmitInlineAsm(const MachineInstr
*MI
) const {
468 assert(MI
->isInlineAsm() && "printInlineAsm only works on inline asms");
470 // Count the number of register definitions to find the asm string.
471 unsigned NumDefs
= 0;
472 for (; MI
->getOperand(NumDefs
).isReg() && MI
->getOperand(NumDefs
).isDef();
474 assert(NumDefs
!= MI
->getNumOperands()-2 && "No asm string?");
476 assert(MI
->getOperand(NumDefs
).isSymbol() && "No asm string?");
478 // Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
479 const char *AsmStr
= MI
->getOperand(NumDefs
).getSymbolName();
481 // If this asmstr is empty, just print the #APP/#NOAPP markers.
482 // These are useful to see where empty asm's wound up.
483 if (AsmStr
[0] == 0) {
484 OutStreamer
->emitRawComment(MAI
->getInlineAsmStart());
485 OutStreamer
->emitRawComment(MAI
->getInlineAsmEnd());
489 // Emit the #APP start marker. This has to happen even if verbose-asm isn't
490 // enabled, so we use emitRawComment.
491 OutStreamer
->emitRawComment(MAI
->getInlineAsmStart());
493 // Get the !srcloc metadata node if we have it, and decode the loc cookie from
495 unsigned LocCookie
= 0;
496 const MDNode
*LocMD
= nullptr;
497 for (unsigned i
= MI
->getNumOperands(); i
!= 0; --i
) {
498 if (MI
->getOperand(i
-1).isMetadata() &&
499 (LocMD
= MI
->getOperand(i
-1).getMetadata()) &&
500 LocMD
->getNumOperands() != 0) {
501 if (const ConstantInt
*CI
=
502 mdconst::dyn_extract
<ConstantInt
>(LocMD
->getOperand(0))) {
503 LocCookie
= CI
->getZExtValue();
509 // Emit the inline asm to a temporary string so we can emit it through
511 SmallString
<256> StringData
;
512 raw_svector_ostream
OS(StringData
);
514 // The variant of the current asmprinter.
515 int AsmPrinterVariant
= MAI
->getAssemblerDialect();
516 AsmPrinter
*AP
= const_cast<AsmPrinter
*>(this);
517 if (MI
->getInlineAsmDialect() == InlineAsm::AD_ATT
)
518 EmitGCCInlineAsmStr(AsmStr
, MI
, MMI
, AsmPrinterVariant
, AP
, LocCookie
, OS
);
520 EmitMSInlineAsmStr(AsmStr
, MI
, MMI
, AP
, LocCookie
, OS
);
522 // Emit warnings if we use reserved registers on the clobber list, as
523 // that might give surprising results.
524 std::vector
<std::string
> RestrRegs
;
525 // Start with the first operand descriptor, and iterate over them.
526 for (unsigned I
= InlineAsm::MIOp_FirstOperand
, NumOps
= MI
->getNumOperands();
528 const MachineOperand
&MO
= MI
->getOperand(I
);
530 unsigned Flags
= MO
.getImm();
531 const TargetRegisterInfo
*TRI
= MF
->getSubtarget().getRegisterInfo();
532 if (InlineAsm::getKind(Flags
) == InlineAsm::Kind_Clobber
&&
533 !TRI
->isAsmClobberable(*MF
, MI
->getOperand(I
+ 1).getReg())) {
534 RestrRegs
.push_back(TRI
->getName(MI
->getOperand(I
+ 1).getReg()));
536 // Skip to one before the next operand descriptor, if it exists.
537 I
+= InlineAsm::getNumOperandRegisters(Flags
);
541 if (!RestrRegs
.empty()) {
542 unsigned BufNum
= addInlineAsmDiagBuffer(OS
.str(), LocMD
);
543 auto &SrcMgr
= DiagInfo
->SrcMgr
;
544 SMLoc Loc
= SMLoc::getFromPointer(
545 SrcMgr
.getMemoryBuffer(BufNum
)->getBuffer().begin());
547 std::string Msg
= "inline asm clobber list contains reserved registers: ";
548 for (auto I
= RestrRegs
.begin(), E
= RestrRegs
.end(); I
!= E
; I
++) {
549 if(I
!= RestrRegs
.begin())
553 std::string Note
= "Reserved registers on the clobber list may not be "
554 "preserved across the asm statement, and clobbering them may "
555 "lead to undefined behaviour.";
556 SrcMgr
.PrintMessage(Loc
, SourceMgr::DK_Warning
, Msg
);
557 SrcMgr
.PrintMessage(Loc
, SourceMgr::DK_Note
, Note
);
560 EmitInlineAsm(OS
.str(), getSubtargetInfo(), TM
.Options
.MCOptions
, LocMD
,
561 MI
->getInlineAsmDialect());
563 // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't
564 // enabled, so we use emitRawComment.
565 OutStreamer
->emitRawComment(MAI
->getInlineAsmEnd());
569 /// PrintSpecial - Print information related to the specified machine instr
570 /// that is independent of the operand, and may be independent of the instr
571 /// itself. This can be useful for portably encoding the comment character
572 /// or other bits of target-specific knowledge into the asmstrings. The
573 /// syntax used is ${:comment}. Targets can override this to add support
574 /// for their own strange codes.
575 void AsmPrinter::PrintSpecial(const MachineInstr
*MI
, raw_ostream
&OS
,
576 const char *Code
) const {
577 if (!strcmp(Code
, "private")) {
578 const DataLayout
&DL
= MF
->getDataLayout();
579 OS
<< DL
.getPrivateGlobalPrefix();
580 } else if (!strcmp(Code
, "comment")) {
581 OS
<< MAI
->getCommentString();
582 } else if (!strcmp(Code
, "uid")) {
583 // Comparing the address of MI isn't sufficient, because machineinstrs may
584 // be allocated to the same address across functions.
586 // If this is a new LastFn instruction, bump the counter.
587 if (LastMI
!= MI
|| LastFn
!= getFunctionNumber()) {
590 LastFn
= getFunctionNumber();
595 raw_string_ostream
Msg(msg
);
596 Msg
<< "Unknown special formatter '" << Code
597 << "' for machine instr: " << *MI
;
598 report_fatal_error(Msg
.str());
602 void AsmPrinter::PrintSymbolOperand(const MachineOperand
&MO
, raw_ostream
&OS
) {
603 assert(MO
.isGlobal() && "caller should check MO.isGlobal");
604 getSymbol(MO
.getGlobal())->print(OS
, MAI
);
605 printOffset(MO
.getOffset(), OS
);
608 /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
609 /// instruction, using the specified assembler variant. Targets should
610 /// override this to format as appropriate for machine specific ExtraCodes
611 /// or when the arch-independent handling would be too complex otherwise.
612 bool AsmPrinter::PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
613 const char *ExtraCode
, raw_ostream
&O
) {
614 // Does this asm operand have a single letter operand modifier?
615 if (ExtraCode
&& ExtraCode
[0]) {
616 if (ExtraCode
[1] != 0) return true; // Unknown modifier.
618 // https://gcc.gnu.org/onlinedocs/gccint/Output-Template.html
619 const MachineOperand
&MO
= MI
->getOperand(OpNo
);
620 switch (ExtraCode
[0]) {
622 return true; // Unknown modifier.
623 case 'a': // Print as memory address.
625 PrintAsmMemoryOperand(MI
, OpNo
, nullptr, O
);
628 LLVM_FALLTHROUGH
; // GCC allows '%a' to behave like '%c' with immediates.
629 case 'c': // Substitute immediate value without immediate syntax
635 PrintSymbolOperand(MO
, O
);
639 case 'n': // Negate the immediate constant.
644 case 's': // The GCC deprecated s modifier
647 O
<< ((32 - MO
.getImm()) & 31);
654 bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
, unsigned OpNo
,
655 const char *ExtraCode
, raw_ostream
&O
) {
656 // Target doesn't support this yet!
660 void AsmPrinter::emitInlineAsmStart() const {}
662 void AsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo
&StartInfo
,
663 const MCSubtargetInfo
*EndInfo
) const {}