diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/Stmt.cpp | 6 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 5 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 41 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 1 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 85 | ||||
-rw-r--r-- | lib/Sema/AnalysisBasedWarnings.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 18 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 5 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 5 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 12 |
12 files changed, 165 insertions, 33 deletions
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index e4d9f0a1ef..97eb4d579e 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -550,6 +550,12 @@ AsmStmt::AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, std::copy(clobbers, clobbers + NumClobbers, Clobbers); } +MSAsmStmt::MSAsmStmt(ASTContext &C, SourceLocation asmloc, std::string &asmstr, + SourceLocation endloc) + : Stmt(MSAsmStmtClass), AsmLoc(asmloc), EndLoc(endloc), AsmStr(asmstr), + IsSimple(true), IsVolatile(true) { +} + ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body, SourceLocation FCL, SourceLocation RPL) diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 2bd4d769e7..30548aea60 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -429,6 +429,11 @@ void StmtPrinter::VisitAsmStmt(AsmStmt *Node) { OS << ");\n"; } +void StmtPrinter::VisitMSAsmStmt(MSAsmStmt *Node) { + // FIXME: Implement MS style inline asm statement printer. + Indent() << "asm ()"; +} + void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) { Indent() << "@try"; if (CompoundStmt *TS = dyn_cast<CompoundStmt>(Node->getTryBody())) { diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 72b979d4c2..2168b64d5b 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -178,6 +178,11 @@ void StmtProfiler::VisitAsmStmt(const AsmStmt *S) { VisitStringLiteral(S->getClobber(I)); } +void StmtProfiler::VisitMSAsmStmt(const MSAsmStmt *S) { + // FIXME: Implement MS style inline asm statement profiler. + VisitStmt(S); +} + void StmtProfiler::VisitCXXCatchStmt(const CXXCatchStmt *S) { VisitStmt(S); VisitType(S->getCaughtType()); diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 86046b70a5..2f06a8ed28 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -133,6 +133,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break; case Stmt::AsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break; + case Stmt::MSAsmStmtClass: EmitMSAsmStmt(cast<MSAsmStmt>(*S)); break; case Stmt::ObjCAtTryStmtClass: EmitObjCAtTryStmt(cast<ObjCAtTryStmt>(*S)); @@ -1681,3 +1682,43 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { EmitStoreThroughLValue(RValue::get(Tmp), ResultRegDests[i]); } } + +void CodeGenFunction::EmitMSAsmStmt(const MSAsmStmt &S) { + // Analyze the asm string to decompose it into its pieces. We know that Sema + // has already done this, so it is guaranteed to be successful. + + // Get all the output and input constraints together. + + std::vector<llvm::Value*> Args; + std::vector<llvm::Type *> ArgTypes; + std::string Constraints; + + // Keep track of inout constraints. + + // Append the "input" part of inout constraints last. + + // Clobbers + + // Add machine specific clobbers + std::string MachineClobbers = Target.getClobbers(); + if (!MachineClobbers.empty()) { + if (!Constraints.empty()) + Constraints += ','; + Constraints += MachineClobbers; + } + + llvm::Type *ResultType = VoidTy; + + llvm::FunctionType *FTy = + llvm::FunctionType::get(ResultType, ArgTypes, false); + + llvm::InlineAsm *IA = + llvm::InlineAsm::get(FTy, *S.getAsmString(), Constraints, true); + llvm::CallInst *Result = Builder.CreateCall(IA, Args); + Result->addAttribute(~0, llvm::Attribute::NoUnwind); + + // Slap the source location of the inline asm into a !srcloc metadata on the + // call. + + // Extract all of the register value results from the asm. +} diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index de7e89e391..a6d77e31c7 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1970,6 +1970,7 @@ public: void EmitCaseStmt(const CaseStmt &S); void EmitCaseStmtRange(const CaseStmt &S); void EmitAsmStmt(const AsmStmt &S); + void EmitMSAsmStmt(const MSAsmStmt &S); void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S); void EmitObjCAtTryStmt(const ObjCAtTryStmt &S); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 6652beaff4..9f49ab59ce 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -20,6 +20,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Basic/SourceManager.h" +#include "llvm/ADT/SmallString.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -1627,9 +1628,24 @@ StmtResult Parser::ParseReturnStatement() { /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled, /// this routine is called to collect the tokens for an MS asm statement. +/// +/// [MS] ms-asm-statement: +/// ms-asm-block +/// ms-asm-block ms-asm-statement +/// +/// [MS] ms-asm-block: +/// '__asm' ms-asm-line '\n' +/// '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt] +/// +/// [MS] ms-asm-instruction-block +/// ms-asm-line +/// ms-asm-line '\n' ms-asm-instruction-block +/// StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { SourceManager &SrcMgr = PP.getSourceManager(); SourceLocation EndLoc = AsmLoc; + SmallVector<Token, 4> AsmToks; + SmallVector<unsigned, 4> LineEnds; do { bool InBraces = false; unsigned short savedBraceCount = 0; @@ -1658,9 +1674,6 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { // If we hit EOF, we're done, period. if (Tok.is(tok::eof)) break; - // When we consume the closing brace, we're done. - if (InBraces && BraceCount == savedBraceCount) - break; if (!InAsmComment && Tok.is(tok::semi)) { // A semicolon in an asm is the start of a comment. @@ -1690,8 +1703,15 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { // does MSVC do here? break; } + } else if (InBraces && Tok.is(tok::r_brace) && + BraceCount == savedBraceCount + 1) { + // Consume the closing brace, and finish + EndLoc = ConsumeBrace(); + break; } + AsmToks.push_back(Tok); + // Consume the next token; make sure we don't modify the brace count etc. // if we are in a comment. EndLoc = TokLoc; @@ -1703,6 +1723,8 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { ++NumTokensRead; } while (1); + LineEnds.push_back(AsmToks.size()); + if (InBraces && BraceCount != savedBraceCount) { // __asm without closing brace (this can happen at EOF). Diag(Tok, diag::err_expected_rbrace); @@ -1719,24 +1741,33 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { break; EndLoc = ConsumeToken(); } while (1); - // FIXME: Need to actually grab the data and pass it on to Sema. Ideally, - // what Sema wants is a string of the entire inline asm, with one instruction - // per line and all the __asm keywords stripped out, and a way of mapping - // from any character of that string to its location in the original source - // code. I'm not entirely sure how to go about that, though. - Token t; - t.setKind(tok::string_literal); - t.setLiteralData("\"/*FIXME: not done*/\""); - t.clearFlag(Token::NeedsCleaning); - t.setLength(21); - ExprResult AsmString(Actions.ActOnStringLiteral(&t, 1)); - ExprVector Constraints(Actions); - ExprVector Exprs(Actions); - ExprVector Clobbers(Actions); - return Actions.ActOnAsmStmt(AsmLoc, true, true, 0, 0, 0, - move_arg(Constraints), move_arg(Exprs), - AsmString.take(), move_arg(Clobbers), - EndLoc, true); + + // Collect the tokens into a string + SmallString<512> Asm; + SmallString<512> TokenBuf; + TokenBuf.resize(512); + unsigned AsmLineNum = 0; + for (unsigned i = 0, e = AsmToks.size(); i < e; i++) { + const char *ThisTokBuf = &TokenBuf[0]; + bool StringInvalid = false; + unsigned ThisTokLen = + Lexer::getSpelling(AsmToks[i], ThisTokBuf, PP.getSourceManager(), + PP.getLangOpts(), &StringInvalid); + if (i && (!AsmLineNum || i != LineEnds[AsmLineNum-1])) + Asm += ' '; // FIXME: Too much whitespace around punctuation + Asm += StringRef(ThisTokBuf, ThisTokLen); + if (i + 1 == LineEnds[AsmLineNum] && i + 1 != AsmToks.size()) { + Asm += '\n'; + ++AsmLineNum; + } + } + + // FIXME: We should be passing the tokens and source locations, rather than + // (or possibly in addition to the) AsmString. Sema is going to interact with + // MC to determine Constraints, Clobbers, etc., which would be simplest to + // do with the tokens. + std::string AsmString = Asm.data(); + return Actions.ActOnMSAsmStmt(AsmLoc, AsmString, EndLoc); } /// ParseAsmStatement - Parse a GNU extended asm statement. @@ -1758,18 +1789,6 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { /// asm-string-literal /// asm-clobbers ',' asm-string-literal /// -/// [MS] ms-asm-statement: -/// ms-asm-block -/// ms-asm-block ms-asm-statement -/// -/// [MS] ms-asm-block: -/// '__asm' ms-asm-line '\n' -/// '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt] -/// -/// [MS] ms-asm-instruction-block -/// ms-asm-line -/// ms-asm-line '\n' ms-asm-instruction-block -/// StmtResult Parser::ParseAsmStatement(bool &msAsm) { assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); SourceLocation AsmLoc = ConsumeToken(); diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index cea8a765c8..7eba772743 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -189,6 +189,12 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { continue; } } + if (isa<MSAsmStmt>(S)) { + // TODO: Verify this is correct. + HasFakeEdge = true; + HasLiveReturn = true; + continue; + } if (isa<CXXTryStmt>(S)) { HasAbnormalEdge = true; continue; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 0e39314966..fb828909c3 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2670,6 +2670,15 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, return Owned(NS); } +StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, + std::string &AsmString, + SourceLocation EndLoc) { + MSAsmStmt *NS = + new (Context) MSAsmStmt(Context, AsmLoc, AsmString, EndLoc); + + return Owned(NS); +} + StmtResult Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen, Decl *Parm, diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 01b82aa3d7..08c7d7d11a 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1179,6 +1179,16 @@ public: RParenLoc, MSAsm); } + /// \brief Build a new MS style inline asm statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildMSAsmStmt(SourceLocation AsmLoc, + std::string &AsmString, + SourceLocation EndLoc) { + return getSema().ActOnMSAsmStmt(AsmLoc, AsmString, EndLoc); + } + /// \brief Build a new Objective-C @try statement. /// /// By default, performs semantic analysis to build the new statement. @@ -5602,6 +5612,14 @@ TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) { S->isMSAsm()); } +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformMSAsmStmt(MSAsmStmt *S) { + // No need to transform the asm string literal. + return getDerived().RebuildMSAsmStmt(S->getAsmLoc(), + *S->getAsmString(), + S->getEndLoc()); +} template<typename Derived> StmtResult diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 965b4d1fac..9823be1942 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -317,6 +317,11 @@ void ASTStmtReader::VisitAsmStmt(AsmStmt *S) { Clobbers.data(), NumClobbers); } +void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) { + // FIXME: Statement reader not yet implemented for MS style inline asm. + VisitStmt(S); +} + void ASTStmtReader::VisitExpr(Expr *E) { VisitStmt(E); E->setType(Reader.readType(F, Record, Idx)); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 9921d6ec47..1d2efe48e4 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -249,6 +249,11 @@ void ASTStmtWriter::VisitAsmStmt(AsmStmt *S) { Code = serialization::STMT_ASM; } +void ASTStmtWriter::VisitMSAsmStmt(MSAsmStmt *S) { + // FIXME: Statement writer not yet implemented for MS style inline asm. + VisitStmt(S); +} + void ASTStmtWriter::VisitExpr(Expr *E) { VisitStmt(E); Writer.AddTypeRef(E->getType(), Record); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 6531265807..a95f565b6c 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -670,6 +670,12 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, Bldr.addNodes(Dst); break; + case Stmt::MSAsmStmtClass: + Bldr.takeNodes(Pred); + VisitMSAsmStmt(cast<MSAsmStmt>(S), Pred, Dst); + Bldr.addNodes(Dst); + break; + case Stmt::BlockExprClass: Bldr.takeNodes(Pred); VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst); @@ -1813,6 +1819,12 @@ void ExprEngine::VisitAsmStmt(const AsmStmt *A, ExplodedNode *Pred, Bldr.generateNode(A, Pred, state); } +void ExprEngine::VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, + ExplodedNodeSet &Dst) { + StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); + Bldr.generateNode(A, Pred, Pred->getState()); +} + //===----------------------------------------------------------------------===// // Visualization. //===----------------------------------------------------------------------===// |