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