Line data Source code
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 : #include "llvm/ADT/SmallString.h"
15 : #include "llvm/ADT/Twine.h"
16 : #include "llvm/CodeGen/AsmPrinter.h"
17 : #include "llvm/CodeGen/MachineBasicBlock.h"
18 : #include "llvm/CodeGen/MachineFunction.h"
19 : #include "llvm/CodeGen/MachineModuleInfo.h"
20 : #include "llvm/CodeGen/TargetInstrInfo.h"
21 : #include "llvm/CodeGen/TargetRegisterInfo.h"
22 : #include "llvm/CodeGen/TargetSubtargetInfo.h"
23 : #include "llvm/IR/Constants.h"
24 : #include "llvm/IR/DataLayout.h"
25 : #include "llvm/IR/InlineAsm.h"
26 : #include "llvm/IR/LLVMContext.h"
27 : #include "llvm/IR/Module.h"
28 : #include "llvm/MC/MCAsmInfo.h"
29 : #include "llvm/MC/MCParser/MCTargetAsmParser.h"
30 : #include "llvm/MC/MCStreamer.h"
31 : #include "llvm/MC/MCSubtargetInfo.h"
32 : #include "llvm/MC/MCSymbol.h"
33 : #include "llvm/Support/ErrorHandling.h"
34 : #include "llvm/Support/MemoryBuffer.h"
35 : #include "llvm/Support/SourceMgr.h"
36 : #include "llvm/Support/TargetRegistry.h"
37 : #include "llvm/Support/raw_ostream.h"
38 : #include "llvm/Target/TargetMachine.h"
39 : using namespace llvm;
40 :
41 : #define DEBUG_TYPE "asm-printer"
42 :
43 : /// srcMgrDiagHandler - This callback is invoked when the SourceMgr for an
44 : /// inline asm has an error in it. diagInfo is a pointer to the SrcMgrDiagInfo
45 : /// struct above.
46 305 : static void srcMgrDiagHandler(const SMDiagnostic &Diag, void *diagInfo) {
47 : AsmPrinter::SrcMgrDiagInfo *DiagInfo =
48 : static_cast<AsmPrinter::SrcMgrDiagInfo *>(diagInfo);
49 : assert(DiagInfo && "Diagnostic context not passed down?");
50 :
51 : // Look up a LocInfo for the buffer this diagnostic is coming from.
52 305 : unsigned BufNum = DiagInfo->SrcMgr.FindBufferContainingLoc(Diag.getLoc());
53 : const MDNode *LocInfo = nullptr;
54 305 : if (BufNum > 0 && BufNum <= DiagInfo->LocInfos.size())
55 9 : LocInfo = DiagInfo->LocInfos[BufNum-1];
56 :
57 : // If the inline asm had metadata associated with it, pull out a location
58 : // cookie corresponding to which line the error occurred on.
59 : unsigned LocCookie = 0;
60 9 : if (LocInfo) {
61 9 : unsigned ErrorLine = Diag.getLineNo()-1;
62 9 : if (ErrorLine >= LocInfo->getNumOperands())
63 : ErrorLine = 0;
64 :
65 9 : if (LocInfo->getNumOperands() != 0)
66 : if (const ConstantInt *CI =
67 : mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine)))
68 9 : LocCookie = CI->getZExtValue();
69 : }
70 :
71 305 : DiagInfo->DiagHandler(Diag, DiagInfo->DiagContext, LocCookie);
72 305 : }
73 :
74 10351 : unsigned AsmPrinter::addInlineAsmDiagBuffer(StringRef AsmStr,
75 : const MDNode *LocMDNode) const {
76 10351 : if (!DiagInfo) {
77 685 : DiagInfo = make_unique<SrcMgrDiagInfo>();
78 :
79 685 : MCContext &Context = MMI->getContext();
80 685 : Context.setInlineSourceManager(&DiagInfo->SrcMgr);
81 :
82 685 : LLVMContext &LLVMCtx = MMI->getModule()->getContext();
83 685 : if (LLVMCtx.getInlineAsmDiagnosticHandler()) {
84 654 : DiagInfo->DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler();
85 654 : DiagInfo->DiagContext = LLVMCtx.getInlineAsmDiagnosticContext();
86 : DiagInfo->SrcMgr.setDiagHandler(srcMgrDiagHandler, DiagInfo.get());
87 : }
88 : }
89 :
90 10351 : SourceMgr &SrcMgr = DiagInfo->SrcMgr;
91 :
92 : std::unique_ptr<MemoryBuffer> Buffer;
93 : // The inline asm source manager will outlive AsmStr, so make a copy of the
94 : // string for SourceMgr to own.
95 10351 : Buffer = MemoryBuffer::getMemBufferCopy(AsmStr, "<inline asm>");
96 :
97 : // Tell SrcMgr about this buffer, it takes ownership of the buffer.
98 20702 : unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
99 :
100 : // Store LocMDNode in DiagInfo, using BufNum as an identifier.
101 10351 : if (LocMDNode) {
102 248 : DiagInfo->LocInfos.resize(BufNum);
103 744 : DiagInfo->LocInfos[BufNum - 1] = LocMDNode;
104 : }
105 :
106 10351 : return BufNum;
107 : }
108 :
109 :
110 : /// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
111 12205 : void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
112 : const MCTargetOptions &MCOptions,
113 : const MDNode *LocMDNode,
114 : InlineAsm::AsmDialect Dialect) const {
115 : assert(!Str.empty() && "Can't emit empty inline asm block");
116 :
117 : // Remember if the buffer is nul terminated or not so we can avoid a copy.
118 12205 : bool isNullTerminated = Str.back() == 0;
119 12205 : if (isNullTerminated)
120 12127 : Str = Str.substr(0, Str.size()-1);
121 :
122 : // If the output streamer does not have mature MC support or the integrated
123 : // assembler has been disabled, just emit the blob textually.
124 : // Otherwise parse the asm and emit it via MC support.
125 : // This is useful in case the asm parser doesn't handle something but the
126 : // system assembler does.
127 12205 : const MCAsmInfo *MCAI = TM.getMCAsmInfo();
128 : assert(MCAI && "No MCAsmInfo");
129 14132 : if (!MCAI->useIntegratedAssembler() &&
130 1927 : !OutStreamer->isIntegratedAssemblerRequired()) {
131 1909 : emitInlineAsmStart();
132 1909 : OutStreamer->EmitRawText(Str);
133 1909 : emitInlineAsmEnd(STI, nullptr);
134 : return;
135 : }
136 :
137 10296 : unsigned BufNum = addInlineAsmDiagBuffer(Str, LocMDNode);
138 10296 : DiagInfo->SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths);
139 :
140 : std::unique_ptr<MCAsmParser> Parser(createMCAsmParser(
141 30888 : DiagInfo->SrcMgr, OutContext, *OutStreamer, *MAI, BufNum));
142 :
143 : // Do not use assembler-level information for parsing inline assembly.
144 : OutStreamer->setUseAssemblerInfoForParsing(false);
145 :
146 : // We create a new MCInstrInfo here since we might be at the module level
147 : // and not have a MachineFunction to initialize the TargetInstrInfo from and
148 : // we only need MCInstrInfo for asm parsing. We create one unconditionally
149 : // because it's not subtarget dependent.
150 10296 : std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo());
151 10296 : std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser(
152 10296 : STI, *Parser, *MII, MCOptions));
153 10296 : if (!TAP)
154 0 : report_fatal_error("Inline asm not supported by this streamer because"
155 : " we don't have an asm parser for this target\n");
156 10296 : Parser->setAssemblerDialect(Dialect);
157 10296 : Parser->setTargetParser(*TAP.get());
158 10296 : Parser->setEnablePrintSchedInfo(EnablePrintSchedInfo);
159 10296 : if (Dialect == InlineAsm::AD_Intel)
160 : // We need this flag to be able to parse numbers like "0bH"
161 20 : Parser->setParsingInlineAsm(true);
162 10296 : if (MF) {
163 10221 : const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
164 10221 : TAP->SetFrameRegister(TRI->getFrameRegister(*MF));
165 : }
166 :
167 10296 : emitInlineAsmStart();
168 : // Don't implicitly switch to the text section before the asm.
169 10296 : int Res = Parser->Run(/*NoInitialTextSection*/ true,
170 10296 : /*NoFinalize*/ true);
171 10296 : emitInlineAsmEnd(STI, &TAP->getSTI());
172 :
173 10296 : if (Res && !DiagInfo->DiagHandler)
174 0 : report_fatal_error("Error parsing inline asm\n");
175 : }
176 :
177 30 : static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
178 : MachineModuleInfo *MMI, int InlineAsmVariant,
179 : AsmPrinter *AP, unsigned LocCookie,
180 : raw_ostream &OS) {
181 : // Switch to the inline assembly variant.
182 30 : OS << "\t.intel_syntax\n\t";
183 :
184 : const char *LastEmitted = AsmStr; // One past the last character emitted.
185 30 : unsigned NumOperands = MI->getNumOperands();
186 :
187 194 : while (*LastEmitted) {
188 164 : switch (*LastEmitted) {
189 89 : default: {
190 : // Not a special case, emit the string section literally.
191 89 : const char *LiteralEnd = LastEmitted+1;
192 878 : while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&
193 1779 : *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')
194 813 : ++LiteralEnd;
195 :
196 89 : OS.write(LastEmitted, LiteralEnd-LastEmitted);
197 : LastEmitted = LiteralEnd;
198 89 : break;
199 : }
200 40 : case '\n':
201 40 : ++LastEmitted; // Consume newline character.
202 : OS << '\n'; // Indent code with newline.
203 : break;
204 35 : case '$': {
205 35 : ++LastEmitted; // Consume '$' character.
206 : bool Done = true;
207 :
208 : // Handle escapes.
209 35 : switch (*LastEmitted) {
210 : default: Done = false; break;
211 3 : case '$':
212 3 : ++LastEmitted; // Consume second '$' character.
213 : break;
214 : }
215 : if (Done) break;
216 :
217 : // If we have ${:foo}, then this is not a real operand reference, it is a
218 : // "magic" string reference, just like in .td files. Arrange to call
219 : // PrintSpecial.
220 32 : if (LastEmitted[0] == '{' && LastEmitted[1] == ':') {
221 2 : LastEmitted += 2;
222 : const char *StrStart = LastEmitted;
223 : const char *StrEnd = strchr(StrStart, '}');
224 2 : if (!StrEnd)
225 0 : report_fatal_error("Unterminated ${:foo} operand in inline asm"
226 : " string: '" + Twine(AsmStr) + "'");
227 :
228 : std::string Val(StrStart, StrEnd);
229 4 : AP->PrintSpecial(MI, OS, Val.c_str());
230 2 : LastEmitted = StrEnd+1;
231 : break;
232 : }
233 :
234 : const char *IDStart = LastEmitted;
235 : const char *IDEnd = IDStart;
236 60 : while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd;
237 :
238 : unsigned Val;
239 30 : if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val))
240 0 : report_fatal_error("Bad $ operand number in inline asm string: '" +
241 : Twine(AsmStr) + "'");
242 : LastEmitted = IDEnd;
243 :
244 30 : if (Val >= NumOperands-1)
245 0 : report_fatal_error("Invalid $ operand number in inline asm string: '" +
246 : Twine(AsmStr) + "'");
247 :
248 : // Okay, we finally have a value number. Ask the target to print this
249 : // operand!
250 : unsigned OpNo = InlineAsm::MIOp_FirstOperand;
251 :
252 : bool Error = false;
253 :
254 : // Scan to find the machine operand number for the operand.
255 62 : for (; Val; --Val) {
256 32 : if (OpNo >= MI->getNumOperands()) break;
257 64 : unsigned OpFlags = MI->getOperand(OpNo).getImm();
258 32 : OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
259 : }
260 :
261 : // We may have a location metadata attached to the end of the
262 : // instruction, and at no point should see metadata at any
263 : // other point while processing. It's an error if so.
264 30 : if (OpNo >= MI->getNumOperands() ||
265 30 : MI->getOperand(OpNo).isMetadata()) {
266 : Error = true;
267 : } else {
268 30 : unsigned OpFlags = MI->getOperand(OpNo).getImm();
269 30 : ++OpNo; // Skip over the ID number.
270 :
271 30 : if (InlineAsm::isMemKind(OpFlags)) {
272 27 : Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant,
273 27 : /*Modifier*/ nullptr, OS);
274 : } else {
275 3 : Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant,
276 3 : /*Modifier*/ nullptr, OS);
277 : }
278 : }
279 30 : if (Error) {
280 : std::string msg;
281 0 : raw_string_ostream Msg(msg);
282 0 : Msg << "invalid operand in inline asm: '" << AsmStr << "'";
283 0 : MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
284 : }
285 : break;
286 : }
287 : }
288 : }
289 30 : OS << "\n\t.att_syntax\n" << (char)0; // null terminate string.
290 30 : }
291 :
292 12097 : static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
293 : MachineModuleInfo *MMI, int InlineAsmVariant,
294 : int AsmPrinterVariant, AsmPrinter *AP,
295 : unsigned LocCookie, raw_ostream &OS) {
296 : int CurVariant = -1; // The number of the {.|.|.} region we are in.
297 : const char *LastEmitted = AsmStr; // One past the last character emitted.
298 12097 : unsigned NumOperands = MI->getNumOperands();
299 :
300 : OS << '\t';
301 :
302 110827 : while (*LastEmitted) {
303 98730 : switch (*LastEmitted) {
304 53297 : default: {
305 : // Not a special case, emit the string section literally.
306 53297 : const char *LiteralEnd = LastEmitted+1;
307 240316 : while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&
308 488477 : *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')
309 194992 : ++LiteralEnd;
310 53297 : if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
311 53292 : OS.write(LastEmitted, LiteralEnd-LastEmitted);
312 : LastEmitted = LiteralEnd;
313 : break;
314 : }
315 14291 : case '\n':
316 14291 : ++LastEmitted; // Consume newline character.
317 : OS << '\n'; // Indent code with newline.
318 : break;
319 31142 : case '$': {
320 31142 : ++LastEmitted; // Consume '$' character.
321 : bool Done = true;
322 :
323 : // Handle escapes.
324 31142 : switch (*LastEmitted) {
325 : default: Done = false; break;
326 704 : case '$': // $$ -> $
327 704 : if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
328 : OS << '$';
329 704 : ++LastEmitted; // Consume second '$' character.
330 704 : break;
331 5 : case '(': // $( -> same as GCC's { character.
332 5 : ++LastEmitted; // Consume '(' character.
333 5 : if (CurVariant != -1)
334 0 : report_fatal_error("Nested variants found in inline asm string: '" +
335 : Twine(AsmStr) + "'");
336 : CurVariant = 0; // We're in the first variant now.
337 : break;
338 21 : case '|':
339 21 : ++LastEmitted; // consume '|' character.
340 21 : if (CurVariant == -1)
341 : OS << '|'; // this is gcc's behavior for | outside a variant
342 : else
343 5 : ++CurVariant; // We're in the next variant.
344 : break;
345 5 : case ')': // $) -> same as GCC's } char.
346 5 : ++LastEmitted; // consume ')' character.
347 5 : if (CurVariant == -1)
348 : OS << '}'; // this is gcc's behavior for } outside a variant
349 : else
350 : CurVariant = -1;
351 : break;
352 : }
353 31142 : if (Done) break;
354 :
355 : bool HasCurlyBraces = false;
356 30407 : if (*LastEmitted == '{') { // ${variable}
357 366 : ++LastEmitted; // Consume '{' character.
358 : HasCurlyBraces = true;
359 : }
360 :
361 : // If we have ${:foo}, then this is not a real operand reference, it is a
362 : // "magic" string reference, just like in .td files. Arrange to call
363 : // PrintSpecial.
364 366 : if (HasCurlyBraces && *LastEmitted == ':') {
365 4 : ++LastEmitted;
366 : const char *StrStart = LastEmitted;
367 : const char *StrEnd = strchr(StrStart, '}');
368 4 : if (!StrEnd)
369 0 : report_fatal_error("Unterminated ${:foo} operand in inline asm"
370 : " string: '" + Twine(AsmStr) + "'");
371 :
372 : std::string Val(StrStart, StrEnd);
373 8 : AP->PrintSpecial(MI, OS, Val.c_str());
374 4 : LastEmitted = StrEnd+1;
375 : break;
376 : }
377 :
378 : const char *IDStart = LastEmitted;
379 : const char *IDEnd = IDStart;
380 60818 : while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd;
381 :
382 : unsigned Val;
383 30403 : if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val))
384 0 : report_fatal_error("Bad $ operand number in inline asm string: '" +
385 : Twine(AsmStr) + "'");
386 : LastEmitted = IDEnd;
387 :
388 30403 : char Modifier[2] = { 0, 0 };
389 :
390 30403 : if (HasCurlyBraces) {
391 : // If we have curly braces, check for a modifier character. This
392 : // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm.
393 362 : if (*LastEmitted == ':') {
394 : ++LastEmitted; // Consume ':' character.
395 352 : if (*LastEmitted == 0)
396 0 : report_fatal_error("Bad ${:} expression in inline asm string: '" +
397 : Twine(AsmStr) + "'");
398 :
399 352 : Modifier[0] = *LastEmitted;
400 352 : ++LastEmitted; // Consume modifier character.
401 : }
402 :
403 362 : if (*LastEmitted != '}')
404 0 : report_fatal_error("Bad ${} expression in inline asm string: '" +
405 : Twine(AsmStr) + "'");
406 362 : ++LastEmitted; // Consume '}' character.
407 : }
408 :
409 30403 : if (Val >= NumOperands-1)
410 0 : report_fatal_error("Invalid $ operand number in inline asm string: '" +
411 : Twine(AsmStr) + "'");
412 :
413 : // Okay, we finally have a value number. Ask the target to print this
414 : // operand!
415 30403 : if (CurVariant == -1 || CurVariant == AsmPrinterVariant) {
416 : unsigned OpNo = InlineAsm::MIOp_FirstOperand;
417 :
418 : bool Error = false;
419 :
420 : // Scan to find the machine operand number for the operand.
421 64840 : for (; Val; --Val) {
422 34437 : if (OpNo >= MI->getNumOperands()) break;
423 68874 : unsigned OpFlags = MI->getOperand(OpNo).getImm();
424 34437 : OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
425 : }
426 :
427 : // We may have a location metadata attached to the end of the
428 : // instruction, and at no point should see metadata at any
429 : // other point while processing. It's an error if so.
430 30403 : if (OpNo >= MI->getNumOperands() ||
431 30403 : MI->getOperand(OpNo).isMetadata()) {
432 : Error = true;
433 : } else {
434 30403 : unsigned OpFlags = MI->getOperand(OpNo).getImm();
435 30403 : ++OpNo; // Skip over the ID number.
436 :
437 30403 : if (Modifier[0] == 'l') { // Labels are target independent.
438 : // FIXME: What if the operand isn't an MBB, report error?
439 2 : const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol();
440 2 : Sym->print(OS, AP->MAI);
441 : } else {
442 30401 : if (InlineAsm::isMemKind(OpFlags)) {
443 7463 : Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant,
444 : Modifier[0] ? Modifier : nullptr,
445 7463 : OS);
446 : } else {
447 22938 : Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant,
448 22938 : Modifier[0] ? Modifier : nullptr, OS);
449 : }
450 : }
451 : }
452 30401 : if (Error) {
453 : std::string msg;
454 2 : raw_string_ostream Msg(msg);
455 2 : Msg << "invalid operand in inline asm: '" << AsmStr << "'";
456 4 : MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
457 : }
458 : }
459 : break;
460 : }
461 : }
462 : }
463 : OS << '\n' << (char)0; // null terminate string.
464 12097 : }
465 :
466 : /// EmitInlineAsm - This method formats and emits the specified machine
467 : /// instruction that is an inline asm.
468 16628 : void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
469 : assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms");
470 :
471 : // Count the number of register definitions to find the asm string.
472 : unsigned NumDefs = 0;
473 33256 : for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef();
474 : ++NumDefs)
475 : assert(NumDefs != MI->getNumOperands()-2 && "No asm string?");
476 :
477 : assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?");
478 :
479 : // Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
480 16628 : const char *AsmStr = MI->getOperand(NumDefs).getSymbolName();
481 :
482 : // If this asmstr is empty, just print the #APP/#NOAPP markers.
483 : // These are useful to see where empty asm's wound up.
484 16628 : if (AsmStr[0] == 0) {
485 9002 : OutStreamer->emitRawComment(MAI->getInlineAsmStart());
486 9002 : OutStreamer->emitRawComment(MAI->getInlineAsmEnd());
487 4501 : return;
488 : }
489 :
490 : // Emit the #APP start marker. This has to happen even if verbose-asm isn't
491 : // enabled, so we use emitRawComment.
492 24254 : OutStreamer->emitRawComment(MAI->getInlineAsmStart());
493 :
494 : // Get the !srcloc metadata node if we have it, and decode the loc cookie from
495 : // it.
496 : unsigned LocCookie = 0;
497 : const MDNode *LocMD = nullptr;
498 156696 : for (unsigned i = MI->getNumOperands(); i != 0; --i) {
499 144849 : if (MI->getOperand(i-1).isMetadata() &&
500 144849 : (LocMD = MI->getOperand(i-1).getMetadata()) &&
501 280 : LocMD->getNumOperands() != 0) {
502 : if (const ConstantInt *CI =
503 : mdconst::dyn_extract<ConstantInt>(LocMD->getOperand(0))) {
504 280 : LocCookie = CI->getZExtValue();
505 280 : break;
506 : }
507 : }
508 : }
509 :
510 : // Emit the inline asm to a temporary string so we can emit it through
511 : // EmitInlineAsm.
512 : SmallString<256> StringData;
513 : raw_svector_ostream OS(StringData);
514 :
515 : // The variant of the current asmprinter.
516 12127 : int AsmPrinterVariant = MAI->getAssemblerDialect();
517 12127 : InlineAsm::AsmDialect InlineAsmVariant = MI->getInlineAsmDialect();
518 : AsmPrinter *AP = const_cast<AsmPrinter*>(this);
519 12127 : if (InlineAsmVariant == InlineAsm::AD_ATT)
520 12097 : EmitGCCInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AsmPrinterVariant,
521 : AP, LocCookie, OS);
522 : else
523 30 : EmitMSInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AP, LocCookie, OS);
524 :
525 : // Reset SanitizeAddress based on the function's attribute.
526 24254 : MCTargetOptions MCOptions = TM.Options.MCOptions;
527 12127 : MCOptions.SanitizeAddress =
528 12127 : MF->getFunction().hasFnAttribute(Attribute::SanitizeAddress);
529 :
530 : // Emit warnings if we use reserved registers on the clobber list, as
531 : // that might give surprising results.
532 12127 : std::vector<std::string> RestrRegs;
533 : // Start with the first operand descriptor, and iterate over them.
534 68276 : for (unsigned I = InlineAsm::MIOp_FirstOperand, NumOps = MI->getNumOperands();
535 68276 : I < NumOps; ++I) {
536 56149 : const MachineOperand &MO = MI->getOperand(I);
537 56149 : if (MO.isImm()) {
538 54864 : unsigned Flags = MO.getImm();
539 54864 : const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
540 95413 : if (InlineAsm::getKind(Flags) == InlineAsm::Kind_Clobber &&
541 81098 : !TRI->isAsmClobberable(*MF, MI->getOperand(I + 1).getReg())) {
542 528 : RestrRegs.push_back(TRI->getName(MI->getOperand(I + 1).getReg()));
543 : }
544 : // Skip to one before the next operand descriptor, if it exists.
545 54864 : I += InlineAsm::getNumOperandRegisters(Flags);
546 : }
547 : }
548 :
549 12127 : if (!RestrRegs.empty()) {
550 110 : unsigned BufNum = addInlineAsmDiagBuffer(OS.str(), LocMD);
551 55 : auto &SrcMgr = DiagInfo->SrcMgr;
552 : SMLoc Loc = SMLoc::getFromPointer(
553 55 : SrcMgr.getMemoryBuffer(BufNum)->getBuffer().begin());
554 :
555 55 : std::string Msg = "inline asm clobber list contains reserved registers: ";
556 187 : for (auto I = RestrRegs.begin(), E = RestrRegs.end(); I != E; I++) {
557 132 : if(I != RestrRegs.begin())
558 : Msg += ", ";
559 : Msg += *I;
560 : }
561 : std::string Note = "Reserved registers on the clobber list may not be "
562 : "preserved across the asm statement, and clobbering them may "
563 55 : "lead to undefined behaviour.";
564 55 : SrcMgr.PrintMessage(Loc, SourceMgr::DK_Warning, Msg);
565 55 : SrcMgr.PrintMessage(Loc, SourceMgr::DK_Note, Note);
566 : }
567 :
568 12127 : EmitInlineAsm(OS.str(), getSubtargetInfo(), MCOptions, LocMD,
569 : MI->getInlineAsmDialect());
570 :
571 : // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't
572 : // enabled, so we use emitRawComment.
573 24254 : OutStreamer->emitRawComment(MAI->getInlineAsmEnd());
574 : }
575 :
576 :
577 : /// PrintSpecial - Print information related to the specified machine instr
578 : /// that is independent of the operand, and may be independent of the instr
579 : /// itself. This can be useful for portably encoding the comment character
580 : /// or other bits of target-specific knowledge into the asmstrings. The
581 : /// syntax used is ${:comment}. Targets can override this to add support
582 : /// for their own strange codes.
583 6 : void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
584 : const char *Code) const {
585 6 : if (!strcmp(Code, "private")) {
586 0 : const DataLayout &DL = MF->getDataLayout();
587 0 : OS << DL.getPrivateGlobalPrefix();
588 6 : } else if (!strcmp(Code, "comment")) {
589 0 : OS << MAI->getCommentString();
590 6 : } else if (!strcmp(Code, "uid")) {
591 : // Comparing the address of MI isn't sufficient, because machineinstrs may
592 : // be allocated to the same address across functions.
593 :
594 : // If this is a new LastFn instruction, bump the counter.
595 6 : if (LastMI != MI || LastFn != getFunctionNumber()) {
596 3 : ++Counter;
597 3 : LastMI = MI;
598 3 : LastFn = getFunctionNumber();
599 : }
600 6 : OS << Counter;
601 : } else {
602 : std::string msg;
603 : raw_string_ostream Msg(msg);
604 0 : Msg << "Unknown special formatter '" << Code
605 0 : << "' for machine instr: " << *MI;
606 0 : report_fatal_error(Msg.str());
607 : }
608 6 : }
609 :
610 : /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
611 : /// instruction, using the specified assembler variant. Targets should
612 : /// override this to format as appropriate.
613 815 : bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
614 : unsigned AsmVariant, const char *ExtraCode,
615 : raw_ostream &O) {
616 : // Does this asm operand have a single letter operand modifier?
617 815 : if (ExtraCode && ExtraCode[0]) {
618 55 : if (ExtraCode[1] != 0) return true; // Unknown modifier.
619 :
620 55 : const MachineOperand &MO = MI->getOperand(OpNo);
621 55 : switch (ExtraCode[0]) {
622 : default:
623 : return true; // Unknown modifier.
624 : case 'c': // Substitute immediate value without immediate syntax
625 6 : if (MO.getType() != MachineOperand::MO_Immediate)
626 : return true;
627 6 : O << MO.getImm();
628 6 : return false;
629 : case 'n': // Negate the immediate constant.
630 5 : if (MO.getType() != MachineOperand::MO_Immediate)
631 : return true;
632 5 : O << -MO.getImm();
633 5 : return false;
634 : case 's': // The GCC deprecated s modifier
635 6 : if (MO.getType() != MachineOperand::MO_Immediate)
636 : return true;
637 1 : O << ((32 - MO.getImm()) & 31);
638 1 : return false;
639 : }
640 : }
641 : return true;
642 : }
643 :
644 0 : bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
645 : unsigned AsmVariant,
646 : const char *ExtraCode, raw_ostream &O) {
647 : // Target doesn't support this yet!
648 0 : return true;
649 : }
650 :
651 11731 : void AsmPrinter::emitInlineAsmStart() const {}
652 :
653 11316 : void AsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
654 11316 : const MCSubtargetInfo *EndInfo) const {}
|