| //===- unittests/Lex/PPMemoryAllocationsTest.cpp - ----------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===--------------------------------------------------------------===// |
| |
| #include "clang/Basic/Diagnostic.h" |
| #include "clang/Basic/DiagnosticOptions.h" |
| #include "clang/Basic/FileManager.h" |
| #include "clang/Basic/LangOptions.h" |
| #include "clang/Basic/SourceManager.h" |
| #include "clang/Basic/TargetInfo.h" |
| #include "clang/Basic/TargetOptions.h" |
| #include "clang/Lex/HeaderSearch.h" |
| #include "clang/Lex/HeaderSearchOptions.h" |
| #include "clang/Lex/ModuleLoader.h" |
| #include "clang/Lex/Preprocessor.h" |
| #include "clang/Lex/PreprocessorOptions.h" |
| #include "gtest/gtest.h" |
| |
| using namespace clang; |
| |
| namespace { |
| |
| class PPMemoryAllocationsTest : public ::testing::Test { |
| protected: |
| PPMemoryAllocationsTest() |
| : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), |
| Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()), |
| SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) { |
| TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; |
| Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); |
| } |
| |
| FileSystemOptions FileMgrOpts; |
| FileManager FileMgr; |
| IntrusiveRefCntPtr<DiagnosticIDs> DiagID; |
| DiagnosticsEngine Diags; |
| SourceManager SourceMgr; |
| LangOptions LangOpts; |
| std::shared_ptr<TargetOptions> TargetOpts; |
| IntrusiveRefCntPtr<TargetInfo> Target; |
| }; |
| |
| TEST_F(PPMemoryAllocationsTest, PPMacroDefinesAllocations) { |
| std::string Source; |
| size_t NumMacros = 1000000; |
| { |
| llvm::raw_string_ostream SourceOS(Source); |
| |
| // Create a combination of 1 or 3 token macros. |
| for (size_t I = 0; I < NumMacros; ++I) { |
| SourceOS << "#define MACRO_ID_" << I << " "; |
| if ((I % 2) == 0) |
| SourceOS << "(" << I << ")"; |
| else |
| SourceOS << I; |
| SourceOS << "\n"; |
| } |
| } |
| |
| std::unique_ptr<llvm::MemoryBuffer> Buf = |
| llvm::MemoryBuffer::getMemBuffer(Source); |
| SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf))); |
| |
| TrivialModuleLoader ModLoader; |
| HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, |
| Diags, LangOpts, Target.get()); |
| Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts, |
| SourceMgr, HeaderInfo, ModLoader, |
| /*IILookup =*/nullptr, |
| /*OwnsHeaderSearch =*/false); |
| PP.Initialize(*Target); |
| PP.EnterMainSourceFile(); |
| |
| while (1) { |
| Token tok; |
| PP.Lex(tok); |
| if (tok.is(tok::eof)) |
| break; |
| } |
| |
| size_t NumAllocated = PP.getPreprocessorAllocator().getBytesAllocated(); |
| float BytesPerDefine = float(NumAllocated) / float(NumMacros); |
| llvm::errs() << "Num preprocessor allocations for " << NumMacros |
| << " #define: " << NumAllocated << "\n"; |
| llvm::errs() << "Bytes per #define: " << BytesPerDefine << "\n"; |
| // On arm64-apple-macos, we get around 120 bytes per define. |
| // Assume a reasonable upper bound based on that number that we don't want |
| // to exceed when storing information about a macro #define with 1 or 3 |
| // tokens. |
| EXPECT_LT(BytesPerDefine, 130.0f); |
| } |
| |
| } // anonymous namespace |