diff options
author | Bruno Ricci <riccibrun@gmail.com> | 2018-11-15 17:31:16 +0000 |
---|---|---|
committer | Bruno Ricci <riccibrun@gmail.com> | 2018-11-15 17:31:16 +0000 |
commit | b94ad1e1d383630f45c3e3d67d8a61a01d8045ed (patch) | |
tree | 90c5c2a854bbe7f4d276c9db2d7f036bfbd4cd7c /clang/lib/AST/Expr.cpp | |
parent | bc56b2432d83d12168680e6b2b50f261d1ff2ded (diff) | |
download | llvm-b94ad1e1d383630f45c3e3d67d8a61a01d8045ed.zip llvm-b94ad1e1d383630f45c3e3d67d8a61a01d8045ed.tar.gz llvm-b94ad1e1d383630f45c3e3d67d8a61a01d8045ed.tar.bz2 |
[AST] Store the string data in StringLiteral in a trailing array of chars
Use the newly available space in the bit-fields of Stmt and store the
string data in a trailing array of chars after the trailing array
of SourceLocation. This cuts the size of StringLiteral by 2 pointers.
Also refactor slightly StringLiteral::Create and StringLiteral::CreateEmpty
so that StringLiteral::Create is just responsible for the allocation, and the
constructor is responsible for doing all the initialization. This match what
is done for the other classes in general.
This patch should have no other functional changes apart from this.
A concern was raised during review about the interaction between
this patch and serialization abbreviations. I believe however that
there is currently no abbreviation defined for StringLiteral.
The only statements/expressions which have abbreviations are currently
DeclRefExpr, IntegerLiteral, CharacterLiteral and ImplicitCastExpr.
Differential Revision: https://reviews.llvm.org/D54166
Reviewed By: dblaikie, rjmccall
llvm-svn: 346969
Diffstat (limited to 'clang/lib/AST/Expr.cpp')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 132 |
1 files changed, 67 insertions, 65 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 37575e7..b811b22 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -912,42 +912,80 @@ unsigned StringLiteral::mapCharByteWidth(TargetInfo const &Target, return CharByteWidth; } -StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str, - StringKind Kind, bool Pascal, QualType Ty, - const SourceLocation *Loc, - unsigned NumStrs) { - assert(C.getAsConstantArrayType(Ty) && +StringLiteral::StringLiteral(const ASTContext &Ctx, StringRef Str, + StringKind Kind, bool Pascal, QualType Ty, + const SourceLocation *Loc, + unsigned NumConcatenated) + : Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false, + false) { + assert(Ctx.getAsConstantArrayType(Ty) && "StringLiteral must be of constant array type!"); + unsigned CharByteWidth = mapCharByteWidth(Ctx.getTargetInfo(), Kind); + unsigned ByteLength = Str.size(); + assert((ByteLength % CharByteWidth == 0) && + "The size of the data must be a multiple of CharByteWidth!"); + + // Avoid the expensive division. The compiler should be able to figure it + // out by itself. However as of clang 7, even with the appropriate + // llvm_unreachable added just here, it is not able to do so. + unsigned Length; + switch (CharByteWidth) { + case 1: + Length = ByteLength; + break; + case 2: + Length = ByteLength / 2; + break; + case 4: + Length = ByteLength / 4; + break; + default: + llvm_unreachable("Unsupported character width!"); + } - // Allocate enough space for the StringLiteral plus an array of locations for - // any concatenated string tokens. - void *Mem = - C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1), - alignof(StringLiteral)); - StringLiteral *SL = new (Mem) StringLiteral(Ty); + StringLiteralBits.Kind = Kind; + StringLiteralBits.CharByteWidth = CharByteWidth; + StringLiteralBits.IsPascal = Pascal; + StringLiteralBits.NumConcatenated = NumConcatenated; + *getTrailingObjects<unsigned>() = Length; - // OPTIMIZE: could allocate this appended to the StringLiteral. - SL->setString(C,Str,Kind,Pascal); + // Initialize the trailing array of SourceLocation. + // This is safe since SourceLocation is POD-like. + std::memcpy(getTrailingObjects<SourceLocation>(), Loc, + NumConcatenated * sizeof(SourceLocation)); - SL->TokLocs[0] = Loc[0]; - SL->NumConcatenated = NumStrs; + // Initialize the trailing array of char holding the string data. + std::memcpy(getTrailingObjects<char>(), Str.data(), ByteLength); +} - if (NumStrs != 1) - memcpy(&SL->TokLocs[1], Loc+1, sizeof(SourceLocation)*(NumStrs-1)); - return SL; +StringLiteral::StringLiteral(EmptyShell Empty, unsigned NumConcatenated, + unsigned Length, unsigned CharByteWidth) + : Expr(StringLiteralClass, Empty) { + StringLiteralBits.CharByteWidth = CharByteWidth; + StringLiteralBits.NumConcatenated = NumConcatenated; + *getTrailingObjects<unsigned>() = Length; } -StringLiteral *StringLiteral::CreateEmpty(const ASTContext &C, - unsigned NumStrs) { - void *Mem = - C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1), - alignof(StringLiteral)); - StringLiteral *SL = - new (Mem) StringLiteral(C.adjustStringLiteralBaseType(QualType())); - SL->CharByteWidth = 0; - SL->Length = 0; - SL->NumConcatenated = NumStrs; - return SL; +StringLiteral *StringLiteral::Create(const ASTContext &Ctx, StringRef Str, + StringKind Kind, bool Pascal, QualType Ty, + const SourceLocation *Loc, + unsigned NumConcatenated) { + void *Mem = Ctx.Allocate(totalSizeToAlloc<unsigned, SourceLocation, char>( + 1, NumConcatenated, Str.size()), + alignof(StringLiteral)); + return new (Mem) + StringLiteral(Ctx, Str, Kind, Pascal, Ty, Loc, NumConcatenated); +} + +StringLiteral *StringLiteral::CreateEmpty(const ASTContext &Ctx, + unsigned NumConcatenated, + unsigned Length, + unsigned CharByteWidth) { + void *Mem = Ctx.Allocate(totalSizeToAlloc<unsigned, SourceLocation, char>( + 1, NumConcatenated, Length * CharByteWidth), + alignof(StringLiteral)); + return new (Mem) + StringLiteral(EmptyShell(), NumConcatenated, Length, CharByteWidth); } void StringLiteral::outputString(raw_ostream &OS) const { @@ -1046,42 +1084,6 @@ void StringLiteral::outputString(raw_ostream &OS) const { OS << '"'; } -void StringLiteral::setString(const ASTContext &C, StringRef Str, - StringKind Kind, bool IsPascal) { - //FIXME: we assume that the string data comes from a target that uses the same - // code unit size and endianness for the type of string. - this->Kind = Kind; - this->IsPascal = IsPascal; - - CharByteWidth = mapCharByteWidth(C.getTargetInfo(),Kind); - assert((Str.size()%CharByteWidth == 0) - && "size of data must be multiple of CharByteWidth"); - Length = Str.size()/CharByteWidth; - - switch(CharByteWidth) { - case 1: { - char *AStrData = new (C) char[Length]; - std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData)); - StrData.asChar = AStrData; - break; - } - case 2: { - uint16_t *AStrData = new (C) uint16_t[Length]; - std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData)); - StrData.asUInt16 = AStrData; - break; - } - case 4: { - uint32_t *AStrData = new (C) uint32_t[Length]; - std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData)); - StrData.asUInt32 = AStrData; - break; - } - default: - llvm_unreachable("unsupported CharByteWidth"); - } -} - /// getLocationOfByte - Return a source location that points to the specified /// byte of this string literal. /// |