17abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao//===-- AsmPrinterInlineAsm.cpp - AsmPrinter Inline Asm Handling ----------===//
27abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao//
37abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao//                     The LLVM Compiler Infrastructure
47abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao//
57abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao// This file is distributed under the University of Illinois Open Source
67abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao// License. See LICENSE.TXT for details.
77abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao//
87abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao//===----------------------------------------------------------------------===//
97abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao//
107abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao// This file implements the inline assembler pieces of the AsmPrinter class.
117abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao//
127abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao//===----------------------------------------------------------------------===//
137abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
147abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#define DEBUG_TYPE "asm-printer"
157abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#include "llvm/CodeGen/AsmPrinter.h"
16d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/OwningPtr.h"
17d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/SmallString.h"
18d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/Twine.h"
197abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#include "llvm/CodeGen/MachineBasicBlock.h"
207abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#include "llvm/CodeGen/MachineModuleInfo.h"
210b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Constants.h"
220b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/InlineAsm.h"
230b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/LLVMContext.h"
240b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Module.h"
257abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#include "llvm/MC/MCAsmInfo.h"
267abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#include "llvm/MC/MCStreamer.h"
27ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng#include "llvm/MC/MCSubtargetInfo.h"
287abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#include "llvm/MC/MCSymbol.h"
2994b9550a32d189704a8eae55505edf62662c0534Evan Cheng#include "llvm/MC/MCTargetAsmParser.h"
307abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#include "llvm/Support/ErrorHandling.h"
317abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#include "llvm/Support/MemoryBuffer.h"
327abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#include "llvm/Support/SourceMgr.h"
333e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetRegistry.h"
347abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#include "llvm/Support/raw_ostream.h"
35d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Target/TargetMachine.h"
367abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaousing namespace llvm;
377abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
386e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattnernamespace {
396e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner  struct SrcMgrDiagInfo {
406e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner    const MDNode *LocInfo;
41f64c889cc94417322b0ff8ad1c61939183bf3c38Bob Wilson    LLVMContext::InlineAsmDiagHandlerTy DiagHandler;
426e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner    void *DiagContext;
436e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner  };
446e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner}
456e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner
46c53ade2889c85207e064e4c3d049383ffffb3319Chad Rosier/// srcMgrDiagHandler - This callback is invoked when the SourceMgr for an
476e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner/// inline asm has an error in it.  diagInfo is a pointer to the SrcMgrDiagInfo
486e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner/// struct above.
49c53ade2889c85207e064e4c3d049383ffffb3319Chad Rosierstatic void srcMgrDiagHandler(const SMDiagnostic &Diag, void *diagInfo) {
506e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner  SrcMgrDiagInfo *DiagInfo = static_cast<SrcMgrDiagInfo *>(diagInfo);
516e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner  assert(DiagInfo && "Diagnostic context not passed down?");
52fe59d853c6bee18aeca1da5f703fc442068853a7Jim Grosbach
53ce1b9ad539e67c6d05cc6b47ca5f6e62a6d91effChris Lattner  // If the inline asm had metadata associated with it, pull out a location
54ce1b9ad539e67c6d05cc6b47ca5f6e62a6d91effChris Lattner  // cookie corresponding to which line the error occurred on.
556e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner  unsigned LocCookie = 0;
56ce1b9ad539e67c6d05cc6b47ca5f6e62a6d91effChris Lattner  if (const MDNode *LocInfo = DiagInfo->LocInfo) {
57ce1b9ad539e67c6d05cc6b47ca5f6e62a6d91effChris Lattner    unsigned ErrorLine = Diag.getLineNo()-1;
58ce1b9ad539e67c6d05cc6b47ca5f6e62a6d91effChris Lattner    if (ErrorLine >= LocInfo->getNumOperands())
59ce1b9ad539e67c6d05cc6b47ca5f6e62a6d91effChris Lattner      ErrorLine = 0;
60fe59d853c6bee18aeca1da5f703fc442068853a7Jim Grosbach
61ce1b9ad539e67c6d05cc6b47ca5f6e62a6d91effChris Lattner    if (LocInfo->getNumOperands() != 0)
62ce1b9ad539e67c6d05cc6b47ca5f6e62a6d91effChris Lattner      if (const ConstantInt *CI =
63ce1b9ad539e67c6d05cc6b47ca5f6e62a6d91effChris Lattner          dyn_cast<ConstantInt>(LocInfo->getOperand(ErrorLine)))
646e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner        LocCookie = CI->getZExtValue();
65ce1b9ad539e67c6d05cc6b47ca5f6e62a6d91effChris Lattner  }
66fe59d853c6bee18aeca1da5f703fc442068853a7Jim Grosbach
674afa12890f679034e9741a687a6ce33f2846f129Chris Lattner  DiagInfo->DiagHandler(Diag, DiagInfo->DiagContext, LocCookie);
686e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner}
696e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner
707abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
71366df7945f0e65052d2e1df701ae1fd16b943642Chad Rosiervoid AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode,
72366df7945f0e65052d2e1df701ae1fd16b943642Chad Rosier                               InlineAsm::AsmDialect Dialect) const {
737abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  assert(!Str.empty() && "Can't emit empty inline asm block");
74ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
757abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  // Remember if the buffer is nul terminated or not so we can avoid a copy.
767abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  bool isNullTerminated = Str.back() == 0;
777abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  if (isNullTerminated)
787abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    Str = Str.substr(0, Str.size()-1);
79ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
807abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  // If the output streamer is actually a .s file, just emit the blob textually.
817abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  // This is useful in case the asm parser doesn't handle something but the
827abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  // system assembler does.
837abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  if (OutStreamer.hasRawTextSupport()) {
847abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    OutStreamer.EmitRawText(Str);
857abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    return;
867abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  }
87ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
887abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  SourceMgr SrcMgr;
896e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner  SrcMgrDiagInfo DiagInfo;
90ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
91f64c889cc94417322b0ff8ad1c61939183bf3c38Bob Wilson  // If the current LLVMContext has an inline asm handler, set it in SourceMgr.
927abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  LLVMContext &LLVMCtx = MMI->getModule()->getContext();
937abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  bool HasDiagHandler = false;
94f64c889cc94417322b0ff8ad1c61939183bf3c38Bob Wilson  if (LLVMCtx.getInlineAsmDiagnosticHandler() != 0) {
95c53ade2889c85207e064e4c3d049383ffffb3319Chad Rosier    // If the source manager has an issue, we arrange for srcMgrDiagHandler
966e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner    // to be invoked, getting DiagInfo passed into it.
976e30c6a1d32f187804d24ecd1868d63c60330b22Chris Lattner    DiagInfo.LocInfo = LocMDNode;
98f64c889cc94417322b0ff8ad1c61939183bf3c38Bob Wilson    DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler();
99f64c889cc94417322b0ff8ad1c61939183bf3c38Bob Wilson    DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext();
100c53ade2889c85207e064e4c3d049383ffffb3319Chad Rosier    SrcMgr.setDiagHandler(srcMgrDiagHandler, &DiagInfo);
1017abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    HasDiagHandler = true;
1027abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  }
103ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
1047abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  MemoryBuffer *Buffer;
1057abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  if (isNullTerminated)
1067abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>");
1077abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  else
1087abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>");
1097abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
1107abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  // Tell SrcMgr about this buffer, it takes ownership of the buffer.
1117abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
112ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
1131b84cce77f8bccc905b4800927ce9016f76c1c40Jim Grosbach  OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr,
114dd7297238f1bcc0edcde64c64a3bb7465aa2f194Daniel Dunbar                                                  OutContext, OutStreamer,
115dd7297238f1bcc0edcde64c64a3bb7465aa2f194Daniel Dunbar                                                  *MAI));
116ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng
117ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng  // FIXME: It would be nice if we can avoid createing a new instance of
118ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng  // MCSubtargetInfo here given TargetSubtargetInfo is available. However,
119ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng  // we have to watch out for asm directives which can change subtarget
120ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng  // state. e.g. .code 16, .code 32.
121ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng  OwningPtr<MCSubtargetInfo>
122ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng    STI(TM.getTarget().createMCSubtargetInfo(TM.getTargetTriple(),
123ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng                                             TM.getTargetCPU(),
124ffc0e73046f737d75e0a62b3a83ef19bcef111e3Evan Cheng                                             TM.getTargetFeatureString()));
12594b9550a32d189704a8eae55505edf62662c0534Evan Cheng  OwningPtr<MCTargetAsmParser>
12694b9550a32d189704a8eae55505edf62662c0534Evan Cheng    TAP(TM.getTarget().createMCAsmParser(*STI, *Parser));
1277abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  if (!TAP)
1287abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    report_fatal_error("Inline asm not supported by this streamer because"
1297abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                       " we don't have an asm parser for this target\n");
130366df7945f0e65052d2e1df701ae1fd16b943642Chad Rosier  Parser->setAssemblerDialect(Dialect);
131dd7297238f1bcc0edcde64c64a3bb7465aa2f194Daniel Dunbar  Parser->setTargetParser(*TAP.get());
1327abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
1337abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  // Don't implicitly switch to the text section before the asm.
134dd7297238f1bcc0edcde64c64a3bb7465aa2f194Daniel Dunbar  int Res = Parser->Run(/*NoInitialTextSection*/ true,
135dd7297238f1bcc0edcde64c64a3bb7465aa2f194Daniel Dunbar                        /*NoFinalize*/ true);
1367abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  if (Res && !HasDiagHandler)
1377abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    report_fatal_error("Error parsing inline asm\n");
1387abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao}
1397abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
140a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosierstatic void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
141a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                               MachineModuleInfo *MMI, int InlineAsmVariant,
142a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                               AsmPrinter *AP, unsigned LocCookie,
143a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                               raw_ostream &OS) {
144a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  // Switch to the inline assembly variant.
145a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  OS << "\t.intel_syntax\n\t";
146ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
147a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  const char *LastEmitted = AsmStr; // One past the last character emitted.
1487abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  unsigned NumOperands = MI->getNumOperands();
149ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
150a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  while (*LastEmitted) {
151a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    switch (*LastEmitted) {
152a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    default: {
153a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      // Not a special case, emit the string section literally.
154a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      const char *LiteralEnd = LastEmitted+1;
155a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&
156a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier             *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')
157a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        ++LiteralEnd;
1587abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
159a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      OS.write(LastEmitted, LiteralEnd-LastEmitted);
160a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      LastEmitted = LiteralEnd;
161a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      break;
162a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    }
163a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    case '\n':
164a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      ++LastEmitted;   // Consume newline character.
165a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      OS << '\n';      // Indent code with newline.
166a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      break;
167a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    case '$': {
168a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      ++LastEmitted;   // Consume '$' character.
169a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      bool Done = true;
1707abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
171a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      // Handle escapes.
172a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      switch (*LastEmitted) {
173a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      default: Done = false; break;
174a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      case '$':
175a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        ++LastEmitted;  // Consume second '$' character.
176a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        break;
177a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      }
178a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      if (Done) break;
1797abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
180a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      const char *IDStart = LastEmitted;
181a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      const char *IDEnd = IDStart;
182a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd;
1837abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
184a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      unsigned Val;
185a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val))
186a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        report_fatal_error("Bad $ operand number in inline asm string: '" +
187a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                           Twine(AsmStr) + "'");
188a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      LastEmitted = IDEnd;
1897abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
190a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      if (Val >= NumOperands-1)
191a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        report_fatal_error("Invalid $ operand number in inline asm string: '" +
192a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                           Twine(AsmStr) + "'");
193ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
194a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      // Okay, we finally have a value number.  Ask the target to print this
195a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      // operand!
196a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      unsigned OpNo = InlineAsm::MIOp_FirstOperand;
197ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
198a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      bool Error = false;
1997abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
200a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      // Scan to find the machine operand number for the operand.
201a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      for (; Val; --Val) {
202a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        if (OpNo >= MI->getNumOperands()) break;
203a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        unsigned OpFlags = MI->getOperand(OpNo).getImm();
204a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
205a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      }
20624f5fddbdff3d54d822555ae792a7f3bb22e342fChad Rosier
207a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      // We may have a location metadata attached to the end of the
208a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      // instruction, and at no point should see metadata at any
209a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      // other point while processing. It's an error if so.
210a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      if (OpNo >= MI->getNumOperands() ||
211a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier          MI->getOperand(OpNo).isMetadata()) {
212a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        Error = true;
213a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      } else {
214a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        unsigned OpFlags = MI->getOperand(OpNo).getImm();
215a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        ++OpNo;  // Skip over the ID number.
216a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier
217a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        if (InlineAsm::isMemKind(OpFlags)) {
218a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier          Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant,
219a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                                            /*Modifier*/ 0, OS);
220a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        } else {
221a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier          Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant,
222a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                                      /*Modifier*/ 0, OS);
223a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        }
224a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      }
225a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      if (Error) {
226a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        std::string msg;
227a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        raw_string_ostream Msg(msg);
228a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        Msg << "invalid operand in inline asm: '" << AsmStr << "'";
229a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
230a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      }
231a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      break;
232a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    }
233a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    }
23424f5fddbdff3d54d822555ae792a7f3bb22e342fChad Rosier  }
235a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  OS << "\n\t.att_syntax\n" << (char)0;  // null terminate string.
236a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier}
2377abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
238a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosierstatic void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
239a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                                MachineModuleInfo *MMI, int InlineAsmVariant,
240a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                                int AsmPrinterVariant, AsmPrinter *AP,
241a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                                unsigned LocCookie, raw_ostream &OS) {
2427abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  int CurVariant = -1;            // The number of the {.|.|.} region we are in.
2437abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  const char *LastEmitted = AsmStr; // One past the last character emitted.
244a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  unsigned NumOperands = MI->getNumOperands();
245a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier
246a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  OS << '\t';
247ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
2487abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  while (*LastEmitted) {
2497abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    switch (*LastEmitted) {
2507abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    default: {
2517abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      // Not a special case, emit the string section literally.
2527abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      const char *LiteralEnd = LastEmitted+1;
2537abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&
2547abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao             *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')
2557abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        ++LiteralEnd;
2567abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
2577abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        OS.write(LastEmitted, LiteralEnd-LastEmitted);
2587abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      LastEmitted = LiteralEnd;
2597abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      break;
2607abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    }
2617abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    case '\n':
2627abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      ++LastEmitted;   // Consume newline character.
2637abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      OS << '\n';      // Indent code with newline.
2647abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      break;
2657abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    case '$': {
2667abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      ++LastEmitted;   // Consume '$' character.
2677abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      bool Done = true;
2687abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
2697abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      // Handle escapes.
2707abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      switch (*LastEmitted) {
2717abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      default: Done = false; break;
2727abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      case '$':     // $$ -> $
2737abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
2747abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          OS << '$';
2757abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        ++LastEmitted;  // Consume second '$' character.
2767abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        break;
2777abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      case '(':             // $( -> same as GCC's { character.
2787abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        ++LastEmitted;      // Consume '(' character.
2797abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        if (CurVariant != -1)
2807abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          report_fatal_error("Nested variants found in inline asm string: '" +
2817abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                             Twine(AsmStr) + "'");
2827abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        CurVariant = 0;     // We're in the first variant now.
2837abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        break;
2847abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      case '|':
2857abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        ++LastEmitted;  // consume '|' character.
2867abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        if (CurVariant == -1)
2877abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          OS << '|';       // this is gcc's behavior for | outside a variant
2887abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        else
2897abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          ++CurVariant;   // We're in the next variant.
2907abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        break;
2917abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      case ')':         // $) -> same as GCC's } char.
2927abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        ++LastEmitted;  // consume ')' character.
2937abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        if (CurVariant == -1)
2947abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          OS << '}';     // this is gcc's behavior for } outside a variant
295ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach        else
2967abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          CurVariant = -1;
2977abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        break;
2987abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      }
2997abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      if (Done) break;
300ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
3017abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      bool HasCurlyBraces = false;
3027abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      if (*LastEmitted == '{') {     // ${variable}
3037abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        ++LastEmitted;               // Consume '{' character.
3047abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        HasCurlyBraces = true;
3057abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      }
306ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
3077abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      // If we have ${:foo}, then this is not a real operand reference, it is a
3087abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      // "magic" string reference, just like in .td files.  Arrange to call
3097abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      // PrintSpecial.
3107abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      if (HasCurlyBraces && *LastEmitted == ':') {
3117abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        ++LastEmitted;
3127abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        const char *StrStart = LastEmitted;
3137abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        const char *StrEnd = strchr(StrStart, '}');
3147abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        if (StrEnd == 0)
3157abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          report_fatal_error("Unterminated ${:foo} operand in inline asm"
3167abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                             " string: '" + Twine(AsmStr) + "'");
317ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
3187abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        std::string Val(StrStart, StrEnd);
319a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        AP->PrintSpecial(MI, OS, Val.c_str());
3207abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        LastEmitted = StrEnd+1;
3217abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        break;
3227abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      }
323ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
3247abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      const char *IDStart = LastEmitted;
3257abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      const char *IDEnd = IDStart;
326ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach      while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd;
327ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
3287abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      unsigned Val;
3297abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val))
3307abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        report_fatal_error("Bad $ operand number in inline asm string: '" +
3317abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                           Twine(AsmStr) + "'");
3327abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      LastEmitted = IDEnd;
333ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
3347abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      char Modifier[2] = { 0, 0 };
335ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
3367abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      if (HasCurlyBraces) {
3377abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        // If we have curly braces, check for a modifier character.  This
3387abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm.
3397abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        if (*LastEmitted == ':') {
3407abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          ++LastEmitted;    // Consume ':' character.
3417abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          if (*LastEmitted == 0)
3427abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao            report_fatal_error("Bad ${:} expression in inline asm string: '" +
3437abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                               Twine(AsmStr) + "'");
344ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
3457abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          Modifier[0] = *LastEmitted;
3467abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          ++LastEmitted;    // Consume modifier character.
3477abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        }
348ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
3497abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        if (*LastEmitted != '}')
3507abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          report_fatal_error("Bad ${} expression in inline asm string: '" +
3517abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                             Twine(AsmStr) + "'");
3527abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        ++LastEmitted;    // Consume '}' character.
3537abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      }
354ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
3557abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      if (Val >= NumOperands-1)
3567abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        report_fatal_error("Invalid $ operand number in inline asm string: '" +
3577abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                           Twine(AsmStr) + "'");
358ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
3597abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      // Okay, we finally have a value number.  Ask the target to print this
3607abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      // operand!
3617abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      if (CurVariant == -1 || CurVariant == AsmPrinterVariant) {
362c36b7069b42bece963b7e6adf020353ce990ef76Evan Cheng        unsigned OpNo = InlineAsm::MIOp_FirstOperand;
3637abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
3647abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        bool Error = false;
3657abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
3667abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        // Scan to find the machine operand number for the operand.
3677abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        for (; Val; --Val) {
3687abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          if (OpNo >= MI->getNumOperands()) break;
3697abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          unsigned OpFlags = MI->getOperand(OpNo).getImm();
3707abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
3717abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        }
3727abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
3739318e484de290b46192e834eb8feca18e0ece153Akira Hatanaka        // We may have a location metadata attached to the end of the
3749318e484de290b46192e834eb8feca18e0ece153Akira Hatanaka        // instruction, and at no point should see metadata at any
3759318e484de290b46192e834eb8feca18e0ece153Akira Hatanaka        // other point while processing. It's an error if so.
376aa206ffa6bf160f90d0d3aae5745ae4abf2d98faEric Christopher        if (OpNo >= MI->getNumOperands() ||
3779318e484de290b46192e834eb8feca18e0ece153Akira Hatanaka            MI->getOperand(OpNo).isMetadata()) {
3787abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          Error = true;
3797abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        } else {
3807abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          unsigned OpFlags = MI->getOperand(OpNo).getImm();
3817abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          ++OpNo;  // Skip over the ID number.
3827abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
3837abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          if (Modifier[0] == 'l')  // labels are target independent
3847abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao            // FIXME: What if the operand isn't an MBB, report error?
3857abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao            OS << *MI->getOperand(OpNo).getMBB()->getSymbol();
3867abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          else {
3877abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao            if (InlineAsm::isMemKind(OpFlags)) {
3883b132fab0bebe7186348d7ab0e2663c9fddab3bbChad Rosier              Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant,
3897abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                                                Modifier[0] ? Modifier : 0,
3907abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                                                OS);
3917abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao            } else {
3923b132fab0bebe7186348d7ab0e2663c9fddab3bbChad Rosier              Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant,
3937abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                                          Modifier[0] ? Modifier : 0, OS);
3947abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao            }
3957abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          }
3967abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        }
3977abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        if (Error) {
3987abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          std::string msg;
3997abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          raw_string_ostream Msg(msg);
4007abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          Msg << "invalid operand in inline asm: '" << AsmStr << "'";
4017abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao          MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
4027abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao        }
4037abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      }
4047abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      break;
4057abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    }
4067abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    }
4077abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  }
408a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  OS << '\n' << (char)0;  // null terminate string.
409a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier}
410a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier
411a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier/// EmitInlineAsm - This method formats and emits the specified machine
412a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier/// instruction that is an inline asm.
413a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosiervoid AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
414a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms");
415a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier
416a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  // Count the number of register definitions to find the asm string.
417a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  unsigned NumDefs = 0;
418a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef();
419a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier       ++NumDefs)
420a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    assert(NumDefs != MI->getNumOperands()-2 && "No asm string?");
421a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier
422a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?");
423a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier
424a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  // Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
425a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  const char *AsmStr = MI->getOperand(NumDefs).getSymbolName();
426a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier
427a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  // If this asmstr is empty, just print the #APP/#NOAPP markers.
428a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  // These are useful to see where empty asm's wound up.
429a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  if (AsmStr[0] == 0) {
430a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    // Don't emit the comments if writing to a .o file.
431a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    if (!OutStreamer.hasRawTextSupport()) return;
432a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier
433a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+
434a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                            MAI->getInlineAsmStart());
435a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+
436a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                            MAI->getInlineAsmEnd());
437a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    return;
43824f5fddbdff3d54d822555ae792a7f3bb22e342fChad Rosier  }
43924f5fddbdff3d54d822555ae792a7f3bb22e342fChad Rosier
440a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  // Emit the #APP start marker.  This has to happen even if verbose-asm isn't
441a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  // enabled, so we use EmitRawText.
442a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  if (OutStreamer.hasRawTextSupport())
443a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+
444a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                            MAI->getInlineAsmStart());
445a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier
446a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  // Get the !srcloc metadata node if we have it, and decode the loc cookie from
447a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  // it.
448a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  unsigned LocCookie = 0;
449a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  const MDNode *LocMD = 0;
450a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  for (unsigned i = MI->getNumOperands(); i != 0; --i) {
451a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    if (MI->getOperand(i-1).isMetadata() &&
452a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        (LocMD = MI->getOperand(i-1).getMetadata()) &&
453a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        LocMD->getNumOperands() != 0) {
454a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      if (const ConstantInt *CI = dyn_cast<ConstantInt>(LocMD->getOperand(0))) {
455a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        LocCookie = CI->getZExtValue();
456a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier        break;
457a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier      }
458a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    }
459a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  }
460a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier
461a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  // Emit the inline asm to a temporary string so we can emit it through
462a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  // EmitInlineAsm.
463a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  SmallString<256> StringData;
464a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  raw_svector_ostream OS(StringData);
465a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier
466a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  // The variant of the current asmprinter.
467a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  int AsmPrinterVariant = MAI->getAssemblerDialect();
468a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  InlineAsm::AsmDialect InlineAsmVariant = MI->getInlineAsmDialect();
469a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  AsmPrinter *AP = const_cast<AsmPrinter*>(this);
470a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  if (InlineAsmVariant == InlineAsm::AD_ATT)
471a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    EmitGCCInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AsmPrinterVariant,
472a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier                        AP, LocCookie, OS);
473a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier  else
474a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier    EmitMSInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AP, LocCookie, OS);
475a7b159ccdd3531853dc49dd91cf8948ce382e1c1Chad Rosier
476366df7945f0e65052d2e1df701ae1fd16b943642Chad Rosier  EmitInlineAsm(OS.str(), LocMD, MI->getInlineAsmDialect());
477ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
4787abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  // Emit the #NOAPP end marker.  This has to happen even if verbose-asm isn't
4797abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  // enabled, so we use EmitRawText.
4807abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  if (OutStreamer.hasRawTextSupport())
4817abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+
4827abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                            MAI->getInlineAsmEnd());
4837abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao}
4847abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
4857abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
4867abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao/// PrintSpecial - Print information related to the specified machine instr
4877abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao/// that is independent of the operand, and may be independent of the instr
4887abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao/// itself.  This can be useful for portably encoding the comment character
4897abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao/// or other bits of target-specific knowledge into the asmstrings.  The
4907abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao/// syntax used is ${:comment}.  Targets can override this to add support
4917abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao/// for their own strange codes.
4927abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaovoid AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
4937abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                              const char *Code) const {
4947abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  if (!strcmp(Code, "private")) {
4957abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    OS << MAI->getPrivateGlobalPrefix();
4967abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  } else if (!strcmp(Code, "comment")) {
4977abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    OS << MAI->getCommentString();
4987abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  } else if (!strcmp(Code, "uid")) {
4997abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    // Comparing the address of MI isn't sufficient, because machineinstrs may
5007abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    // be allocated to the same address across functions.
501ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach
5027abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    // If this is a new LastFn instruction, bump the counter.
5037abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    if (LastMI != MI || LastFn != getFunctionNumber()) {
5047abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      ++Counter;
5057abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      LastMI = MI;
5067abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao      LastFn = getFunctionNumber();
5077abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    }
5087abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    OS << Counter;
5097abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  } else {
5107abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    std::string msg;
5117abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    raw_string_ostream Msg(msg);
5127abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    Msg << "Unknown special formatter '" << Code
5137abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao         << "' for machine instr: " << *MI;
5147abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    report_fatal_error(Msg.str());
515ce027318293ddd2a0ea0cab4e9fa6af059d3bed2Jim Grosbach  }
5167abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao}
5177abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
5187abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
5197abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao/// instruction, using the specified assembler variant.  Targets should
5207abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao/// override this to format as appropriate.
5217abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaobool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
52226c5d5f0a93640008ccd01554b9c26e1e42dc892Chad Rosier                                 unsigned AsmVariant, const char *ExtraCode,
52326c5d5f0a93640008ccd01554b9c26e1e42dc892Chad Rosier                                 raw_ostream &O) {
524d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter  // Does this asm operand have a single letter operand modifier?
525d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter  if (ExtraCode && ExtraCode[0]) {
526d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter    if (ExtraCode[1] != 0) return true; // Unknown modifier.
527d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter
528d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter    const MachineOperand &MO = MI->getOperand(OpNo);
529d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter    switch (ExtraCode[0]) {
530d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter    default:
531d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter      return true;  // Unknown modifier.
532d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter    case 'c': // Substitute immediate value without immediate syntax
5334db98becf798a013ee00b82691af154e261d648eJack Carter      if (MO.getType() != MachineOperand::MO_Immediate)
534d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter        return true;
535d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter      O << MO.getImm();
536d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter      return false;
5374db98becf798a013ee00b82691af154e261d648eJack Carter    case 'n':  // Negate the immediate constant.
5384db98becf798a013ee00b82691af154e261d648eJack Carter      if (MO.getType() != MachineOperand::MO_Immediate)
5394db98becf798a013ee00b82691af154e261d648eJack Carter        return true;
5404db98becf798a013ee00b82691af154e261d648eJack Carter      O << -MO.getImm();
5414db98becf798a013ee00b82691af154e261d648eJack Carter      return false;
542d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter    }
543d5e11ad51a3966c0b80ce2119946cd1aa3558aecJack Carter  }
5447abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  return true;
5457abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao}
5467abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
5477abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaobool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
5487abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                                       unsigned AsmVariant,
5497abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao                                       const char *ExtraCode, raw_ostream &O) {
5507abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  // Target doesn't support this yet!
5517abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  return true;
5527abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao}
5537abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
554