clang API Documentation

ParseStmtAsm.cpp
Go to the documentation of this file.
00001 //===---- ParseStmtAsm.cpp - Assembly Statement Parser --------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements parsing for GCC and Microsoft inline assembly. 
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "clang/Parse/Parser.h"
00015 #include "RAIIObjectsForParser.h"
00016 #include "clang/AST/ASTContext.h"
00017 #include "clang/Basic/Diagnostic.h"
00018 #include "clang/Basic/TargetInfo.h"
00019 #include "llvm/ADT/SmallString.h"
00020 #include "llvm/MC/MCAsmInfo.h"
00021 #include "llvm/MC/MCContext.h"
00022 #include "llvm/MC/MCInstPrinter.h"
00023 #include "llvm/MC/MCInstrInfo.h"
00024 #include "llvm/MC/MCObjectFileInfo.h"
00025 #include "llvm/MC/MCParser/MCAsmParser.h"
00026 #include "llvm/MC/MCRegisterInfo.h"
00027 #include "llvm/MC/MCStreamer.h"
00028 #include "llvm/MC/MCSubtargetInfo.h"
00029 #include "llvm/MC/MCTargetAsmParser.h"
00030 #include "llvm/MC/MCTargetOptions.h"
00031 #include "llvm/Support/SourceMgr.h"
00032 #include "llvm/Support/TargetRegistry.h"
00033 #include "llvm/Support/TargetSelect.h"
00034 using namespace clang;
00035 
00036 namespace {
00037 class ClangAsmParserCallback : public llvm::MCAsmParserSemaCallback {
00038   Parser &TheParser;
00039   SourceLocation AsmLoc;
00040   StringRef AsmString;
00041 
00042   /// The tokens we streamed into AsmString and handed off to MC.
00043   ArrayRef<Token> AsmToks;
00044 
00045   /// The offset of each token in AsmToks within AsmString.
00046   ArrayRef<unsigned> AsmTokOffsets;
00047 
00048 public:
00049   ClangAsmParserCallback(Parser &P, SourceLocation Loc, StringRef AsmString,
00050                          ArrayRef<Token> Toks, ArrayRef<unsigned> Offsets)
00051       : TheParser(P), AsmLoc(Loc), AsmString(AsmString), AsmToks(Toks),
00052         AsmTokOffsets(Offsets) {
00053     assert(AsmToks.size() == AsmTokOffsets.size());
00054   }
00055 
00056   void *LookupInlineAsmIdentifier(StringRef &LineBuf,
00057                                   llvm::InlineAsmIdentifierInfo &Info,
00058                                   bool IsUnevaluatedContext) override {
00059     // Collect the desired tokens.
00060     SmallVector<Token, 16> LineToks;
00061     const Token *FirstOrigToken = nullptr;
00062     findTokensForString(LineBuf, LineToks, FirstOrigToken);
00063 
00064     unsigned NumConsumedToks;
00065     ExprResult Result = TheParser.ParseMSAsmIdentifier(
00066         LineToks, NumConsumedToks, &Info, IsUnevaluatedContext);
00067 
00068     // If we consumed the entire line, tell MC that.
00069     // Also do this if we consumed nothing as a way of reporting failure.
00070     if (NumConsumedToks == 0 || NumConsumedToks == LineToks.size()) {
00071       // By not modifying LineBuf, we're implicitly consuming it all.
00072 
00073       // Otherwise, consume up to the original tokens.
00074     } else {
00075       assert(FirstOrigToken && "not using original tokens?");
00076 
00077       // Since we're using original tokens, apply that offset.
00078       assert(FirstOrigToken[NumConsumedToks].getLocation() ==
00079              LineToks[NumConsumedToks].getLocation());
00080       unsigned FirstIndex = FirstOrigToken - AsmToks.begin();
00081       unsigned LastIndex = FirstIndex + NumConsumedToks - 1;
00082 
00083       // The total length we've consumed is the relative offset
00084       // of the last token we consumed plus its length.
00085       unsigned TotalOffset =
00086           (AsmTokOffsets[LastIndex] + AsmToks[LastIndex].getLength() -
00087            AsmTokOffsets[FirstIndex]);
00088       LineBuf = LineBuf.substr(0, TotalOffset);
00089     }
00090 
00091     // Initialize the "decl" with the lookup result.
00092     Info.OpDecl = static_cast<void *>(Result.get());
00093     return Info.OpDecl;
00094   }
00095 
00096   StringRef LookupInlineAsmLabel(StringRef Identifier, llvm::SourceMgr &LSM,
00097                                  llvm::SMLoc Location,
00098                                  bool Create) override {
00099     SourceLocation Loc = translateLocation(LSM, Location);
00100     LabelDecl *Label =
00101       TheParser.getActions().GetOrCreateMSAsmLabel(Identifier, Loc, Create);
00102     return Label->getMSAsmLabel();
00103   }
00104 
00105   bool LookupInlineAsmField(StringRef Base, StringRef Member,
00106                             unsigned &Offset) override {
00107     return TheParser.getActions().LookupInlineAsmField(Base, Member, Offset,
00108                                                        AsmLoc);
00109   }
00110 
00111   static void DiagHandlerCallback(const llvm::SMDiagnostic &D, void *Context) {
00112     ((ClangAsmParserCallback *)Context)->handleDiagnostic(D);
00113   }
00114 
00115 private:
00116   /// Collect the appropriate tokens for the given string.
00117   void findTokensForString(StringRef Str, SmallVectorImpl<Token> &TempToks,
00118                            const Token *&FirstOrigToken) const {
00119     // For now, assert that the string we're working with is a substring
00120     // of what we gave to MC.  This lets us use the original tokens.
00121     assert(!std::less<const char *>()(Str.begin(), AsmString.begin()) &&
00122            !std::less<const char *>()(AsmString.end(), Str.end()));
00123 
00124     // Try to find a token whose offset matches the first token.
00125     unsigned FirstCharOffset = Str.begin() - AsmString.begin();
00126     const unsigned *FirstTokOffset = std::lower_bound(
00127         AsmTokOffsets.begin(), AsmTokOffsets.end(), FirstCharOffset);
00128 
00129     // For now, assert that the start of the string exactly
00130     // corresponds to the start of a token.
00131     assert(*FirstTokOffset == FirstCharOffset);
00132 
00133     // Use all the original tokens for this line.  (We assume the
00134     // end of the line corresponds cleanly to a token break.)
00135     unsigned FirstTokIndex = FirstTokOffset - AsmTokOffsets.begin();
00136     FirstOrigToken = &AsmToks[FirstTokIndex];
00137     unsigned LastCharOffset = Str.end() - AsmString.begin();
00138     for (unsigned i = FirstTokIndex, e = AsmTokOffsets.size(); i != e; ++i) {
00139       if (AsmTokOffsets[i] >= LastCharOffset)
00140         break;
00141       TempToks.push_back(AsmToks[i]);
00142     }
00143   }
00144 
00145   SourceLocation translateLocation(const llvm::SourceMgr &LSM, llvm::SMLoc SMLoc) {
00146     // Compute an offset into the inline asm buffer.
00147     // FIXME: This isn't right if .macro is involved (but hopefully, no
00148     // real-world code does that).
00149     const llvm::MemoryBuffer *LBuf =
00150         LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(SMLoc));
00151     unsigned Offset = SMLoc.getPointer() - LBuf->getBufferStart();
00152 
00153     // Figure out which token that offset points into.
00154     const unsigned *TokOffsetPtr =
00155         std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), Offset);
00156     unsigned TokIndex = TokOffsetPtr - AsmTokOffsets.begin();
00157     unsigned TokOffset = *TokOffsetPtr;
00158 
00159     // If we come up with an answer which seems sane, use it; otherwise,
00160     // just point at the __asm keyword.
00161     // FIXME: Assert the answer is sane once we handle .macro correctly.
00162     SourceLocation Loc = AsmLoc;
00163     if (TokIndex < AsmToks.size()) {
00164       const Token &Tok = AsmToks[TokIndex];
00165       Loc = Tok.getLocation();
00166       Loc = Loc.getLocWithOffset(Offset - TokOffset);
00167     }
00168     return Loc;
00169   }
00170 
00171   void handleDiagnostic(const llvm::SMDiagnostic &D) {
00172     const llvm::SourceMgr &LSM = *D.getSourceMgr();
00173     SourceLocation Loc = translateLocation(LSM, D.getLoc());
00174     TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage();
00175   }
00176 };
00177 }
00178 
00179 /// Parse an identifier in an MS-style inline assembly block.
00180 ///
00181 /// \param CastInfo - a void* so that we don't have to teach Parser.h
00182 ///   about the actual type.
00183 ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
00184                                         unsigned &NumLineToksConsumed,
00185                                         void *CastInfo,
00186                                         bool IsUnevaluatedContext) {
00187   llvm::InlineAsmIdentifierInfo &Info =
00188       *(llvm::InlineAsmIdentifierInfo *)CastInfo;
00189 
00190   // Push a fake token on the end so that we don't overrun the token
00191   // stream.  We use ';' because it expression-parsing should never
00192   // overrun it.
00193   const tok::TokenKind EndOfStream = tok::semi;
00194   Token EndOfStreamTok;
00195   EndOfStreamTok.startToken();
00196   EndOfStreamTok.setKind(EndOfStream);
00197   LineToks.push_back(EndOfStreamTok);
00198 
00199   // Also copy the current token over.
00200   LineToks.push_back(Tok);
00201 
00202   PP.EnterTokenStream(LineToks.begin(), LineToks.size(),
00203                       /*disable macros*/ true,
00204                       /*owns tokens*/ false);
00205 
00206   // Clear the current token and advance to the first token in LineToks.
00207   ConsumeAnyToken();
00208 
00209   // Parse an optional scope-specifier if we're in C++.
00210   CXXScopeSpec SS;
00211   if (getLangOpts().CPlusPlus) {
00212     ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
00213   }
00214 
00215   // Require an identifier here.
00216   SourceLocation TemplateKWLoc;
00217   UnqualifiedId Id;
00218   bool Invalid =
00219       ParseUnqualifiedId(SS,
00220                          /*EnteringContext=*/false,
00221                          /*AllowDestructorName=*/false,
00222                          /*AllowConstructorName=*/false,
00223                          /*ObjectType=*/ParsedType(), TemplateKWLoc, Id);
00224 
00225   // Figure out how many tokens we are into LineToks.
00226   unsigned LineIndex = 0;
00227   if (Tok.is(EndOfStream)) {
00228     LineIndex = LineToks.size() - 2;
00229   } else {
00230     while (LineToks[LineIndex].getLocation() != Tok.getLocation()) {
00231       LineIndex++;
00232       assert(LineIndex < LineToks.size() - 2); // we added two extra tokens
00233     }
00234   }
00235 
00236   // If we've run into the poison token we inserted before, or there
00237   // was a parsing error, then claim the entire line.
00238   if (Invalid || Tok.is(EndOfStream)) {
00239     NumLineToksConsumed = LineToks.size() - 2;
00240   } else {
00241     // Otherwise, claim up to the start of the next token.
00242     NumLineToksConsumed = LineIndex;
00243   }
00244 
00245   // Finally, restore the old parsing state by consuming all the tokens we
00246   // staged before, implicitly killing off the token-lexer we pushed.
00247   for (unsigned i = 0, e = LineToks.size() - LineIndex - 2; i != e; ++i) {
00248     ConsumeAnyToken();
00249   }
00250   assert(Tok.is(EndOfStream));
00251   ConsumeToken();
00252 
00253   // Leave LineToks in its original state.
00254   LineToks.pop_back();
00255   LineToks.pop_back();
00256 
00257   // Perform the lookup.
00258   return Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info,
00259                                            IsUnevaluatedContext);
00260 }
00261 
00262 /// Turn a sequence of our tokens back into a string that we can hand
00263 /// to the MC asm parser.
00264 static bool buildMSAsmString(Preprocessor &PP, SourceLocation AsmLoc,
00265                              ArrayRef<Token> AsmToks,
00266                              SmallVectorImpl<unsigned> &TokOffsets,
00267                              SmallString<512> &Asm) {
00268   assert(!AsmToks.empty() && "Didn't expect an empty AsmToks!");
00269 
00270   // Is this the start of a new assembly statement?
00271   bool isNewStatement = true;
00272 
00273   for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
00274     const Token &Tok = AsmToks[i];
00275 
00276     // Start each new statement with a newline and a tab.
00277     if (!isNewStatement && (Tok.is(tok::kw_asm) || Tok.isAtStartOfLine())) {
00278       Asm += "\n\t";
00279       isNewStatement = true;
00280     }
00281 
00282     // Preserve the existence of leading whitespace except at the
00283     // start of a statement.
00284     if (!isNewStatement && Tok.hasLeadingSpace())
00285       Asm += ' ';
00286 
00287     // Remember the offset of this token.
00288     TokOffsets.push_back(Asm.size());
00289 
00290     // Don't actually write '__asm' into the assembly stream.
00291     if (Tok.is(tok::kw_asm)) {
00292       // Complain about __asm at the end of the stream.
00293       if (i + 1 == e) {
00294         PP.Diag(AsmLoc, diag::err_asm_empty);
00295         return true;
00296       }
00297 
00298       continue;
00299     }
00300 
00301     // Append the spelling of the token.
00302     SmallString<32> SpellingBuffer;
00303     bool SpellingInvalid = false;
00304     Asm += PP.getSpelling(Tok, SpellingBuffer, &SpellingInvalid);
00305     assert(!SpellingInvalid && "spelling was invalid after correct parse?");
00306 
00307     // We are no longer at the start of a statement.
00308     isNewStatement = false;
00309   }
00310 
00311   // Ensure that the buffer is null-terminated.
00312   Asm.push_back('\0');
00313   Asm.pop_back();
00314 
00315   assert(TokOffsets.size() == AsmToks.size());
00316   return false;
00317 }
00318 
00319 /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled,
00320 /// this routine is called to collect the tokens for an MS asm statement.
00321 ///
00322 /// [MS]  ms-asm-statement:
00323 ///         ms-asm-block
00324 ///         ms-asm-block ms-asm-statement
00325 ///
00326 /// [MS]  ms-asm-block:
00327 ///         '__asm' ms-asm-line '\n'
00328 ///         '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt]
00329 ///
00330 /// [MS]  ms-asm-instruction-block
00331 ///         ms-asm-line
00332 ///         ms-asm-line '\n' ms-asm-instruction-block
00333 ///
00334 StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
00335   SourceManager &SrcMgr = PP.getSourceManager();
00336   SourceLocation EndLoc = AsmLoc;
00337   SmallVector<Token, 4> AsmToks;
00338 
00339   bool SingleLineMode = true;
00340   unsigned BraceNesting = 0;
00341   unsigned short savedBraceCount = BraceCount;
00342   bool InAsmComment = false;
00343   FileID FID;
00344   unsigned LineNo = 0;
00345   unsigned NumTokensRead = 0;
00346   SmallVector<SourceLocation, 4> LBraceLocs;
00347   bool SkippedStartOfLine = false;
00348 
00349   if (Tok.is(tok::l_brace)) {
00350     // Braced inline asm: consume the opening brace.
00351     SingleLineMode = false;
00352     BraceNesting = 1;
00353     EndLoc = ConsumeBrace();
00354     LBraceLocs.push_back(EndLoc);
00355     ++NumTokensRead;
00356   } else {
00357     // Single-line inline asm; compute which line it is on.
00358     std::pair<FileID, unsigned> ExpAsmLoc =
00359         SrcMgr.getDecomposedExpansionLoc(EndLoc);
00360     FID = ExpAsmLoc.first;
00361     LineNo = SrcMgr.getLineNumber(FID, ExpAsmLoc.second);
00362     LBraceLocs.push_back(SourceLocation());
00363   }
00364 
00365   SourceLocation TokLoc = Tok.getLocation();
00366   do {
00367     // If we hit EOF, we're done, period.
00368     if (isEofOrEom())
00369       break;
00370 
00371     if (!InAsmComment && Tok.is(tok::l_brace)) {
00372       // Consume the opening brace.
00373       SkippedStartOfLine = Tok.isAtStartOfLine();
00374       EndLoc = ConsumeBrace();
00375       BraceNesting++;
00376       LBraceLocs.push_back(EndLoc);
00377       TokLoc = Tok.getLocation();
00378       ++NumTokensRead;
00379       continue;
00380     } else if (!InAsmComment && Tok.is(tok::semi)) {
00381       // A semicolon in an asm is the start of a comment.
00382       InAsmComment = true;
00383       if (!SingleLineMode) {
00384         // Compute which line the comment is on.
00385         std::pair<FileID, unsigned> ExpSemiLoc =
00386             SrcMgr.getDecomposedExpansionLoc(TokLoc);
00387         FID = ExpSemiLoc.first;
00388         LineNo = SrcMgr.getLineNumber(FID, ExpSemiLoc.second);
00389       }
00390     } else if (SingleLineMode || InAsmComment) {
00391       // If end-of-line is significant, check whether this token is on a
00392       // new line.
00393       std::pair<FileID, unsigned> ExpLoc =
00394           SrcMgr.getDecomposedExpansionLoc(TokLoc);
00395       if (ExpLoc.first != FID ||
00396           SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) {
00397         // If this is a single-line __asm, we're done, except if the next
00398         // line begins with an __asm too, in which case we finish a comment
00399         // if needed and then keep processing the next line as a single
00400         // line __asm.
00401         bool isAsm = Tok.is(tok::kw_asm);
00402         if (SingleLineMode && !isAsm)
00403           break;
00404         // We're no longer in a comment.
00405         InAsmComment = false;
00406         if (isAsm) {
00407           LineNo = SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second);
00408           SkippedStartOfLine = Tok.isAtStartOfLine();
00409         }
00410       } else if (!InAsmComment && Tok.is(tok::r_brace)) {
00411         // In MSVC mode, braces only participate in brace matching and
00412         // separating the asm statements.  This is an intentional
00413         // departure from the Apple gcc behavior.
00414         if (!BraceNesting)
00415           break;
00416       }
00417     }
00418     if (!InAsmComment && BraceNesting && Tok.is(tok::r_brace) &&
00419         BraceCount == (savedBraceCount + BraceNesting)) {
00420       // Consume the closing brace.
00421       SkippedStartOfLine = Tok.isAtStartOfLine();
00422       EndLoc = ConsumeBrace();
00423       BraceNesting--;
00424       // Finish if all of the opened braces in the inline asm section were
00425       // consumed.
00426       if (BraceNesting == 0 && !SingleLineMode)
00427         break;
00428       else {
00429         LBraceLocs.pop_back();
00430         TokLoc = Tok.getLocation();
00431         ++NumTokensRead;
00432         continue;
00433       }
00434     }
00435 
00436     // Consume the next token; make sure we don't modify the brace count etc.
00437     // if we are in a comment.
00438     EndLoc = TokLoc;
00439     if (InAsmComment)
00440       PP.Lex(Tok);
00441     else {
00442       // Set the token as the start of line if we skipped the original start
00443       // of line token in case it was a nested brace.
00444       if (SkippedStartOfLine)
00445         Tok.setFlag(Token::StartOfLine);
00446       AsmToks.push_back(Tok);
00447       ConsumeAnyToken();
00448     }
00449     TokLoc = Tok.getLocation();
00450     ++NumTokensRead;
00451     SkippedStartOfLine = false;
00452   } while (1);
00453 
00454   if (BraceNesting && BraceCount != savedBraceCount) {
00455     // __asm without closing brace (this can happen at EOF).
00456     for (unsigned i = 0; i < BraceNesting; ++i) {
00457       Diag(Tok, diag::err_expected) << tok::r_brace;
00458       Diag(LBraceLocs.back(), diag::note_matching) << tok::l_brace;
00459       LBraceLocs.pop_back();
00460     }
00461     return StmtError();
00462   } else if (NumTokensRead == 0) {
00463     // Empty __asm.
00464     Diag(Tok, diag::err_expected) << tok::l_brace;
00465     return StmtError();
00466   }
00467 
00468   // Okay, prepare to use MC to parse the assembly.
00469   SmallVector<StringRef, 4> ConstraintRefs;
00470   SmallVector<Expr *, 4> Exprs;
00471   SmallVector<StringRef, 4> ClobberRefs;
00472 
00473   // We need an actual supported target.
00474   const llvm::Triple &TheTriple = Actions.Context.getTargetInfo().getTriple();
00475   llvm::Triple::ArchType ArchTy = TheTriple.getArch();
00476   const std::string &TT = TheTriple.getTriple();
00477   const llvm::Target *TheTarget = nullptr;
00478   bool UnsupportedArch =
00479       (ArchTy != llvm::Triple::x86 && ArchTy != llvm::Triple::x86_64);
00480   if (UnsupportedArch) {
00481     Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName();
00482   } else {
00483     std::string Error;
00484     TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error);
00485     if (!TheTarget)
00486       Diag(AsmLoc, diag::err_msasm_unable_to_create_target) << Error;
00487   }
00488 
00489   assert(!LBraceLocs.empty() && "Should have at least one location here");
00490 
00491   // If we don't support assembly, or the assembly is empty, we don't
00492   // need to instantiate the AsmParser, etc.
00493   if (!TheTarget || AsmToks.empty()) {
00494     return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, StringRef(),
00495                                   /*NumOutputs*/ 0, /*NumInputs*/ 0,
00496                                   ConstraintRefs, ClobberRefs, Exprs, EndLoc);
00497   }
00498 
00499   // Expand the tokens into a string buffer.
00500   SmallString<512> AsmString;
00501   SmallVector<unsigned, 8> TokOffsets;
00502   if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString))
00503     return StmtError();
00504 
00505   std::unique_ptr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
00506   std::unique_ptr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT));
00507   // Get the instruction descriptor.
00508   std::unique_ptr<llvm::MCInstrInfo> MII(TheTarget->createMCInstrInfo());
00509   std::unique_ptr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
00510   std::unique_ptr<llvm::MCSubtargetInfo> STI(
00511       TheTarget->createMCSubtargetInfo(TT, "", ""));
00512 
00513   llvm::SourceMgr TempSrcMgr;
00514   llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr);
00515   MOFI->InitMCObjectFileInfo(TT, llvm::Reloc::Default, llvm::CodeModel::Default,
00516                              Ctx);
00517   std::unique_ptr<llvm::MemoryBuffer> Buffer =
00518       llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>");
00519 
00520   // Tell SrcMgr about this buffer, which is what the parser will pick up.
00521   TempSrcMgr.AddNewSourceBuffer(std::move(Buffer), llvm::SMLoc());
00522 
00523   std::unique_ptr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
00524   std::unique_ptr<llvm::MCAsmParser> Parser(
00525       createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI));
00526 
00527   // FIXME: init MCOptions from sanitizer flags here.
00528   llvm::MCTargetOptions MCOptions;
00529   std::unique_ptr<llvm::MCTargetAsmParser> TargetParser(
00530       TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions));
00531 
00532   std::unique_ptr<llvm::MCInstPrinter> IP(
00533       TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI));
00534 
00535   // Change to the Intel dialect.
00536   Parser->setAssemblerDialect(1);
00537   Parser->setTargetParser(*TargetParser.get());
00538   Parser->setParsingInlineAsm(true);
00539   TargetParser->setParsingInlineAsm(true);
00540 
00541   ClangAsmParserCallback Callback(*this, AsmLoc, AsmString, AsmToks,
00542                                   TokOffsets);
00543   TargetParser->setSemaCallback(&Callback);
00544   TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback,
00545                             &Callback);
00546 
00547   unsigned NumOutputs;
00548   unsigned NumInputs;
00549   std::string AsmStringIR;
00550   SmallVector<std::pair<void *, bool>, 4> OpExprs;
00551   SmallVector<std::string, 4> Constraints;
00552   SmallVector<std::string, 4> Clobbers;
00553   if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, NumOutputs,
00554                                NumInputs, OpExprs, Constraints, Clobbers,
00555                                MII.get(), IP.get(), Callback))
00556     return StmtError();
00557 
00558   // Filter out "fpsw".  Clang doesn't accept it, and it always lists flags and
00559   // fpsr as clobbers.
00560   auto End = std::remove(Clobbers.begin(), Clobbers.end(), "fpsw");
00561   Clobbers.erase(End, Clobbers.end());
00562 
00563   // Build the vector of clobber StringRefs.
00564   ClobberRefs.insert(ClobberRefs.end(), Clobbers.begin(), Clobbers.end());
00565 
00566   // Recast the void pointers and build the vector of constraint StringRefs.
00567   unsigned NumExprs = NumOutputs + NumInputs;
00568   ConstraintRefs.resize(NumExprs);
00569   Exprs.resize(NumExprs);
00570   for (unsigned i = 0, e = NumExprs; i != e; ++i) {
00571     Expr *OpExpr = static_cast<Expr *>(OpExprs[i].first);
00572     if (!OpExpr)
00573       return StmtError();
00574 
00575     // Need address of variable.
00576     if (OpExprs[i].second)
00577       OpExpr =
00578           Actions.BuildUnaryOp(getCurScope(), AsmLoc, UO_AddrOf, OpExpr).get();
00579 
00580     ConstraintRefs[i] = StringRef(Constraints[i]);
00581     Exprs[i] = OpExpr;
00582   }
00583 
00584   // FIXME: We should be passing source locations for better diagnostics.
00585   return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmStringIR,
00586                                 NumOutputs, NumInputs, ConstraintRefs,
00587                                 ClobberRefs, Exprs, EndLoc);
00588 }
00589 
00590 /// ParseAsmStatement - Parse a GNU extended asm statement.
00591 ///       asm-statement:
00592 ///         gnu-asm-statement
00593 ///         ms-asm-statement
00594 ///
00595 /// [GNU] gnu-asm-statement:
00596 ///         'asm' type-qualifier[opt] '(' asm-argument ')' ';'
00597 ///
00598 /// [GNU] asm-argument:
00599 ///         asm-string-literal
00600 ///         asm-string-literal ':' asm-operands[opt]
00601 ///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
00602 ///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
00603 ///                 ':' asm-clobbers
00604 ///
00605 /// [GNU] asm-clobbers:
00606 ///         asm-string-literal
00607 ///         asm-clobbers ',' asm-string-literal
00608 ///
00609 StmtResult Parser::ParseAsmStatement(bool &msAsm) {
00610   assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
00611   SourceLocation AsmLoc = ConsumeToken();
00612 
00613   if (getLangOpts().AsmBlocks && Tok.isNot(tok::l_paren) &&
00614       !isTypeQualifier()) {
00615     msAsm = true;
00616     return ParseMicrosoftAsmStatement(AsmLoc);
00617   }
00618   DeclSpec DS(AttrFactory);
00619   SourceLocation Loc = Tok.getLocation();
00620   ParseTypeQualifierListOpt(DS, AR_VendorAttributesParsed);
00621 
00622   // GNU asms accept, but warn, about type-qualifiers other than volatile.
00623   if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
00624     Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
00625   if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
00626     Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
00627   // FIXME: Once GCC supports _Atomic, check whether it permits it here.
00628   if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
00629     Diag(Loc, diag::w_asm_qualifier_ignored) << "_Atomic";
00630 
00631   // Remember if this was a volatile asm.
00632   bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
00633   if (Tok.isNot(tok::l_paren)) {
00634     Diag(Tok, diag::err_expected_lparen_after) << "asm";
00635     SkipUntil(tok::r_paren, StopAtSemi);
00636     return StmtError();
00637   }
00638   BalancedDelimiterTracker T(*this, tok::l_paren);
00639   T.consumeOpen();
00640 
00641   ExprResult AsmString(ParseAsmStringLiteral());
00642   if (AsmString.isInvalid()) {
00643     // Consume up to and including the closing paren.
00644     T.skipToEnd();
00645     return StmtError();
00646   }
00647 
00648   SmallVector<IdentifierInfo *, 4> Names;
00649   ExprVector Constraints;
00650   ExprVector Exprs;
00651   ExprVector Clobbers;
00652 
00653   if (Tok.is(tok::r_paren)) {
00654     // We have a simple asm expression like 'asm("foo")'.
00655     T.consumeClose();
00656     return Actions.ActOnGCCAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
00657                                    /*NumOutputs*/ 0, /*NumInputs*/ 0, nullptr,
00658                                    Constraints, Exprs, AsmString.get(),
00659                                    Clobbers, T.getCloseLocation());
00660   }
00661 
00662   // Parse Outputs, if present.
00663   bool AteExtraColon = false;
00664   if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
00665     // In C++ mode, parse "::" like ": :".
00666     AteExtraColon = Tok.is(tok::coloncolon);
00667     ConsumeToken();
00668 
00669     if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
00670       return StmtError();
00671   }
00672 
00673   unsigned NumOutputs = Names.size();
00674 
00675   // Parse Inputs, if present.
00676   if (AteExtraColon || Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
00677     // In C++ mode, parse "::" like ": :".
00678     if (AteExtraColon)
00679       AteExtraColon = false;
00680     else {
00681       AteExtraColon = Tok.is(tok::coloncolon);
00682       ConsumeToken();
00683     }
00684 
00685     if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
00686       return StmtError();
00687   }
00688 
00689   assert(Names.size() == Constraints.size() &&
00690          Constraints.size() == Exprs.size() && "Input operand size mismatch!");
00691 
00692   unsigned NumInputs = Names.size() - NumOutputs;
00693 
00694   // Parse the clobbers, if present.
00695   if (AteExtraColon || Tok.is(tok::colon)) {
00696     if (!AteExtraColon)
00697       ConsumeToken();
00698 
00699     // Parse the asm-string list for clobbers if present.
00700     if (Tok.isNot(tok::r_paren)) {
00701       while (1) {
00702         ExprResult Clobber(ParseAsmStringLiteral());
00703 
00704         if (Clobber.isInvalid())
00705           break;
00706 
00707         Clobbers.push_back(Clobber.get());
00708 
00709         if (!TryConsumeToken(tok::comma))
00710           break;
00711       }
00712     }
00713   }
00714 
00715   T.consumeClose();
00716   return Actions.ActOnGCCAsmStmt(
00717       AsmLoc, false, isVolatile, NumOutputs, NumInputs, Names.data(),
00718       Constraints, Exprs, AsmString.get(), Clobbers, T.getCloseLocation());
00719 }
00720 
00721 /// ParseAsmOperands - Parse the asm-operands production as used by
00722 /// asm-statement, assuming the leading ':' token was eaten.
00723 ///
00724 /// [GNU] asm-operands:
00725 ///         asm-operand
00726 ///         asm-operands ',' asm-operand
00727 ///
00728 /// [GNU] asm-operand:
00729 ///         asm-string-literal '(' expression ')'
00730 ///         '[' identifier ']' asm-string-literal '(' expression ')'
00731 ///
00732 //
00733 // FIXME: Avoid unnecessary std::string trashing.
00734 bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
00735                                  SmallVectorImpl<Expr *> &Constraints,
00736                                  SmallVectorImpl<Expr *> &Exprs) {
00737   // 'asm-operands' isn't present?
00738   if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
00739     return false;
00740 
00741   while (1) {
00742     // Read the [id] if present.
00743     if (Tok.is(tok::l_square)) {
00744       BalancedDelimiterTracker T(*this, tok::l_square);
00745       T.consumeOpen();
00746 
00747       if (Tok.isNot(tok::identifier)) {
00748         Diag(Tok, diag::err_expected) << tok::identifier;
00749         SkipUntil(tok::r_paren, StopAtSemi);
00750         return true;
00751       }
00752 
00753       IdentifierInfo *II = Tok.getIdentifierInfo();
00754       ConsumeToken();
00755 
00756       Names.push_back(II);
00757       T.consumeClose();
00758     } else
00759       Names.push_back(nullptr);
00760 
00761     ExprResult Constraint(ParseAsmStringLiteral());
00762     if (Constraint.isInvalid()) {
00763       SkipUntil(tok::r_paren, StopAtSemi);
00764       return true;
00765     }
00766     Constraints.push_back(Constraint.get());
00767 
00768     if (Tok.isNot(tok::l_paren)) {
00769       Diag(Tok, diag::err_expected_lparen_after) << "asm operand";
00770       SkipUntil(tok::r_paren, StopAtSemi);
00771       return true;
00772     }
00773 
00774     // Read the parenthesized expression.
00775     BalancedDelimiterTracker T(*this, tok::l_paren);
00776     T.consumeOpen();
00777     ExprResult Res(ParseExpression());
00778     T.consumeClose();
00779     if (Res.isInvalid()) {
00780       SkipUntil(tok::r_paren, StopAtSemi);
00781       return true;
00782     }
00783     Exprs.push_back(Res.get());
00784     // Eat the comma and continue parsing if it exists.
00785     if (!TryConsumeToken(tok::comma))
00786       return false;
00787   }
00788 }