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