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

Generated by: LCOV version 1.13