From 03d6fb99224c36935c9af9f4785cb33453c99b2b Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 21 Aug 2007 04:43:17 +0000 Subject: [PATCH] Add the ability to visit binary operators without having to match on binop then explicitly switching again. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41214 91177308-0d34-0410-b5e6-96231b3b80d8 --- CodeGen/CGAggExpr.cpp | 16 ++---- include/clang/AST/Expr.h | 1 + include/clang/AST/StmtVisitor.h | 98 ++++++++++++++++++++++++++++++--- 3 files changed, 97 insertions(+), 18 deletions(-) diff --git a/CodeGen/CGAggExpr.cpp b/CodeGen/CGAggExpr.cpp index f0601cc5bd..869e35dac5 100644 --- a/CodeGen/CGAggExpr.cpp +++ b/CodeGen/CGAggExpr.cpp @@ -89,7 +89,7 @@ public: // case Expr::CastExprClass: // case Expr::CallExprClass: void VisitBinaryOperator(const BinaryOperator *BO); - void VisitBinaryAssign(const BinaryOperator *E); + void VisitBinAssign(const BinaryOperator *E); void VisitConditionalOperator(const ConditionalOperator *CO); @@ -128,12 +128,12 @@ void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) { } void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) { + fprintf(stderr, "Unimplemented aggregate binary expr!\n"); + E->dump(); +#if 0 switch (E->getOpcode()) { default: - fprintf(stderr, "Unimplemented aggregate binary expr!\n"); - E->dump(); return; -#if 0 case BinaryOperator::Mul: LHS = EmitExpr(E->getLHS()); RHS = EmitExpr(E->getRHS()); @@ -183,10 +183,6 @@ void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) { LHS = EmitExpr(E->getLHS()); RHS = EmitExpr(E->getRHS()); return EmitOr(LHS, RHS, E->getType()); -#endif - case BinaryOperator::Assign: return VisitBinaryAssign(E); - -#if 0 case BinaryOperator::MulAssign: { const CompoundAssignOperator *CAO = cast(E); LValue LHSLV; @@ -258,11 +254,11 @@ void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) { return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); } case BinaryOperator::Comma: return EmitBinaryComma(E); -#endif } +#endif } -void AggExprEmitter::VisitBinaryAssign(const BinaryOperator *E) { +void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { assert(E->getLHS()->getType().getCanonicalType() == E->getRHS()->getType().getCanonicalType() && "Invalid assignment"); LValue LHS = CGF.EmitLValue(E->getLHS()); diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 2397c58b34..d65831d423 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -595,6 +595,7 @@ class BinaryOperator : public Expr { public: enum Opcode { // Operators listed in order of precedence. + // Note that additions to this should also update the StmtVisitor class. Mul, Div, Rem, // [C99 6.5.5] Multiplicative operators. Add, Sub, // [C99 6.5.6] Additive operators. Shl, Shr, // [C99 6.5.7] Bitwise shift operators. diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h index 43f8637861..a6770b0f86 100644 --- a/include/clang/AST/StmtVisitor.h +++ b/include/clang/AST/StmtVisitor.h @@ -18,19 +18,52 @@ namespace clang { +#define DISPATCH(NAME, CLASS) \ + return static_cast(this)->Visit ## NAME(static_cast(S)) + /// StmtVisitor - This class implements a simple visitor for Stmt subclasses. /// Since Expr derives from Stmt, this also includes support for visiting Exprs. template class StmtVisitor { public: RetTy Visit(Stmt *S) { + + // If we have a binary expr, dispatch to the subcode of the binop. A smart + // optimizer (e.g. LLVM) will fold this comparison into the switch stmt + // below. + if (BinaryOperator *BinOp = dyn_cast(S)) { + switch (BinOp->getOpcode()) { + default: assert(0 && "Unknown binary operator!"); + case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator); + case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator); + case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator); + case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator); + case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator); + case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator); + case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator); + case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator); + case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator); + case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator); + case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator); + case BinaryOperator::MulAssign: DISPATCH(BinMulAssign, BinaryOperator); + case BinaryOperator::DivAssign: DISPATCH(BinDivAssign, BinaryOperator); + case BinaryOperator::RemAssign: DISPATCH(BinRemAssign, BinaryOperator); + case BinaryOperator::AddAssign: DISPATCH(BinAddAssign, BinaryOperator); + case BinaryOperator::SubAssign: DISPATCH(BinSubAssign, BinaryOperator); + case BinaryOperator::ShlAssign: DISPATCH(BinShlAssign, BinaryOperator); + case BinaryOperator::ShrAssign: DISPATCH(BinShrAssign, BinaryOperator); + case BinaryOperator::AndAssign: DISPATCH(BinAndAssign, BinaryOperator); + case BinaryOperator::OrAssign: DISPATCH(BinOrAssign, BinaryOperator); + case BinaryOperator::XorAssign: DISPATCH(BinXorAssign, BinaryOperator); + case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator); + } + } + // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. switch (S->getStmtClass()) { default: assert(0 && "Unknown stmt kind!"); #define STMT(N, CLASS, PARENT) \ - case Stmt::CLASS ## Class: \ - return static_cast(this)->Visit ## CLASS( \ - static_cast(S)); + case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS); #include "clang/AST/StmtNodes.def" } } @@ -38,15 +71,64 @@ public: // If the implementation chooses not to implement a certain visit method, fall // back on VisitExpr or whatever else is the superclass. #define STMT(N, CLASS, PARENT) \ - RetTy Visit ## CLASS(CLASS *Node) { \ - return static_cast(this)->Visit ## PARENT(Node); \ - } + RetTy Visit ## CLASS(CLASS *S) { DISPATCH(PARENT, PARENT); } #include "clang/AST/StmtNodes.def" + // If the implementation doesn't implement binary operator methods, fall back + // on VisitBinaryOperator. + RetTy VisitBinMul(BinaryOperator *S){DISPATCH(BinaryOperator,BinaryOperator);} + RetTy VisitBinDiv(BinaryOperator *S){DISPATCH(BinaryOperator,BinaryOperator);} + RetTy VisitBinRem(BinaryOperator *S){DISPATCH(BinaryOperator,BinaryOperator);} + RetTy VisitBinAdd(BinaryOperator *S){DISPATCH(BinaryOperator,BinaryOperator);} + RetTy VisitBinSub(BinaryOperator *S){DISPATCH(BinaryOperator,BinaryOperator);} + RetTy VisitBinShl(BinaryOperator *S){DISPATCH(BinaryOperator,BinaryOperator);} + RetTy VisitBinShr(BinaryOperator *S){DISPATCH(BinaryOperator,BinaryOperator);} + RetTy VisitBinAnd(BinaryOperator *S){DISPATCH(BinaryOperator,BinaryOperator);} + RetTy VisitBinXor(BinaryOperator *S){DISPATCH(BinaryOperator,BinaryOperator);} + RetTy VisitBinOr(BinaryOperator *S){DISPATCH(BinaryOperator,BinaryOperator);} + RetTy VisitBinAssign(BinaryOperator *S) { + DISPATCH(BinaryOperator,BinaryOperator); + } + RetTy VisitBinMulAssign(BinaryOperator *S) { + DISPATCH(BinaryOperator,BinaryOperator); + } + RetTy VisitBinDivAssign(BinaryOperator *S) { + DISPATCH(BinaryOperator,BinaryOperator); + } + RetTy VisitBinRemAssign(BinaryOperator *S) { + DISPATCH(BinaryOperator,BinaryOperator); + } + RetTy VisitBinAddAssign(BinaryOperator *S) { + DISPATCH(BinaryOperator,BinaryOperator); + } + RetTy VisitBinSubAssign(BinaryOperator *S) { + DISPATCH(BinaryOperator,BinaryOperator); + } + RetTy VisitBinShlAssign(BinaryOperator *S) { + DISPATCH(BinaryOperator,BinaryOperator); + } + RetTy VisitBinShrAssign(BinaryOperator *S) { + DISPATCH(BinaryOperator,BinaryOperator); + } + RetTy VisitBinAndAssign(BinaryOperator *S) { + DISPATCH(BinaryOperator,BinaryOperator); + } + RetTy VisitBinOrAssign(BinaryOperator *S) { + DISPATCH(BinaryOperator,BinaryOperator); + } + RetTy VisitBinXorAssign(BinaryOperator *S) { + DISPATCH(BinaryOperator,BinaryOperator); + } + RetTy VisitBinComma(BinaryOperator *S) { + DISPATCH(BinaryOperator,BinaryOperator); + } + // Base case, ignore it. :) RetTy VisitStmt(Stmt *Node) { return RetTy(); } }; - -} + +#undef DISPATCH + +} // end namespace clang #endif -- 2.40.0