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