100cd6c04SAlex Lorenz //===- unittests/Lex/PPMemoryAllocationsTest.cpp - ----------------===//
200cd6c04SAlex Lorenz //
300cd6c04SAlex Lorenz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
400cd6c04SAlex Lorenz // See https://llvm.org/LICENSE.txt for license information.
500cd6c04SAlex Lorenz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
600cd6c04SAlex Lorenz //
700cd6c04SAlex Lorenz //===--------------------------------------------------------------===//
800cd6c04SAlex Lorenz
900cd6c04SAlex Lorenz #include "clang/Basic/Diagnostic.h"
1000cd6c04SAlex Lorenz #include "clang/Basic/DiagnosticOptions.h"
1100cd6c04SAlex Lorenz #include "clang/Basic/FileManager.h"
1200cd6c04SAlex Lorenz #include "clang/Basic/LangOptions.h"
1300cd6c04SAlex Lorenz #include "clang/Basic/SourceManager.h"
1400cd6c04SAlex Lorenz #include "clang/Basic/TargetInfo.h"
1500cd6c04SAlex Lorenz #include "clang/Basic/TargetOptions.h"
1600cd6c04SAlex Lorenz #include "clang/Lex/HeaderSearch.h"
1700cd6c04SAlex Lorenz #include "clang/Lex/HeaderSearchOptions.h"
1800cd6c04SAlex Lorenz #include "clang/Lex/ModuleLoader.h"
1900cd6c04SAlex Lorenz #include "clang/Lex/Preprocessor.h"
2000cd6c04SAlex Lorenz #include "clang/Lex/PreprocessorOptions.h"
2100cd6c04SAlex Lorenz #include "gtest/gtest.h"
2200cd6c04SAlex Lorenz
2300cd6c04SAlex Lorenz using namespace clang;
2400cd6c04SAlex Lorenz
2500cd6c04SAlex Lorenz namespace {
2600cd6c04SAlex Lorenz
2700cd6c04SAlex Lorenz class PPMemoryAllocationsTest : public ::testing::Test {
2800cd6c04SAlex Lorenz protected:
PPMemoryAllocationsTest()2900cd6c04SAlex Lorenz PPMemoryAllocationsTest()
3000cd6c04SAlex Lorenz : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()),
3100cd6c04SAlex Lorenz Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
3200cd6c04SAlex Lorenz SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) {
3300cd6c04SAlex Lorenz TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
3400cd6c04SAlex Lorenz Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
3500cd6c04SAlex Lorenz }
3600cd6c04SAlex Lorenz
3700cd6c04SAlex Lorenz FileSystemOptions FileMgrOpts;
3800cd6c04SAlex Lorenz FileManager FileMgr;
3900cd6c04SAlex Lorenz IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
4000cd6c04SAlex Lorenz DiagnosticsEngine Diags;
4100cd6c04SAlex Lorenz SourceManager SourceMgr;
4200cd6c04SAlex Lorenz LangOptions LangOpts;
4300cd6c04SAlex Lorenz std::shared_ptr<TargetOptions> TargetOpts;
4400cd6c04SAlex Lorenz IntrusiveRefCntPtr<TargetInfo> Target;
4500cd6c04SAlex Lorenz };
4600cd6c04SAlex Lorenz
TEST_F(PPMemoryAllocationsTest,PPMacroDefinesAllocations)4700cd6c04SAlex Lorenz TEST_F(PPMemoryAllocationsTest, PPMacroDefinesAllocations) {
4800cd6c04SAlex Lorenz std::string Source;
4900cd6c04SAlex Lorenz size_t NumMacros = 1000000;
5000cd6c04SAlex Lorenz {
5100cd6c04SAlex Lorenz llvm::raw_string_ostream SourceOS(Source);
5200cd6c04SAlex Lorenz
5300cd6c04SAlex Lorenz // Create a combination of 1 or 3 token macros.
5400cd6c04SAlex Lorenz for (size_t I = 0; I < NumMacros; ++I) {
5500cd6c04SAlex Lorenz SourceOS << "#define MACRO_ID_" << I << " ";
5600cd6c04SAlex Lorenz if ((I % 2) == 0)
5700cd6c04SAlex Lorenz SourceOS << "(" << I << ")";
5800cd6c04SAlex Lorenz else
5900cd6c04SAlex Lorenz SourceOS << I;
6000cd6c04SAlex Lorenz SourceOS << "\n";
6100cd6c04SAlex Lorenz }
6200cd6c04SAlex Lorenz }
6300cd6c04SAlex Lorenz
6400cd6c04SAlex Lorenz std::unique_ptr<llvm::MemoryBuffer> Buf =
6500cd6c04SAlex Lorenz llvm::MemoryBuffer::getMemBuffer(Source);
6600cd6c04SAlex Lorenz SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
6700cd6c04SAlex Lorenz
6800cd6c04SAlex Lorenz TrivialModuleLoader ModLoader;
6900cd6c04SAlex Lorenz HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
7000cd6c04SAlex Lorenz Diags, LangOpts, Target.get());
7100cd6c04SAlex Lorenz Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
7200cd6c04SAlex Lorenz SourceMgr, HeaderInfo, ModLoader,
7300cd6c04SAlex Lorenz /*IILookup =*/nullptr,
7400cd6c04SAlex Lorenz /*OwnsHeaderSearch =*/false);
7500cd6c04SAlex Lorenz PP.Initialize(*Target);
7600cd6c04SAlex Lorenz PP.EnterMainSourceFile();
7700cd6c04SAlex Lorenz
78*3116d604SJonas Hahnfeld PP.LexTokensUntilEOF();
7900cd6c04SAlex Lorenz
8000cd6c04SAlex Lorenz size_t NumAllocated = PP.getPreprocessorAllocator().getBytesAllocated();
8100cd6c04SAlex Lorenz float BytesPerDefine = float(NumAllocated) / float(NumMacros);
8200cd6c04SAlex Lorenz llvm::errs() << "Num preprocessor allocations for " << NumMacros
8300cd6c04SAlex Lorenz << " #define: " << NumAllocated << "\n";
8400cd6c04SAlex Lorenz llvm::errs() << "Bytes per #define: " << BytesPerDefine << "\n";
8500cd6c04SAlex Lorenz // On arm64-apple-macos, we get around 120 bytes per define.
8600cd6c04SAlex Lorenz // Assume a reasonable upper bound based on that number that we don't want
8700cd6c04SAlex Lorenz // to exceed when storing information about a macro #define with 1 or 3
8800cd6c04SAlex Lorenz // tokens.
8900cd6c04SAlex Lorenz EXPECT_LT(BytesPerDefine, 130.0f);
9000cd6c04SAlex Lorenz }
9100cd6c04SAlex Lorenz
9200cd6c04SAlex Lorenz } // anonymous namespace
93