<div dir="ltr">I want this space saving optimization for clang-cl, but it strives for ABI compatibility with MSVC, and tweaking the preprocessor logic here would break that. What do you think about defining an LLVM_PTR_SIZE macro in Compiler.h and using that with __attribute__((aligned())) and __declspec(align)?<div><br></div><div>Defining LLVM_PTR_SIZE is pretty difficult because no compiler provides any bit or byte width macros for pointer size. We can't use autoconf checks because config.h isn't exported, but we can infer the width from __UINTPTR_MAX__ in GCC and _WIN64 for MSVC.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Apr 2, 2015 at 8:29 AM, Benjamin Kramer <span dir="ltr"><<a href="mailto:benny.kra@googlemail.com" target="_blank">benny.kra@googlemail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: d0k<br>
Date: Thu Apr 2 10:29:07 2015<br>
New Revision: 233921<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=233921&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=233921&view=rev</a><br>
Log:<br>
[ast] Put the Stmt hierarchy on a diet for 64 bit targets.<br>
<br>
Previously we would waste 32 bits on alignment, use LLVM_ALIGNAS to<br>
free that space for derived classes an place. Sadly still have to #ifdef<br>
out MSVC 2013 because it can't align based on a sizeof expr.<br>
<br>
No intended functionality change. New byte counts:<br>
sizeof(before) | sizeof(after)<br>
<br>
LabelStmt: 32 | LabelStmt: 24<br>
SwitchStmt: 48 | SwitchStmt: 40<br>
WhileStmt: 40 | WhileStmt: 32<br>
DoStmt: 40 | DoStmt: 32<br>
ForStmt: 64 | ForStmt: 56<br>
ContinueStmt: 16 | ContinueStmt: 8<br>
BreakStmt: 16 | BreakStmt: 8<br>
ReturnStmt: 32 | ReturnStmt: 24<br>
AsmStmt: 40 | AsmStmt: 32<br>
GCCAsmStmt: 80 | GCCAsmStmt: 72<br>
MSAsmStmt: 96 | MSAsmStmt: 88<br>
SEHExceptStmt: 32 | SEHExceptStmt: 24<br>
SEHFinallyStmt: 24 | SEHFinallyStmt: 16<br>
SEHLeaveStmt: 16 | SEHLeaveStmt: 8<br>
CapturedStmt: 32 | CapturedStmt: 24<br>
CXXCatchStmt: 32 | CXXCatchStmt: 24<br>
CXXForRangeStmt: 72 | CXXForRangeStmt: 64<br>
ObjCAtFinallyStmt: 24 | ObjCAtFinallyStmt: 16<br>
ObjCAtSynchronizedStmt: 32 | ObjCAtSynchronizedStmt: 24<br>
ObjCAtThrowStmt: 24 | ObjCAtThrowStmt: 16<br>
ObjCAutoreleasePoolStmt: 24 | ObjCAutoreleasePoolStmt: 16<br>
<br>
Modified:<br>
cfe/trunk/include/clang/AST/Stmt.h<br>
cfe/trunk/include/clang/AST/StmtCXX.h<br>
cfe/trunk/include/clang/AST/StmtObjC.h<br>
cfe/trunk/lib/AST/Stmt.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/Stmt.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=233921&r1=233920&r2=233921&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=233921&r1=233920&r2=233921&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/Stmt.h (original)<br>
+++ cfe/trunk/include/clang/AST/Stmt.h Thu Apr 2 10:29:07 2015<br>
@@ -101,7 +101,13 @@ namespace clang {<br>
<br>
/// Stmt - This represents one statement.<br>
///<br>
+#if !defined(_MSC_VER) || LLVM_MSC_PREREQ(1900)<br>
+class LLVM_ALIGNAS(sizeof(void *)) Stmt {<br>
+#else<br>
+// Old MSVC has issues to align this. Drop when we retire MSVC 2013. When GCC<br>
+// 4.7 is also gone this can be just alignof(void *).<br>
class Stmt {<br>
+#endif<br>
public:<br>
enum StmtClass {<br>
NoStmtClass = 0,<br>
@@ -287,8 +293,10 @@ protected:<br>
};<br>
<br>
union {<br>
+#if !(!defined(_MSC_VER) || LLVM_MSC_PREREQ(1900))<br>
// FIXME: this is wasteful on 64-bit platforms.<br>
void *Aligner;<br>
+#endif<br>
<br>
StmtBitfields StmtBits;<br>
CompoundStmtBitfields CompoundStmtBits;<br>
@@ -688,10 +696,10 @@ public:<br>
};<br>
<br>
class CaseStmt : public SwitchCase {<br>
+ SourceLocation EllipsisLoc;<br>
enum { LHS, RHS, SUBSTMT, END_EXPR };<br>
Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for<br>
// GNU "case 1 ... 4" extension<br>
- SourceLocation EllipsisLoc;<br>
public:<br>
CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,<br>
SourceLocation ellipsisLoc, SourceLocation colonLoc)<br>
@@ -788,13 +796,13 @@ inline SourceLocation SwitchCase::getLoc<br>
/// foo: return;<br>
///<br>
class LabelStmt : public Stmt {<br>
+ SourceLocation IdentLoc;<br>
LabelDecl *TheDecl;<br>
Stmt *SubStmt;<br>
- SourceLocation IdentLoc;<br>
+<br>
public:<br>
LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt)<br>
- : Stmt(LabelStmtClass), TheDecl(D), SubStmt(substmt), IdentLoc(IL) {<br>
- }<br>
+ : Stmt(LabelStmtClass), IdentLoc(IL), TheDecl(D), SubStmt(substmt) {}<br>
<br>
// \brief Build an empty label statement.<br>
explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { }<br>
@@ -943,16 +951,14 @@ public:<br>
/// SwitchStmt - This represents a 'switch' stmt.<br>
///<br>
class SwitchStmt : public Stmt {<br>
+ SourceLocation SwitchLoc;<br>
enum { VAR, COND, BODY, END_EXPR };<br>
Stmt* SubExprs[END_EXPR];<br>
- // This points to a linked list of case and default statements.<br>
- SwitchCase *FirstCase;<br>
- SourceLocation SwitchLoc;<br>
-<br>
- /// If the SwitchStmt is a switch on an enum value, this records whether<br>
- /// all the enum values were covered by CaseStmts. This value is meant to<br>
- /// be a hint for possible clients.<br>
- unsigned AllEnumCasesCovered : 1;<br>
+ // This points to a linked list of case and default statements and, if the<br>
+ // SwitchStmt is a switch on an enum value, records whether all the enum<br>
+ // values were covered by CaseStmts. The coverage information value is meant<br>
+ // to be a hint for possible clients.<br>
+ llvm::PointerIntPair<SwitchCase *, 1, bool> FirstCase;<br>
<br>
public:<br>
SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond);<br>
@@ -980,16 +986,16 @@ public:<br>
<br>
const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}<br>
const Stmt *getBody() const { return SubExprs[BODY]; }<br>
- const SwitchCase *getSwitchCaseList() const { return FirstCase; }<br>
+ const SwitchCase *getSwitchCaseList() const { return FirstCase.getPointer(); }<br>
<br>
Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);}<br>
void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }<br>
Stmt *getBody() { return SubExprs[BODY]; }<br>
void setBody(Stmt *S) { SubExprs[BODY] = S; }<br>
- SwitchCase *getSwitchCaseList() { return FirstCase; }<br>
+ SwitchCase *getSwitchCaseList() { return FirstCase.getPointer(); }<br>
<br>
/// \brief Set the case list for this switch statement.<br>
- void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }<br>
+ void setSwitchCaseList(SwitchCase *SC) { FirstCase.setPointer(SC); }<br>
<br>
SourceLocation getSwitchLoc() const { return SwitchLoc; }<br>
void setSwitchLoc(SourceLocation L) { SwitchLoc = L; }<br>
@@ -1001,21 +1007,17 @@ public:<br>
void addSwitchCase(SwitchCase *SC) {<br>
assert(!SC->getNextSwitchCase()<br>
&& "case/default already added to a switch");<br>
- SC->setNextSwitchCase(FirstCase);<br>
- FirstCase = SC;<br>
+ SC->setNextSwitchCase(FirstCase.getPointer());<br>
+ FirstCase.setPointer(SC);<br>
}<br>
<br>
/// Set a flag in the SwitchStmt indicating that if the 'switch (X)' is a<br>
/// switch over an enum value then all cases have been explicitly covered.<br>
- void setAllEnumCasesCovered() {<br>
- AllEnumCasesCovered = 1;<br>
- }<br>
+ void setAllEnumCasesCovered() { FirstCase.setInt(true); }<br>
<br>
/// Returns true if the SwitchStmt is a switch of an enum value and all cases<br>
/// have been explicitly covered.<br>
- bool isAllEnumCasesCovered() const {<br>
- return (bool) AllEnumCasesCovered;<br>
- }<br>
+ bool isAllEnumCasesCovered() const { return FirstCase.getInt(); }<br>
<br>
SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; }<br>
SourceLocation getLocEnd() const LLVM_READONLY {<br>
@@ -1036,9 +1038,9 @@ public:<br>
/// WhileStmt - This represents a 'while' stmt.<br>
///<br>
class WhileStmt : public Stmt {<br>
+ SourceLocation WhileLoc;<br>
enum { VAR, COND, BODY, END_EXPR };<br>
Stmt* SubExprs[END_EXPR];<br>
- SourceLocation WhileLoc;<br>
public:<br>
WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,<br>
SourceLocation WL);<br>
@@ -1091,9 +1093,9 @@ public:<br>
/// DoStmt - This represents a 'do/while' stmt.<br>
///<br>
class DoStmt : public Stmt {<br>
+ SourceLocation DoLoc;<br>
enum { BODY, COND, END_EXPR };<br>
Stmt* SubExprs[END_EXPR];<br>
- SourceLocation DoLoc;<br>
SourceLocation WhileLoc;<br>
SourceLocation RParenLoc; // Location of final ')' in do stmt condition.<br>
<br>
@@ -1142,9 +1144,9 @@ public:<br>
/// specified in the source.<br>
///<br>
class ForStmt : public Stmt {<br>
+ SourceLocation ForLoc;<br>
enum { INIT, CONDVAR, COND, INC, BODY, END_EXPR };<br>
Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt.<br>
- SourceLocation ForLoc;<br>
SourceLocation LParenLoc, RParenLoc;<br>
<br>
public:<br>
@@ -1345,18 +1347,16 @@ public:<br>
/// depend on the return type of the function and the presence of an argument.<br>
///<br>
class ReturnStmt : public Stmt {<br>
- Stmt *RetExpr;<br>
SourceLocation RetLoc;<br>
+ Stmt *RetExpr;<br>
const VarDecl *NRVOCandidate;<br>
<br>
public:<br>
- ReturnStmt(SourceLocation RL)<br>
- : Stmt(ReturnStmtClass), RetExpr(nullptr), RetLoc(RL),<br>
- NRVOCandidate(nullptr) {}<br>
+ explicit ReturnStmt(SourceLocation RL) : ReturnStmt(RL, nullptr, nullptr) {}<br>
<br>
ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)<br>
- : Stmt(ReturnStmtClass), RetExpr((Stmt*) E), RetLoc(RL),<br>
- NRVOCandidate(NRVOCandidate) {}<br>
+ : Stmt(ReturnStmtClass), RetLoc(RL), RetExpr((Stmt *)E),<br>
+ NRVOCandidate(NRVOCandidate) {}<br>
<br>
/// \brief Build an empty return expression.<br>
explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { }<br>
<br>
Modified: cfe/trunk/include/clang/AST/StmtCXX.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtCXX.h?rev=233921&r1=233920&r2=233921&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtCXX.h?rev=233921&r1=233920&r2=233921&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/StmtCXX.h (original)<br>
+++ cfe/trunk/include/clang/AST/StmtCXX.h Thu Apr 2 10:29:07 2015<br>
@@ -126,11 +126,11 @@ public:<br>
/// analysis of the constituent components. The original syntactic components<br>
/// can be extracted using getLoopVariable and getRangeInit.<br>
class CXXForRangeStmt : public Stmt {<br>
+ SourceLocation ForLoc;<br>
enum { RANGE, BEGINEND, COND, INC, LOOPVAR, BODY, END };<br>
// SubExprs[RANGE] is an expression or declstmt.<br>
// SubExprs[COND] and SubExprs[INC] are expressions.<br>
Stmt *SubExprs[END];<br>
- SourceLocation ForLoc;<br>
SourceLocation ColonLoc;<br>
SourceLocation RParenLoc;<br>
public:<br>
<br>
Modified: cfe/trunk/include/clang/AST/StmtObjC.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtObjC.h?rev=233921&r1=233920&r2=233921&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtObjC.h?rev=233921&r1=233920&r2=233921&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/StmtObjC.h (original)<br>
+++ cfe/trunk/include/clang/AST/StmtObjC.h Thu Apr 2 10:29:07 2015<br>
@@ -118,12 +118,13 @@ public:<br>
<br>
/// \brief Represents Objective-C's \@finally statement<br>
class ObjCAtFinallyStmt : public Stmt {<br>
- Stmt *AtFinallyStmt;<br>
SourceLocation AtFinallyLoc;<br>
+ Stmt *AtFinallyStmt;<br>
+<br>
public:<br>
ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt)<br>
- : Stmt(ObjCAtFinallyStmtClass),<br>
- AtFinallyStmt(atFinallyStmt), AtFinallyLoc(atFinallyLoc) {}<br>
+ : Stmt(ObjCAtFinallyStmtClass), AtFinallyLoc(atFinallyLoc),<br>
+ AtFinallyStmt(atFinallyStmt) {}<br>
<br>
explicit ObjCAtFinallyStmt(EmptyShell Empty) :<br>
Stmt(ObjCAtFinallyStmtClass, Empty) { }<br>
@@ -260,9 +261,9 @@ public:<br>
/// \endcode<br>
class ObjCAtSynchronizedStmt : public Stmt {<br>
private:<br>
+ SourceLocation AtSynchronizedLoc;<br>
enum { SYNC_EXPR, SYNC_BODY, END_EXPR };<br>
Stmt* SubStmts[END_EXPR];<br>
- SourceLocation AtSynchronizedLoc;<br>
<br>
public:<br>
ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr,<br>
@@ -310,8 +311,9 @@ public:<br>
<br>
/// \brief Represents Objective-C's \@throw statement.<br>
class ObjCAtThrowStmt : public Stmt {<br>
- Stmt *Throw;<br>
SourceLocation AtThrowLoc;<br>
+ Stmt *Throw;<br>
+<br>
public:<br>
ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr)<br>
: Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) {<br>
@@ -341,13 +343,12 @@ public:<br>
<br>
/// \brief Represents Objective-C's \@autoreleasepool Statement<br>
class ObjCAutoreleasePoolStmt : public Stmt {<br>
- Stmt *SubStmt;<br>
SourceLocation AtLoc;<br>
+ Stmt *SubStmt;<br>
+<br>
public:<br>
- ObjCAutoreleasePoolStmt(SourceLocation atLoc,<br>
- Stmt *subStmt)<br>
- : Stmt(ObjCAutoreleasePoolStmtClass),<br>
- SubStmt(subStmt), AtLoc(atLoc) {}<br>
+ ObjCAutoreleasePoolStmt(SourceLocation atLoc, Stmt *subStmt)<br>
+ : Stmt(ObjCAutoreleasePoolStmtClass), AtLoc(atLoc), SubStmt(subStmt) {}<br>
<br>
explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) :<br>
Stmt(ObjCAutoreleasePoolStmtClass, Empty) { }<br>
<br>
Modified: cfe/trunk/lib/AST/Stmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=233921&r1=233920&r2=233921&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=233921&r1=233920&r2=233921&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/Stmt.cpp (original)<br>
+++ cfe/trunk/lib/AST/Stmt.cpp Thu Apr 2 10:29:07 2015<br>
@@ -940,8 +940,7 @@ void ForStmt::setConditionVariable(const<br>
}<br>
<br>
SwitchStmt::SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond)<br>
- : Stmt(SwitchStmtClass), FirstCase(nullptr), AllEnumCasesCovered(0)<br>
-{<br>
+ : Stmt(SwitchStmtClass), FirstCase(nullptr, false) {<br>
setConditionVariable(C, Var);<br>
SubExprs[COND] = cond;<br>
SubExprs[BODY] = nullptr;<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>