summaryrefslogtreecommitdiffstats
path: root/clang/Lex/MacroExpander.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-07-21 06:38:30 +0000
committerChris Lattner <sabre@nondot.org>2006-07-21 06:38:30 +0000
commit36b6e8134eafb62da4a56581c35b4aa1ce3a797a (patch)
tree1b3952faaa539e1c6e19fbe8f850d4f87512583a /clang/Lex/MacroExpander.cpp
parent7fa8c889e2ba17be982a5279deceb91cdaa89e6a (diff)
downloadbcm5719-llvm-36b6e8134eafb62da4a56581c35b4aa1ce3a797a.tar.gz
bcm5719-llvm-36b6e8134eafb62da4a56581c35b4aa1ce3a797a.zip
speed up a brutal macro-expansion torture test by about 30% (1.5 -> 1.0s)
by turning vectors of vectors into a single vector, reducing pressure on malloc. This can still be improved. llvm-svn: 38753
Diffstat (limited to 'clang/Lex/MacroExpander.cpp')
-rw-r--r--clang/Lex/MacroExpander.cpp115
1 files changed, 60 insertions, 55 deletions
diff --git a/clang/Lex/MacroExpander.cpp b/clang/Lex/MacroExpander.cpp
index 38970eca510..817f68aa952 100644
--- a/clang/Lex/MacroExpander.cpp
+++ b/clang/Lex/MacroExpander.cpp
@@ -24,45 +24,34 @@ using namespace clang;
// MacroArgs Implementation
//===----------------------------------------------------------------------===//
-MacroArgs::MacroArgs(const MacroInfo *MI) {
+MacroArgs::MacroArgs(const MacroInfo *MI, std::vector<LexerToken> &UnexpArgs) {
assert(MI->isFunctionLike() &&
"Can't have args for an object-like macro!");
- // Reserve space for arguments to avoid reallocation.
- unsigned NumArgs = MI->getNumArgs();
- if (MI->isC99Varargs() || MI->isGNUVarargs())
- NumArgs += 3; // Varargs can have more than this, just some guess.
-
- UnexpArgTokens.reserve(NumArgs);
+ UnexpArgTokens.swap(UnexpArgs);
}
-/// addArgument - Add an argument for this invocation. This method destroys
-/// the vector passed in to avoid extraneous memory copies. This adds the EOF
-/// token to the end of the argument list as a marker. 'Loc' specifies a
-/// location at the end of the argument, e.g. the ',' token or the ')'.
-void MacroArgs::addArgument(std::vector<LexerToken> &ArgToks,
- SourceLocation Loc) {
- UnexpArgTokens.push_back(std::vector<LexerToken>());
- UnexpArgTokens.back().swap(ArgToks);
-
- // Add a marker EOF token to the end of the argument list, useful for handling
- // empty arguments and macro pre-expansion.
- LexerToken EOFTok;
- EOFTok.StartToken();
- EOFTok.SetKind(tok::eof);
- EOFTok.SetLocation(Loc);
- EOFTok.SetLength(0);
- UnexpArgTokens.back().push_back(EOFTok);
+/// getUnexpArgument - Return the unexpanded tokens for the specified formal.
+///
+const LexerToken *MacroArgs::getUnexpArgument(unsigned Arg) const {
+ // Scan to find Arg.
+ const LexerToken *Start = &UnexpArgTokens[0];
+ const LexerToken *Result = Start;
+ for (; Arg; ++Result) {
+ assert(Result < Start+UnexpArgTokens.size() && "Invalid arg #");
+ if (Result->getKind() == tok::eof)
+ --Arg;
+ }
+ return Result;
}
+
/// ArgNeedsPreexpansion - If we can prove that the argument won't be affected
/// by pre-expansion, return false. Otherwise, conservatively return true.
-bool MacroArgs::ArgNeedsPreexpansion(unsigned ArgNo) const {
- const std::vector<LexerToken> &ArgTokens = getUnexpArgument(ArgNo);
-
+bool MacroArgs::ArgNeedsPreexpansion(const LexerToken *ArgTok) const {
// If there are no identifiers in the argument list, or if the identifiers are
// known to not be macros, pre-expansion won't modify it.
- for (unsigned i = 0, e = ArgTokens.size()-1; i != e; ++i)
- if (IdentifierInfo *II = ArgTokens[i].getIdentifierInfo()) {
+ for (; ArgTok->getKind() != tok::eof; ++ArgTok)
+ if (IdentifierInfo *II = ArgTok->getIdentifierInfo()) {
if (II->getMacroInfo() && II->getMacroInfo()->isEnabled())
// Return true even though the macro could be a function-like macro
// without a following '(' token.
@@ -84,11 +73,21 @@ MacroArgs::getPreExpArgument(unsigned Arg, Preprocessor &PP) {
std::vector<LexerToken> &Result = PreExpArgTokens[Arg];
if (!Result.empty()) return Result;
+ // FIXME
+ // FIXME: Don't require copying into a temporary vector!!!
+ // FIXME
+
+ std::vector<LexerToken> UnexpArgToks;
+ const LexerToken *AT = getUnexpArgument(Arg);
+ for (; AT->getKind() != tok::eof; ++AT)
+ UnexpArgToks.push_back(*AT);
+ UnexpArgToks.push_back(*AT); // push the EOF too.
+
// Otherwise, we have to pre-expand this argument, populating Result. To do
// this, we set up a fake MacroExpander to lex from the unexpanded argument
// list. With this installed, we lex expanded tokens until we hit the EOF
// token at the end of the unexp list.
- PP.EnterTokenStream(UnexpArgTokens[Arg]);
+ PP.EnterTokenStream(UnexpArgToks);
// Lex all of the macro-expanded tokens into Result.
do {
@@ -110,19 +109,23 @@ MacroArgs::getPreExpArgument(unsigned Arg, Preprocessor &PP) {
/// tokens into the literal string token that should be produced by the C #
/// preprocessor operator.
///
-static LexerToken StringifyArgument(const std::vector<LexerToken> &Toks,
+static LexerToken StringifyArgument(const LexerToken *ArgToks,
Preprocessor &PP, bool Charify = false) {
LexerToken Tok;
Tok.StartToken();
Tok.SetKind(tok::string_literal);
+ const LexerToken *ArgTokStart = ArgToks;
+
// Stringify all the tokens.
std::string Result = "\"";
// FIXME: Optimize this loop to not use std::strings.
- for (unsigned i = 0, e = Toks.size()-1 /*no eof*/; i != e; ++i) {
- const LexerToken &Tok = Toks[i];
- if (i != 0 && Tok.hasLeadingSpace())
+ bool isFirst = true;
+ for (; ArgToks->getKind() != tok::eof; ++ArgToks) {
+ const LexerToken &Tok = *ArgToks;
+ if (!isFirst && Tok.hasLeadingSpace())
Result += ' ';
+ isFirst = false;
// If this is a string or character constant, escape the token as specified
// by 6.10.3.2p2.
@@ -146,7 +149,7 @@ static LexerToken StringifyArgument(const std::vector<LexerToken> &Toks,
--FirstNonSlash;
if ((Result.size()-1-FirstNonSlash) & 1) {
// Diagnose errors for things like: #define F(X) #X / F(\)
- PP.Diag(Toks.back(), diag::pp_invalid_string_literal);
+ PP.Diag(ArgToks[-1], diag::pp_invalid_string_literal);
Result.erase(Result.end()-1); // remove one of the \'s.
}
}
@@ -168,8 +171,7 @@ static LexerToken StringifyArgument(const std::vector<LexerToken> &Toks,
}
if (isBad) {
- assert(!Toks.empty() && "No eof token at least?");
- PP.Diag(Toks[0], diag::err_invalid_character_to_charify);
+ PP.Diag(ArgTokStart[0], diag::err_invalid_character_to_charify);
Result = "' '"; // Use something arbitrary, but legal.
}
}
@@ -190,7 +192,7 @@ const LexerToken &MacroArgs::getStringifiedArgument(unsigned ArgNo,
sizeof(StringifiedArgs[0])*getNumArguments());
}
if (StringifiedArgs[ArgNo].getKind() != tok::string_literal)
- StringifiedArgs[ArgNo] = StringifyArgument(UnexpArgTokens[ArgNo], PP);
+ StringifiedArgs[ArgNo] = StringifyArgument(getUnexpArgument(ArgNo), PP);
return StringifiedArgs[ArgNo];
}
@@ -305,34 +307,37 @@ void MacroExpander::ExpandFunctionArguments() {
// argument and substitute the expanded tokens into the result. This is
// C99 6.10.3.1p1.
if (!PasteBefore && !PasteAfter) {
- const std::vector<LexerToken> *ArgToks;
+ const LexerToken *ResultArgToks;
+
// Only preexpand the argument if it could possibly need it. This
// avoids some work in common cases.
- if (ActualArgs->ArgNeedsPreexpansion(ArgNo))
- ArgToks = &ActualArgs->getPreExpArgument(ArgNo, PP);
+ const LexerToken *ArgTok = ActualArgs->getUnexpArgument(ArgNo);
+ if (ActualArgs->ArgNeedsPreexpansion(ArgTok))
+ ResultArgToks = &ActualArgs->getPreExpArgument(ArgNo, PP)[0];
else
- ArgToks = &ActualArgs->getUnexpArgument(ArgNo);
+ ResultArgToks = ArgTok; // Use non-preexpanded tokens.
- unsigned FirstTok = ResultToks.size();
- ResultToks.insert(ResultToks.end(), ArgToks->begin(), ArgToks->end()-1);
+ if (ResultArgToks->getKind() != tok::eof) {
+ unsigned FirstResult = ResultToks.size();
+ for (; ResultArgToks->getKind() != tok::eof; ++ResultArgToks)
+ ResultToks.push_back(*ResultArgToks);
- // If any tokens were substituted from the argument, the whitespace
- // before the first token should match the whitespace of the arg
- // identifier.
- if (FirstTok != ResultToks.size())
- ResultToks[FirstTok].SetFlagValue(LexerToken::LeadingSpace,
- CurTok.hasLeadingSpace());
+ // If any tokens were substituted from the argument, the whitespace
+ // before the first token should match the whitespace of the arg
+ // identifier.
+ ResultToks[FirstResult].SetFlagValue(LexerToken::LeadingSpace,
+ CurTok.hasLeadingSpace());
+ }
continue;
}
// Okay, we have a token that is either the LHS or RHS of a paste (##)
// argument. It gets substituted as its non-pre-expanded tokens.
- const std::vector<LexerToken> &ArgToks =
- ActualArgs->getUnexpArgument(ArgNo);
- assert(ArgToks.back().getKind() == tok::eof && "Bad argument!");
+ const LexerToken *ArgToks = ActualArgs->getUnexpArgument(ArgNo);
- if (ArgToks.size() != 1) { // Not just an EOF token?
- ResultToks.insert(ResultToks.end(), ArgToks.begin(), ArgToks.end()-1);
+ if (ArgToks->getKind() != tok::eof) { // Not an empty argument?
+ for (; ArgToks->getKind() != tok::eof; ++ArgToks)
+ ResultToks.push_back(*ArgToks);
continue;
}
OpenPOWER on IntegriCloud