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