AsmPrinterInlineAsm.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. //===-- AsmPrinterInlineAsm.cpp - AsmPrinter Inline Asm Handling ----------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements the inline assembler pieces of the AsmPrinter class.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "llvm/ADT/SmallString.h"
  13. #include "llvm/ADT/SmallVector.h"
  14. #include "llvm/ADT/Twine.h"
  15. #include "llvm/CodeGen/AsmPrinter.h"
  16. #include "llvm/CodeGen/MachineBasicBlock.h"
  17. #include "llvm/CodeGen/MachineFunction.h"
  18. #include "llvm/CodeGen/MachineModuleInfo.h"
  19. #include "llvm/CodeGen/TargetRegisterInfo.h"
  20. #include "llvm/CodeGen/TargetSubtargetInfo.h"
  21. #include "llvm/IR/Constants.h"
  22. #include "llvm/IR/DataLayout.h"
  23. #include "llvm/IR/DiagnosticInfo.h"
  24. #include "llvm/IR/InlineAsm.h"
  25. #include "llvm/IR/LLVMContext.h"
  26. #include "llvm/IR/Module.h"
  27. #include "llvm/MC/MCAsmInfo.h"
  28. #include "llvm/MC/MCInstrInfo.h"
  29. #include "llvm/MC/MCParser/MCAsmLexer.h"
  30. #include "llvm/MC/MCParser/MCTargetAsmParser.h"
  31. #include "llvm/MC/MCStreamer.h"
  32. #include "llvm/MC/MCSymbol.h"
  33. #include "llvm/MC/TargetRegistry.h"
  34. #include "llvm/Support/ErrorHandling.h"
  35. #include "llvm/Support/MemoryBuffer.h"
  36. #include "llvm/Support/SourceMgr.h"
  37. #include "llvm/Support/raw_ostream.h"
  38. #include "llvm/Target/TargetMachine.h"
  39. using namespace llvm;
  40. #define DEBUG_TYPE "asm-printer"
  41. unsigned AsmPrinter::addInlineAsmDiagBuffer(StringRef AsmStr,
  42. const MDNode *LocMDNode) const {
  43. MCContext &Context = MMI->getContext();
  44. Context.initInlineSourceManager();
  45. SourceMgr &SrcMgr = *Context.getInlineSourceManager();
  46. std::vector<const MDNode *> &LocInfos = Context.getLocInfos();
  47. std::unique_ptr<MemoryBuffer> Buffer;
  48. // The inline asm source manager will outlive AsmStr, so make a copy of the
  49. // string for SourceMgr to own.
  50. Buffer = MemoryBuffer::getMemBufferCopy(AsmStr, "<inline asm>");
  51. // Tell SrcMgr about this buffer, it takes ownership of the buffer.
  52. unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
  53. // Store LocMDNode in DiagInfo, using BufNum as an identifier.
  54. if (LocMDNode) {
  55. LocInfos.resize(BufNum);
  56. LocInfos[BufNum - 1] = LocMDNode;
  57. }
  58. return BufNum;
  59. }
  60. /// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
  61. void AsmPrinter::emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
  62. const MCTargetOptions &MCOptions,
  63. const MDNode *LocMDNode,
  64. InlineAsm::AsmDialect Dialect) const {
  65. assert(!Str.empty() && "Can't emit empty inline asm block");
  66. // Remember if the buffer is nul terminated or not so we can avoid a copy.
  67. bool isNullTerminated = Str.back() == 0;
  68. if (isNullTerminated)
  69. Str = Str.substr(0, Str.size()-1);
  70. // If the output streamer does not have mature MC support or the integrated
  71. // assembler has been disabled or not required, just emit the blob textually.
  72. // Otherwise parse the asm and emit it via MC support.
  73. // This is useful in case the asm parser doesn't handle something but the
  74. // system assembler does.
  75. const MCAsmInfo *MCAI = TM.getMCAsmInfo();
  76. assert(MCAI && "No MCAsmInfo");
  77. if (!MCAI->useIntegratedAssembler() &&
  78. !MCAI->parseInlineAsmUsingAsmParser() &&
  79. !OutStreamer->isIntegratedAssemblerRequired()) {
  80. emitInlineAsmStart();
  81. OutStreamer->emitRawText(Str);
  82. emitInlineAsmEnd(STI, nullptr);
  83. return;
  84. }
  85. unsigned BufNum = addInlineAsmDiagBuffer(Str, LocMDNode);
  86. SourceMgr &SrcMgr = *MMI->getContext().getInlineSourceManager();
  87. SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths);
  88. std::unique_ptr<MCAsmParser> Parser(
  89. createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum));
  90. // Do not use assembler-level information for parsing inline assembly.
  91. OutStreamer->setUseAssemblerInfoForParsing(false);
  92. // We create a new MCInstrInfo here since we might be at the module level
  93. // and not have a MachineFunction to initialize the TargetInstrInfo from and
  94. // we only need MCInstrInfo for asm parsing. We create one unconditionally
  95. // because it's not subtarget dependent.
  96. std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo());
  97. assert(MII && "Failed to create instruction info");
  98. std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser(
  99. STI, *Parser, *MII, MCOptions));
  100. if (!TAP)
  101. report_fatal_error("Inline asm not supported by this streamer because"
  102. " we don't have an asm parser for this target\n");
  103. Parser->setAssemblerDialect(Dialect);
  104. Parser->setTargetParser(*TAP);
  105. // Enable lexing Masm binary and hex integer literals in intel inline
  106. // assembly.
  107. if (Dialect == InlineAsm::AD_Intel)
  108. Parser->getLexer().setLexMasmIntegers(true);
  109. emitInlineAsmStart();
  110. // Don't implicitly switch to the text section before the asm.
  111. (void)Parser->Run(/*NoInitialTextSection*/ true,
  112. /*NoFinalize*/ true);
  113. emitInlineAsmEnd(STI, &TAP->getSTI());
  114. }
  115. static void EmitInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
  116. MachineModuleInfo *MMI, const MCAsmInfo *MAI,
  117. AsmPrinter *AP, uint64_t LocCookie,
  118. raw_ostream &OS) {
  119. bool InputIsIntelDialect = MI->getInlineAsmDialect() == InlineAsm::AD_Intel;
  120. if (InputIsIntelDialect) {
  121. // Switch to the inline assembly variant.
  122. OS << "\t.intel_syntax\n\t";
  123. }
  124. int CurVariant = -1; // The number of the {.|.|.} region we are in.
  125. const char *LastEmitted = AsmStr; // One past the last character emitted.
  126. unsigned NumOperands = MI->getNumOperands();
  127. int AsmPrinterVariant;
  128. if (InputIsIntelDialect)
  129. AsmPrinterVariant = 1; // X86MCAsmInfo.cpp's AsmWriterFlavorTy::Intel.
  130. else
  131. AsmPrinterVariant = MMI->getTarget().unqualifiedInlineAsmVariant();
  132. // FIXME: Should this happen for `asm inteldialect` as well?
  133. if (!InputIsIntelDialect && MAI->getEmitGNUAsmStartIndentationMarker())
  134. OS << '\t';
  135. while (*LastEmitted) {
  136. switch (*LastEmitted) {
  137. default: {
  138. // Not a special case, emit the string section literally.
  139. const char *LiteralEnd = LastEmitted+1;
  140. while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&
  141. *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')
  142. ++LiteralEnd;
  143. if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
  144. OS.write(LastEmitted, LiteralEnd - LastEmitted);
  145. LastEmitted = LiteralEnd;
  146. break;
  147. }
  148. case '\n':
  149. ++LastEmitted; // Consume newline character.
  150. OS << '\n'; // Indent code with newline.
  151. break;
  152. case '$': {
  153. ++LastEmitted; // Consume '$' character.
  154. bool Done = true;
  155. // Handle escapes.
  156. switch (*LastEmitted) {
  157. default: Done = false; break;
  158. case '$': // $$ -> $
  159. if (!InputIsIntelDialect)
  160. if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
  161. OS << '$';
  162. ++LastEmitted; // Consume second '$' character.
  163. break;
  164. case '(': // $( -> same as GCC's { character.
  165. ++LastEmitted; // Consume '(' character.
  166. if (CurVariant != -1)
  167. report_fatal_error("Nested variants found in inline asm string: '" +
  168. Twine(AsmStr) + "'");
  169. CurVariant = 0; // We're in the first variant now.
  170. break;
  171. case '|':
  172. ++LastEmitted; // Consume '|' character.
  173. if (CurVariant == -1)
  174. OS << '|'; // This is gcc's behavior for | outside a variant.
  175. else
  176. ++CurVariant; // We're in the next variant.
  177. break;
  178. case ')': // $) -> same as GCC's } char.
  179. ++LastEmitted; // Consume ')' character.
  180. if (CurVariant == -1)
  181. OS << '}'; // This is gcc's behavior for } outside a variant.
  182. else
  183. CurVariant = -1;
  184. break;
  185. }
  186. if (Done) break;
  187. bool HasCurlyBraces = false;
  188. if (*LastEmitted == '{') { // ${variable}
  189. ++LastEmitted; // Consume '{' character.
  190. HasCurlyBraces = true;
  191. }
  192. // If we have ${:foo}, then this is not a real operand reference, it is a
  193. // "magic" string reference, just like in .td files. Arrange to call
  194. // PrintSpecial.
  195. if (HasCurlyBraces && *LastEmitted == ':') {
  196. ++LastEmitted;
  197. const char *StrStart = LastEmitted;
  198. const char *StrEnd = strchr(StrStart, '}');
  199. if (!StrEnd)
  200. report_fatal_error("Unterminated ${:foo} operand in inline asm"
  201. " string: '" + Twine(AsmStr) + "'");
  202. if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
  203. AP->PrintSpecial(MI, OS, StringRef(StrStart, StrEnd - StrStart));
  204. LastEmitted = StrEnd+1;
  205. break;
  206. }
  207. const char *IDStart = LastEmitted;
  208. const char *IDEnd = IDStart;
  209. while (isDigit(*IDEnd))
  210. ++IDEnd;
  211. unsigned Val;
  212. if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val))
  213. report_fatal_error("Bad $ operand number in inline asm string: '" +
  214. Twine(AsmStr) + "'");
  215. LastEmitted = IDEnd;
  216. if (Val >= NumOperands - 1)
  217. report_fatal_error("Invalid $ operand number in inline asm string: '" +
  218. Twine(AsmStr) + "'");
  219. char Modifier[2] = { 0, 0 };
  220. if (HasCurlyBraces) {
  221. // If we have curly braces, check for a modifier character. This
  222. // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm.
  223. if (*LastEmitted == ':') {
  224. ++LastEmitted; // Consume ':' character.
  225. if (*LastEmitted == 0)
  226. report_fatal_error("Bad ${:} expression in inline asm string: '" +
  227. Twine(AsmStr) + "'");
  228. Modifier[0] = *LastEmitted;
  229. ++LastEmitted; // Consume modifier character.
  230. }
  231. if (*LastEmitted != '}')
  232. report_fatal_error("Bad ${} expression in inline asm string: '" +
  233. Twine(AsmStr) + "'");
  234. ++LastEmitted; // Consume '}' character.
  235. }
  236. // Okay, we finally have a value number. Ask the target to print this
  237. // operand!
  238. if (CurVariant == -1 || CurVariant == AsmPrinterVariant) {
  239. unsigned OpNo = InlineAsm::MIOp_FirstOperand;
  240. bool Error = false;
  241. // Scan to find the machine operand number for the operand.
  242. for (; Val; --Val) {
  243. if (OpNo >= MI->getNumOperands())
  244. break;
  245. unsigned OpFlags = MI->getOperand(OpNo).getImm();
  246. OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
  247. }
  248. // We may have a location metadata attached to the end of the
  249. // instruction, and at no point should see metadata at any
  250. // other point while processing. It's an error if so.
  251. if (OpNo >= MI->getNumOperands() || MI->getOperand(OpNo).isMetadata()) {
  252. Error = true;
  253. } else {
  254. unsigned OpFlags = MI->getOperand(OpNo).getImm();
  255. ++OpNo; // Skip over the ID number.
  256. // FIXME: Shouldn't arch-independent output template handling go into
  257. // PrintAsmOperand?
  258. // Labels are target independent.
  259. if (MI->getOperand(OpNo).isBlockAddress()) {
  260. const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress();
  261. MCSymbol *Sym = AP->GetBlockAddressSymbol(BA);
  262. Sym->print(OS, AP->MAI);
  263. MMI->getContext().registerInlineAsmLabel(Sym);
  264. } else if (MI->getOperand(OpNo).isMBB()) {
  265. const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol();
  266. Sym->print(OS, AP->MAI);
  267. } else if (InlineAsm::isMemKind(OpFlags)) {
  268. Error = AP->PrintAsmMemoryOperand(
  269. MI, OpNo, Modifier[0] ? Modifier : nullptr, OS);
  270. } else {
  271. Error = AP->PrintAsmOperand(MI, OpNo,
  272. Modifier[0] ? Modifier : nullptr, OS);
  273. }
  274. }
  275. if (Error) {
  276. std::string msg;
  277. raw_string_ostream Msg(msg);
  278. Msg << "invalid operand in inline asm: '" << AsmStr << "'";
  279. MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
  280. }
  281. }
  282. break;
  283. }
  284. }
  285. }
  286. if (InputIsIntelDialect)
  287. OS << "\n\t.att_syntax";
  288. OS << '\n' << (char)0; // null terminate string.
  289. }
  290. /// This method formats and emits the specified machine instruction that is an
  291. /// inline asm.
  292. void AsmPrinter::emitInlineAsm(const MachineInstr *MI) const {
  293. assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms");
  294. // Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
  295. const char *AsmStr = MI->getOperand(0).getSymbolName();
  296. // If this asmstr is empty, just print the #APP/#NOAPP markers.
  297. // These are useful to see where empty asm's wound up.
  298. if (AsmStr[0] == 0) {
  299. OutStreamer->emitRawComment(MAI->getInlineAsmStart());
  300. OutStreamer->emitRawComment(MAI->getInlineAsmEnd());
  301. return;
  302. }
  303. // Emit the #APP start marker. This has to happen even if verbose-asm isn't
  304. // enabled, so we use emitRawComment.
  305. OutStreamer->emitRawComment(MAI->getInlineAsmStart());
  306. // Get the !srcloc metadata node if we have it, and decode the loc cookie from
  307. // it.
  308. uint64_t LocCookie = 0;
  309. const MDNode *LocMD = nullptr;
  310. for (const MachineOperand &MO : llvm::reverse(MI->operands())) {
  311. if (MO.isMetadata() && (LocMD = MO.getMetadata()) &&
  312. LocMD->getNumOperands() != 0) {
  313. if (const ConstantInt *CI =
  314. mdconst::dyn_extract<ConstantInt>(LocMD->getOperand(0))) {
  315. LocCookie = CI->getZExtValue();
  316. break;
  317. }
  318. }
  319. }
  320. // Emit the inline asm to a temporary string so we can emit it through
  321. // EmitInlineAsm.
  322. SmallString<256> StringData;
  323. raw_svector_ostream OS(StringData);
  324. AsmPrinter *AP = const_cast<AsmPrinter*>(this);
  325. EmitInlineAsmStr(AsmStr, MI, MMI, MAI, AP, LocCookie, OS);
  326. // Emit warnings if we use reserved registers on the clobber list, as
  327. // that might lead to undefined behaviour.
  328. SmallVector<Register, 8> RestrRegs;
  329. const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
  330. // Start with the first operand descriptor, and iterate over them.
  331. for (unsigned I = InlineAsm::MIOp_FirstOperand, NumOps = MI->getNumOperands();
  332. I < NumOps; ++I) {
  333. const MachineOperand &MO = MI->getOperand(I);
  334. if (!MO.isImm())
  335. continue;
  336. unsigned Flags = MO.getImm();
  337. if (InlineAsm::getKind(Flags) == InlineAsm::Kind_Clobber) {
  338. Register Reg = MI->getOperand(I + 1).getReg();
  339. if (!TRI->isAsmClobberable(*MF, Reg))
  340. RestrRegs.push_back(Reg);
  341. }
  342. // Skip to one before the next operand descriptor, if it exists.
  343. I += InlineAsm::getNumOperandRegisters(Flags);
  344. }
  345. if (!RestrRegs.empty()) {
  346. std::string Msg = "inline asm clobber list contains reserved registers: ";
  347. ListSeparator LS;
  348. for (const Register RR : RestrRegs) {
  349. Msg += LS;
  350. Msg += TRI->getRegAsmName(RR);
  351. }
  352. const char *Note =
  353. "Reserved registers on the clobber list may not be "
  354. "preserved across the asm statement, and clobbering them may "
  355. "lead to undefined behaviour.";
  356. MMI->getModule()->getContext().diagnose(DiagnosticInfoInlineAsm(
  357. LocCookie, Msg, DiagnosticSeverity::DS_Warning));
  358. MMI->getModule()->getContext().diagnose(
  359. DiagnosticInfoInlineAsm(LocCookie, Note, DiagnosticSeverity::DS_Note));
  360. for (const Register RR : RestrRegs) {
  361. if (std::optional<std::string> reason =
  362. TRI->explainReservedReg(*MF, RR)) {
  363. MMI->getModule()->getContext().diagnose(DiagnosticInfoInlineAsm(
  364. LocCookie, *reason, DiagnosticSeverity::DS_Note));
  365. }
  366. }
  367. }
  368. emitInlineAsm(OS.str(), getSubtargetInfo(), TM.Options.MCOptions, LocMD,
  369. MI->getInlineAsmDialect());
  370. // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't
  371. // enabled, so we use emitRawComment.
  372. OutStreamer->emitRawComment(MAI->getInlineAsmEnd());
  373. }
  374. /// PrintSpecial - Print information related to the specified machine instr
  375. /// that is independent of the operand, and may be independent of the instr
  376. /// itself. This can be useful for portably encoding the comment character
  377. /// or other bits of target-specific knowledge into the asmstrings. The
  378. /// syntax used is ${:comment}. Targets can override this to add support
  379. /// for their own strange codes.
  380. void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
  381. StringRef Code) const {
  382. if (Code == "private") {
  383. const DataLayout &DL = MF->getDataLayout();
  384. OS << DL.getPrivateGlobalPrefix();
  385. } else if (Code == "comment") {
  386. OS << MAI->getCommentString();
  387. } else if (Code == "uid") {
  388. // Comparing the address of MI isn't sufficient, because machineinstrs may
  389. // be allocated to the same address across functions.
  390. // If this is a new LastFn instruction, bump the counter.
  391. if (LastMI != MI || LastFn != getFunctionNumber()) {
  392. ++Counter;
  393. LastMI = MI;
  394. LastFn = getFunctionNumber();
  395. }
  396. OS << Counter;
  397. } else {
  398. std::string msg;
  399. raw_string_ostream Msg(msg);
  400. Msg << "Unknown special formatter '" << Code
  401. << "' for machine instr: " << *MI;
  402. report_fatal_error(Twine(Msg.str()));
  403. }
  404. }
  405. void AsmPrinter::PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS) {
  406. assert(MO.isGlobal() && "caller should check MO.isGlobal");
  407. getSymbolPreferLocal(*MO.getGlobal())->print(OS, MAI);
  408. printOffset(MO.getOffset(), OS);
  409. }
  410. /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
  411. /// instruction, using the specified assembler variant. Targets should
  412. /// override this to format as appropriate for machine specific ExtraCodes
  413. /// or when the arch-independent handling would be too complex otherwise.
  414. bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
  415. const char *ExtraCode, raw_ostream &O) {
  416. // Does this asm operand have a single letter operand modifier?
  417. if (ExtraCode && ExtraCode[0]) {
  418. if (ExtraCode[1] != 0) return true; // Unknown modifier.
  419. // https://gcc.gnu.org/onlinedocs/gccint/Output-Template.html
  420. const MachineOperand &MO = MI->getOperand(OpNo);
  421. switch (ExtraCode[0]) {
  422. default:
  423. return true; // Unknown modifier.
  424. case 'a': // Print as memory address.
  425. if (MO.isReg()) {
  426. PrintAsmMemoryOperand(MI, OpNo, nullptr, O);
  427. return false;
  428. }
  429. [[fallthrough]]; // GCC allows '%a' to behave like '%c' with immediates.
  430. case 'c': // Substitute immediate value without immediate syntax
  431. if (MO.isImm()) {
  432. O << MO.getImm();
  433. return false;
  434. }
  435. if (MO.isGlobal()) {
  436. PrintSymbolOperand(MO, O);
  437. return false;
  438. }
  439. return true;
  440. case 'n': // Negate the immediate constant.
  441. if (!MO.isImm())
  442. return true;
  443. O << -MO.getImm();
  444. return false;
  445. case 's': // The GCC deprecated s modifier
  446. if (!MO.isImm())
  447. return true;
  448. O << ((32 - MO.getImm()) & 31);
  449. return false;
  450. }
  451. }
  452. return true;
  453. }
  454. bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
  455. const char *ExtraCode, raw_ostream &O) {
  456. // Target doesn't support this yet!
  457. return true;
  458. }
  459. void AsmPrinter::emitInlineAsmStart() const {}
  460. void AsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
  461. const MCSubtargetInfo *EndInfo) const {}