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