LCOV - code coverage report
Current view: top level - lib/CodeGen/AsmPrinter - AsmPrinterInlineAsm.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 249 288 86.5 %
Date: 2017-09-14 15:23:50 Functions: 9 10 90.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             :       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         158 :   unsigned BufNum = DiagInfo->SrcMgr.FindBufferContainingLoc(Diag.getLoc());
      53         158 :   const MDNode *LocInfo = nullptr;
      54         316 :   if (BufNum > 0 && BufNum <= DiagInfo->LocInfos.size())
      55          18 :     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           9 :   unsigned LocCookie = 0;
      60           9 :   if (LocInfo) {
      61           9 :     unsigned ErrorLine = Diag.getLineNo()-1;
      62           9 :     if (ErrorLine >= LocInfo->getNumOperands())
      63           0 :       ErrorLine = 0;
      64             : 
      65           9 :     if (LocInfo->getNumOperands() != 0)
      66             :       if (const ConstantInt *CI =
      67          18 :               mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine)))
      68           9 :         LocCookie = CI->getZExtValue();
      69             :   }
      70             : 
      71         158 :   DiagInfo->DiagHandler(Diag, DiagInfo->DiagContext, LocCookie);
      72         158 : }
      73             : 
      74             : /// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
      75        4516 : 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        4516 :   bool isNullTerminated = Str.back() == 0;
      83        4516 :   if (isNullTerminated)
      84        8894 :     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        4516 :   const MCAsmInfo *MCAI = TM.getMCAsmInfo();
      92             :   assert(MCAI && "No MCAsmInfo");
      93        6218 :   if (!MCAI->useIntegratedAssembler() &&
      94        3404 :       !OutStreamer->isIntegratedAssemblerRequired()) {
      95        1687 :     emitInlineAsmStart();
      96        5061 :     OutStreamer->EmitRawText(Str);
      97        1687 :     emitInlineAsmEnd(STI, nullptr);
      98        1687 :     return;
      99             :   }
     100             : 
     101        5658 :   if (!DiagInfo) {
     102         453 :     DiagInfo = make_unique<SrcMgrDiagInfo>();
     103             : 
     104         453 :     MCContext &Context = MMI->getContext();
     105        1359 :     Context.setInlineSourceManager(&DiagInfo->SrcMgr);
     106             : 
     107         453 :     LLVMContext &LLVMCtx = MMI->getModule()->getContext();
     108         453 :     if (LLVMCtx.getInlineAsmDiagnosticHandler()) {
     109         854 :       DiagInfo->DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler();
     110         854 :       DiagInfo->DiagContext = LLVMCtx.getInlineAsmDiagnosticContext();
     111        1281 :       DiagInfo->SrcMgr.setDiagHandler(srcMgrDiagHandler, DiagInfo.get());
     112             :     }
     113             :   }
     114             : 
     115        5658 :   SourceMgr &SrcMgr = DiagInfo->SrcMgr;
     116        5658 :   SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths);
     117             : 
     118        5658 :   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        8487 :   Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>");
     122             : 
     123             :   // Tell SrcMgr about this buffer, it takes ownership of the buffer.
     124        8487 :   unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
     125             : 
     126             :   // Store LocMDNode in DiagInfo, using BufNum as an identifier.
     127        2829 :   if (LocMDNode) {
     128         322 :     DiagInfo->LocInfos.resize(BufNum);
     129         483 :     DiagInfo->LocInfos[BufNum-1] = LocMDNode;
     130             :   }
     131             : 
     132             :   std::unique_ptr<MCAsmParser> Parser(
     133       11316 :       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       11316 :   std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo());
     140        2829 :   std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser(
     141       14145 :       STI, *Parser, *MII, MCOptions));
     142        2829 :   if (!TAP)
     143           0 :     report_fatal_error("Inline asm not supported by this streamer because"
     144             :                        " we don't have an asm parser for this target\n");
     145        2829 :   Parser->setAssemblerDialect(Dialect);
     146        5658 :   Parser->setTargetParser(*TAP.get());
     147        2829 :   if (Dialect == InlineAsm::AD_Intel)
     148             :     // We need this flag to be able to parse numbers like "0bH"
     149          17 :     Parser->setParsingInlineAsm(true);
     150        2829 :   if (MF) {
     151        2762 :     const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
     152        2762 :     TAP->SetFrameRegister(TRI->getFrameRegister(*MF));
     153             :   }
     154             : 
     155        2829 :   emitInlineAsmStart();
     156             :   // Don't implicitly switch to the text section before the asm.
     157        5658 :   int Res = Parser->Run(/*NoInitialTextSection*/ true,
     158        5658 :                         /*NoFinalize*/ true);
     159        5658 :   emitInlineAsmEnd(STI, &TAP->getSTI());
     160             : 
     161        2861 :   if (Res && !DiagInfo->DiagHandler)
     162           0 :     report_fatal_error("Error parsing inline asm\n");
     163             : }
     164             : 
     165          27 : static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
     166             :                                MachineModuleInfo *MMI, int InlineAsmVariant,
     167             :                                AsmPrinter *AP, unsigned LocCookie,
     168             :                                raw_ostream &OS) {
     169             :   // Switch to the inline assembly variant.
     170          27 :   OS << "\t.intel_syntax\n\t";
     171             : 
     172          27 :   const char *LastEmitted = AsmStr; // One past the last character emitted.
     173          27 :   unsigned NumOperands = MI->getNumOperands();
     174             : 
     175         180 :   while (*LastEmitted) {
     176         153 :     switch (*LastEmitted) {
     177          83 :     default: {
     178             :       // Not a special case, emit the string section literally.
     179          83 :       const char *LiteralEnd = LastEmitted+1;
     180        2494 :       while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&
     181        1710 :              *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')
     182         783 :         ++LiteralEnd;
     183             : 
     184          83 :       OS.write(LastEmitted, LiteralEnd-LastEmitted);
     185          83 :       LastEmitted = LiteralEnd;
     186          83 :       break;
     187             :     }
     188          37 :     case '\n':
     189          37 :       ++LastEmitted;   // Consume newline character.
     190             :       OS << '\n';      // Indent code with newline.
     191             :       break;
     192          33 :     case '$': {
     193          33 :       ++LastEmitted;   // Consume '$' character.
     194          33 :       bool Done = true;
     195             : 
     196             :       // Handle escapes.
     197          33 :       switch (*LastEmitted) {
     198             :       default: Done = false; break;
     199           3 :       case '$':
     200           3 :         ++LastEmitted;  // Consume second '$' character.
     201             :         break;
     202             :       }
     203             :       if (Done) break;
     204             : 
     205             :       // If we have ${:foo}, then this is not a real operand reference, it is a
     206             :       // "magic" string reference, just like in .td files.  Arrange to call
     207             :       // PrintSpecial.
     208          32 :       if (LastEmitted[0] == '{' && LastEmitted[1] == ':') {
     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             : 
     216           8 :         std::string Val(StrStart, StrEnd);
     217           4 :         AP->PrintSpecial(MI, OS, Val.c_str());
     218           2 :         LastEmitted = StrEnd+1;
     219             :         break;
     220             :       }
     221             : 
     222             :       const char *IDStart = LastEmitted;
     223             :       const char *IDEnd = IDStart;
     224          56 :       while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd;
     225             : 
     226             :       unsigned Val;
     227          84 :       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             : 
     232          28 :       if (Val >= NumOperands-1)
     233           0 :         report_fatal_error("Invalid $ operand number in inline asm string: '" +
     234           0 :                            Twine(AsmStr) + "'");
     235             : 
     236             :       // Okay, we finally have a value number.  Ask the target to print this
     237             :       // operand!
     238             :       unsigned OpNo = InlineAsm::MIOp_FirstOperand;
     239             : 
     240             :       bool Error = false;
     241             : 
     242             :       // Scan to find the machine operand number for the operand.
     243          90 :       for (; Val; --Val) {
     244          31 :         if (OpNo >= MI->getNumOperands()) break;
     245          62 :         unsigned OpFlags = MI->getOperand(OpNo).getImm();
     246          31 :         OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
     247             :       }
     248             : 
     249             :       // We may have a location metadata attached to the end of the
     250             :       // instruction, and at no point should see metadata at any
     251             :       // other point while processing. It's an error if so.
     252          56 :       if (OpNo >= MI->getNumOperands() ||
     253          84 :           MI->getOperand(OpNo).isMetadata()) {
     254             :         Error = true;
     255             :       } else {
     256          28 :         unsigned OpFlags = MI->getOperand(OpNo).getImm();
     257          28 :         ++OpNo;  // Skip over the ID number.
     258             : 
     259          28 :         if (InlineAsm::isMemKind(OpFlags)) {
     260          25 :           Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant,
     261          25 :                                             /*Modifier*/ nullptr, OS);
     262             :         } else {
     263           3 :           Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant,
     264           3 :                                       /*Modifier*/ nullptr, OS);
     265             :         }
     266             :       }
     267          28 :       if (Error) {
     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             :       }
     273             :       break;
     274             :     }
     275             :     }
     276             :   }
     277          54 :   OS << "\n\t.att_syntax\n" << (char)0;  // null terminate string.
     278          27 : }
     279             : 
     280        4420 : static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
     281             :                                 MachineModuleInfo *MMI, int InlineAsmVariant,
     282             :                                 int AsmPrinterVariant, AsmPrinter *AP,
     283             :                                 unsigned LocCookie, raw_ostream &OS) {
     284        4420 :   int CurVariant = -1;            // The number of the {.|.|.} region we are in.
     285        4420 :   const char *LastEmitted = AsmStr; // One past the last character emitted.
     286        4420 :   unsigned NumOperands = MI->getNumOperands();
     287             : 
     288             :   OS << '\t';
     289             : 
     290       18834 :   while (*LastEmitted) {
     291       14414 :     switch (*LastEmitted) {
     292        8493 :     default: {
     293             :       // Not a special case, emit the string section literally.
     294        8493 :       const char *LiteralEnd = LastEmitted+1;
     295      133662 :       while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&
     296       93815 :              *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')
     297       39809 :         ++LiteralEnd;
     298        8493 :       if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
     299        8488 :         OS.write(LastEmitted, LiteralEnd-LastEmitted);
     300             :       LastEmitted = LiteralEnd;
     301             :       break;
     302             :     }
     303        1380 :     case '\n':
     304        1380 :       ++LastEmitted;   // Consume newline character.
     305             :       OS << '\n';      // Indent code with newline.
     306             :       break;
     307        4541 :     case '$': {
     308        4541 :       ++LastEmitted;   // Consume '$' character.
     309        4541 :       bool Done = true;
     310             : 
     311             :       // Handle escapes.
     312        4541 :       switch (*LastEmitted) {
     313             :       default: Done = false; break;
     314         702 :       case '$':     // $$ -> $
     315         702 :         if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
     316             :           OS << '$';
     317         702 :         ++LastEmitted;  // Consume second '$' character.
     318         702 :         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             :         CurVariant = 0;     // We're in the first variant now.
     325             :         break;
     326          21 :       case '|':
     327          21 :         ++LastEmitted;  // consume '|' character.
     328          21 :         if (CurVariant == -1)
     329             :           OS << '|';       // this is gcc's behavior for | outside a variant
     330             :         else
     331           5 :           ++CurVariant;   // We're in the next variant.
     332             :         break;
     333           5 :       case ')':         // $) -> same as GCC's } char.
     334           5 :         ++LastEmitted;  // consume ')' character.
     335           5 :         if (CurVariant == -1)
     336             :           OS << '}';     // this is gcc's behavior for } outside a variant
     337             :         else
     338             :           CurVariant = -1;
     339             :         break;
     340             :       }
     341        4541 :       if (Done) break;
     342             : 
     343        3808 :       bool HasCurlyBraces = false;
     344        3808 :       if (*LastEmitted == '{') {     // ${variable}
     345         287 :         ++LastEmitted;               // Consume '{' character.
     346         287 :         HasCurlyBraces = true;
     347             :       }
     348             : 
     349             :       // If we have ${:foo}, then this is not a real operand reference, it is a
     350             :       // "magic" string reference, just like in .td files.  Arrange to call
     351             :       // PrintSpecial.
     352         287 :       if (HasCurlyBraces && *LastEmitted == ':') {
     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             : 
     360          16 :         std::string Val(StrStart, StrEnd);
     361           8 :         AP->PrintSpecial(MI, OS, Val.c_str());
     362           4 :         LastEmitted = StrEnd+1;
     363             :         break;
     364             :       }
     365             : 
     366             :       const char *IDStart = LastEmitted;
     367             :       const char *IDEnd = IDStart;
     368        7611 :       while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd;
     369             : 
     370             :       unsigned Val;
     371       11412 :       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        3804 :       LastEmitted = IDEnd;
     375             : 
     376        3804 :       char Modifier[2] = { 0, 0 };
     377             : 
     378        3804 :       if (HasCurlyBraces) {
     379             :         // If we have curly braces, check for a modifier character.  This
     380             :         // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm.
     381         283 :         if (*LastEmitted == ':') {
     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             : 
     387         276 :           Modifier[0] = *LastEmitted;
     388         276 :           ++LastEmitted;    // Consume modifier character.
     389             :         }
     390             : 
     391         283 :         if (*LastEmitted != '}')
     392           0 :           report_fatal_error("Bad ${} expression in inline asm string: '" +
     393           0 :                              Twine(AsmStr) + "'");
     394         283 :         ++LastEmitted;    // Consume '}' character.
     395             :       }
     396             : 
     397        3804 :       if (Val >= NumOperands-1)
     398           0 :         report_fatal_error("Invalid $ operand number in inline asm string: '" +
     399           0 :                            Twine(AsmStr) + "'");
     400             : 
     401             :       // Okay, we finally have a value number.  Ask the target to print this
     402             :       // operand!
     403        3804 :       if (CurVariant == -1 || CurVariant == AsmPrinterVariant) {
     404             :         unsigned OpNo = InlineAsm::MIOp_FirstOperand;
     405             : 
     406             :         bool Error = false;
     407             : 
     408             :         // Scan to find the machine operand number for the operand.
     409        9554 :         for (; Val; --Val) {
     410        2875 :           if (OpNo >= MI->getNumOperands()) break;
     411        5750 :           unsigned OpFlags = MI->getOperand(OpNo).getImm();
     412        2875 :           OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
     413             :         }
     414             : 
     415             :         // We may have a location metadata attached to the end of the
     416             :         // instruction, and at no point should see metadata at any
     417             :         // other point while processing. It's an error if so.
     418        7608 :         if (OpNo >= MI->getNumOperands() ||
     419       11412 :             MI->getOperand(OpNo).isMetadata()) {
     420             :           Error = true;
     421             :         } else {
     422        3804 :           unsigned OpFlags = MI->getOperand(OpNo).getImm();
     423        3804 :           ++OpNo;  // Skip over the ID number.
     424             : 
     425        3804 :           if (Modifier[0] == 'l') { // Labels are target independent.
     426             :             // FIXME: What if the operand isn't an MBB, report error?
     427           4 :             const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol();
     428           2 :             Sym->print(OS, AP->MAI);
     429             :           } else {
     430        3802 :             if (InlineAsm::isMemKind(OpFlags)) {
     431         342 :               Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant,
     432             :                                                 Modifier[0] ? Modifier : nullptr,
     433         342 :                                                 OS);
     434             :             } else {
     435        3460 :               Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant,
     436        3460 :                                           Modifier[0] ? Modifier : nullptr, OS);
     437             :             }
     438             :           }
     439             :         }
     440        3802 :         if (Error) {
     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             :         }
     446             :       }
     447             :       break;
     448             :     }
     449             :     }
     450             :   }
     451        8840 :   OS << '\n' << (char)0;  // null terminate string.
     452        4420 : }
     453             : 
     454             : /// EmitInlineAsm - This method formats and emits the specified machine
     455             : /// instruction that is an inline asm.
     456        8670 : void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
     457             :   assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms");
     458             : 
     459             :   // Count the number of register definitions to find the asm string.
     460        8670 :   unsigned NumDefs = 0;
     461       26010 :   for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef();
     462             :        ++NumDefs)
     463             :     assert(NumDefs != MI->getNumOperands()-2 && "No asm string?");
     464             : 
     465             :   assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?");
     466             : 
     467             :   // Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
     468        8670 :   const char *AsmStr = MI->getOperand(NumDefs).getSymbolName();
     469             : 
     470             :   // If this asmstr is empty, just print the #APP/#NOAPP markers.
     471             :   // These are useful to see where empty asm's wound up.
     472        8670 :   if (AsmStr[0] == 0) {
     473       12669 :     OutStreamer->emitRawComment(MAI->getInlineAsmStart());
     474       12669 :     OutStreamer->emitRawComment(MAI->getInlineAsmEnd());
     475        4223 :     return;
     476             :   }
     477             : 
     478             :   // Emit the #APP start marker.  This has to happen even if verbose-asm isn't
     479             :   // enabled, so we use emitRawComment.
     480       13341 :   OutStreamer->emitRawComment(MAI->getInlineAsmStart());
     481             : 
     482             :   // Get the !srcloc metadata node if we have it, and decode the loc cookie from
     483             :   // it.
     484        4447 :   unsigned LocCookie = 0;
     485        4447 :   const MDNode *LocMD = nullptr;
     486        4447 :   for (unsigned i = MI->getNumOperands(); i != 0; --i) {
     487      291609 :     if (MI->getOperand(i-1).isMetadata() &&
     488       97319 :         (LocMD = MI->getOperand(i-1).getMetadata()) &&
     489             :         LocMD->getNumOperands() != 0) {
     490             :       if (const ConstantInt *CI =
     491         348 :               mdconst::dyn_extract<ConstantInt>(LocMD->getOperand(0))) {
     492         174 :         LocCookie = CI->getZExtValue();
     493         174 :         break;
     494             :       }
     495             :     }
     496             :   }
     497             : 
     498             :   // Emit the inline asm to a temporary string so we can emit it through
     499             :   // EmitInlineAsm.
     500        8894 :   SmallString<256> StringData;
     501        8894 :   raw_svector_ostream OS(StringData);
     502             : 
     503             :   // The variant of the current asmprinter.
     504        4447 :   int AsmPrinterVariant = MAI->getAssemblerDialect();
     505        4447 :   InlineAsm::AsmDialect InlineAsmVariant = MI->getInlineAsmDialect();
     506        4447 :   AsmPrinter *AP = const_cast<AsmPrinter*>(this);
     507        4447 :   if (InlineAsmVariant == InlineAsm::AD_ATT)
     508        4420 :     EmitGCCInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AsmPrinterVariant,
     509             :                         AP, LocCookie, OS);
     510             :   else
     511          27 :     EmitMSInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AP, LocCookie, OS);
     512             : 
     513             :   // Reset SanitizeAddress based on the function's attribute.
     514        8894 :   MCTargetOptions MCOptions = TM.Options.MCOptions;
     515        4447 :   MCOptions.SanitizeAddress =
     516        8894 :       MF->getFunction()->hasFnAttribute(Attribute::SanitizeAddress);
     517             : 
     518        4447 :   EmitInlineAsm(OS.str(), getSubtargetInfo(), MCOptions, LocMD,
     519             :                 MI->getInlineAsmDialect());
     520             : 
     521             :   // Emit the #NOAPP end marker.  This has to happen even if verbose-asm isn't
     522             :   // enabled, so we use emitRawComment.
     523       13341 :   OutStreamer->emitRawComment(MAI->getInlineAsmEnd());
     524             : }
     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           6 : void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
     534             :                               const char *Code) const {
     535           6 :   if (!strcmp(Code, "private")) {
     536           0 :     const DataLayout &DL = MF->getDataLayout();
     537           0 :     OS << DL.getPrivateGlobalPrefix();
     538           6 :   } else if (!strcmp(Code, "comment")) {
     539           0 :     OS << MAI->getCommentString();
     540           6 :   } else if (!strcmp(Code, "uid")) {
     541             :     // Comparing the address of MI isn't sufficient, because machineinstrs may
     542             :     // be allocated to the same address across functions.
     543             : 
     544             :     // If this is a new LastFn instruction, bump the counter.
     545           6 :     if (LastMI != MI || LastFn != getFunctionNumber()) {
     546           3 :       ++Counter;
     547           3 :       LastMI = MI;
     548           3 :       LastFn = getFunctionNumber();
     549             :     }
     550           6 :     OS << Counter;
     551             :   } 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             :   }
     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         684 : bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
     564             :                                  unsigned AsmVariant, const char *ExtraCode,
     565             :                                  raw_ostream &O) {
     566             :   // Does this asm operand have a single letter operand modifier?
     567         684 :   if (ExtraCode && ExtraCode[0]) {
     568          53 :     if (ExtraCode[1] != 0) return true; // Unknown modifier.
     569             : 
     570         106 :     const MachineOperand &MO = MI->getOperand(OpNo);
     571          53 :     switch (ExtraCode[0]) {
     572             :     default:
     573             :       return true;  // Unknown modifier.
     574           5 :     case 'c': // Substitute immediate value without immediate syntax
     575           5 :       if (MO.getType() != MachineOperand::MO_Immediate)
     576             :         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             :         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             :         return true;
     587           1 :       O << ((32 - MO.getImm()) & 31);
     588           1 :       return false;
     589             :     }
     590             :   }
     591             :   return true;
     592             : }
     593             : 
     594           0 : bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
     595             :                                        unsigned AsmVariant,
     596             :                                        const char *ExtraCode, raw_ostream &O) {
     597             :   // Target doesn't support this yet!
     598           0 :   return true;
     599             : }
     600             : 
     601        4104 : void AsmPrinter::emitInlineAsmStart() const {}
     602             : 
     603        3776 : void AsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
     604        3776 :                                   const MCSubtargetInfo *EndInfo) const {}

Generated by: LCOV version 1.13