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