clang API Documentation
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 }