AsmPrinterInlineAsm.cpp revision a71642b2a4944eaa269d881cf71b02b8e8fe5638
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#define DEBUG_TYPE "asm-printer"
15#include "llvm/CodeGen/AsmPrinter.h"
16#include "llvm/Constants.h"
17#include "llvm/InlineAsm.h"
18#include "llvm/LLVMContext.h"
19#include "llvm/Module.h"
20#include "llvm/CodeGen/MachineBasicBlock.h"
21#include "llvm/CodeGen/MachineModuleInfo.h"
22#include "llvm/MC/MCAsmInfo.h"
23#include "llvm/MC/MCStreamer.h"
24#include "llvm/MC/MCSubtargetInfo.h"
25#include "llvm/MC/MCSymbol.h"
26#include "llvm/Target/TargetAsmParser.h"
27#include "llvm/Target/TargetMachine.h"
28#include "llvm/Target/TargetRegistry.h"
29#include "llvm/ADT/OwningPtr.h"
30#include "llvm/ADT/SmallString.h"
31#include "llvm/ADT/Twine.h"
32#include "llvm/Support/ErrorHandling.h"
33#include "llvm/Support/MemoryBuffer.h"
34#include "llvm/Support/SourceMgr.h"
35#include "llvm/Support/raw_ostream.h"
36using namespace llvm;
37
38namespace {
39  struct SrcMgrDiagInfo {
40    const MDNode *LocInfo;
41    LLVMContext::InlineAsmDiagHandlerTy DiagHandler;
42    void *DiagContext;
43  };
44}
45
46/// SrcMgrDiagHandler - This callback is invoked when the SourceMgr for an
47/// inline asm has an error in it.  diagInfo is a pointer to the SrcMgrDiagInfo
48/// struct above.
49static void SrcMgrDiagHandler(const SMDiagnostic &Diag, void *diagInfo) {
50  SrcMgrDiagInfo *DiagInfo = static_cast<SrcMgrDiagInfo *>(diagInfo);
51  assert(DiagInfo && "Diagnostic context not passed down?");
52
53  // If the inline asm had metadata associated with it, pull out a location
54  // cookie corresponding to which line the error occurred on.
55  unsigned LocCookie = 0;
56  if (const MDNode *LocInfo = DiagInfo->LocInfo) {
57    unsigned ErrorLine = Diag.getLineNo()-1;
58    if (ErrorLine >= LocInfo->getNumOperands())
59      ErrorLine = 0;
60
61    if (LocInfo->getNumOperands() != 0)
62      if (const ConstantInt *CI =
63          dyn_cast<ConstantInt>(LocInfo->getOperand(ErrorLine)))
64        LocCookie = CI->getZExtValue();
65  }
66
67  DiagInfo->DiagHandler(Diag, DiagInfo->DiagContext, LocCookie);
68}
69
70/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
71void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode) const {
72#ifndef ANDROID_TARGET_BUILD
73  assert(!Str.empty() && "Can't emit empty inline asm block");
74
75  // Remember if the buffer is nul terminated or not so we can avoid a copy.
76  bool isNullTerminated = Str.back() == 0;
77  if (isNullTerminated)
78    Str = Str.substr(0, Str.size()-1);
79
80  // If the output streamer is actually a .s file, just emit the blob textually.
81  // This is useful in case the asm parser doesn't handle something but the
82  // system assembler does.
83  if (OutStreamer.hasRawTextSupport()) {
84    OutStreamer.EmitRawText(Str);
85    return;
86  }
87
88  SourceMgr SrcMgr;
89  SrcMgrDiagInfo DiagInfo;
90
91  // If the current LLVMContext has an inline asm handler, set it in SourceMgr.
92  LLVMContext &LLVMCtx = MMI->getModule()->getContext();
93  bool HasDiagHandler = false;
94  if (LLVMCtx.getInlineAsmDiagnosticHandler() != 0) {
95    // If the source manager has an issue, we arrange for SrcMgrDiagHandler
96    // to be invoked, getting DiagInfo passed into it.
97    DiagInfo.LocInfo = LocMDNode;
98    DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler();
99    DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext();
100    SrcMgr.setDiagHandler(SrcMgrDiagHandler, &DiagInfo);
101    HasDiagHandler = true;
102  }
103
104  MemoryBuffer *Buffer;
105  if (isNullTerminated)
106    Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>");
107  else
108    Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>");
109
110  // Tell SrcMgr about this buffer, it takes ownership of the buffer.
111  SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
112
113  OwningPtr<MCAsmParser> Parser(createMCAsmParser(TM.getTarget(), SrcMgr,
114                                                  OutContext, OutStreamer,
115                                                  *MAI));
116
117  // FIXME: It would be nice if we can avoid createing a new instance of
118  // MCSubtargetInfo here given TargetSubtargetInfo is available. However,
119  // we have to watch out for asm directives which can change subtarget
120  // state. e.g. .code 16, .code 32.
121  OwningPtr<MCSubtargetInfo>
122    STI(TM.getTarget().createMCSubtargetInfo(TM.getTargetTriple(),
123                                             TM.getTargetCPU(),
124                                             TM.getTargetFeatureString()));
125  OwningPtr<TargetAsmParser> TAP(TM.getTarget().createAsmParser(*STI, *Parser));
126  if (!TAP)
127    report_fatal_error("Inline asm not supported by this streamer because"
128                       " we don't have an asm parser for this target\n");
129  Parser->setTargetParser(*TAP.get());
130
131  // Don't implicitly switch to the text section before the asm.
132  int Res = Parser->Run(/*NoInitialTextSection*/ true,
133                        /*NoFinalize*/ true);
134  if (Res && !HasDiagHandler)
135    report_fatal_error("Error parsing inline asm\n");
136#endif // ANDROID_TARGET_BUILD
137}
138
139
140/// EmitInlineAsm - This method formats and emits the specified machine
141/// instruction that is an inline asm.
142void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
143#ifndef ANDROID_TARGET_BUILD
144  assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms");
145
146  unsigned NumOperands = MI->getNumOperands();
147
148  // Count the number of register definitions to find the asm string.
149  unsigned NumDefs = 0;
150  for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef();
151       ++NumDefs)
152    assert(NumDefs != NumOperands-2 && "No asm string?");
153
154  assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?");
155
156  // Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
157  const char *AsmStr = MI->getOperand(NumDefs).getSymbolName();
158
159  // If this asmstr is empty, just print the #APP/#NOAPP markers.
160  // These are useful to see where empty asm's wound up.
161  if (AsmStr[0] == 0) {
162    // Don't emit the comments if writing to a .o file.
163    if (!OutStreamer.hasRawTextSupport()) return;
164
165    OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+
166                            MAI->getInlineAsmStart());
167    OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+
168                            MAI->getInlineAsmEnd());
169    return;
170  }
171
172  // Emit the #APP start marker.  This has to happen even if verbose-asm isn't
173  // enabled, so we use EmitRawText.
174  if (OutStreamer.hasRawTextSupport())
175    OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+
176                            MAI->getInlineAsmStart());
177
178  // Get the !srcloc metadata node if we have it, and decode the loc cookie from
179  // it.
180  unsigned LocCookie = 0;
181  const MDNode *LocMD = 0;
182  for (unsigned i = MI->getNumOperands(); i != 0; --i) {
183    if (MI->getOperand(i-1).isMetadata() &&
184        (LocMD = MI->getOperand(i-1).getMetadata()) &&
185        LocMD->getNumOperands() != 0) {
186      if (const ConstantInt *CI = dyn_cast<ConstantInt>(LocMD->getOperand(0))) {
187        LocCookie = CI->getZExtValue();
188        break;
189      }
190    }
191  }
192
193  // Emit the inline asm to a temporary string so we can emit it through
194  // EmitInlineAsm.
195  SmallString<256> StringData;
196  raw_svector_ostream OS(StringData);
197
198  OS << '\t';
199
200  // The variant of the current asmprinter.
201  int AsmPrinterVariant = MAI->getAssemblerDialect();
202
203  int CurVariant = -1;            // The number of the {.|.|.} region we are in.
204  const char *LastEmitted = AsmStr; // One past the last character emitted.
205
206  while (*LastEmitted) {
207    switch (*LastEmitted) {
208    default: {
209      // Not a special case, emit the string section literally.
210      const char *LiteralEnd = LastEmitted+1;
211      while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&
212             *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')
213        ++LiteralEnd;
214      if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
215        OS.write(LastEmitted, LiteralEnd-LastEmitted);
216      LastEmitted = LiteralEnd;
217      break;
218    }
219    case '\n':
220      ++LastEmitted;   // Consume newline character.
221      OS << '\n';      // Indent code with newline.
222      break;
223    case '$': {
224      ++LastEmitted;   // Consume '$' character.
225      bool Done = true;
226
227      // Handle escapes.
228      switch (*LastEmitted) {
229      default: Done = false; break;
230      case '$':     // $$ -> $
231        if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
232          OS << '$';
233        ++LastEmitted;  // Consume second '$' character.
234        break;
235      case '(':             // $( -> same as GCC's { character.
236        ++LastEmitted;      // Consume '(' character.
237        if (CurVariant != -1)
238          report_fatal_error("Nested variants found in inline asm string: '" +
239                             Twine(AsmStr) + "'");
240        CurVariant = 0;     // We're in the first variant now.
241        break;
242      case '|':
243        ++LastEmitted;  // consume '|' character.
244        if (CurVariant == -1)
245          OS << '|';       // this is gcc's behavior for | outside a variant
246        else
247          ++CurVariant;   // We're in the next variant.
248        break;
249      case ')':         // $) -> same as GCC's } char.
250        ++LastEmitted;  // consume ')' character.
251        if (CurVariant == -1)
252          OS << '}';     // this is gcc's behavior for } outside a variant
253        else
254          CurVariant = -1;
255        break;
256      }
257      if (Done) break;
258
259      bool HasCurlyBraces = false;
260      if (*LastEmitted == '{') {     // ${variable}
261        ++LastEmitted;               // Consume '{' character.
262        HasCurlyBraces = true;
263      }
264
265      // If we have ${:foo}, then this is not a real operand reference, it is a
266      // "magic" string reference, just like in .td files.  Arrange to call
267      // PrintSpecial.
268      if (HasCurlyBraces && *LastEmitted == ':') {
269        ++LastEmitted;
270        const char *StrStart = LastEmitted;
271        const char *StrEnd = strchr(StrStart, '}');
272        if (StrEnd == 0)
273          report_fatal_error("Unterminated ${:foo} operand in inline asm"
274                             " string: '" + Twine(AsmStr) + "'");
275
276        std::string Val(StrStart, StrEnd);
277        PrintSpecial(MI, OS, Val.c_str());
278        LastEmitted = StrEnd+1;
279        break;
280      }
281
282      const char *IDStart = LastEmitted;
283      const char *IDEnd = IDStart;
284      while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd;
285
286      unsigned Val;
287      if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val))
288        report_fatal_error("Bad $ operand number in inline asm string: '" +
289                           Twine(AsmStr) + "'");
290      LastEmitted = IDEnd;
291
292      char Modifier[2] = { 0, 0 };
293
294      if (HasCurlyBraces) {
295        // If we have curly braces, check for a modifier character.  This
296        // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm.
297        if (*LastEmitted == ':') {
298          ++LastEmitted;    // Consume ':' character.
299          if (*LastEmitted == 0)
300            report_fatal_error("Bad ${:} expression in inline asm string: '" +
301                               Twine(AsmStr) + "'");
302
303          Modifier[0] = *LastEmitted;
304          ++LastEmitted;    // Consume modifier character.
305        }
306
307        if (*LastEmitted != '}')
308          report_fatal_error("Bad ${} expression in inline asm string: '" +
309                             Twine(AsmStr) + "'");
310        ++LastEmitted;    // Consume '}' character.
311      }
312
313      if (Val >= NumOperands-1)
314        report_fatal_error("Invalid $ operand number in inline asm string: '" +
315                           Twine(AsmStr) + "'");
316
317      // Okay, we finally have a value number.  Ask the target to print this
318      // operand!
319      if (CurVariant == -1 || CurVariant == AsmPrinterVariant) {
320        unsigned OpNo = InlineAsm::MIOp_FirstOperand;
321
322        bool Error = false;
323
324        // Scan to find the machine operand number for the operand.
325        for (; Val; --Val) {
326          if (OpNo >= MI->getNumOperands()) break;
327          unsigned OpFlags = MI->getOperand(OpNo).getImm();
328          OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
329        }
330
331        if (OpNo >= MI->getNumOperands()) {
332          Error = true;
333        } else {
334          unsigned OpFlags = MI->getOperand(OpNo).getImm();
335          ++OpNo;  // Skip over the ID number.
336
337          if (Modifier[0] == 'l')  // labels are target independent
338            // FIXME: What if the operand isn't an MBB, report error?
339            OS << *MI->getOperand(OpNo).getMBB()->getSymbol();
340          else {
341            AsmPrinter *AP = const_cast<AsmPrinter*>(this);
342            if (InlineAsm::isMemKind(OpFlags)) {
343              Error = AP->PrintAsmMemoryOperand(MI, OpNo, AsmPrinterVariant,
344                                                Modifier[0] ? Modifier : 0,
345                                                OS);
346            } else {
347              Error = AP->PrintAsmOperand(MI, OpNo, AsmPrinterVariant,
348                                          Modifier[0] ? Modifier : 0, OS);
349            }
350          }
351        }
352        if (Error) {
353          std::string msg;
354          raw_string_ostream Msg(msg);
355          Msg << "invalid operand in inline asm: '" << AsmStr << "'";
356          MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
357        }
358      }
359      break;
360    }
361    }
362  }
363  OS << '\n' << (char)0;  // null terminate string.
364  EmitInlineAsm(OS.str(), LocMD);
365
366  // Emit the #NOAPP end marker.  This has to happen even if verbose-asm isn't
367  // enabled, so we use EmitRawText.
368  if (OutStreamer.hasRawTextSupport())
369    OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+
370                            MAI->getInlineAsmEnd());
371#endif // ANDROID_TARGET_BUILD
372}
373
374
375/// PrintSpecial - Print information related to the specified machine instr
376/// that is independent of the operand, and may be independent of the instr
377/// itself.  This can be useful for portably encoding the comment character
378/// or other bits of target-specific knowledge into the asmstrings.  The
379/// syntax used is ${:comment}.  Targets can override this to add support
380/// for their own strange codes.
381void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
382                              const char *Code) const {
383  if (!strcmp(Code, "private")) {
384    OS << MAI->getPrivateGlobalPrefix();
385  } else if (!strcmp(Code, "comment")) {
386    OS << MAI->getCommentString();
387  } else if (!strcmp(Code, "uid")) {
388    // Comparing the address of MI isn't sufficient, because machineinstrs may
389    // be allocated to the same address across functions.
390
391    // If this is a new LastFn instruction, bump the counter.
392    if (LastMI != MI || LastFn != getFunctionNumber()) {
393      ++Counter;
394      LastMI = MI;
395      LastFn = getFunctionNumber();
396    }
397    OS << Counter;
398  } else {
399    std::string msg;
400    raw_string_ostream Msg(msg);
401    Msg << "Unknown special formatter '" << Code
402         << "' for machine instr: " << *MI;
403    report_fatal_error(Msg.str());
404  }
405}
406
407/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
408/// instruction, using the specified assembler variant.  Targets should
409/// override this to format as appropriate.
410bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
411                                 unsigned AsmVariant, const char *ExtraCode,
412                                 raw_ostream &O) {
413  // Target doesn't support this yet!
414  return true;
415}
416
417bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
418                                       unsigned AsmVariant,
419                                       const char *ExtraCode, raw_ostream &O) {
420  // Target doesn't support this yet!
421  return true;
422}
423
424