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 const TargetRegisterInfo
*TRI
= MF
->getSubtarget().getRegisterInfo();
162 TAP
->SetFrameRegister(TRI
->getFrameRegister(*MF
));
165 emitInlineAsmStart();
166 // Don't implicitly switch to the text section before the asm.
167 int Res
= Parser
->Run(/*NoInitialTextSection*/ true,
168 /*NoFinalize*/ true);
169 emitInlineAsmEnd(STI
, &TAP
->getSTI());
171 if (Res
&& !DiagInfo
->DiagHandler
)
172 report_fatal_error("Error parsing inline asm\n");
175 static void EmitMSInlineAsmStr(const char *AsmStr
, const MachineInstr
*MI
,
176 MachineModuleInfo
*MMI
, int InlineAsmVariant
,
177 AsmPrinter
*AP
, unsigned LocCookie
,
179 // Switch to the inline assembly variant.
180 OS
<< "\t.intel_syntax\n\t";
182 const char *LastEmitted
= AsmStr
; // One past the last character emitted.
183 unsigned NumOperands
= MI
->getNumOperands();
185 while (*LastEmitted
) {
186 switch (*LastEmitted
) {
188 // Not a special case, emit the string section literally.
189 const char *LiteralEnd
= LastEmitted
+1;
190 while (*LiteralEnd
&& *LiteralEnd
!= '{' && *LiteralEnd
!= '|' &&
191 *LiteralEnd
!= '}' && *LiteralEnd
!= '$' && *LiteralEnd
!= '\n')
194 OS
.write(LastEmitted
, LiteralEnd
-LastEmitted
);
195 LastEmitted
= LiteralEnd
;
199 ++LastEmitted
; // Consume newline character.
200 OS
<< '\n'; // Indent code with newline.
203 ++LastEmitted
; // Consume '$' character.
207 switch (*LastEmitted
) {
208 default: Done
= false; break;
210 ++LastEmitted
; // Consume second '$' character.
215 // If we have ${:foo}, then this is not a real operand reference, it is a
216 // "magic" string reference, just like in .td files. Arrange to call
218 if (LastEmitted
[0] == '{' && LastEmitted
[1] == ':') {
220 const char *StrStart
= LastEmitted
;
221 const char *StrEnd
= strchr(StrStart
, '}');
223 report_fatal_error("Unterminated ${:foo} operand in inline asm"
224 " string: '" + Twine(AsmStr
) + "'");
226 std::string
Val(StrStart
, StrEnd
);
227 AP
->PrintSpecial(MI
, OS
, Val
.c_str());
228 LastEmitted
= StrEnd
+1;
232 const char *IDStart
= LastEmitted
;
233 const char *IDEnd
= IDStart
;
234 while (*IDEnd
>= '0' && *IDEnd
<= '9') ++IDEnd
;
237 if (StringRef(IDStart
, IDEnd
-IDStart
).getAsInteger(10, Val
))
238 report_fatal_error("Bad $ operand number in inline asm string: '" +
239 Twine(AsmStr
) + "'");
242 if (Val
>= NumOperands
-1)
243 report_fatal_error("Invalid $ operand number in inline asm string: '" +
244 Twine(AsmStr
) + "'");
246 // Okay, we finally have a value number. Ask the target to print this
248 unsigned OpNo
= InlineAsm::MIOp_FirstOperand
;
252 // Scan to find the machine operand number for the operand.
254 if (OpNo
>= MI
->getNumOperands()) break;
255 unsigned OpFlags
= MI
->getOperand(OpNo
).getImm();
256 OpNo
+= InlineAsm::getNumOperandRegisters(OpFlags
) + 1;
259 // We may have a location metadata attached to the end of the
260 // instruction, and at no point should see metadata at any
261 // other point while processing. It's an error if so.
262 if (OpNo
>= MI
->getNumOperands() ||
263 MI
->getOperand(OpNo
).isMetadata()) {
266 unsigned OpFlags
= MI
->getOperand(OpNo
).getImm();
267 ++OpNo
; // Skip over the ID number.
269 if (InlineAsm::isMemKind(OpFlags
)) {
270 Error
= AP
->PrintAsmMemoryOperand(MI
, OpNo
, InlineAsmVariant
,
271 /*Modifier*/ nullptr, OS
);
273 Error
= AP
->PrintAsmOperand(MI
, OpNo
, InlineAsmVariant
,
274 /*Modifier*/ nullptr, OS
);
279 raw_string_ostream
Msg(msg
);
280 Msg
<< "invalid operand in inline asm: '" << AsmStr
<< "'";
281 MMI
->getModule()->getContext().emitError(LocCookie
, Msg
.str());
287 OS
<< "\n\t.att_syntax\n" << (char)0; // null terminate string.
290 static void EmitGCCInlineAsmStr(const char *AsmStr
, const MachineInstr
*MI
,
291 MachineModuleInfo
*MMI
, int InlineAsmVariant
,
292 int AsmPrinterVariant
, AsmPrinter
*AP
,
293 unsigned LocCookie
, raw_ostream
&OS
) {
294 int CurVariant
= -1; // The number of the {.|.|.} region we are in.
295 const char *LastEmitted
= AsmStr
; // One past the last character emitted.
296 unsigned NumOperands
= MI
->getNumOperands();
300 while (*LastEmitted
) {
301 switch (*LastEmitted
) {
303 // Not a special case, emit the string section literally.
304 const char *LiteralEnd
= LastEmitted
+1;
305 while (*LiteralEnd
&& *LiteralEnd
!= '{' && *LiteralEnd
!= '|' &&
306 *LiteralEnd
!= '}' && *LiteralEnd
!= '$' && *LiteralEnd
!= '\n')
308 if (CurVariant
== -1 || CurVariant
== AsmPrinterVariant
)
309 OS
.write(LastEmitted
, LiteralEnd
-LastEmitted
);
310 LastEmitted
= LiteralEnd
;
314 ++LastEmitted
; // Consume newline character.
315 OS
<< '\n'; // Indent code with newline.
318 ++LastEmitted
; // Consume '$' character.
322 switch (*LastEmitted
) {
323 default: Done
= false; break;
325 if (CurVariant
== -1 || CurVariant
== AsmPrinterVariant
)
327 ++LastEmitted
; // Consume second '$' character.
329 case '(': // $( -> same as GCC's { character.
330 ++LastEmitted
; // Consume '(' character.
331 if (CurVariant
!= -1)
332 report_fatal_error("Nested variants found in inline asm string: '" +
333 Twine(AsmStr
) + "'");
334 CurVariant
= 0; // We're in the first variant now.
337 ++LastEmitted
; // consume '|' character.
338 if (CurVariant
== -1)
339 OS
<< '|'; // this is gcc's behavior for | outside a variant
341 ++CurVariant
; // We're in the next variant.
343 case ')': // $) -> same as GCC's } char.
344 ++LastEmitted
; // consume ')' character.
345 if (CurVariant
== -1)
346 OS
<< '}'; // this is gcc's behavior for } outside a variant
353 bool HasCurlyBraces
= false;
354 if (*LastEmitted
== '{') { // ${variable}
355 ++LastEmitted
; // Consume '{' character.
356 HasCurlyBraces
= true;
359 // If we have ${:foo}, then this is not a real operand reference, it is a
360 // "magic" string reference, just like in .td files. Arrange to call
362 if (HasCurlyBraces
&& *LastEmitted
== ':') {
364 const char *StrStart
= LastEmitted
;
365 const char *StrEnd
= strchr(StrStart
, '}');
367 report_fatal_error("Unterminated ${:foo} operand in inline asm"
368 " string: '" + Twine(AsmStr
) + "'");
370 std::string
Val(StrStart
, StrEnd
);
371 AP
->PrintSpecial(MI
, OS
, Val
.c_str());
372 LastEmitted
= StrEnd
+1;
376 const char *IDStart
= LastEmitted
;
377 const char *IDEnd
= IDStart
;
378 while (*IDEnd
>= '0' && *IDEnd
<= '9') ++IDEnd
;
381 if (StringRef(IDStart
, IDEnd
-IDStart
).getAsInteger(10, Val
))
382 report_fatal_error("Bad $ operand number in inline asm string: '" +
383 Twine(AsmStr
) + "'");
386 char Modifier
[2] = { 0, 0 };
388 if (HasCurlyBraces
) {
389 // If we have curly braces, check for a modifier character. This
390 // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm.
391 if (*LastEmitted
== ':') {
392 ++LastEmitted
; // Consume ':' character.
393 if (*LastEmitted
== 0)
394 report_fatal_error("Bad ${:} expression in inline asm string: '" +
395 Twine(AsmStr
) + "'");
397 Modifier
[0] = *LastEmitted
;
398 ++LastEmitted
; // Consume modifier character.
401 if (*LastEmitted
!= '}')
402 report_fatal_error("Bad ${} expression in inline asm string: '" +
403 Twine(AsmStr
) + "'");
404 ++LastEmitted
; // Consume '}' character.
407 if (Val
>= NumOperands
-1)
408 report_fatal_error("Invalid $ operand number in inline asm string: '" +
409 Twine(AsmStr
) + "'");
411 // Okay, we finally have a value number. Ask the target to print this
413 if (CurVariant
== -1 || CurVariant
== AsmPrinterVariant
) {
414 unsigned OpNo
= InlineAsm::MIOp_FirstOperand
;
418 // Scan to find the machine operand number for the operand.
420 if (OpNo
>= MI
->getNumOperands()) break;
421 unsigned OpFlags
= MI
->getOperand(OpNo
).getImm();
422 OpNo
+= InlineAsm::getNumOperandRegisters(OpFlags
) + 1;
425 // We may have a location metadata attached to the end of the
426 // instruction, and at no point should see metadata at any
427 // other point while processing. It's an error if so.
428 if (OpNo
>= MI
->getNumOperands() ||
429 MI
->getOperand(OpNo
).isMetadata()) {
432 unsigned OpFlags
= MI
->getOperand(OpNo
).getImm();
433 ++OpNo
; // Skip over the ID number.
435 if (Modifier
[0] == 'l') { // Labels are target independent.
436 if (MI
->getOperand(OpNo
).isBlockAddress()) {
437 const BlockAddress
*BA
= MI
->getOperand(OpNo
).getBlockAddress();
438 MCSymbol
*Sym
= AP
->GetBlockAddressSymbol(BA
);
439 Sym
->print(OS
, AP
->MAI
);
440 } else if (MI
->getOperand(OpNo
).isMBB()) {
441 const MCSymbol
*Sym
= MI
->getOperand(OpNo
).getMBB()->getSymbol();
442 Sym
->print(OS
, AP
->MAI
);
447 if (InlineAsm::isMemKind(OpFlags
)) {
448 Error
= AP
->PrintAsmMemoryOperand(MI
, OpNo
, InlineAsmVariant
,
449 Modifier
[0] ? Modifier
: nullptr,
452 Error
= AP
->PrintAsmOperand(MI
, OpNo
, InlineAsmVariant
,
453 Modifier
[0] ? Modifier
: nullptr, OS
);
459 raw_string_ostream
Msg(msg
);
460 Msg
<< "invalid operand in inline asm: '" << AsmStr
<< "'";
461 MMI
->getModule()->getContext().emitError(LocCookie
, Msg
.str());
468 OS
<< '\n' << (char)0; // null terminate string.
471 /// EmitInlineAsm - This method formats and emits the specified machine
472 /// instruction that is an inline asm.
473 void AsmPrinter::EmitInlineAsm(const MachineInstr
*MI
) const {
474 assert(MI
->isInlineAsm() && "printInlineAsm only works on inline asms");
476 // Count the number of register definitions to find the asm string.
477 unsigned NumDefs
= 0;
478 for (; MI
->getOperand(NumDefs
).isReg() && MI
->getOperand(NumDefs
).isDef();
480 assert(NumDefs
!= MI
->getNumOperands()-2 && "No asm string?");
482 assert(MI
->getOperand(NumDefs
).isSymbol() && "No asm string?");
484 // Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
485 const char *AsmStr
= MI
->getOperand(NumDefs
).getSymbolName();
487 // If this asmstr is empty, just print the #APP/#NOAPP markers.
488 // These are useful to see where empty asm's wound up.
489 if (AsmStr
[0] == 0) {
490 OutStreamer
->emitRawComment(MAI
->getInlineAsmStart());
491 OutStreamer
->emitRawComment(MAI
->getInlineAsmEnd());
495 // Emit the #APP start marker. This has to happen even if verbose-asm isn't
496 // enabled, so we use emitRawComment.
497 OutStreamer
->emitRawComment(MAI
->getInlineAsmStart());
499 // Get the !srcloc metadata node if we have it, and decode the loc cookie from
501 unsigned LocCookie
= 0;
502 const MDNode
*LocMD
= nullptr;
503 for (unsigned i
= MI
->getNumOperands(); i
!= 0; --i
) {
504 if (MI
->getOperand(i
-1).isMetadata() &&
505 (LocMD
= MI
->getOperand(i
-1).getMetadata()) &&
506 LocMD
->getNumOperands() != 0) {
507 if (const ConstantInt
*CI
=
508 mdconst::dyn_extract
<ConstantInt
>(LocMD
->getOperand(0))) {
509 LocCookie
= CI
->getZExtValue();
515 // Emit the inline asm to a temporary string so we can emit it through
517 SmallString
<256> StringData
;
518 raw_svector_ostream
OS(StringData
);
520 // The variant of the current asmprinter.
521 int AsmPrinterVariant
= MAI
->getAssemblerDialect();
522 InlineAsm::AsmDialect InlineAsmVariant
= MI
->getInlineAsmDialect();
523 AsmPrinter
*AP
= const_cast<AsmPrinter
*>(this);
524 if (InlineAsmVariant
== InlineAsm::AD_ATT
)
525 EmitGCCInlineAsmStr(AsmStr
, MI
, MMI
, InlineAsmVariant
, AsmPrinterVariant
,
528 EmitMSInlineAsmStr(AsmStr
, MI
, MMI
, InlineAsmVariant
, AP
, LocCookie
, OS
);
530 // Reset SanitizeAddress based on the function's attribute.
531 MCTargetOptions MCOptions
= TM
.Options
.MCOptions
;
532 MCOptions
.SanitizeAddress
=
533 MF
->getFunction().hasFnAttribute(Attribute::SanitizeAddress
);
535 // Emit warnings if we use reserved registers on the clobber list, as
536 // that might give surprising results.
537 std::vector
<std::string
> RestrRegs
;
538 // Start with the first operand descriptor, and iterate over them.
539 for (unsigned I
= InlineAsm::MIOp_FirstOperand
, NumOps
= MI
->getNumOperands();
541 const MachineOperand
&MO
= MI
->getOperand(I
);
543 unsigned Flags
= MO
.getImm();
544 const TargetRegisterInfo
*TRI
= MF
->getSubtarget().getRegisterInfo();
545 if (InlineAsm::getKind(Flags
) == InlineAsm::Kind_Clobber
&&
546 !TRI
->isAsmClobberable(*MF
, MI
->getOperand(I
+ 1).getReg())) {
547 RestrRegs
.push_back(TRI
->getName(MI
->getOperand(I
+ 1).getReg()));
549 // Skip to one before the next operand descriptor, if it exists.
550 I
+= InlineAsm::getNumOperandRegisters(Flags
);
554 if (!RestrRegs
.empty()) {
555 unsigned BufNum
= addInlineAsmDiagBuffer(OS
.str(), LocMD
);
556 auto &SrcMgr
= DiagInfo
->SrcMgr
;
557 SMLoc Loc
= SMLoc::getFromPointer(
558 SrcMgr
.getMemoryBuffer(BufNum
)->getBuffer().begin());
560 std::string Msg
= "inline asm clobber list contains reserved registers: ";
561 for (auto I
= RestrRegs
.begin(), E
= RestrRegs
.end(); I
!= E
; I
++) {
562 if(I
!= RestrRegs
.begin())
566 std::string Note
= "Reserved registers on the clobber list may not be "
567 "preserved across the asm statement, and clobbering them may "
568 "lead to undefined behaviour.";
569 SrcMgr
.PrintMessage(Loc
, SourceMgr::DK_Warning
, Msg
);
570 SrcMgr
.PrintMessage(Loc
, SourceMgr::DK_Note
, Note
);
573 EmitInlineAsm(OS
.str(), getSubtargetInfo(), MCOptions
, LocMD
,
574 MI
->getInlineAsmDialect());
576 // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't
577 // enabled, so we use emitRawComment.
578 OutStreamer
->emitRawComment(MAI
->getInlineAsmEnd());
582 /// PrintSpecial - Print information related to the specified machine instr
583 /// that is independent of the operand, and may be independent of the instr
584 /// itself. This can be useful for portably encoding the comment character
585 /// or other bits of target-specific knowledge into the asmstrings. The
586 /// syntax used is ${:comment}. Targets can override this to add support
587 /// for their own strange codes.
588 void AsmPrinter::PrintSpecial(const MachineInstr
*MI
, raw_ostream
&OS
,
589 const char *Code
) const {
590 if (!strcmp(Code
, "private")) {
591 const DataLayout
&DL
= MF
->getDataLayout();
592 OS
<< DL
.getPrivateGlobalPrefix();
593 } else if (!strcmp(Code
, "comment")) {
594 OS
<< MAI
->getCommentString();
595 } else if (!strcmp(Code
, "uid")) {
596 // Comparing the address of MI isn't sufficient, because machineinstrs may
597 // be allocated to the same address across functions.
599 // If this is a new LastFn instruction, bump the counter.
600 if (LastMI
!= MI
|| LastFn
!= getFunctionNumber()) {
603 LastFn
= getFunctionNumber();
608 raw_string_ostream
Msg(msg
);
609 Msg
<< "Unknown special formatter '" << Code
610 << "' for machine instr: " << *MI
;
611 report_fatal_error(Msg
.str());
615 /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
616 /// instruction, using the specified assembler variant. Targets should
617 /// override this to format as appropriate.
618 bool AsmPrinter::PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
619 unsigned AsmVariant
, const char *ExtraCode
,
621 // Does this asm operand have a single letter operand modifier?
622 if (ExtraCode
&& ExtraCode
[0]) {
623 if (ExtraCode
[1] != 0) return true; // Unknown modifier.
625 const MachineOperand
&MO
= MI
->getOperand(OpNo
);
626 switch (ExtraCode
[0]) {
628 return true; // Unknown modifier.
629 case 'c': // Substitute immediate value without immediate syntax
630 if (MO
.getType() != MachineOperand::MO_Immediate
)
634 case 'n': // Negate the immediate constant.
635 if (MO
.getType() != MachineOperand::MO_Immediate
)
639 case 's': // The GCC deprecated s modifier
640 if (MO
.getType() != MachineOperand::MO_Immediate
)
642 O
<< ((32 - MO
.getImm()) & 31);
649 bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
, unsigned OpNo
,
651 const char *ExtraCode
, raw_ostream
&O
) {
652 // Target doesn't support this yet!
656 void AsmPrinter::emitInlineAsmStart() const {}
658 void AsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo
&StartInfo
,
659 const MCSubtargetInfo
*EndInfo
) const {}