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 = true;
    219   ExprResult Result;
    220   if (Tok.is(tok::kw_this)) {
    221     Result = ParseCXXThis();
    222     Invalid = false;
    223   } else {
    224     Invalid =
    225         ParseUnqualifiedId(SS,
    226                            /*EnteringContext=*/false,
    227                            /*AllowDestructorName=*/false,
    228                            /*AllowConstructorName=*/false,
    229                            /*ObjectType=*/ParsedType(), TemplateKWLoc, Id);
    230     // Perform the lookup.
    231     Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info,
    232                                                IsUnevaluatedContext);
    233   }
    234   // While the next two tokens are 'period' 'identifier', repeatedly parse it as
    235   // a field access. We have to avoid consuming assembler directives that look
    236   // like '.' 'else'.
    237   while (Result.isUsable() && Tok.is(tok::period)) {
    238     Token IdTok = PP.LookAhead(0);
    239     if (IdTok.isNot(tok::identifier))
    240       break;
    241     ConsumeToken(); // Consume the period.
    242     IdentifierInfo *Id = Tok.getIdentifierInfo();
    243     ConsumeToken(); // Consume the identifier.
    244     unsigned OffsetUnused;
    245     Result = Actions.LookupInlineAsmVarDeclField(
    246         Result.get(), Id->getName(), OffsetUnused, Info, Tok.getLocation());
    247   }
    248 
    249   // Figure out how many tokens we are into LineToks.
    250   unsigned LineIndex = 0;
    251   if (Tok.is(EndOfStream)) {
    252     LineIndex = LineToks.size() - 2;
    253   } else {
    254     while (LineToks[LineIndex].getLocation() != Tok.getLocation()) {
    255       LineIndex++;
    256       assert(LineIndex < LineToks.size() - 2); // we added two extra tokens
    257     }
    258   }
    259 
    260   // If we've run into the poison token we inserted before, or there
    261   // was a parsing error, then claim the entire line.
    262   if (Invalid || Tok.is(EndOfStream)) {
    263     NumLineToksConsumed = LineToks.size() - 2;
    264   } else {
    265     // Otherwise, claim up to the start of the next token.
    266     NumLineToksConsumed = LineIndex;
    267   }
    268 
    269   // Finally, restore the old parsing state by consuming all the tokens we
    270   // staged before, implicitly killing off the token-lexer we pushed.
    271   for (unsigned i = 0, e = LineToks.size() - LineIndex - 2; i != e; ++i) {
    272     ConsumeAnyToken();
    273   }
    274   assert(Tok.is(EndOfStream));
    275   ConsumeToken();
    276 
    277   // Leave LineToks in its original state.
    278   LineToks.pop_back();
    279   LineToks.pop_back();
    280 
    281   return Result;
    282 }
    283 
    284 /// Turn a sequence of our tokens back into a string that we can hand
    285 /// to the MC asm parser.
    286 static bool buildMSAsmString(Preprocessor &PP, SourceLocation AsmLoc,
    287                              ArrayRef<Token> AsmToks,
    288                              SmallVectorImpl<unsigned> &TokOffsets,
    289                              SmallString<512> &Asm) {
    290   assert(!AsmToks.empty() && "Didn't expect an empty AsmToks!");
    291 
    292   // Is this the start of a new assembly statement?
    293   bool isNewStatement = true;
    294 
    295   for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
    296     const Token &Tok = AsmToks[i];
    297 
    298     // Start each new statement with a newline and a tab.
    299     if (!isNewStatement && (Tok.is(tok::kw_asm) || Tok.isAtStartOfLine())) {
    300       Asm += "\n\t";
    301       isNewStatement = true;
    302     }
    303 
    304     // Preserve the existence of leading whitespace except at the
    305     // start of a statement.
    306     if (!isNewStatement && Tok.hasLeadingSpace())
    307       Asm += ' ';
    308 
    309     // Remember the offset of this token.
    310     TokOffsets.push_back(Asm.size());
    311 
    312     // Don't actually write '__asm' into the assembly stream.
    313     if (Tok.is(tok::kw_asm)) {
    314       // Complain about __asm at the end of the stream.
    315       if (i + 1 == e) {
    316         PP.Diag(AsmLoc, diag::err_asm_empty);
    317         return true;
    318       }
    319 
    320       continue;
    321     }
    322 
    323     // Append the spelling of the token.
    324     SmallString<32> SpellingBuffer;
    325     bool SpellingInvalid = false;
    326     Asm += PP.getSpelling(Tok, SpellingBuffer, &SpellingInvalid);
    327     assert(!SpellingInvalid && "spelling was invalid after correct parse?");
    328 
    329     // We are no longer at the start of a statement.
    330     isNewStatement = false;
    331   }
    332 
    333   // Ensure that the buffer is null-terminated.
    334   Asm.push_back('\0');
    335   Asm.pop_back();
    336 
    337   assert(TokOffsets.size() == AsmToks.size());
    338   return false;
    339 }
    340 
    341 /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled,
    342 /// this routine is called to collect the tokens for an MS asm statement.
    343 ///
    344 /// [MS]  ms-asm-statement:
    345 ///         ms-asm-block
    346 ///         ms-asm-block ms-asm-statement
    347 ///
    348 /// [MS]  ms-asm-block:
    349 ///         '__asm' ms-asm-line '\n'
    350 ///         '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt]
    351 ///
    352 /// [MS]  ms-asm-instruction-block
    353 ///         ms-asm-line
    354 ///         ms-asm-line '\n' ms-asm-instruction-block
    355 ///
    356 StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
    357   SourceManager &SrcMgr = PP.getSourceManager();
    358   SourceLocation EndLoc = AsmLoc;
    359   SmallVector<Token, 4> AsmToks;
    360 
    361   bool SingleLineMode = true;
    362   unsigned BraceNesting = 0;
    363   unsigned short savedBraceCount = BraceCount;
    364   bool InAsmComment = false;
    365   FileID FID;
    366   unsigned LineNo = 0;
    367   unsigned NumTokensRead = 0;
    368   SmallVector<SourceLocation, 4> LBraceLocs;
    369   bool SkippedStartOfLine = false;
    370 
    371   if (Tok.is(tok::l_brace)) {
    372     // Braced inline asm: consume the opening brace.
    373     SingleLineMode = false;
    374     BraceNesting = 1;
    375     EndLoc = ConsumeBrace();
    376     LBraceLocs.push_back(EndLoc);
    377     ++NumTokensRead;
    378   } else {
    379     // Single-line inline asm; compute which line it is on.
    380     std::pair<FileID, unsigned> ExpAsmLoc =
    381         SrcMgr.getDecomposedExpansionLoc(EndLoc);
    382     FID = ExpAsmLoc.first;
    383     LineNo = SrcMgr.getLineNumber(FID, ExpAsmLoc.second);
    384     LBraceLocs.push_back(SourceLocation());
    385   }
    386 
    387   SourceLocation TokLoc = Tok.getLocation();
    388   do {
    389     // If we hit EOF, we're done, period.
    390     if (isEofOrEom())
    391       break;
    392 
    393     if (!InAsmComment && Tok.is(tok::l_brace)) {
    394       // Consume the opening brace.
    395       SkippedStartOfLine = Tok.isAtStartOfLine();
    396       EndLoc = ConsumeBrace();
    397       BraceNesting++;
    398       LBraceLocs.push_back(EndLoc);
    399       TokLoc = Tok.getLocation();
    400       ++NumTokensRead;
    401       continue;
    402     } else if (!InAsmComment && Tok.is(tok::semi)) {
    403       // A semicolon in an asm is the start of a comment.
    404       InAsmComment = true;
    405       if (!SingleLineMode) {
    406         // Compute which line the comment is on.
    407         std::pair<FileID, unsigned> ExpSemiLoc =
    408             SrcMgr.getDecomposedExpansionLoc(TokLoc);
    409         FID = ExpSemiLoc.first;
    410         LineNo = SrcMgr.getLineNumber(FID, ExpSemiLoc.second);
    411       }
    412     } else if (SingleLineMode || InAsmComment) {
    413       // If end-of-line is significant, check whether this token is on a
    414       // new line.
    415       std::pair<FileID, unsigned> ExpLoc =
    416           SrcMgr.getDecomposedExpansionLoc(TokLoc);
    417       if (ExpLoc.first != FID ||
    418           SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) {
    419         // If this is a single-line __asm, we're done, except if the next
    420         // line begins with an __asm too, in which case we finish a comment
    421         // if needed and then keep processing the next line as a single
    422         // line __asm.
    423         bool isAsm = Tok.is(tok::kw_asm);
    424         if (SingleLineMode && !isAsm)
    425           break;
    426         // We're no longer in a comment.
    427         InAsmComment = false;
    428         if (isAsm) {
    429           LineNo = SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second);
    430           SkippedStartOfLine = Tok.isAtStartOfLine();
    431         }
    432       } else if (!InAsmComment && Tok.is(tok::r_brace)) {
    433         // In MSVC mode, braces only participate in brace matching and
    434         // separating the asm statements.  This is an intentional
    435         // departure from the Apple gcc behavior.
    436         if (!BraceNesting)
    437           break;
    438       }
    439     }
    440     if (!InAsmComment && BraceNesting && Tok.is(tok::r_brace) &&
    441         BraceCount == (savedBraceCount + BraceNesting)) {
    442       // Consume the closing brace.
    443       SkippedStartOfLine = Tok.isAtStartOfLine();
    444       EndLoc = ConsumeBrace();
    445       BraceNesting--;
    446       // Finish if all of the opened braces in the inline asm section were
    447       // consumed.
    448       if (BraceNesting == 0 && !SingleLineMode)
    449         break;
    450       else {
    451         LBraceLocs.pop_back();
    452         TokLoc = Tok.getLocation();
    453         ++NumTokensRead;
    454         continue;
    455       }
    456     }
    457 
    458     // Consume the next token; make sure we don't modify the brace count etc.
    459     // if we are in a comment.
    460     EndLoc = TokLoc;
    461     if (InAsmComment)
    462       PP.Lex(Tok);
    463     else {
    464       // Set the token as the start of line if we skipped the original start
    465       // of line token in case it was a nested brace.
    466       if (SkippedStartOfLine)
    467         Tok.setFlag(Token::StartOfLine);
    468       AsmToks.push_back(Tok);
    469       ConsumeAnyToken();
    470     }
    471     TokLoc = Tok.getLocation();
    472     ++NumTokensRead;
    473     SkippedStartOfLine = false;
    474   } while (1);
    475 
    476   if (BraceNesting && BraceCount != savedBraceCount) {
    477     // __asm without closing brace (this can happen at EOF).
    478     for (unsigned i = 0; i < BraceNesting; ++i) {
    479       Diag(Tok, diag::err_expected) << tok::r_brace;
    480       Diag(LBraceLocs.back(), diag::note_matching) << tok::l_brace;
    481       LBraceLocs.pop_back();
    482     }
    483     return StmtError();
    484   } else if (NumTokensRead == 0) {
    485     // Empty __asm.
    486     Diag(Tok, diag::err_expected) << tok::l_brace;
    487     return StmtError();
    488   }
    489 
    490   // Okay, prepare to use MC to parse the assembly.
    491   SmallVector<StringRef, 4> ConstraintRefs;
    492   SmallVector<Expr *, 4> Exprs;
    493   SmallVector<StringRef, 4> ClobberRefs;
    494 
    495   // We need an actual supported target.
    496   const llvm::Triple &TheTriple = Actions.Context.getTargetInfo().getTriple();
    497   llvm::Triple::ArchType ArchTy = TheTriple.getArch();
    498   const std::string &TT = TheTriple.getTriple();
    499   const llvm::Target *TheTarget = nullptr;
    500   bool UnsupportedArch =
    501       (ArchTy != llvm::Triple::x86 && ArchTy != llvm::Triple::x86_64);
    502   if (UnsupportedArch) {
    503     Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName();
    504   } else {
    505     std::string Error;
    506     TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error);
    507     if (!TheTarget)
    508       Diag(AsmLoc, diag::err_msasm_unable_to_create_target) << Error;
    509   }
    510 
    511   assert(!LBraceLocs.empty() && "Should have at least one location here");
    512 
    513   // If we don't support assembly, or the assembly is empty, we don't
    514   // need to instantiate the AsmParser, etc.
    515   if (!TheTarget || AsmToks.empty()) {
    516     return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, StringRef(),
    517                                   /*NumOutputs*/ 0, /*NumInputs*/ 0,
    518                                   ConstraintRefs, ClobberRefs, Exprs, EndLoc);
    519   }
    520 
    521   // Expand the tokens into a string buffer.
    522   SmallString<512> AsmString;
    523   SmallVector<unsigned, 8> TokOffsets;
    524   if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString))
    525     return StmtError();
    526 
    527   std::unique_ptr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
    528   std::unique_ptr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT));
    529   // Get the instruction descriptor.
    530   std::unique_ptr<llvm::MCInstrInfo> MII(TheTarget->createMCInstrInfo());
    531   std::unique_ptr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
    532   std::unique_ptr<llvm::MCSubtargetInfo> STI(
    533       TheTarget->createMCSubtargetInfo(TT, "", ""));
    534 
    535   llvm::SourceMgr TempSrcMgr;
    536   llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr);
    537   MOFI->InitMCObjectFileInfo(TheTriple, llvm::Reloc::Default,
    538                              llvm::CodeModel::Default, Ctx);
    539   std::unique_ptr<llvm::MemoryBuffer> Buffer =
    540       llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>");
    541 
    542   // Tell SrcMgr about this buffer, which is what the parser will pick up.
    543   TempSrcMgr.AddNewSourceBuffer(std::move(Buffer), llvm::SMLoc());
    544 
    545   std::unique_ptr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
    546   std::unique_ptr<llvm::MCAsmParser> Parser(
    547       createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI));
    548 
    549   // FIXME: init MCOptions from sanitizer flags here.
    550   llvm::MCTargetOptions MCOptions;
    551   std::unique_ptr<llvm::MCTargetAsmParser> TargetParser(
    552       TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions));
    553 
    554   std::unique_ptr<llvm::MCInstPrinter> IP(
    555       TheTarget->createMCInstPrinter(llvm::Triple(TT), 1, *MAI, *MII, *MRI));
    556 
    557   // Change to the Intel dialect.
    558   Parser->setAssemblerDialect(1);
    559   Parser->setTargetParser(*TargetParser.get());
    560   Parser->setParsingInlineAsm(true);
    561   TargetParser->setParsingInlineAsm(true);
    562 
    563   ClangAsmParserCallback Callback(*this, AsmLoc, AsmString, AsmToks,
    564                                   TokOffsets);
    565   TargetParser->setSemaCallback(&Callback);
    566   TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback,
    567                             &Callback);
    568 
    569   unsigned NumOutputs;
    570   unsigned NumInputs;
    571   std::string AsmStringIR;
    572   SmallVector<std::pair<void *, bool>, 4> OpExprs;
    573   SmallVector<std::string, 4> Constraints;
    574   SmallVector<std::string, 4> Clobbers;
    575   if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, NumOutputs,
    576                                NumInputs, OpExprs, Constraints, Clobbers,
    577                                MII.get(), IP.get(), Callback))
    578     return StmtError();
    579 
    580   // Filter out "fpsw".  Clang doesn't accept it, and it always lists flags and
    581   // fpsr as clobbers.
    582   auto End = std::remove(Clobbers.begin(), Clobbers.end(), "fpsw");
    583   Clobbers.erase(End, Clobbers.end());
    584 
    585   // Build the vector of clobber StringRefs.
    586   ClobberRefs.insert(ClobberRefs.end(), Clobbers.begin(), Clobbers.end());
    587 
    588   // Recast the void pointers and build the vector of constraint StringRefs.
    589   unsigned NumExprs = NumOutputs + NumInputs;
    590   ConstraintRefs.resize(NumExprs);
    591   Exprs.resize(NumExprs);
    592   for (unsigned i = 0, e = NumExprs; i != e; ++i) {
    593     Expr *OpExpr = static_cast<Expr *>(OpExprs[i].first);
    594     if (!OpExpr)
    595       return StmtError();
    596 
    597     // Need address of variable.
    598     if (OpExprs[i].second)
    599       OpExpr =
    600           Actions.BuildUnaryOp(getCurScope(), AsmLoc, UO_AddrOf, OpExpr).get();
    601 
    602     ConstraintRefs[i] = StringRef(Constraints[i]);
    603     Exprs[i] = OpExpr;
    604   }
    605 
    606   // FIXME: We should be passing source locations for better diagnostics.
    607   return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmStringIR,
    608                                 NumOutputs, NumInputs, ConstraintRefs,
    609                                 ClobberRefs, Exprs, EndLoc);
    610 }
    611 
    612 /// ParseAsmStatement - Parse a GNU extended asm statement.
    613 ///       asm-statement:
    614 ///         gnu-asm-statement
    615 ///         ms-asm-statement
    616 ///
    617 /// [GNU] gnu-asm-statement:
    618 ///         'asm' type-qualifier[opt] '(' asm-argument ')' ';'
    619 ///
    620 /// [GNU] asm-argument:
    621 ///         asm-string-literal
    622 ///         asm-string-literal ':' asm-operands[opt]
    623 ///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
    624 ///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
    625 ///                 ':' asm-clobbers
    626 ///
    627 /// [GNU] asm-clobbers:
    628 ///         asm-string-literal
    629 ///         asm-clobbers ',' asm-string-literal
    630 ///
    631 StmtResult Parser::ParseAsmStatement(bool &msAsm) {
    632   assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
    633   SourceLocation AsmLoc = ConsumeToken();
    634 
    635   if (getLangOpts().AsmBlocks && Tok.isNot(tok::l_paren) &&
    636       !isTypeQualifier()) {
    637     msAsm = true;
    638     return ParseMicrosoftAsmStatement(AsmLoc);
    639   }
    640 
    641   DeclSpec DS(AttrFactory);
    642   SourceLocation Loc = Tok.getLocation();
    643   ParseTypeQualifierListOpt(DS, AR_VendorAttributesParsed);
    644 
    645   // GNU asms accept, but warn, about type-qualifiers other than volatile.
    646   if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
    647     Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
    648   if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
    649     Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
    650   // FIXME: Once GCC supports _Atomic, check whether it permits it here.
    651   if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
    652     Diag(Loc, diag::w_asm_qualifier_ignored) << "_Atomic";
    653 
    654   // Remember if this was a volatile asm.
    655   bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
    656   if (Tok.isNot(tok::l_paren)) {
    657     Diag(Tok, diag::err_expected_lparen_after) << "asm";
    658     SkipUntil(tok::r_paren, StopAtSemi);
    659     return StmtError();
    660   }
    661   BalancedDelimiterTracker T(*this, tok::l_paren);
    662   T.consumeOpen();
    663 
    664   ExprResult AsmString(ParseAsmStringLiteral());
    665 
    666   // Check if GNU-style InlineAsm is disabled.
    667   // Error on anything other than empty string.
    668   if (!(getLangOpts().GNUAsm || AsmString.isInvalid())) {
    669     const auto *SL = cast<StringLiteral>(AsmString.get());
    670     if (!SL->getString().trim().empty())
    671       Diag(Loc, diag::err_gnu_inline_asm_disabled);
    672   }
    673 
    674   if (AsmString.isInvalid()) {
    675     // Consume up to and including the closing paren.
    676     T.skipToEnd();
    677     return StmtError();
    678   }
    679 
    680   SmallVector<IdentifierInfo *, 4> Names;
    681   ExprVector Constraints;
    682   ExprVector Exprs;
    683   ExprVector Clobbers;
    684 
    685   if (Tok.is(tok::r_paren)) {
    686     // We have a simple asm expression like 'asm("foo")'.
    687     T.consumeClose();
    688     return Actions.ActOnGCCAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
    689                                    /*NumOutputs*/ 0, /*NumInputs*/ 0, nullptr,
    690                                    Constraints, Exprs, AsmString.get(),
    691                                    Clobbers, T.getCloseLocation());
    692   }
    693 
    694   // Parse Outputs, if present.
    695   bool AteExtraColon = false;
    696   if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
    697     // In C++ mode, parse "::" like ": :".
    698     AteExtraColon = Tok.is(tok::coloncolon);
    699     ConsumeToken();
    700 
    701     if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
    702       return StmtError();
    703   }
    704 
    705   unsigned NumOutputs = Names.size();
    706 
    707   // Parse Inputs, if present.
    708   if (AteExtraColon || Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
    709     // In C++ mode, parse "::" like ": :".
    710     if (AteExtraColon)
    711       AteExtraColon = false;
    712     else {
    713       AteExtraColon = Tok.is(tok::coloncolon);
    714       ConsumeToken();
    715     }
    716 
    717     if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
    718       return StmtError();
    719   }
    720 
    721   assert(Names.size() == Constraints.size() &&
    722          Constraints.size() == Exprs.size() && "Input operand size mismatch!");
    723 
    724   unsigned NumInputs = Names.size() - NumOutputs;
    725 
    726   // Parse the clobbers, if present.
    727   if (AteExtraColon || Tok.is(tok::colon)) {
    728     if (!AteExtraColon)
    729       ConsumeToken();
    730 
    731     // Parse the asm-string list for clobbers if present.
    732     if (Tok.isNot(tok::r_paren)) {
    733       while (1) {
    734         ExprResult Clobber(ParseAsmStringLiteral());
    735 
    736         if (Clobber.isInvalid())
    737           break;
    738 
    739         Clobbers.push_back(Clobber.get());
    740 
    741         if (!TryConsumeToken(tok::comma))
    742           break;
    743       }
    744     }
    745   }
    746 
    747   T.consumeClose();
    748   return Actions.ActOnGCCAsmStmt(
    749       AsmLoc, false, isVolatile, NumOutputs, NumInputs, Names.data(),
    750       Constraints, Exprs, AsmString.get(), Clobbers, T.getCloseLocation());
    751 }
    752 
    753 /// ParseAsmOperands - Parse the asm-operands production as used by
    754 /// asm-statement, assuming the leading ':' token was eaten.
    755 ///
    756 /// [GNU] asm-operands:
    757 ///         asm-operand
    758 ///         asm-operands ',' asm-operand
    759 ///
    760 /// [GNU] asm-operand:
    761 ///         asm-string-literal '(' expression ')'
    762 ///         '[' identifier ']' asm-string-literal '(' expression ')'
    763 ///
    764 //
    765 // FIXME: Avoid unnecessary std::string trashing.
    766 bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
    767                                  SmallVectorImpl<Expr *> &Constraints,
    768                                  SmallVectorImpl<Expr *> &Exprs) {
    769   // 'asm-operands' isn't present?
    770   if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
    771     return false;
    772 
    773   while (1) {
    774     // Read the [id] if present.
    775     if (Tok.is(tok::l_square)) {
    776       BalancedDelimiterTracker T(*this, tok::l_square);
    777       T.consumeOpen();
    778 
    779       if (Tok.isNot(tok::identifier)) {
    780         Diag(Tok, diag::err_expected) << tok::identifier;
    781         SkipUntil(tok::r_paren, StopAtSemi);
    782         return true;
    783       }
    784 
    785       IdentifierInfo *II = Tok.getIdentifierInfo();
    786       ConsumeToken();
    787 
    788       Names.push_back(II);
    789       T.consumeClose();
    790     } else
    791       Names.push_back(nullptr);
    792 
    793     ExprResult Constraint(ParseAsmStringLiteral());
    794     if (Constraint.isInvalid()) {
    795       SkipUntil(tok::r_paren, StopAtSemi);
    796       return true;
    797     }
    798     Constraints.push_back(Constraint.get());
    799 
    800     if (Tok.isNot(tok::l_paren)) {
    801       Diag(Tok, diag::err_expected_lparen_after) << "asm operand";
    802       SkipUntil(tok::r_paren, StopAtSemi);
    803       return true;
    804     }
    805 
    806     // Read the parenthesized expression.
    807     BalancedDelimiterTracker T(*this, tok::l_paren);
    808     T.consumeOpen();
    809     ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression());
    810     T.consumeClose();
    811     if (Res.isInvalid()) {
    812       SkipUntil(tok::r_paren, StopAtSemi);
    813       return true;
    814     }
    815     Exprs.push_back(Res.get());
    816     // Eat the comma and continue parsing if it exists.
    817     if (!TryConsumeToken(tok::comma))
    818       return false;
    819   }
    820 }
    821