AsmPrinterInlineAsm.cpp revision 7abe37e4aee38cc79d91dd069a37d7e91d5bef53
187e552db94588455c081efd87dbde0cd96d02942Ian Rogers//===-- AsmPrinterInlineAsm.cpp - AsmPrinter Inline Asm Handling ----------===// 287e552db94588455c081efd87dbde0cd96d02942Ian Rogers// 387e552db94588455c081efd87dbde0cd96d02942Ian Rogers// The LLVM Compiler Infrastructure 487e552db94588455c081efd87dbde0cd96d02942Ian Rogers// 587e552db94588455c081efd87dbde0cd96d02942Ian Rogers// This file is distributed under the University of Illinois Open Source 687e552db94588455c081efd87dbde0cd96d02942Ian Rogers// License. See LICENSE.TXT for details. 787e552db94588455c081efd87dbde0cd96d02942Ian Rogers// 887e552db94588455c081efd87dbde0cd96d02942Ian Rogers//===----------------------------------------------------------------------===// 987e552db94588455c081efd87dbde0cd96d02942Ian Rogers// 1087e552db94588455c081efd87dbde0cd96d02942Ian Rogers// This file implements the inline assembler pieces of the AsmPrinter class. 1187e552db94588455c081efd87dbde0cd96d02942Ian Rogers// 1287e552db94588455c081efd87dbde0cd96d02942Ian Rogers//===----------------------------------------------------------------------===// 1387e552db94588455c081efd87dbde0cd96d02942Ian Rogers 1487e552db94588455c081efd87dbde0cd96d02942Ian Rogers#define DEBUG_TYPE "asm-printer" 1587e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include "llvm/CodeGen/AsmPrinter.h" 1687e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include "llvm/Constants.h" 1787e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include "llvm/InlineAsm.h" 1887e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include "llvm/LLVMContext.h" 1922d5e735f403c57525fe868304c7123f0ce66399Ian Rogers#include "llvm/Module.h" 2022d5e735f403c57525fe868304c7123f0ce66399Ian Rogers#include "llvm/CodeGen/MachineBasicBlock.h" 2107ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "llvm/CodeGen/MachineModuleInfo.h" 222dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "llvm/MC/MCAsmInfo.h" 234f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "llvm/MC/MCStreamer.h" 2475b2a4abea8a608d7aec3e417498b69b31026a74Sebastien Hertz#include "llvm/MC/MCSymbol.h" 2587e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include "llvm/MC/MCParser/AsmParser.h" 26ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "llvm/Target/TargetAsmParser.h" 274f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "llvm/Target/TargetMachine.h" 282dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "llvm/Target/TargetRegistry.h" 292dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "llvm/ADT/OwningPtr.h" 3087e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include "llvm/ADT/SmallString.h" 312d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz#include "llvm/ADT/Twine.h" 3287e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include "llvm/Support/ErrorHandling.h" 3387e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include "llvm/Support/MemoryBuffer.h" 3487e552db94588455c081efd87dbde0cd96d02942Ian Rogers#include "llvm/Support/SourceMgr.h" 35ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#include "llvm/Support/raw_ostream.h" 36b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogersusing namespace llvm; 3787e552db94588455c081efd87dbde0cd96d02942Ian Rogers 38f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. 3987e552db94588455c081efd87dbde0cd96d02942Ian Rogersvoid AsmPrinter::EmitInlineAsm(StringRef Str, unsigned LocCookie) const { 4062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers assert(!Str.empty() && "Can't emit empty inline asm block"); 4162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 4287e552db94588455c081efd87dbde0cd96d02942Ian Rogers // Remember if the buffer is nul terminated or not so we can avoid a copy. 4387e552db94588455c081efd87dbde0cd96d02942Ian Rogers bool isNullTerminated = Str.back() == 0; 4487e552db94588455c081efd87dbde0cd96d02942Ian Rogers if (isNullTerminated) 4587e552db94588455c081efd87dbde0cd96d02942Ian Rogers Str = Str.substr(0, Str.size()-1); 4662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 47ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers // If the output streamer is actually a .s file, just emit the blob textually. 48b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers // This is useful in case the asm parser doesn't handle something but the 4962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // system assembler does. 5062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (OutStreamer.hasRawTextSupport()) { 5162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers OutStreamer.EmitRawText(Str); 5262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return; 5362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 5462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 5562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers SourceMgr SrcMgr; 5662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 5762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // If the current LLVMContext has an inline asm handler, set it in SourceMgr. 5862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LLVMContext &LLVMCtx = MMI->getModule()->getContext(); 5962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers bool HasDiagHandler = false; 6062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (void *DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler()) { 6162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers SrcMgr.setDiagHandler((SourceMgr::DiagHandlerTy)(intptr_t)DiagHandler, 6262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LLVMCtx.getInlineAsmDiagnosticContext(), LocCookie); 6362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers HasDiagHandler = true; 6487e552db94588455c081efd87dbde0cd96d02942Ian Rogers } 6587e552db94588455c081efd87dbde0cd96d02942Ian Rogers 6687e552db94588455c081efd87dbde0cd96d02942Ian Rogers MemoryBuffer *Buffer; 67329d18806792771dfee064203fe27875d79cd53aAndreas Gampe if (isNullTerminated) 68329d18806792771dfee064203fe27875d79cd53aAndreas Gampe Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>"); 69329d18806792771dfee064203fe27875d79cd53aAndreas Gampe else 70329d18806792771dfee064203fe27875d79cd53aAndreas Gampe Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); 71329d18806792771dfee064203fe27875d79cd53aAndreas Gampe 72329d18806792771dfee064203fe27875d79cd53aAndreas Gampe // Tell SrcMgr about this buffer, it takes ownership of the buffer. 73329d18806792771dfee064203fe27875d79cd53aAndreas Gampe SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); 74329d18806792771dfee064203fe27875d79cd53aAndreas Gampe 75329d18806792771dfee064203fe27875d79cd53aAndreas Gampe AsmParser Parser(SrcMgr, OutContext, OutStreamer, *MAI); 76329d18806792771dfee064203fe27875d79cd53aAndreas Gampe OwningPtr<TargetAsmParser> TAP(TM.getTarget().createAsmParser(Parser)); 77329d18806792771dfee064203fe27875d79cd53aAndreas Gampe if (!TAP) 78329d18806792771dfee064203fe27875d79cd53aAndreas Gampe report_fatal_error("Inline asm not supported by this streamer because" 79329d18806792771dfee064203fe27875d79cd53aAndreas Gampe " we don't have an asm parser for this target\n"); 80329d18806792771dfee064203fe27875d79cd53aAndreas Gampe Parser.setTargetParser(*TAP.get()); 81329d18806792771dfee064203fe27875d79cd53aAndreas Gampe 82329d18806792771dfee064203fe27875d79cd53aAndreas Gampe // Don't implicitly switch to the text section before the asm. 83329d18806792771dfee064203fe27875d79cd53aAndreas Gampe int Res = Parser.Run(/*NoInitialTextSection*/ true, 84329d18806792771dfee064203fe27875d79cd53aAndreas Gampe /*NoFinalize*/ true); 85329d18806792771dfee064203fe27875d79cd53aAndreas Gampe if (Res && !HasDiagHandler) 86329d18806792771dfee064203fe27875d79cd53aAndreas Gampe report_fatal_error("Error parsing inline asm\n"); 87329d18806792771dfee064203fe27875d79cd53aAndreas Gampe} 88329d18806792771dfee064203fe27875d79cd53aAndreas Gampe 8956adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz 9056adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz/// EmitInlineAsm - This method formats and emits the specified machine 91ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers/// instruction that is an inline asm. 9256adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertzvoid AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { 9356adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms"); 9456adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz 9556adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz unsigned NumOperands = MI->getNumOperands(); 9656adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz 9762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Count the number of register definitions to find the asm string. 9887e552db94588455c081efd87dbde0cd96d02942Ian Rogers unsigned NumDefs = 0; 990a3b863fb1acae912b54f4be2c1928d3afa5e936Sebastien Hertz for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); 10062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ++NumDefs) 10187e552db94588455c081efd87dbde0cd96d02942Ian Rogers assert(NumDefs != NumOperands-2 && "No asm string?"); 10287e552db94588455c081efd87dbde0cd96d02942Ian Rogers 10362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?"); 10462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 10562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Disassemble the AsmStr, printing out the literal pieces, the operands, etc. 10662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers const char *AsmStr = MI->getOperand(NumDefs).getSymbolName(); 10762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 10887e552db94588455c081efd87dbde0cd96d02942Ian Rogers // If this asmstr is empty, just print the #APP/#NOAPP markers. 10987e552db94588455c081efd87dbde0cd96d02942Ian Rogers // These are useful to see where empty asm's wound up. 11062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (AsmStr[0] == 0) { 11162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Don't emit the comments if writing to a .o file. 112ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (!OutStreamer.hasRawTextSupport()) return; 11362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 11462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ 11562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers MAI->getInlineAsmStart()); 11662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ 11762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers MAI->getInlineAsmEnd()); 11862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return; 11962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 12062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 121ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers // Emit the #APP start marker. This has to happen even if verbose-asm isn't 12262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // enabled, so we use EmitRawText. 12362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (OutStreamer.hasRawTextSupport()) 12462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ 12562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers MAI->getInlineAsmStart()); 12662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 12762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Get the !srcloc metadata node if we have it, and decode the loc cookie from 12862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // it. 12962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers unsigned LocCookie = 0; 13062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers for (unsigned i = MI->getNumOperands(); i != 0; --i) { 13162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (MI->getOperand(i-1).isMetadata()) 13262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (const MDNode *SrcLoc = MI->getOperand(i-1).getMetadata()) 13362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (SrcLoc->getNumOperands() != 0) 13462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (const ConstantInt *CI = 13562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers dyn_cast<ConstantInt>(SrcLoc->getOperand(0))) { 13662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LocCookie = CI->getZExtValue(); 13762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers break; 13887e552db94588455c081efd87dbde0cd96d02942Ian Rogers } 13987e552db94588455c081efd87dbde0cd96d02942Ian Rogers } 14062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 14162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Emit the inline asm to a temporary string so we can emit it through 142ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers // EmitInlineAsm. 14362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers SmallString<256> StringData; 14462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers raw_svector_ostream OS(StringData); 14562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 14662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers OS << '\t'; 14762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 14887e552db94588455c081efd87dbde0cd96d02942Ian Rogers // The variant of the current asmprinter. 14987e552db94588455c081efd87dbde0cd96d02942Ian Rogers int AsmPrinterVariant = MAI->getAssemblerDialect(); 1502dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 15187e552db94588455c081efd87dbde0cd96d02942Ian Rogers int CurVariant = -1; // The number of the {.|.|.} region we are in. 152b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers const char *LastEmitted = AsmStr; // One past the last character emitted. 15387e552db94588455c081efd87dbde0cd96d02942Ian Rogers 15462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers while (*LastEmitted) { 15587e552db94588455c081efd87dbde0cd96d02942Ian Rogers switch (*LastEmitted) { 15687e552db94588455c081efd87dbde0cd96d02942Ian Rogers default: { 1572dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers // Not a special case, emit the string section literally. 158ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const char *LiteralEnd = LastEmitted+1; 15987e552db94588455c081efd87dbde0cd96d02942Ian Rogers while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && 16087e552db94588455c081efd87dbde0cd96d02942Ian Rogers *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') 161b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers ++LiteralEnd; 162b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers if (CurVariant == -1 || CurVariant == AsmPrinterVariant) 16387e552db94588455c081efd87dbde0cd96d02942Ian Rogers OS.write(LastEmitted, LiteralEnd-LastEmitted); 16462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LastEmitted = LiteralEnd; 16587e552db94588455c081efd87dbde0cd96d02942Ian Rogers break; 16687e552db94588455c081efd87dbde0cd96d02942Ian Rogers } 167ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom case '\n': 16887e552db94588455c081efd87dbde0cd96d02942Ian Rogers ++LastEmitted; // Consume newline character. 16987e552db94588455c081efd87dbde0cd96d02942Ian Rogers OS << '\n'; // Indent code with newline. 17087e552db94588455c081efd87dbde0cd96d02942Ian Rogers break; 17162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers case '$': { 17287e552db94588455c081efd87dbde0cd96d02942Ian Rogers ++LastEmitted; // Consume '$' character. 17387e552db94588455c081efd87dbde0cd96d02942Ian Rogers bool Done = true; 174ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom 17587e552db94588455c081efd87dbde0cd96d02942Ian Rogers // Handle escapes. 17687e552db94588455c081efd87dbde0cd96d02942Ian Rogers switch (*LastEmitted) { 17787e552db94588455c081efd87dbde0cd96d02942Ian Rogers default: Done = false; break; 17862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers case '$': // $$ -> $ 17987e552db94588455c081efd87dbde0cd96d02942Ian Rogers if (CurVariant == -1 || CurVariant == AsmPrinterVariant) 18087e552db94588455c081efd87dbde0cd96d02942Ian Rogers OS << '$'; 181ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers ++LastEmitted; // Consume second '$' character. 182ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom break; 18387e552db94588455c081efd87dbde0cd96d02942Ian Rogers case '(': // $( -> same as GCC's { character. 18487e552db94588455c081efd87dbde0cd96d02942Ian Rogers ++LastEmitted; // Consume '(' character. 18587e552db94588455c081efd87dbde0cd96d02942Ian Rogers if (CurVariant != -1) 186ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom report_fatal_error("Nested variants found in inline asm string: '" + 187ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom Twine(AsmStr) + "'"); 18862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers CurVariant = 0; // We're in the first variant now. 18962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers break; 19062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers case '|': 1912ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom ++LastEmitted; // consume '|' character. 19262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (CurVariant == -1) 19362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers OS << '|'; // this is gcc's behavior for | outside a variant 19462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers else 19562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ++CurVariant; // We're in the next variant. 19687e552db94588455c081efd87dbde0cd96d02942Ian Rogers break; 19787e552db94588455c081efd87dbde0cd96d02942Ian Rogers case ')': // $) -> same as GCC's } char. 19811d5d8fffe41cc7daadbfa2ca98ecb978f3029afJeff Hao ++LastEmitted; // consume ')' character. 19911d5d8fffe41cc7daadbfa2ca98ecb978f3029afJeff Hao if (CurVariant == -1) 20011d5d8fffe41cc7daadbfa2ca98ecb978f3029afJeff Hao OS << '}'; // this is gcc's behavior for } outside a variant 20111d5d8fffe41cc7daadbfa2ca98ecb978f3029afJeff Hao else 20211d5d8fffe41cc7daadbfa2ca98ecb978f3029afJeff Hao CurVariant = -1; 20311d5d8fffe41cc7daadbfa2ca98ecb978f3029afJeff Hao break; 20462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 20562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (Done) break; 20662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 20762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers bool HasCurlyBraces = false; 20862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (*LastEmitted == '{') { // ${variable} 20962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ++LastEmitted; // Consume '{' character. 21062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers HasCurlyBraces = true; 21187e552db94588455c081efd87dbde0cd96d02942Ian Rogers } 21287e552db94588455c081efd87dbde0cd96d02942Ian Rogers 21387e552db94588455c081efd87dbde0cd96d02942Ian Rogers // If we have ${:foo}, then this is not a real operand reference, it is a 214ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom // "magic" string reference, just like in .td files. Arrange to call 215ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers // PrintSpecial. 21687e552db94588455c081efd87dbde0cd96d02942Ian Rogers if (HasCurlyBraces && *LastEmitted == ':') { 21787e552db94588455c081efd87dbde0cd96d02942Ian Rogers ++LastEmitted; 21887e552db94588455c081efd87dbde0cd96d02942Ian Rogers const char *StrStart = LastEmitted; 21962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers const char *StrEnd = strchr(StrStart, '}'); 22062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (StrEnd == 0) 22162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers report_fatal_error("Unterminated ${:foo} operand in inline asm" 22287e552db94588455c081efd87dbde0cd96d02942Ian Rogers " string: '" + Twine(AsmStr) + "'"); 22387e552db94588455c081efd87dbde0cd96d02942Ian Rogers 224ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers std::string Val(StrStart, StrEnd); 2252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers PrintSpecial(MI, OS, Val.c_str()); 226ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers LastEmitted = StrEnd+1; 22787e552db94588455c081efd87dbde0cd96d02942Ian Rogers break; 22887e552db94588455c081efd87dbde0cd96d02942Ian Rogers } 22987e552db94588455c081efd87dbde0cd96d02942Ian Rogers 23087e552db94588455c081efd87dbde0cd96d02942Ian Rogers const char *IDStart = LastEmitted; 23187e552db94588455c081efd87dbde0cd96d02942Ian Rogers const char *IDEnd = IDStart; 23287e552db94588455c081efd87dbde0cd96d02942Ian Rogers while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd; 23387e552db94588455c081efd87dbde0cd96d02942Ian Rogers 23487e552db94588455c081efd87dbde0cd96d02942Ian Rogers unsigned Val; 23562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val)) 23662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers report_fatal_error("Bad $ operand number in inline asm string: '" + 23762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Twine(AsmStr) + "'"); 23887e552db94588455c081efd87dbde0cd96d02942Ian Rogers LastEmitted = IDEnd; 23987e552db94588455c081efd87dbde0cd96d02942Ian Rogers 240ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers char Modifier[2] = { 0, 0 }; 241ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 24287e552db94588455c081efd87dbde0cd96d02942Ian Rogers if (HasCurlyBraces) { 24387e552db94588455c081efd87dbde0cd96d02942Ian Rogers // If we have curly braces, check for a modifier character. This 244b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm. 245b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers if (*LastEmitted == ':') { 24662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ++LastEmitted; // Consume ':' character. 24762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (*LastEmitted == 0) 24862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers report_fatal_error("Bad ${:} expression in inline asm string: '" + 24962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Twine(AsmStr) + "'"); 250ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 25162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Modifier[0] = *LastEmitted; 25262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ++LastEmitted; // Consume modifier character. 25362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 25462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 25562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (*LastEmitted != '}') 25662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers report_fatal_error("Bad ${} expression in inline asm string: '" + 2578d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers Twine(AsmStr) + "'"); 2588d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers ++LastEmitted; // Consume '}' character. 2598d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers } 2608d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers 2618d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (Val >= NumOperands-1) 2628d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers report_fatal_error("Invalid $ operand number in inline asm string: '" + 2638d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers Twine(AsmStr) + "'"); 2648d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers 2658d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers // Okay, we finally have a value number. Ask the target to print this 266329d18806792771dfee064203fe27875d79cd53aAndreas Gampe // operand! 267329d18806792771dfee064203fe27875d79cd53aAndreas Gampe if (CurVariant == -1 || CurVariant == AsmPrinterVariant) { 268329d18806792771dfee064203fe27875d79cd53aAndreas Gampe unsigned OpNo = 1; 269329d18806792771dfee064203fe27875d79cd53aAndreas Gampe 270329d18806792771dfee064203fe27875d79cd53aAndreas Gampe bool Error = false; 271329d18806792771dfee064203fe27875d79cd53aAndreas Gampe 272329d18806792771dfee064203fe27875d79cd53aAndreas Gampe // Scan to find the machine operand number for the operand. 27362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers for (; Val; --Val) { 27462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (OpNo >= MI->getNumOperands()) break; 275ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers unsigned OpFlags = MI->getOperand(OpNo).getImm(); 27662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; 27762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 27862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 27962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (OpNo >= MI->getNumOperands()) { 28062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Error = true; 28162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else { 28262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers unsigned OpFlags = MI->getOperand(OpNo).getImm(); 28362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ++OpNo; // Skip over the ID number. 28462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 285ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom if (Modifier[0] == 'l') // labels are target independent 286ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom // FIXME: What if the operand isn't an MBB, report error? 28762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers OS << *MI->getOperand(OpNo).getMBB()->getSymbol(); 28862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers else { 28962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers AsmPrinter *AP = const_cast<AsmPrinter*>(this); 29062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (InlineAsm::isMemKind(OpFlags)) { 29162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Error = AP->PrintAsmMemoryOperand(MI, OpNo, AsmPrinterVariant, 29262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Modifier[0] ? Modifier : 0, 29362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers OS); 29462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else { 29562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Error = AP->PrintAsmOperand(MI, OpNo, AsmPrinterVariant, 29662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Modifier[0] ? Modifier : 0, OS); 29762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 29862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 299cb6b0f31ede2275e79e6199ec391147585a37a2aIan Rogers } 30062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (Error) { 301cb6b0f31ede2275e79e6199ec391147585a37a2aIan Rogers std::string msg; 30262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers raw_string_ostream Msg(msg); 30387e552db94588455c081efd87dbde0cd96d02942Ian Rogers Msg << "invalid operand in inline asm: '" << AsmStr << "'"; 30487e552db94588455c081efd87dbde0cd96d02942Ian Rogers MMI->getModule()->getContext().emitError(LocCookie, Msg.str()); 30587e552db94588455c081efd87dbde0cd96d02942Ian Rogers } 30687e552db94588455c081efd87dbde0cd96d02942Ian Rogers } 3072dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers break; 308d91d6d6a80748f277fd938a412211e5af28913b1Ian Rogers } 30987e552db94588455c081efd87dbde0cd96d02942Ian Rogers } 310cb6b0f31ede2275e79e6199ec391147585a37a2aIan Rogers } 31187e552db94588455c081efd87dbde0cd96d02942Ian Rogers OS << '\n' << (char)0; // null terminate string. 312cb6b0f31ede2275e79e6199ec391147585a37a2aIan Rogers EmitInlineAsm(OS.str(), LocCookie); 31362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 31487e552db94588455c081efd87dbde0cd96d02942Ian Rogers // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't 31587e552db94588455c081efd87dbde0cd96d02942Ian Rogers // enabled, so we use EmitRawText. 31662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (OutStreamer.hasRawTextSupport()) 31762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ 31862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers MAI->getInlineAsmEnd()); 31962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 3204445a7e3398a6143939168097a3aa275b734504dIan Rogers 32187e552db94588455c081efd87dbde0cd96d02942Ian Rogers 32287e552db94588455c081efd87dbde0cd96d02942Ian Rogers/// PrintSpecial - Print information related to the specified machine instr 32362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers/// that is independent of the operand, and may be independent of the instr 32462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers/// itself. This can be useful for portably encoding the comment character 32562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers/// or other bits of target-specific knowledge into the asmstrings. The 32662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers/// syntax used is ${:comment}. Targets can override this to add support 32762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers/// for their own strange codes. 32862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS, 32962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers const char *Code) const { 330ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom if (!strcmp(Code, "private")) { 33162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers OS << MAI->getPrivateGlobalPrefix(); 33262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else if (!strcmp(Code, "comment")) { 33362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers OS << MAI->getCommentString(); 33462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else if (!strcmp(Code, "uid")) { 33562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Comparing the address of MI isn't sufficient, because machineinstrs may 33662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // be allocated to the same address across functions. 3372d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz 3382d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz // If this is a new LastFn instruction, bump the counter. 3392d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz if (LastMI != MI || LastFn != getFunctionNumber()) { 3402d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz ++Counter; 3412d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz LastMI = MI; 34262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LastFn = getFunctionNumber(); 34362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 34462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers OS << Counter; 34562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else { 34662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers std::string msg; 34762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers raw_string_ostream Msg(msg); 348ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom Msg << "Unknown special formatter '" << Code 349ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom << "' for machine instr: " << *MI; 3502d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz report_fatal_error(Msg.str()); 3512d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz } 3522d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz} 3532d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz 3542d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM 3552d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz/// instruction, using the specified assembler variant. Targets should 3562d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz/// override this to format as appropriate. 3572d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertzbool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 358ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom unsigned AsmVariant, const char *ExtraCode, 3592d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz raw_ostream &O) { 3602d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz // Target doesn't support this yet! 3612d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz return true; 3622d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz} 3632d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz 3642d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertzbool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 3652d6ba5158d7fd459db2870df47300b517dc4d08cSebastien Hertz unsigned AsmVariant, 36662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers const char *ExtraCode, raw_ostream &O) { 367bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier // Target doesn't support this yet! 36862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return true; 36962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 37062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 37162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers