From b235fc2cf37621c7fc6511bb2b8788c95f9fb9fc Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Thu, 22 Nov 2007 01:36:19 +0000 Subject: [PATCH] Store output and input operands as well as clobber information in the AsmStmt. Ted, could you please review the serialization/deserialization code? git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44266 91177308-0d34-0410-b5e6-96231b3b80d8 --- AST/Stmt.cpp | 23 ++++++++++++++ AST/StmtPrinter.cpp | 51 +++++++++++++++++++++++++++++++ AST/StmtSerialization.cpp | 51 ++++++++++++++++++++++++++++++- Parse/ParseStmt.cpp | 58 +++++++++++++++++++++++++++--------- Sema/Sema.h | 7 +++++ Sema/SemaStmt.cpp | 20 ++++++++++++- include/clang/AST/Stmt.h | 41 +++++++++++++++++++++---- include/clang/Parse/Action.h | 7 +++++ include/clang/Parse/Parser.h | 5 +++- 9 files changed, 241 insertions(+), 22 deletions(-) diff --git a/AST/Stmt.cpp b/AST/Stmt.cpp index ccd27afce1..9a4d4347b6 100644 --- a/AST/Stmt.cpp +++ b/AST/Stmt.cpp @@ -111,6 +111,29 @@ bool Stmt::hasImplicitControlFlow() const { } } +AsmStmt::AsmStmt(SourceLocation asmloc, + unsigned numoutputs, + unsigned numinputs, + std::string *names, + StringLiteral **constraints, + Expr **exprs, + StringLiteral *asmstr, + unsigned numclobbers, + StringLiteral **clobbers, + SourceLocation rparenloc) + : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr) + , NumOutputs(numoutputs), NumInputs(numinputs) +{ + for (unsigned i = 0, e = numinputs + numoutputs; i != e; i++) { + Names.push_back(names[i]); + Exprs.push_back(exprs[i]); + Constraints.push_back(constraints[i]); + } + + for (unsigned i = 0; i != numclobbers; i++) + Clobbers.push_back(clobbers[i]); +} + //===----------------------------------------------------------------------===// // Child Iterators for iterating over subexpressions/substatements //===----------------------------------------------------------------------===// diff --git a/AST/StmtPrinter.cpp b/AST/StmtPrinter.cpp index 306bfcb18e..cc6ffda86d 100644 --- a/AST/StmtPrinter.cpp +++ b/AST/StmtPrinter.cpp @@ -328,6 +328,57 @@ void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) { void StmtPrinter::VisitAsmStmt(AsmStmt *Node) { Indent() << "asm ("; VisitStringLiteral(Node->getAsmString()); + + // Outputs + if (Node->getNumOutputs() != 0 || Node->getNumInputs() != 0 || + Node->getNumClobbers() != 0) + OS << " : "; + + for (unsigned i = 0, e = Node->getNumOutputs(); i != e; ++i) { + if (i != 0) + OS << ", "; + + if (!Node->getOutputName(i).empty()) { + OS << '['; + OS << Node->getOutputName(i); + OS << "] "; + } + + VisitStringLiteral(Node->getOutputConstraint(i)); + OS << " "; + Visit(Node->getOutputExpr(i)); + } + + // Inputs + if (Node->getNumInputs() != 0 || Node->getNumClobbers() != 0) + OS << " : "; + + for (unsigned i = 0, e = Node->getNumInputs(); i != e; ++i) { + if (i != 0) + OS << ", "; + + if (!Node->getInputName(i).empty()) { + OS << '['; + OS << Node->getInputName(i); + OS << "] "; + } + + VisitStringLiteral(Node->getInputConstraint(i)); + OS << " "; + Visit(Node->getInputExpr(i)); + } + + // Clobbers + if (Node->getNumClobbers() != 0) + OS << " : "; + + for (unsigned i = 0, e = Node->getNumClobbers(); i != e; ++i) { + if (i != 0) + OS << ", "; + + VisitStringLiteral(Node->getClobber(i)); + } + OS << ");\n"; } diff --git a/AST/StmtSerialization.cpp b/AST/StmtSerialization.cpp index f2c7834e72..46f8559c6c 100644 --- a/AST/StmtSerialization.cpp +++ b/AST/StmtSerialization.cpp @@ -197,8 +197,27 @@ ArraySubscriptExpr* ArraySubscriptExpr::CreateImpl(Deserializer& D) { void AsmStmt::EmitImpl(Serializer& S) const { S.Emit(AsmLoc); + getAsmString()->EmitImpl(S); S.Emit(RParenLoc); + + S.EmitInt(NumOutputs); + S.EmitInt(NumInputs); + + unsigned size = NumOutputs + NumInputs; + + for (unsigned i = 0; i < size; ++i) + S.EmitCStr(Names[i].c_str()); + + for (unsigned i = 0; i < size; ++i) + Constraints[i]->EmitImpl(S); + + for (unsigned i = 0; i < size; ++i) + S.EmitOwnedPtr(Exprs[i]); + + S.EmitInt(Clobbers.size()); + for (unsigned i = 0, e = Clobbers.size(); i != e; ++i) + Clobbers[i]->EmitImpl(S); } AsmStmt* AsmStmt::CreateImpl(Deserializer& D) { @@ -206,7 +225,37 @@ AsmStmt* AsmStmt::CreateImpl(Deserializer& D) { StringLiteral *AsmStr = StringLiteral::CreateImpl(D); SourceLocation PLoc = SourceLocation::ReadVal(D); - return new AsmStmt(ALoc, AsmStr, PLoc); + AsmStmt *Stmt = new AsmStmt(ALoc, 0, 0, 0, 0, 0, + AsmStr, + 0, 0, PLoc); + + Stmt->NumOutputs = D.ReadInt(); + Stmt->NumInputs = D.ReadInt(); + + unsigned size = Stmt->NumOutputs + Stmt->NumInputs; + + Stmt->Names.reserve(size); + for (unsigned i = 0; i < size; ++i) { + std::vector data; + D.ReadCStr(data, false); + + Stmt->Names.push_back(std::string(&data[0], data.size())); + } + + Stmt->Constraints.reserve(size); + for (unsigned i = 0; i < size; ++i) + Stmt->Constraints.push_back(StringLiteral::CreateImpl(D)); + + Stmt->Exprs.reserve(size); + for (unsigned i = 0; i < size; ++i) + Stmt->Exprs.push_back(D.ReadOwnedPtr()); + + unsigned NumClobbers = D.ReadInt(); + Stmt->Clobbers.reserve(NumClobbers); + for (unsigned i = 0; i < NumClobbers; ++i) + Stmt->Clobbers.push_back(StringLiteral::CreateImpl(D)); + + return Stmt; } void BinaryOperator::EmitImpl(Serializer& S) const { diff --git a/Parse/ParseStmt.cpp b/Parse/ParseStmt.cpp index 6f871da118..5a5217131b 100644 --- a/Parse/ParseStmt.cpp +++ b/Parse/ParseStmt.cpp @@ -946,12 +946,25 @@ Parser::StmtResult Parser::ParseAsmStatement() { ExprResult AsmString = ParseAsmStringLiteral(); if (AsmString.isInvalid) return true; - - // Parse Outputs, if present. - ParseAsmOperandsOpt(); + + llvm::SmallVector Names; + llvm::SmallVector Constraints; + llvm::SmallVector Exprs; + + // Parse Outputs, if present. + ParseAsmOperandsOpt(Names, Constraints, Exprs); + + unsigned NumOutputs = Names.size(); // Parse Inputs, if present. - ParseAsmOperandsOpt(); + ParseAsmOperandsOpt(Names, Constraints, Exprs); + assert(Names.size() == Constraints.size() && + Constraints.size() == Exprs.size() + && "Input operand size mismatch!"); + + unsigned NumInputs = Names.size() - NumOutputs; + + llvm::SmallVector Clobbers; // Parse the clobbers, if present. if (Tok.is(tok::colon)) { @@ -959,8 +972,13 @@ Parser::StmtResult Parser::ParseAsmStatement() { // Parse the asm-string list for clobbers. while (1) { - ParseAsmStringLiteral(); + ExprResult Clobber = ParseAsmStringLiteral(); + if (Clobber.isInvalid) + break; + + Clobbers.push_back(Clobber.Val); + if (Tok.isNot(tok::comma)) break; ConsumeToken(); } @@ -968,8 +986,11 @@ Parser::StmtResult Parser::ParseAsmStatement() { SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc); - // FIXME: Pass all the details down to the action. - return Actions.ActOnAsmStmt(AsmLoc, AsmString.Val, RParenLoc); + return Actions.ActOnAsmStmt(AsmLoc, NumOutputs, NumInputs, + &Names[0], &Constraints[0], &Exprs[0], + AsmString.Val, + Clobbers.size(), &Clobbers[0], + RParenLoc); } /// ParseAsmOperands - Parse the asm-operands production as used by @@ -984,7 +1005,9 @@ Parser::StmtResult Parser::ParseAsmStatement() { /// asm-string-literal '(' expression ')' /// '[' identifier ']' asm-string-literal '(' expression ')' /// -void Parser::ParseAsmOperandsOpt() { +void Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl &Names, + llvm::SmallVectorImpl &Constraints, + llvm::SmallVectorImpl &Exprs) { // Only do anything if this operand is present. if (Tok.isNot(tok::colon)) return; ConsumeToken(); @@ -993,7 +1016,7 @@ void Parser::ParseAsmOperandsOpt() { if (!isTokenStringLiteral() && Tok.isNot(tok::l_square)) return; - while (1) { + while (1) { // Read the [id] if present. if (Tok.is(tok::l_square)) { SourceLocation Loc = ConsumeBracket(); @@ -1004,13 +1027,20 @@ void Parser::ParseAsmOperandsOpt() { return; } - // Eat the identifier, FIXME: capture it. + IdentifierInfo *II = Tok.getIdentifierInfo(); ConsumeToken(); - + + Names.push_back(std::string(II->getName(), II->getLength())); MatchRHSPunctuation(tok::r_square, Loc); - } + } else + Names.push_back(std::string()); - ParseAsmStringLiteral(); + ExprResult Constraint = ParseAsmStringLiteral(); + if (Constraint.isInvalid) { + SkipUntil(tok::r_paren); + return; + } + Constraints.push_back(Constraint.Val); if (Tok.isNot(tok::l_paren)) { Diag(Tok, diag::err_expected_lparen_after, "asm operand"); @@ -1024,7 +1054,7 @@ void Parser::ParseAsmOperandsOpt() { SkipUntil(tok::r_paren); return; } - + Exprs.push_back(Res.Val); // Eat the comma and continue parsing if it exists. if (Tok.isNot(tok::comma)) return; ConsumeToken(); diff --git a/Sema/Sema.h b/Sema/Sema.h index 78cc888f34..f747cefcb2 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -347,7 +347,14 @@ public: ExprTy *RetValExp); virtual StmtResult ActOnAsmStmt(SourceLocation AsmLoc, + unsigned NumOutputs, + unsigned NumInputs, + std::string *Names, + ExprTy **Constraints, + ExprTy **Exprs, ExprTy *AsmString, + unsigned NumClobbers, + ExprTy **Clobbers, SourceLocation RParenLoc); virtual StmtResult ActOnObjcAtCatchStmt(SourceLocation AtLoc, diff --git a/Sema/SemaStmt.cpp b/Sema/SemaStmt.cpp index ad3d2e4ee6..f7aa6a9e27 100644 --- a/Sema/SemaStmt.cpp +++ b/Sema/SemaStmt.cpp @@ -645,11 +645,29 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprTy *rex) { } Sema::StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, + unsigned NumOutputs, + unsigned NumInputs, + std::string *Names, + ExprTy **Constraints, + ExprTy **Exprs, ExprTy *AsmString, + unsigned NumClobbers, + ExprTy **Clobbers, SourceLocation RParenLoc) { Expr *E = (Expr *)AsmString; - return new AsmStmt(AsmLoc, cast(E), RParenLoc); + // FIXME: Make sure that the expressions are valid. + + return new AsmStmt(AsmLoc, + NumOutputs, + NumInputs, + Names, + reinterpret_cast(Constraints), + reinterpret_cast(Exprs), + cast(E), + NumClobbers, + reinterpret_cast(Clobbers), + RParenLoc); } Action::StmtResult diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 802c025cdb..7516705a07 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -706,16 +706,47 @@ public: class AsmStmt : public Stmt { SourceLocation AsmLoc, RParenLoc; StringLiteral *AsmStr; - // FIXME: This doesn't capture most of the interesting pieces. + + unsigned NumOutputs; + unsigned NumInputs; + + llvm::SmallVector Names; + llvm::SmallVector Constraints; + llvm::SmallVector Exprs; + + llvm::SmallVector Clobbers; public: - AsmStmt(SourceLocation asmloc, StringLiteral *asmstr, - SourceLocation rparenloc) - : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), - AsmStr(asmstr) {} + AsmStmt(SourceLocation asmloc, + unsigned numoutputs, + unsigned numinputs, + std::string *names, + StringLiteral **constraints, + Expr **exprs, + StringLiteral *asmstr, + unsigned numclobbers, + StringLiteral **clobbers, + SourceLocation rparenloc); + + unsigned getNumOutputs() const { return NumOutputs; } + const std::string &getOutputName(unsigned i) const + { return Names[i]; } + StringLiteral *getOutputConstraint(unsigned i) + { return Constraints[i]; } + Expr *getOutputExpr(unsigned i) { return Exprs[i]; } + + unsigned getNumInputs() const { return NumInputs; } + const std::string &getInputName(unsigned i) const + { return Names[i + NumOutputs]; } + StringLiteral *getInputConstraint(unsigned i) + { return Constraints[i + NumOutputs]; } + Expr *getInputExpr(unsigned i) { return Exprs[i + NumOutputs]; } const StringLiteral *getAsmString() const { return AsmStr; } StringLiteral *getAsmString() { return AsmStr; } + unsigned getNumClobbers() const { return Clobbers.size(); } + StringLiteral *getClobber(unsigned i) { return Clobbers[i]; } + virtual SourceRange getSourceRange() const { return SourceRange(AsmLoc, RParenLoc); } diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 2da8e01149..9f599c422d 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -287,7 +287,14 @@ public: return 0; } virtual StmtResult ActOnAsmStmt(SourceLocation AsmLoc, + unsigned NumOutputs, + unsigned NumInputs, + std::string *Names, + ExprTy **Constraints, + ExprTy **Exprs, ExprTy *AsmString, + unsigned NumClobbers, + ExprTy **Clobbers, SourceLocation RParenLoc) { return 0; } diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 9d7f27e184..3fb3e2e7c8 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -388,7 +388,10 @@ private: StmtResult ParseAsmStatement(); StmtResult ParseObjCTryStmt(SourceLocation atLoc); StmtResult ParseObjCThrowStmt(SourceLocation atLoc); - void ParseAsmOperandsOpt(); + void ParseAsmOperandsOpt(llvm::SmallVectorImpl &Names, + llvm::SmallVectorImpl &Constraints, + llvm::SmallVectorImpl &Exprs); + //===--------------------------------------------------------------------===// // C99 6.7: Declarations. -- 2.50.1