]> granicus.if.org Git - clang/commitdiff
[ast] Put the Stmt hierarchy on a diet for 64 bit targets.
authorBenjamin Kramer <benny.kra@googlemail.com>
Thu, 2 Apr 2015 15:29:07 +0000 (15:29 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Thu, 2 Apr 2015 15:29:07 +0000 (15:29 +0000)
Previously we would waste 32 bits on alignment, use LLVM_ALIGNAS to
free that space for derived classes an place. Sadly still have to #ifdef
out MSVC 2013 because it can't align based on a sizeof expr.

No intended functionality change. New byte counts:
sizeof(before) | sizeof(after)

LabelStmt: 32 | LabelStmt: 24
SwitchStmt: 48 | SwitchStmt: 40
WhileStmt: 40 | WhileStmt: 32
DoStmt: 40 | DoStmt: 32
ForStmt: 64 | ForStmt: 56
ContinueStmt: 16 | ContinueStmt: 8
BreakStmt: 16 | BreakStmt: 8
ReturnStmt: 32 | ReturnStmt: 24
AsmStmt: 40 | AsmStmt: 32
GCCAsmStmt: 80 | GCCAsmStmt: 72
MSAsmStmt: 96 | MSAsmStmt: 88
SEHExceptStmt: 32 | SEHExceptStmt: 24
SEHFinallyStmt: 24 | SEHFinallyStmt: 16
SEHLeaveStmt: 16 | SEHLeaveStmt: 8
CapturedStmt: 32 | CapturedStmt: 24
CXXCatchStmt: 32 | CXXCatchStmt: 24
CXXForRangeStmt: 72 | CXXForRangeStmt: 64
ObjCAtFinallyStmt: 24 | ObjCAtFinallyStmt: 16
ObjCAtSynchronizedStmt: 32 | ObjCAtSynchronizedStmt: 24
ObjCAtThrowStmt: 24 | ObjCAtThrowStmt: 16
ObjCAutoreleasePoolStmt: 24 | ObjCAutoreleasePoolStmt: 16

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@233921 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Stmt.h
include/clang/AST/StmtCXX.h
include/clang/AST/StmtObjC.h
lib/AST/Stmt.cpp

index a55cba9d1a40c6879cdd0ced6376f27d274864b1..9a0fa8a8dd6f7f506153290677f586b4656b31e0 100644 (file)
@@ -101,7 +101,13 @@ namespace clang {
 
 /// Stmt - This represents one statement.
 ///
+#if !defined(_MSC_VER) || LLVM_MSC_PREREQ(1900)
+class LLVM_ALIGNAS(sizeof(void *)) Stmt {
+#else
+// Old MSVC has issues to align this. Drop when we retire MSVC 2013. When GCC
+// 4.7 is also gone this can be just alignof(void *).
 class Stmt {
+#endif
 public:
   enum StmtClass {
     NoStmtClass = 0,
@@ -287,8 +293,10 @@ protected:
   };
 
   union {
+#if !(!defined(_MSC_VER) || LLVM_MSC_PREREQ(1900))
     // FIXME: this is wasteful on 64-bit platforms.
     void *Aligner;
+#endif
 
     StmtBitfields StmtBits;
     CompoundStmtBitfields CompoundStmtBits;
@@ -688,10 +696,10 @@ public:
 };
 
 class CaseStmt : public SwitchCase {
+  SourceLocation EllipsisLoc;
   enum { LHS, RHS, SUBSTMT, END_EXPR };
   Stmt* SubExprs[END_EXPR];  // The expression for the RHS is Non-null for
                              // GNU "case 1 ... 4" extension
-  SourceLocation EllipsisLoc;
 public:
   CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
            SourceLocation ellipsisLoc, SourceLocation colonLoc)
@@ -788,13 +796,13 @@ inline SourceLocation SwitchCase::getLocEnd() const {
 ///    foo: return;
 ///
 class LabelStmt : public Stmt {
+  SourceLocation IdentLoc;
   LabelDecl *TheDecl;
   Stmt *SubStmt;
-  SourceLocation IdentLoc;
+
 public:
   LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt)
-    : Stmt(LabelStmtClass), TheDecl(D), SubStmt(substmt), IdentLoc(IL) {
-  }
+      : Stmt(LabelStmtClass), IdentLoc(IL), TheDecl(D), SubStmt(substmt) {}
 
   // \brief Build an empty label statement.
   explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { }
@@ -943,16 +951,14 @@ public:
 /// SwitchStmt - This represents a 'switch' stmt.
 ///
 class SwitchStmt : public Stmt {
+  SourceLocation SwitchLoc;
   enum { VAR, COND, BODY, END_EXPR };
   Stmt* SubExprs[END_EXPR];
-  // This points to a linked list of case and default statements.
-  SwitchCase *FirstCase;
-  SourceLocation SwitchLoc;
-
-  /// If the SwitchStmt is a switch on an enum value, this records whether
-  /// all the enum values were covered by CaseStmts.  This value is meant to
-  /// be a hint for possible clients.
-  unsigned AllEnumCasesCovered : 1;
+  // This points to a linked list of case and default statements and, if the
+  // SwitchStmt is a switch on an enum value, records whether all the enum
+  // values were covered by CaseStmts.  The coverage information value is meant
+  // to be a hint for possible clients.
+  llvm::PointerIntPair<SwitchCase *, 1, bool> FirstCase;
 
 public:
   SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond);
@@ -980,16 +986,16 @@ public:
 
   const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
   const Stmt *getBody() const { return SubExprs[BODY]; }
-  const SwitchCase *getSwitchCaseList() const { return FirstCase; }
+  const SwitchCase *getSwitchCaseList() const { return FirstCase.getPointer(); }
 
   Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);}
   void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
   Stmt *getBody() { return SubExprs[BODY]; }
   void setBody(Stmt *S) { SubExprs[BODY] = S; }
-  SwitchCase *getSwitchCaseList() { return FirstCase; }
+  SwitchCase *getSwitchCaseList() { return FirstCase.getPointer(); }
 
   /// \brief Set the case list for this switch statement.
-  void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }
+  void setSwitchCaseList(SwitchCase *SC) { FirstCase.setPointer(SC); }
 
   SourceLocation getSwitchLoc() const { return SwitchLoc; }
   void setSwitchLoc(SourceLocation L) { SwitchLoc = L; }
@@ -1001,21 +1007,17 @@ public:
   void addSwitchCase(SwitchCase *SC) {
     assert(!SC->getNextSwitchCase()
            && "case/default already added to a switch");
-    SC->setNextSwitchCase(FirstCase);
-    FirstCase = SC;
+    SC->setNextSwitchCase(FirstCase.getPointer());
+    FirstCase.setPointer(SC);
   }
 
   /// Set a flag in the SwitchStmt indicating that if the 'switch (X)' is a
   /// switch over an enum value then all cases have been explicitly covered.
-  void setAllEnumCasesCovered() {
-    AllEnumCasesCovered = 1;
-  }
+  void setAllEnumCasesCovered() { FirstCase.setInt(true); }
 
   /// Returns true if the SwitchStmt is a switch of an enum value and all cases
   /// have been explicitly covered.
-  bool isAllEnumCasesCovered() const {
-    return (bool) AllEnumCasesCovered;
-  }
+  bool isAllEnumCasesCovered() const { return FirstCase.getInt(); }
 
   SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; }
   SourceLocation getLocEnd() const LLVM_READONLY {
@@ -1036,9 +1038,9 @@ public:
 /// WhileStmt - This represents a 'while' stmt.
 ///
 class WhileStmt : public Stmt {
+  SourceLocation WhileLoc;
   enum { VAR, COND, BODY, END_EXPR };
   Stmt* SubExprs[END_EXPR];
-  SourceLocation WhileLoc;
 public:
   WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
             SourceLocation WL);
@@ -1091,9 +1093,9 @@ public:
 /// DoStmt - This represents a 'do/while' stmt.
 ///
 class DoStmt : public Stmt {
+  SourceLocation DoLoc;
   enum { BODY, COND, END_EXPR };
   Stmt* SubExprs[END_EXPR];
-  SourceLocation DoLoc;
   SourceLocation WhileLoc;
   SourceLocation RParenLoc;  // Location of final ')' in do stmt condition.
 
@@ -1142,9 +1144,9 @@ public:
 /// specified in the source.
 ///
 class ForStmt : public Stmt {
+  SourceLocation ForLoc;
   enum { INIT, CONDVAR, COND, INC, BODY, END_EXPR };
   Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt.
-  SourceLocation ForLoc;
   SourceLocation LParenLoc, RParenLoc;
 
 public:
@@ -1345,18 +1347,16 @@ public:
 /// depend on the return type of the function and the presence of an argument.
 ///
 class ReturnStmt : public Stmt {
-  Stmt *RetExpr;
   SourceLocation RetLoc;
+  Stmt *RetExpr;
   const VarDecl *NRVOCandidate;
 
 public:
-  ReturnStmt(SourceLocation RL)
-    : Stmt(ReturnStmtClass), RetExpr(nullptr), RetLoc(RL),
-      NRVOCandidate(nullptr) {}
+  explicit ReturnStmt(SourceLocation RL) : ReturnStmt(RL, nullptr, nullptr) {}
 
   ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
-    : Stmt(ReturnStmtClass), RetExpr((Stmt*) E), RetLoc(RL),
-      NRVOCandidate(NRVOCandidate) {}
+      : Stmt(ReturnStmtClass), RetLoc(RL), RetExpr((Stmt *)E),
+        NRVOCandidate(NRVOCandidate) {}
 
   /// \brief Build an empty return expression.
   explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { }
index 837dc45d1224219355fc94836bbca11604198344..567a7728843031719706fe52253fb8dde02047dd 100644 (file)
@@ -126,11 +126,11 @@ public:
 /// analysis of the constituent components. The original syntactic components
 /// can be extracted using getLoopVariable and getRangeInit.
 class CXXForRangeStmt : public Stmt {
+  SourceLocation ForLoc;
   enum { RANGE, BEGINEND, COND, INC, LOOPVAR, BODY, END };
   // SubExprs[RANGE] is an expression or declstmt.
   // SubExprs[COND] and SubExprs[INC] are expressions.
   Stmt *SubExprs[END];
-  SourceLocation ForLoc;
   SourceLocation ColonLoc;
   SourceLocation RParenLoc;
 public:
index d0527e2d8b615d87a7a47670997fdcebdc64c8f8..68fe3ef697bc68c8effb3f5e45c68ad929dea2ed 100644 (file)
@@ -118,12 +118,13 @@ public:
 
 /// \brief Represents Objective-C's \@finally statement
 class ObjCAtFinallyStmt : public Stmt {
-  Stmt *AtFinallyStmt;
   SourceLocation AtFinallyLoc;
+  Stmt *AtFinallyStmt;
+
 public:
   ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt)
-  : Stmt(ObjCAtFinallyStmtClass),
-    AtFinallyStmt(atFinallyStmt), AtFinallyLoc(atFinallyLoc) {}
+      : Stmt(ObjCAtFinallyStmtClass), AtFinallyLoc(atFinallyLoc),
+        AtFinallyStmt(atFinallyStmt) {}
 
   explicit ObjCAtFinallyStmt(EmptyShell Empty) :
     Stmt(ObjCAtFinallyStmtClass, Empty) { }
@@ -260,9 +261,9 @@ public:
 /// \endcode
 class ObjCAtSynchronizedStmt : public Stmt {
 private:
+  SourceLocation AtSynchronizedLoc;
   enum { SYNC_EXPR, SYNC_BODY, END_EXPR };
   Stmt* SubStmts[END_EXPR];
-  SourceLocation AtSynchronizedLoc;
 
 public:
   ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr,
@@ -310,8 +311,9 @@ public:
 
 /// \brief Represents Objective-C's \@throw statement.
 class ObjCAtThrowStmt : public Stmt {
-  Stmt *Throw;
   SourceLocation AtThrowLoc;
+  Stmt *Throw;
+
 public:
   ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr)
   : Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) {
@@ -341,13 +343,12 @@ public:
 
 /// \brief Represents Objective-C's \@autoreleasepool Statement
 class ObjCAutoreleasePoolStmt : public Stmt {
-  Stmt *SubStmt;
   SourceLocation AtLoc;
+  Stmt *SubStmt;
+
 public:
-  ObjCAutoreleasePoolStmt(SourceLocation atLoc, 
-                            Stmt *subStmt)
-  : Stmt(ObjCAutoreleasePoolStmtClass),
-    SubStmt(subStmt), AtLoc(atLoc) {}
+  ObjCAutoreleasePoolStmt(SourceLocation atLoc, Stmt *subStmt)
+      : Stmt(ObjCAutoreleasePoolStmtClass), AtLoc(atLoc), SubStmt(subStmt) {}
 
   explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) :
     Stmt(ObjCAutoreleasePoolStmtClass, Empty) { }
index f5d8213ded69cee852047fdc9c02c1989d724c70..98ad4d47f5521bee6d4ff6d071d4e4c30c1a38fe 100644 (file)
@@ -940,8 +940,7 @@ void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
 }
 
 SwitchStmt::SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond)
-  : Stmt(SwitchStmtClass), FirstCase(nullptr), AllEnumCasesCovered(0)
-{
+    : Stmt(SwitchStmtClass), FirstCase(nullptr, false) {
   setConditionVariable(C, Var);
   SubExprs[COND] = cond;
   SubExprs[BODY] = nullptr;