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

Generated by: LCOV version 1.13