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