Home | History | Annotate | Download | only in Parse
      1 //===---- ParseStmtAsm.cpp - Assembly Statement Parser --------------------===//
      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 parsing for GCC and Microsoft inline assembly.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "clang/Parse/Parser.h"
     15 #include "RAIIObjectsForParser.h"
     16 #include "clang/AST/ASTContext.h"
     17 #include "clang/Basic/Diagnostic.h"
     18 #include "clang/Basic/TargetInfo.h"
     19 #include "llvm/ADT/SmallString.h"
     20 #include "llvm/MC/MCAsmInfo.h"
     21 #include "llvm/MC/MCContext.h"
     22 #include "llvm/MC/MCInstPrinter.h"
     23 #include "llvm/MC/MCInstrInfo.h"
     24 #include "llvm/MC/MCObjectFileInfo.h"
     25 #include "llvm/MC/MCParser/MCAsmParser.h"
     26 #include "llvm/MC/MCRegisterInfo.h"
     27 #include "llvm/MC/MCStreamer.h"
     28 #include "llvm/MC/MCSubtargetInfo.h"
     29 #include "llvm/MC/MCTargetAsmParser.h"
     30 #include "llvm/MC/MCTargetOptions.h"
     31 #include "llvm/Support/SourceMgr.h"
     32 #include "llvm/Support/TargetRegistry.h"
     33 #include "llvm/Support/TargetSelect.h"
     34 using namespace clang;
     35 
     36 namespace {
     37 class ClangAsmParserCallback : public llvm::MCAsmParserSemaCallback {
     38   Parser &TheParser;
     39   SourceLocation AsmLoc;
     40   StringRef AsmString;
     41 
     42   /// The tokens we streamed into AsmString and handed off to MC.
     43   ArrayRef<Token> AsmToks;
     44 
     45   /// The offset of each token in AsmToks within AsmString.
     46   ArrayRef<unsigned> AsmTokOffsets;
     47 
     48 public:
     49   ClangAsmParserCallback(Parser &P, SourceLocation Loc, StringRef AsmString,
     50                          ArrayRef<Token> Toks, ArrayRef<unsigned> Offsets)
     51       : TheParser(P), AsmLoc(Loc), AsmString(AsmString), AsmToks(Toks),
     52         AsmTokOffsets(Offsets) {
     53     assert(AsmToks.size() == AsmTokOffsets.size());
     54   }
     55 
     56   void *LookupInlineAsmIdentifier(StringRef &LineBuf,
     57                                   llvm::InlineAsmIdentifierInfo &Info,
     58                                   bool IsUnevaluatedContext) override {
     59     // Collect the desired tokens.
     60     SmallVector<Token, 16> LineToks;
     61     const Token *FirstOrigToken = nullptr;
     62     findTokensForString(LineBuf, LineToks, FirstOrigToken);
     63 
     64     unsigned NumConsumedToks;
     65     ExprResult Result = TheParser.ParseMSAsmIdentifier(
     66         LineToks, NumConsumedToks, &Info, IsUnevaluatedContext);
     67 
     68     // If we consumed the entire line, tell MC that.
     69     // Also do this if we consumed nothing as a way of reporting failure.
     70     if (NumConsumedToks == 0 || NumConsumedToks == LineToks.size()) {
     71       // By not modifying LineBuf, we're implicitly consuming it all.
     72 
     73       // Otherwise, consume up to the original tokens.
     74     } else {
     75       assert(FirstOrigToken && "not using original tokens?");
     76 
     77       // Since we're using original tokens, apply that offset.
     78       assert(FirstOrigToken[NumConsumedToks].getLocation() ==
     79              LineToks[NumConsumedToks].getLocation());
     80       unsigned FirstIndex = FirstOrigToken - AsmToks.begin();
     81       unsigned LastIndex = FirstIndex + NumConsumedToks - 1;
     82 
     83       // The total length we've consumed is the relative offset
     84       // of the last token we consumed plus its length.
     85       unsigned TotalOffset =
     86           (AsmTokOffsets[LastIndex] + AsmToks[LastIndex].getLength() -
     87            AsmTokOffsets[FirstIndex]);
     88       LineBuf = LineBuf.substr(0, TotalOffset);
     89     }
     90 
     91     // Initialize the "decl" with the lookup result.
     92     Info.OpDecl = static_cast<void *>(Result.get());
     93     return Info.OpDecl;
     94   }
     95 
     96   StringRef LookupInlineAsmLabel(StringRef Identifier, llvm::SourceMgr &LSM,
     97                                  llvm::SMLoc Location,
     98                                  bool Create) override {
     99     SourceLocation Loc = translateLocation(LSM, Location);
    100     LabelDecl *Label =
    101       TheParser.getActions().GetOrCreateMSAsmLabel(Identifier, Loc, Create);
    102     return Label->getMSAsmLabel();
    103   }
    104 
    105   bool LookupInlineAsmField(StringRef Base, StringRef Member,
    106                             unsigned &Offset) override {
    107     return TheParser.getActions().LookupInlineAsmField(Base, Member, Offset,
    108                                                        AsmLoc);
    109   }
    110 
    111   static void DiagHandlerCallback(const llvm::SMDiagnostic &D, void *Context) {
    112     ((ClangAsmParserCallback *)Context)->handleDiagnostic(D);
    113   }
    114 
    115 private:
    116   /// Collect the appropriate tokens for the given string.
    117   void findTokensForString(StringRef Str, SmallVectorImpl<Token> &TempToks,
    118                            const Token *&FirstOrigToken) const {
    119     // For now, assert that the string we're working with is a substring
    120     // of what we gave to MC.  This lets us use the original tokens.
    121     assert(!std::less<const char *>()(Str.begin(), AsmString.begin()) &&
    122            !std::less<const char *>()(AsmString.end(), Str.end()));
    123 
    124     // Try to find a token whose offset matches the first token.
    125     unsigned FirstCharOffset = Str.begin() - AsmString.begin();
    126     const unsigned *FirstTokOffset = std::lower_bound(
    127         AsmTokOffsets.begin(), AsmTokOffsets.end(), FirstCharOffset);
    128 
    129     // For now, assert that the start of the string exactly
    130     // corresponds to the start of a token.
    131     assert(*FirstTokOffset == FirstCharOffset);
    132 
    133     // Use all the original tokens for this line.  (We assume the
    134     // end of the line corresponds cleanly to a token break.)
    135     unsigned FirstTokIndex = FirstTokOffset - AsmTokOffsets.begin();
    136     FirstOrigToken = &AsmToks[FirstTokIndex];
    137     unsigned LastCharOffset = Str.end() - AsmString.begin();
    138     for (unsigned i = FirstTokIndex, e = AsmTokOffsets.size(); i != e; ++i) {
    139       if (AsmTokOffsets[i] >= LastCharOffset)
    140         break;
    141       TempToks.push_back(AsmToks[i]);
    142     }
    143   }
    144 
    145   SourceLocation translateLocation(const llvm::SourceMgr &LSM, llvm::SMLoc SMLoc) {
    146     // Compute an offset into the inline asm buffer.
    147     // FIXME: This isn't right if .macro is involved (but hopefully, no
    148     // real-world code does that).
    149     const llvm::MemoryBuffer *LBuf =
    150         LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(SMLoc));
    151     unsigned Offset = SMLoc.getPointer() - LBuf->getBufferStart();
    152 
    153     // Figure out which token that offset points into.
    154     const unsigned *TokOffsetPtr =
    155         std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), Offset);
    156     unsigned TokIndex = TokOffsetPtr - AsmTokOffsets.begin();
    157     unsigned TokOffset = *TokOffsetPtr;
    158 
    159     // If we come up with an answer which seems sane, use it; otherwise,
    160     // just point at the __asm keyword.
    161     // FIXME: Assert the answer is sane once we handle .macro correctly.
    162     SourceLocation Loc = AsmLoc;
    163     if (TokIndex < AsmToks.size()) {
    164       const Token &Tok = AsmToks[TokIndex];
    165       Loc = Tok.getLocation();
    166       Loc = Loc.getLocWithOffset(Offset - TokOffset);
    167     }
    168     return Loc;
    169   }
    170 
    171   void handleDiagnostic(const llvm::SMDiagnostic &D) {
    172     const llvm::SourceMgr &LSM = *D.getSourceMgr();
    173     SourceLocation Loc = translateLocation(LSM, D.getLoc());
    174     TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage();
    175   }
    176 };
    177 }
    178 
    179 /// Parse an identifier in an MS-style inline assembly block.
    180 ///
    181 /// \param CastInfo - a void* so that we don't have to teach Parser.h
    182 ///   about the actual type.
    183 ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
    184                                         unsigned &NumLineToksConsumed,
    185                                         void *CastInfo,
    186                                         bool IsUnevaluatedContext) {
    187   llvm::InlineAsmIdentifierInfo &Info =
    188       *(llvm::InlineAsmIdentifierInfo *)CastInfo;
    189 
    190   // Push a fake token on the end so that we don't overrun the token
    191   // stream.  We use ';' because it expression-parsing should never
    192   // overrun it.
    193   const tok::TokenKind EndOfStream = tok::semi;
    194   Token EndOfStreamTok;
    195   EndOfStreamTok.startToken();
    196   EndOfStreamTok.setKind(EndOfStream);
    197   LineToks.push_back(EndOfStreamTok);
    198 
    199   // Also copy the current token over.
    200   LineToks.push_back(Tok);
    201 
    202   PP.EnterTokenStream(LineToks.begin(), LineToks.size(),
    203                       /*disable macros*/ true,
    204                       /*owns tokens*/ false);
    205 
    206   // Clear the current token and advance to the first token in LineToks.
    207   ConsumeAnyToken();
    208 
    209   // Parse an optional scope-specifier if we're in C++.
    210   CXXScopeSpec SS;
    211   if (getLangOpts().CPlusPlus) {
    212     ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
    213   }
    214 
    215   // Require an identifier here.
    216   SourceLocation TemplateKWLoc;
    217   UnqualifiedId Id;
    218   bool Invalid =
    219       ParseUnqualifiedId(SS,
    220                          /*EnteringContext=*/false,
    221                          /*AllowDestructorName=*/false,
    222                          /*AllowConstructorName=*/false,
    223                          /*ObjectType=*/ParsedType(), TemplateKWLoc, Id);
    224 
    225   // Figure out how many tokens we are into LineToks.
    226   unsigned LineIndex = 0;
    227   if (Tok.is(EndOfStream)) {
    228     LineIndex = LineToks.size() - 2;
    229   } else {
    230     while (LineToks[LineIndex].getLocation() != Tok.getLocation()) {
    231       LineIndex++;
    232       assert(LineIndex < LineToks.size() - 2); // we added two extra tokens
    233     }
    234   }
    235 
    236   // If we've run into the poison token we inserted before, or there
    237   // was a parsing error, then claim the entire line.
    238   if (Invalid || Tok.is(EndOfStream)) {
    239     NumLineToksConsumed = LineToks.size() - 2;
    240   } else {
    241     // Otherwise, claim up to the start of the next token.
    242     NumLineToksConsumed = LineIndex;
    243   }
    244 
    245   // Finally, restore the old parsing state by consuming all the tokens we
    246   // staged before, implicitly killing off the token-lexer we pushed.
    247   for (unsigned i = 0, e = LineToks.size() - LineIndex - 2; i != e; ++i) {
    248     ConsumeAnyToken();
    249   }
    250   assert(Tok.is(EndOfStream));
    251   ConsumeToken();
    252 
    253   // Leave LineToks in its original state.
    254   LineToks.pop_back();
    255   LineToks.pop_back();
    256 
    257   // Perform the lookup.
    258   return Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info,
    259                                            IsUnevaluatedContext);
    260 }
    261 
    262 /// Turn a sequence of our tokens back into a string that we can hand
    263 /// to the MC asm parser.
    264 static bool buildMSAsmString(Preprocessor &PP, SourceLocation AsmLoc,
    265                              ArrayRef<Token> AsmToks,
    266                              SmallVectorImpl<unsigned> &TokOffsets,
    267                              SmallString<512> &Asm) {
    268   assert(!AsmToks.empty() && "Didn't expect an empty AsmToks!");
    269 
    270   // Is this the start of a new assembly statement?
    271   bool isNewStatement = true;
    272 
    273   for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
    274     const Token &Tok = AsmToks[i];
    275 
    276     // Start each new statement with a newline and a tab.
    277     if (!isNewStatement && (Tok.is(tok::kw_asm) || Tok.isAtStartOfLine())) {
    278       Asm += "\n\t";
    279       isNewStatement = true;
    280     }
    281 
    282     // Preserve the existence of leading whitespace except at the
    283     // start of a statement.
    284     if (!isNewStatement && Tok.hasLeadingSpace())
    285       Asm += ' ';
    286 
    287     // Remember the offset of this token.
    288     TokOffsets.push_back(Asm.size());
    289 
    290     // Don't actually write '__asm' into the assembly stream.
    291     if (Tok.is(tok::kw_asm)) {
    292       // Complain about __asm at the end of the stream.
    293       if (i + 1 == e) {
    294         PP.Diag(AsmLoc, diag::err_asm_empty);
    295         return true;
    296       }
    297 
    298       continue;
    299     }
    300 
    301     // Append the spelling of the token.
    302     SmallString<32> SpellingBuffer;
    303     bool SpellingInvalid = false;
    304     Asm += PP.getSpelling(Tok, SpellingBuffer, &SpellingInvalid);
    305     assert(!SpellingInvalid && "spelling was invalid after correct parse?");
    306 
    307     // We are no longer at the start of a statement.
    308     isNewStatement = false;
    309   }
    310 
    311   // Ensure that the buffer is null-terminated.
    312   Asm.push_back('\0');
    313   Asm.pop_back();
    314 
    315   assert(TokOffsets.size() == AsmToks.size());
    316   return false;
    317 }
    318 
    319 /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled,
    320 /// this routine is called to collect the tokens for an MS asm statement.
    321 ///
    322 /// [MS]  ms-asm-statement:
    323 ///         ms-asm-block
    324 ///         ms-asm-block ms-asm-statement
    325 ///
    326 /// [MS]  ms-asm-block:
    327 ///         '__asm' ms-asm-line '\n'
    328 ///         '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt]
    329 ///
    330 /// [MS]  ms-asm-instruction-block
    331 ///         ms-asm-line
    332 ///         ms-asm-line '\n' ms-asm-instruction-block
    333 ///
    334 StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
    335   SourceManager &SrcMgr = PP.getSourceManager();
    336   SourceLocation EndLoc = AsmLoc;
    337   SmallVector<Token, 4> AsmToks;
    338 
    339   bool SingleLineMode = true;
    340   unsigned BraceNesting = 0;
    341   unsigned short savedBraceCount = BraceCount;
    342   bool InAsmComment = false;
    343   FileID FID;
    344   unsigned LineNo = 0;
    345   unsigned NumTokensRead = 0;
    346   SmallVector<SourceLocation, 4> LBraceLocs;
    347   bool SkippedStartOfLine = false;
    348 
    349   if (Tok.is(tok::l_brace)) {
    350     // Braced inline asm: consume the opening brace.
    351     SingleLineMode = false;
    352     BraceNesting = 1;
    353     EndLoc = ConsumeBrace();
    354     LBraceLocs.push_back(EndLoc);
    355     ++NumTokensRead;
    356   } else {
    357     // Single-line inline asm; compute which line it is on.
    358     std::pair<FileID, unsigned> ExpAsmLoc =
    359         SrcMgr.getDecomposedExpansionLoc(EndLoc);
    360     FID = ExpAsmLoc.first;
    361     LineNo = SrcMgr.getLineNumber(FID, ExpAsmLoc.second);
    362     LBraceLocs.push_back(SourceLocation());
    363   }
    364 
    365   SourceLocation TokLoc = Tok.getLocation();
    366   do {
    367     // If we hit EOF, we're done, period.
    368     if (isEofOrEom())
    369       break;
    370 
    371     if (!InAsmComment && Tok.is(tok::l_brace)) {
    372       // Consume the opening brace.
    373       SkippedStartOfLine = Tok.isAtStartOfLine();
    374       EndLoc = ConsumeBrace();
    375       BraceNesting++;
    376       LBraceLocs.push_back(EndLoc);
    377       TokLoc = Tok.getLocation();
    378       ++NumTokensRead;
    379       continue;
    380     } else if (!InAsmComment && Tok.is(tok::semi)) {
    381       // A semicolon in an asm is the start of a comment.
    382       InAsmComment = true;
    383       if (!SingleLineMode) {
    384         // Compute which line the comment is on.
    385         std::pair<FileID, unsigned> ExpSemiLoc =
    386             SrcMgr.getDecomposedExpansionLoc(TokLoc);
    387         FID = ExpSemiLoc.first;
    388         LineNo = SrcMgr.getLineNumber(FID, ExpSemiLoc.second);
    389       }
    390     } else if (SingleLineMode || InAsmComment) {
    391       // If end-of-line is significant, check whether this token is on a
    392       // new line.
    393       std::pair<FileID, unsigned> ExpLoc =
    394           SrcMgr.getDecomposedExpansionLoc(TokLoc);
    395       if (ExpLoc.first != FID ||
    396           SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) {
    397         // If this is a single-line __asm, we're done, except if the next
    398         // line begins with an __asm too, in which case we finish a comment
    399         // if needed and then keep processing the next line as a single
    400         // line __asm.
    401         bool isAsm = Tok.is(tok::kw_asm);
    402         if (SingleLineMode && !isAsm)
    403           break;
    404         // We're no longer in a comment.
    405         InAsmComment = false;
    406         if (isAsm) {
    407           LineNo = SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second);
    408           SkippedStartOfLine = Tok.isAtStartOfLine();
    409         }
    410       } else if (!InAsmComment && Tok.is(tok::r_brace)) {
    411         // In MSVC mode, braces only participate in brace matching and
    412         // separating the asm statements.  This is an intentional
    413         // departure from the Apple gcc behavior.
    414         if (!BraceNesting)
    415           break;
    416       }
    417     }
    418     if (!InAsmComment && BraceNesting && Tok.is(tok::r_brace) &&
    419         BraceCount == (savedBraceCount + BraceNesting)) {
    420       // Consume the closing brace.
    421       SkippedStartOfLine = Tok.isAtStartOfLine();
    422       EndLoc = ConsumeBrace();
    423       BraceNesting--;
    424       // Finish if all of the opened braces in the inline asm section were
    425       // consumed.
    426       if (BraceNesting == 0 && !SingleLineMode)
    427         break;
    428       else {
    429         LBraceLocs.pop_back();
    430         TokLoc = Tok.getLocation();
    431         ++NumTokensRead;
    432         continue;
    433       }
    434     }
    435 
    436     // Consume the next token; make sure we don't modify the brace count etc.
    437     // if we are in a comment.
    438     EndLoc = TokLoc;
    439     if (InAsmComment)
    440       PP.Lex(Tok);
    441     else {
    442       // Set the token as the start of line if we skipped the original start
    443       // of line token in case it was a nested brace.
    444       if (SkippedStartOfLine)
    445         Tok.setFlag(Token::StartOfLine);
    446       AsmToks.push_back(Tok);
    447       ConsumeAnyToken();
    448     }
    449     TokLoc = Tok.getLocation();
    450     ++NumTokensRead;
    451     SkippedStartOfLine = false;
    452   } while (1);
    453 
    454   if (BraceNesting && BraceCount != savedBraceCount) {
    455     // __asm without closing brace (this can happen at EOF).
    456     for (unsigned i = 0; i < BraceNesting; ++i) {
    457       Diag(Tok, diag::err_expected) << tok::r_brace;
    458       Diag(LBraceLocs.back(), diag::note_matching) << tok::l_brace;
    459       LBraceLocs.pop_back();
    460     }
    461     return StmtError();
    462   } else if (NumTokensRead == 0) {
    463     // Empty __asm.
    464     Diag(Tok, diag::err_expected) << tok::l_brace;
    465     return StmtError();
    466   }
    467 
    468   // Okay, prepare to use MC to parse the assembly.
    469   SmallVector<StringRef, 4> ConstraintRefs;
    470   SmallVector<Expr *, 4> Exprs;
    471   SmallVector<StringRef, 4> ClobberRefs;
    472 
    473   // We need an actual supported target.
    474   const llvm::Triple &TheTriple = Actions.Context.getTargetInfo().getTriple();
    475   llvm::Triple::ArchType ArchTy = TheTriple.getArch();
    476   const std::string &TT = TheTriple.getTriple();
    477   const llvm::Target *TheTarget = nullptr;
    478   bool UnsupportedArch =
    479       (ArchTy != llvm::Triple::x86 && ArchTy != llvm::Triple::x86_64);
    480   if (UnsupportedArch) {
    481     Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName();
    482   } else {
    483     std::string Error;
    484     TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error);
    485     if (!TheTarget)
    486       Diag(AsmLoc, diag::err_msasm_unable_to_create_target) << Error;
    487   }
    488 
    489   assert(!LBraceLocs.empty() && "Should have at least one location here");
    490 
    491   // If we don't support assembly, or the assembly is empty, we don't
    492   // need to instantiate the AsmParser, etc.
    493   if (!TheTarget || AsmToks.empty()) {
    494     return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, StringRef(),
    495                                   /*NumOutputs*/ 0, /*NumInputs*/ 0,
    496                                   ConstraintRefs, ClobberRefs, Exprs, EndLoc);
    497   }
    498 
    499   // Expand the tokens into a string buffer.
    500   SmallString<512> AsmString;
    501   SmallVector<unsigned, 8> TokOffsets;
    502   if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString))
    503     return StmtError();
    504 
    505   std::unique_ptr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
    506   std::unique_ptr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT));
    507   // Get the instruction descriptor.
    508   std::unique_ptr<llvm::MCInstrInfo> MII(TheTarget->createMCInstrInfo());
    509   std::unique_ptr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
    510   std::unique_ptr<llvm::MCSubtargetInfo> STI(
    511       TheTarget->createMCSubtargetInfo(TT, "", ""));
    512 
    513   llvm::SourceMgr TempSrcMgr;
    514   llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr);
    515   MOFI->InitMCObjectFileInfo(TT, llvm::Reloc::Default, llvm::CodeModel::Default,
    516                              Ctx);
    517   std::unique_ptr<llvm::MemoryBuffer> Buffer =
    518       llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>");
    519 
    520   // Tell SrcMgr about this buffer, which is what the parser will pick up.
    521   TempSrcMgr.AddNewSourceBuffer(std::move(Buffer), llvm::SMLoc());
    522 
    523   std::unique_ptr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
    524   std::unique_ptr<llvm::MCAsmParser> Parser(
    525       createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI));
    526 
    527   // FIXME: init MCOptions from sanitizer flags here.
    528   llvm::MCTargetOptions MCOptions;
    529   std::unique_ptr<llvm::MCTargetAsmParser> TargetParser(
    530       TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions));
    531 
    532   std::unique_ptr<llvm::MCInstPrinter> IP(
    533       TheTarget->createMCInstPrinter(llvm::Triple(TT), 1, *MAI, *MII, *MRI));
    534 
    535   // Change to the Intel dialect.
    536   Parser->setAssemblerDialect(1);
    537   Parser->setTargetParser(*TargetParser.get());
    538   Parser->setParsingInlineAsm(true);
    539   TargetParser->setParsingInlineAsm(true);
    540 
    541   ClangAsmParserCallback Callback(*this, AsmLoc, AsmString, AsmToks,
    542                                   TokOffsets);
    543   TargetParser->setSemaCallback(&Callback);
    544   TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback,
    545                             &Callback);
    546 
    547   unsigned NumOutputs;
    548   unsigned NumInputs;
    549   std::string AsmStringIR;
    550   SmallVector<std::pair<void *, bool>, 4> OpExprs;
    551   SmallVector<std::string, 4> Constraints;
    552   SmallVector<std::string, 4> Clobbers;
    553   if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, NumOutputs,
    554                                NumInputs, OpExprs, Constraints, Clobbers,
    555                                MII.get(), IP.get(), Callback))
    556     return StmtError();
    557 
    558   // Filter out "fpsw".  Clang doesn't accept it, and it always lists flags and
    559   // fpsr as clobbers.
    560   auto End = std::remove(Clobbers.begin(), Clobbers.end(), "fpsw");
    561   Clobbers.erase(End, Clobbers.end());
    562 
    563   // Build the vector of clobber StringRefs.
    564   ClobberRefs.insert(ClobberRefs.end(), Clobbers.begin(), Clobbers.end());
    565 
    566   // Recast the void pointers and build the vector of constraint StringRefs.
    567   unsigned NumExprs = NumOutputs + NumInputs;
    568   ConstraintRefs.resize(NumExprs);
    569   Exprs.resize(NumExprs);
    570   for (unsigned i = 0, e = NumExprs; i != e; ++i) {
    571     Expr *OpExpr = static_cast<Expr *>(OpExprs[i].first);
    572     if (!OpExpr)
    573       return StmtError();
    574 
    575     // Need address of variable.
    576     if (OpExprs[i].second)
    577       OpExpr =
    578           Actions.BuildUnaryOp(getCurScope(), AsmLoc, UO_AddrOf, OpExpr).get();
    579 
    580     ConstraintRefs[i] = StringRef(Constraints[i]);
    581     Exprs[i] = OpExpr;
    582   }
    583 
    584   // FIXME: We should be passing source locations for better diagnostics.
    585   return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmStringIR,
    586                                 NumOutputs, NumInputs, ConstraintRefs,
    587                                 ClobberRefs, Exprs, EndLoc);
    588 }
    589 
    590 /// ParseAsmStatement - Parse a GNU extended asm statement.
    591 ///       asm-statement:
    592 ///         gnu-asm-statement
    593 ///         ms-asm-statement
    594 ///
    595 /// [GNU] gnu-asm-statement:
    596 ///         'asm' type-qualifier[opt] '(' asm-argument ')' ';'
    597 ///
    598 /// [GNU] asm-argument:
    599 ///         asm-string-literal
    600 ///         asm-string-literal ':' asm-operands[opt]
    601 ///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
    602 ///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
    603 ///                 ':' asm-clobbers
    604 ///
    605 /// [GNU] asm-clobbers:
    606 ///         asm-string-literal
    607 ///         asm-clobbers ',' asm-string-literal
    608 ///
    609 StmtResult Parser::ParseAsmStatement(bool &msAsm) {
    610   assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
    611   SourceLocation AsmLoc = ConsumeToken();
    612 
    613   if (getLangOpts().AsmBlocks && Tok.isNot(tok::l_paren) &&
    614       !isTypeQualifier()) {
    615     msAsm = true;
    616     return ParseMicrosoftAsmStatement(AsmLoc);
    617   }
    618 
    619   // Check if GNU-style inline Asm is disabled.
    620   if (!getLangOpts().GNUAsm)
    621     Diag(AsmLoc, diag::err_gnu_inline_asm_disabled);
    622 
    623   DeclSpec DS(AttrFactory);
    624   SourceLocation Loc = Tok.getLocation();
    625   ParseTypeQualifierListOpt(DS, AR_VendorAttributesParsed);
    626 
    627   // GNU asms accept, but warn, about type-qualifiers other than volatile.
    628   if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
    629     Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
    630   if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
    631     Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
    632   // FIXME: Once GCC supports _Atomic, check whether it permits it here.
    633   if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
    634     Diag(Loc, diag::w_asm_qualifier_ignored) << "_Atomic";
    635 
    636   // Remember if this was a volatile asm.
    637   bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
    638   if (Tok.isNot(tok::l_paren)) {
    639     Diag(Tok, diag::err_expected_lparen_after) << "asm";
    640     SkipUntil(tok::r_paren, StopAtSemi);
    641     return StmtError();
    642   }
    643   BalancedDelimiterTracker T(*this, tok::l_paren);
    644   T.consumeOpen();
    645 
    646   ExprResult AsmString(ParseAsmStringLiteral());
    647   if (AsmString.isInvalid()) {
    648     // Consume up to and including the closing paren.
    649     T.skipToEnd();
    650     return StmtError();
    651   }
    652 
    653   SmallVector<IdentifierInfo *, 4> Names;
    654   ExprVector Constraints;
    655   ExprVector Exprs;
    656   ExprVector Clobbers;
    657 
    658   if (Tok.is(tok::r_paren)) {
    659     // We have a simple asm expression like 'asm("foo")'.
    660     T.consumeClose();
    661     return Actions.ActOnGCCAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
    662                                    /*NumOutputs*/ 0, /*NumInputs*/ 0, nullptr,
    663                                    Constraints, Exprs, AsmString.get(),
    664                                    Clobbers, T.getCloseLocation());
    665   }
    666 
    667   // Parse Outputs, if present.
    668   bool AteExtraColon = false;
    669   if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
    670     // In C++ mode, parse "::" like ": :".
    671     AteExtraColon = Tok.is(tok::coloncolon);
    672     ConsumeToken();
    673 
    674     if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
    675       return StmtError();
    676   }
    677 
    678   unsigned NumOutputs = Names.size();
    679 
    680   // Parse Inputs, if present.
    681   if (AteExtraColon || Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
    682     // In C++ mode, parse "::" like ": :".
    683     if (AteExtraColon)
    684       AteExtraColon = false;
    685     else {
    686       AteExtraColon = Tok.is(tok::coloncolon);
    687       ConsumeToken();
    688     }
    689 
    690     if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
    691       return StmtError();
    692   }
    693 
    694   assert(Names.size() == Constraints.size() &&
    695          Constraints.size() == Exprs.size() && "Input operand size mismatch!");
    696 
    697   unsigned NumInputs = Names.size() - NumOutputs;
    698 
    699   // Parse the clobbers, if present.
    700   if (AteExtraColon || Tok.is(tok::colon)) {
    701     if (!AteExtraColon)
    702       ConsumeToken();
    703 
    704     // Parse the asm-string list for clobbers if present.
    705     if (Tok.isNot(tok::r_paren)) {
    706       while (1) {
    707         ExprResult Clobber(ParseAsmStringLiteral());
    708 
    709         if (Clobber.isInvalid())
    710           break;
    711 
    712         Clobbers.push_back(Clobber.get());
    713 
    714         if (!TryConsumeToken(tok::comma))
    715           break;
    716       }
    717     }
    718   }
    719 
    720   T.consumeClose();
    721   return Actions.ActOnGCCAsmStmt(
    722       AsmLoc, false, isVolatile, NumOutputs, NumInputs, Names.data(),
    723       Constraints, Exprs, AsmString.get(), Clobbers, T.getCloseLocation());
    724 }
    725 
    726 /// ParseAsmOperands - Parse the asm-operands production as used by
    727 /// asm-statement, assuming the leading ':' token was eaten.
    728 ///
    729 /// [GNU] asm-operands:
    730 ///         asm-operand
    731 ///         asm-operands ',' asm-operand
    732 ///
    733 /// [GNU] asm-operand:
    734 ///         asm-string-literal '(' expression ')'
    735 ///         '[' identifier ']' asm-string-literal '(' expression ')'
    736 ///
    737 //
    738 // FIXME: Avoid unnecessary std::string trashing.
    739 bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
    740                                  SmallVectorImpl<Expr *> &Constraints,
    741                                  SmallVectorImpl<Expr *> &Exprs) {
    742   // 'asm-operands' isn't present?
    743   if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
    744     return false;
    745 
    746   while (1) {
    747     // Read the [id] if present.
    748     if (Tok.is(tok::l_square)) {
    749       BalancedDelimiterTracker T(*this, tok::l_square);
    750       T.consumeOpen();
    751 
    752       if (Tok.isNot(tok::identifier)) {
    753         Diag(Tok, diag::err_expected) << tok::identifier;
    754         SkipUntil(tok::r_paren, StopAtSemi);
    755         return true;
    756       }
    757 
    758       IdentifierInfo *II = Tok.getIdentifierInfo();
    759       ConsumeToken();
    760 
    761       Names.push_back(II);
    762       T.consumeClose();
    763     } else
    764       Names.push_back(nullptr);
    765 
    766     ExprResult Constraint(ParseAsmStringLiteral());
    767     if (Constraint.isInvalid()) {
    768       SkipUntil(tok::r_paren, StopAtSemi);
    769       return true;
    770     }
    771     Constraints.push_back(Constraint.get());
    772 
    773     if (Tok.isNot(tok::l_paren)) {
    774       Diag(Tok, diag::err_expected_lparen_after) << "asm operand";
    775       SkipUntil(tok::r_paren, StopAtSemi);
    776       return true;
    777     }
    778 
    779     // Read the parenthesized expression.
    780     BalancedDelimiterTracker T(*this, tok::l_paren);
    781     T.consumeOpen();
    782     ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression());
    783     T.consumeClose();
    784     if (Res.isInvalid()) {
    785       SkipUntil(tok::r_paren, StopAtSemi);
    786       return true;
    787     }
    788     Exprs.push_back(Res.get());
    789     // Eat the comma and continue parsing if it exists.
    790     if (!TryConsumeToken(tok::comma))
    791       return false;
    792   }
    793 }
    794