diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-12-10 01:11:47 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-12-10 01:11:47 +0000 |
commit | efb116fba6a88c42fc6d7e4449557700747f8da7 (patch) | |
tree | c8b05d0a99dd1348649ed349b28304640e852fd7 /clang/lib/AST/Expr.cpp | |
parent | 6fd28dfe5da554363ba599981a15c5a859a86ddd (diff) | |
download | bcm5719-llvm-efb116fba6a88c42fc6d7e4449557700747f8da7.tar.gz bcm5719-llvm-efb116fba6a88c42fc6d7e4449557700747f8da7.zip |
PR25416: Improve performance of processing inline assembly consisting of many
implicitly-concatenated string literals. When looking for the start of a token
in the inline assembly, start from the end of the previous token, not the start
of the entire string.
Patch by Yunlian Jiang!
llvm-svn: 255198
Diffstat (limited to 'clang/lib/AST/Expr.cpp')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 49 |
1 files changed, 39 insertions, 10 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 9996546a176..69b1121f3dc 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1007,15 +1007,33 @@ void StringLiteral::setString(const ASTContext &C, StringRef Str, /// can have escape sequences in them in addition to the usual trigraph and /// escaped newline business. This routine handles this complexity. /// -SourceLocation StringLiteral:: -getLocationOfByte(unsigned ByteNo, const SourceManager &SM, - const LangOptions &Features, const TargetInfo &Target) const { +/// The *StartToken sets the first token to be searched in this function and +/// the *StartTokenByteOffset is the byte offset of the first token. Before +/// returning, it updates the *StartToken to the TokNo of the token being found +/// and sets *StartTokenByteOffset to the byte offset of the token in the +/// string. +/// Using these two parameters can reduce the time complexity from O(n^2) to +/// O(n) if one wants to get the location of byte for all the tokens in a +/// string. +/// +SourceLocation +StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM, + const LangOptions &Features, + const TargetInfo &Target, unsigned *StartToken, + unsigned *StartTokenByteOffset) const { assert((Kind == StringLiteral::Ascii || Kind == StringLiteral::UTF8) && "Only narrow string literals are currently supported"); // Loop over all of the tokens in this string until we find the one that // contains the byte we're looking for. unsigned TokNo = 0; + unsigned StringOffset = 0; + if (StartToken) + TokNo = *StartToken; + if (StartTokenByteOffset) { + StringOffset = *StartTokenByteOffset; + ByteNo -= StringOffset; + } while (1) { assert(TokNo < getNumConcatenated() && "Invalid byte number!"); SourceLocation StrTokLoc = getStrTokenLoc(TokNo); @@ -1024,14 +1042,20 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM, // the string literal, not the identifier for the macro it is potentially // expanded through. SourceLocation StrTokSpellingLoc = SM.getSpellingLoc(StrTokLoc); - + // Re-lex the token to get its length and original spelling. - std::pair<FileID, unsigned> LocInfo =SM.getDecomposedLoc(StrTokSpellingLoc); + std::pair<FileID, unsigned> LocInfo = + SM.getDecomposedLoc(StrTokSpellingLoc); bool Invalid = false; StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); - if (Invalid) + if (Invalid) { + if (StartTokenByteOffset != nullptr) + *StartTokenByteOffset = StringOffset; + if (StartToken != nullptr) + *StartToken = TokNo; return StrTokSpellingLoc; - + } + const char *StrData = Buffer.data()+LocInfo.second; // Create a lexer starting at the beginning of this token. @@ -1047,14 +1071,19 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM, // If the byte is in this token, return the location of the byte. if (ByteNo < TokNumBytes || (ByteNo == TokNumBytes && TokNo == getNumConcatenated() - 1)) { - unsigned Offset = SLP.getOffsetOfStringByte(TheTok, ByteNo); - + unsigned Offset = SLP.getOffsetOfStringByte(TheTok, ByteNo); + // Now that we know the offset of the token in the spelling, use the // preprocessor to get the offset in the original source. + if (StartTokenByteOffset != nullptr) + *StartTokenByteOffset = StringOffset; + if (StartToken != nullptr) + *StartToken = TokNo; return Lexer::AdvanceToTokenCharacter(StrTokLoc, Offset, SM, Features); } - + // Move to the next string token. + StringOffset += TokNumBytes; ++TokNo; ByteNo -= TokNumBytes; } |