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