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/ADT/OwningPtr.h" 17 #include "llvm/ADT/SmallString.h" 18 #include "llvm/ADT/Twine.h" 19 #include "llvm/CodeGen/MachineBasicBlock.h" 20 #include "llvm/CodeGen/MachineModuleInfo.h" 21 #include "llvm/IR/Constants.h" 22 #include "llvm/IR/DataLayout.h" 23 #include "llvm/IR/InlineAsm.h" 24 #include "llvm/IR/LLVMContext.h" 25 #include "llvm/IR/Module.h" 26 #include "llvm/MC/MCAsmInfo.h" 27 #include "llvm/MC/MCStreamer.h" 28 #include "llvm/MC/MCSubtargetInfo.h" 29 #include "llvm/MC/MCSymbol.h" 30 #include "llvm/MC/MCTargetAsmParser.h" 31 #include "llvm/Support/ErrorHandling.h" 32 #include "llvm/Support/MemoryBuffer.h" 33 #include "llvm/Support/SourceMgr.h" 34 #include "llvm/Support/TargetRegistry.h" 35 #include "llvm/Support/raw_ostream.h" 36 #include "llvm/Target/TargetMachine.h" 37 #include "llvm/Target/TargetSubtargetInfo.h" 38 using namespace llvm; 39 40 namespace { 41 struct SrcMgrDiagInfo { 42 const MDNode *LocInfo; 43 LLVMContext::InlineAsmDiagHandlerTy DiagHandler; 44 void *DiagContext; 45 }; 46 } 47 48 /// srcMgrDiagHandler - This callback is invoked when the SourceMgr for an 49 /// inline asm has an error in it. diagInfo is a pointer to the SrcMgrDiagInfo 50 /// struct above. 51 static void srcMgrDiagHandler(const SMDiagnostic &Diag, void *diagInfo) { 52 SrcMgrDiagInfo *DiagInfo = static_cast<SrcMgrDiagInfo *>(diagInfo); 53 assert(DiagInfo && "Diagnostic context not passed down?"); 54 55 // If the inline asm had metadata associated with it, pull out a location 56 // cookie corresponding to which line the error occurred on. 57 unsigned LocCookie = 0; 58 if (const MDNode *LocInfo = DiagInfo->LocInfo) { 59 unsigned ErrorLine = Diag.getLineNo()-1; 60 if (ErrorLine >= LocInfo->getNumOperands()) 61 ErrorLine = 0; 62 63 if (LocInfo->getNumOperands() != 0) 64 if (const ConstantInt *CI = 65 dyn_cast<ConstantInt>(LocInfo->getOperand(ErrorLine))) 66 LocCookie = CI->getZExtValue(); 67 } 68 69 DiagInfo->DiagHandler(Diag, DiagInfo->DiagContext, LocCookie); 70 } 71 72 /// EmitInlineAsm - Emit a blob of inline asm to the output streamer. 73 void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, 74 InlineAsm::AsmDialect Dialect) const { 75 assert(!Str.empty() && "Can't emit empty inline asm block"); 76 77 // Remember if the buffer is nul terminated or not so we can avoid a copy. 78 bool isNullTerminated = Str.back() == 0; 79 if (isNullTerminated) 80 Str = Str.substr(0, Str.size()-1); 81 82 // If the output streamer does not have mature MC support or the integrated 83 // assembler has been disabled, just emit the blob textually. 84 // Otherwise parse the asm and emit it via MC support. 85 // This is useful in case the asm parser doesn't handle something but the 86 // system assembler does. 87 const MCAsmInfo *MCAI = TM.getMCAsmInfo(); 88 assert(MCAI && "No MCAsmInfo"); 89 if (!MCAI->useIntegratedAssembler() && 90 !OutStreamer.isIntegratedAssemblerRequired()) { 91 OutStreamer.EmitRawText(Str); 92 emitInlineAsmEnd(TM.getSubtarget<MCSubtargetInfo>(), 0); 93 return; 94 } 95 96 SourceMgr SrcMgr; 97 SrcMgrDiagInfo DiagInfo; 98 99 // If the current LLVMContext has an inline asm handler, set it in SourceMgr. 100 LLVMContext &LLVMCtx = MMI->getModule()->getContext(); 101 bool HasDiagHandler = false; 102 if (LLVMCtx.getInlineAsmDiagnosticHandler() != 0) { 103 // If the source manager has an issue, we arrange for srcMgrDiagHandler 104 // to be invoked, getting DiagInfo passed into it. 105 DiagInfo.LocInfo = LocMDNode; 106 DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); 107 DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); 108 SrcMgr.setDiagHandler(srcMgrDiagHandler, &DiagInfo); 109 HasDiagHandler = true; 110 } 111 112 MemoryBuffer *Buffer; 113 if (isNullTerminated) 114 Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>"); 115 else 116 Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); 117 118 // Tell SrcMgr about this buffer, it takes ownership of the buffer. 119 SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); 120 121 OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, 122 OutContext, OutStreamer, 123 *MAI)); 124 125 // Initialize the parser with a fresh subtarget info. It is better to use a 126 // new STI here because the parser may modify it and we do not want those 127 // modifications to persist after parsing the inlineasm. The modifications 128 // made by the parser will be seen by the code emitters because it passes 129 // the current STI down to the EncodeInstruction() method. 130 OwningPtr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo( 131 TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString())); 132 133 // Preserve a copy of the original STI because the parser may modify it. For 134 // example, when switching between arm and thumb mode. If the target needs to 135 // emit code to return to the original state it can do so in emitInlineAsmEnd(). 136 MCSubtargetInfo STIOrig = *STI; 137 138 OwningPtr<MCTargetAsmParser> 139 TAP(TM.getTarget().createMCAsmParser(*STI, *Parser, *MII)); 140 if (!TAP) 141 report_fatal_error("Inline asm not supported by this streamer because" 142 " we don't have an asm parser for this target\n"); 143 Parser->setAssemblerDialect(Dialect); 144 Parser->setTargetParser(*TAP.get()); 145 146 // Don't implicitly switch to the text section before the asm. 147 int Res = Parser->Run(/*NoInitialTextSection*/ true, 148 /*NoFinalize*/ true); 149 emitInlineAsmEnd(STIOrig, STI.get()); 150 if (Res && !HasDiagHandler) 151 report_fatal_error("Error parsing inline asm\n"); 152 } 153 154 static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI, 155 MachineModuleInfo *MMI, int InlineAsmVariant, 156 AsmPrinter *AP, unsigned LocCookie, 157 raw_ostream &OS) { 158 // Switch to the inline assembly variant. 159 OS << "\t.intel_syntax\n\t"; 160 161 const char *LastEmitted = AsmStr; // One past the last character emitted. 162 unsigned NumOperands = MI->getNumOperands(); 163 164 while (*LastEmitted) { 165 switch (*LastEmitted) { 166 default: { 167 // Not a special case, emit the string section literally. 168 const char *LiteralEnd = LastEmitted+1; 169 while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && 170 *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') 171 ++LiteralEnd; 172 173 OS.write(LastEmitted, LiteralEnd-LastEmitted); 174 LastEmitted = LiteralEnd; 175 break; 176 } 177 case '\n': 178 ++LastEmitted; // Consume newline character. 179 OS << '\n'; // Indent code with newline. 180 break; 181 case '$': { 182 ++LastEmitted; // Consume '$' character. 183 bool Done = true; 184 185 // Handle escapes. 186 switch (*LastEmitted) { 187 default: Done = false; break; 188 case '$': 189 ++LastEmitted; // Consume second '$' character. 190 break; 191 } 192 if (Done) break; 193 194 const char *IDStart = LastEmitted; 195 const char *IDEnd = IDStart; 196 while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd; 197 198 unsigned Val; 199 if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val)) 200 report_fatal_error("Bad $ operand number in inline asm string: '" + 201 Twine(AsmStr) + "'"); 202 LastEmitted = IDEnd; 203 204 if (Val >= NumOperands-1) 205 report_fatal_error("Invalid $ operand number in inline asm string: '" + 206 Twine(AsmStr) + "'"); 207 208 // Okay, we finally have a value number. Ask the target to print this 209 // operand! 210 unsigned OpNo = InlineAsm::MIOp_FirstOperand; 211 212 bool Error = false; 213 214 // Scan to find the machine operand number for the operand. 215 for (; Val; --Val) { 216 if (OpNo >= MI->getNumOperands()) break; 217 unsigned OpFlags = MI->getOperand(OpNo).getImm(); 218 OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; 219 } 220 221 // We may have a location metadata attached to the end of the 222 // instruction, and at no point should see metadata at any 223 // other point while processing. It's an error if so. 224 if (OpNo >= MI->getNumOperands() || 225 MI->getOperand(OpNo).isMetadata()) { 226 Error = true; 227 } else { 228 unsigned OpFlags = MI->getOperand(OpNo).getImm(); 229 ++OpNo; // Skip over the ID number. 230 231 if (InlineAsm::isMemKind(OpFlags)) { 232 Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant, 233 /*Modifier*/ 0, OS); 234 } else { 235 Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant, 236 /*Modifier*/ 0, OS); 237 } 238 } 239 if (Error) { 240 std::string msg; 241 raw_string_ostream Msg(msg); 242 Msg << "invalid operand in inline asm: '" << AsmStr << "'"; 243 MMI->getModule()->getContext().emitError(LocCookie, Msg.str()); 244 } 245 break; 246 } 247 } 248 } 249 OS << "\n\t.att_syntax\n" << (char)0; // null terminate string. 250 } 251 252 static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI, 253 MachineModuleInfo *MMI, int InlineAsmVariant, 254 int AsmPrinterVariant, AsmPrinter *AP, 255 unsigned LocCookie, raw_ostream &OS) { 256 int CurVariant = -1; // The number of the {.|.|.} region we are in. 257 const char *LastEmitted = AsmStr; // One past the last character emitted. 258 unsigned NumOperands = MI->getNumOperands(); 259 260 OS << '\t'; 261 262 while (*LastEmitted) { 263 switch (*LastEmitted) { 264 default: { 265 // Not a special case, emit the string section literally. 266 const char *LiteralEnd = LastEmitted+1; 267 while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && 268 *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') 269 ++LiteralEnd; 270 if (CurVariant == -1 || CurVariant == AsmPrinterVariant) 271 OS.write(LastEmitted, LiteralEnd-LastEmitted); 272 LastEmitted = LiteralEnd; 273 break; 274 } 275 case '\n': 276 ++LastEmitted; // Consume newline character. 277 OS << '\n'; // Indent code with newline. 278 break; 279 case '$': { 280 ++LastEmitted; // Consume '$' character. 281 bool Done = true; 282 283 // Handle escapes. 284 switch (*LastEmitted) { 285 default: Done = false; break; 286 case '$': // $$ -> $ 287 if (CurVariant == -1 || CurVariant == AsmPrinterVariant) 288 OS << '$'; 289 ++LastEmitted; // Consume second '$' character. 290 break; 291 case '(': // $( -> same as GCC's { character. 292 ++LastEmitted; // Consume '(' character. 293 if (CurVariant != -1) 294 report_fatal_error("Nested variants found in inline asm string: '" + 295 Twine(AsmStr) + "'"); 296 CurVariant = 0; // We're in the first variant now. 297 break; 298 case '|': 299 ++LastEmitted; // consume '|' character. 300 if (CurVariant == -1) 301 OS << '|'; // this is gcc's behavior for | outside a variant 302 else 303 ++CurVariant; // We're in the next variant. 304 break; 305 case ')': // $) -> same as GCC's } char. 306 ++LastEmitted; // consume ')' character. 307 if (CurVariant == -1) 308 OS << '}'; // this is gcc's behavior for } outside a variant 309 else 310 CurVariant = -1; 311 break; 312 } 313 if (Done) break; 314 315 bool HasCurlyBraces = false; 316 if (*LastEmitted == '{') { // ${variable} 317 ++LastEmitted; // Consume '{' character. 318 HasCurlyBraces = true; 319 } 320 321 // If we have ${:foo}, then this is not a real operand reference, it is a 322 // "magic" string reference, just like in .td files. Arrange to call 323 // PrintSpecial. 324 if (HasCurlyBraces && *LastEmitted == ':') { 325 ++LastEmitted; 326 const char *StrStart = LastEmitted; 327 const char *StrEnd = strchr(StrStart, '}'); 328 if (StrEnd == 0) 329 report_fatal_error("Unterminated ${:foo} operand in inline asm" 330 " string: '" + Twine(AsmStr) + "'"); 331 332 std::string Val(StrStart, StrEnd); 333 AP->PrintSpecial(MI, OS, Val.c_str()); 334 LastEmitted = StrEnd+1; 335 break; 336 } 337 338 const char *IDStart = LastEmitted; 339 const char *IDEnd = IDStart; 340 while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd; 341 342 unsigned Val; 343 if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val)) 344 report_fatal_error("Bad $ operand number in inline asm string: '" + 345 Twine(AsmStr) + "'"); 346 LastEmitted = IDEnd; 347 348 char Modifier[2] = { 0, 0 }; 349 350 if (HasCurlyBraces) { 351 // If we have curly braces, check for a modifier character. This 352 // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm. 353 if (*LastEmitted == ':') { 354 ++LastEmitted; // Consume ':' character. 355 if (*LastEmitted == 0) 356 report_fatal_error("Bad ${:} expression in inline asm string: '" + 357 Twine(AsmStr) + "'"); 358 359 Modifier[0] = *LastEmitted; 360 ++LastEmitted; // Consume modifier character. 361 } 362 363 if (*LastEmitted != '}') 364 report_fatal_error("Bad ${} expression in inline asm string: '" + 365 Twine(AsmStr) + "'"); 366 ++LastEmitted; // Consume '}' character. 367 } 368 369 if (Val >= NumOperands-1) 370 report_fatal_error("Invalid $ operand number in inline asm string: '" + 371 Twine(AsmStr) + "'"); 372 373 // Okay, we finally have a value number. Ask the target to print this 374 // operand! 375 if (CurVariant == -1 || CurVariant == AsmPrinterVariant) { 376 unsigned OpNo = InlineAsm::MIOp_FirstOperand; 377 378 bool Error = false; 379 380 // Scan to find the machine operand number for the operand. 381 for (; Val; --Val) { 382 if (OpNo >= MI->getNumOperands()) break; 383 unsigned OpFlags = MI->getOperand(OpNo).getImm(); 384 OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; 385 } 386 387 // We may have a location metadata attached to the end of the 388 // instruction, and at no point should see metadata at any 389 // other point while processing. It's an error if so. 390 if (OpNo >= MI->getNumOperands() || 391 MI->getOperand(OpNo).isMetadata()) { 392 Error = true; 393 } else { 394 unsigned OpFlags = MI->getOperand(OpNo).getImm(); 395 ++OpNo; // Skip over the ID number. 396 397 if (Modifier[0] == 'l') // labels are target independent 398 // FIXME: What if the operand isn't an MBB, report error? 399 OS << *MI->getOperand(OpNo).getMBB()->getSymbol(); 400 else { 401 if (InlineAsm::isMemKind(OpFlags)) { 402 Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant, 403 Modifier[0] ? Modifier : 0, 404 OS); 405 } else { 406 Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant, 407 Modifier[0] ? Modifier : 0, OS); 408 } 409 } 410 } 411 if (Error) { 412 std::string msg; 413 raw_string_ostream Msg(msg); 414 Msg << "invalid operand in inline asm: '" << AsmStr << "'"; 415 MMI->getModule()->getContext().emitError(LocCookie, Msg.str()); 416 } 417 } 418 break; 419 } 420 } 421 } 422 OS << '\n' << (char)0; // null terminate string. 423 } 424 425 /// EmitInlineAsm - This method formats and emits the specified machine 426 /// instruction that is an inline asm. 427 void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { 428 assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms"); 429 430 // Count the number of register definitions to find the asm string. 431 unsigned NumDefs = 0; 432 for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); 433 ++NumDefs) 434 assert(NumDefs != MI->getNumOperands()-2 && "No asm string?"); 435 436 assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?"); 437 438 // Disassemble the AsmStr, printing out the literal pieces, the operands, etc. 439 const char *AsmStr = MI->getOperand(NumDefs).getSymbolName(); 440 441 // If this asmstr is empty, just print the #APP/#NOAPP markers. 442 // These are useful to see where empty asm's wound up. 443 if (AsmStr[0] == 0) { 444 OutStreamer.emitRawComment(MAI->getInlineAsmStart()); 445 OutStreamer.emitRawComment(MAI->getInlineAsmEnd()); 446 return; 447 } 448 449 // Emit the #APP start marker. This has to happen even if verbose-asm isn't 450 // enabled, so we use emitRawComment. 451 OutStreamer.emitRawComment(MAI->getInlineAsmStart()); 452 453 // Get the !srcloc metadata node if we have it, and decode the loc cookie from 454 // it. 455 unsigned LocCookie = 0; 456 const MDNode *LocMD = 0; 457 for (unsigned i = MI->getNumOperands(); i != 0; --i) { 458 if (MI->getOperand(i-1).isMetadata() && 459 (LocMD = MI->getOperand(i-1).getMetadata()) && 460 LocMD->getNumOperands() != 0) { 461 if (const ConstantInt *CI = dyn_cast<ConstantInt>(LocMD->getOperand(0))) { 462 LocCookie = CI->getZExtValue(); 463 break; 464 } 465 } 466 } 467 468 // Emit the inline asm to a temporary string so we can emit it through 469 // EmitInlineAsm. 470 SmallString<256> StringData; 471 raw_svector_ostream OS(StringData); 472 473 // The variant of the current asmprinter. 474 int AsmPrinterVariant = MAI->getAssemblerDialect(); 475 InlineAsm::AsmDialect InlineAsmVariant = MI->getInlineAsmDialect(); 476 AsmPrinter *AP = const_cast<AsmPrinter*>(this); 477 if (InlineAsmVariant == InlineAsm::AD_ATT) 478 EmitGCCInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AsmPrinterVariant, 479 AP, LocCookie, OS); 480 else 481 EmitMSInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AP, LocCookie, OS); 482 483 EmitInlineAsm(OS.str(), LocMD, MI->getInlineAsmDialect()); 484 485 // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't 486 // enabled, so we use emitRawComment. 487 OutStreamer.emitRawComment(MAI->getInlineAsmEnd()); 488 } 489 490 491 /// PrintSpecial - Print information related to the specified machine instr 492 /// that is independent of the operand, and may be independent of the instr 493 /// itself. This can be useful for portably encoding the comment character 494 /// or other bits of target-specific knowledge into the asmstrings. The 495 /// syntax used is ${:comment}. Targets can override this to add support 496 /// for their own strange codes. 497 void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS, 498 const char *Code) const { 499 const DataLayout *DL = TM.getDataLayout(); 500 if (!strcmp(Code, "private")) { 501 OS << DL->getPrivateGlobalPrefix(); 502 } else if (!strcmp(Code, "comment")) { 503 OS << MAI->getCommentString(); 504 } else if (!strcmp(Code, "uid")) { 505 // Comparing the address of MI isn't sufficient, because machineinstrs may 506 // be allocated to the same address across functions. 507 508 // If this is a new LastFn instruction, bump the counter. 509 if (LastMI != MI || LastFn != getFunctionNumber()) { 510 ++Counter; 511 LastMI = MI; 512 LastFn = getFunctionNumber(); 513 } 514 OS << Counter; 515 } else { 516 std::string msg; 517 raw_string_ostream Msg(msg); 518 Msg << "Unknown special formatter '" << Code 519 << "' for machine instr: " << *MI; 520 report_fatal_error(Msg.str()); 521 } 522 } 523 524 /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM 525 /// instruction, using the specified assembler variant. Targets should 526 /// override this to format as appropriate. 527 bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 528 unsigned AsmVariant, const char *ExtraCode, 529 raw_ostream &O) { 530 // Does this asm operand have a single letter operand modifier? 531 if (ExtraCode && ExtraCode[0]) { 532 if (ExtraCode[1] != 0) return true; // Unknown modifier. 533 534 const MachineOperand &MO = MI->getOperand(OpNo); 535 switch (ExtraCode[0]) { 536 default: 537 return true; // Unknown modifier. 538 case 'c': // Substitute immediate value without immediate syntax 539 if (MO.getType() != MachineOperand::MO_Immediate) 540 return true; 541 O << MO.getImm(); 542 return false; 543 case 'n': // Negate the immediate constant. 544 if (MO.getType() != MachineOperand::MO_Immediate) 545 return true; 546 O << -MO.getImm(); 547 return false; 548 } 549 } 550 return true; 551 } 552 553 bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 554 unsigned AsmVariant, 555 const char *ExtraCode, raw_ostream &O) { 556 // Target doesn't support this yet! 557 return true; 558 } 559 560 void AsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, 561 const MCSubtargetInfo *EndInfo) const {} 562