xref: /llvm-project/clang/unittests/Interpreter/IncrementalProcessingTest.cpp (revision 647d2728c4dbc387521ce3984ebfda78ff2b031f)
192f9852fSVassil Vassilev //=== unittests/CodeGen/IncrementalProcessingTest.cpp - IncrementalCodeGen ===//
292f9852fSVassil Vassilev //
392f9852fSVassil Vassilev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
492f9852fSVassil Vassilev // See https://llvm.org/LICENSE.txt for license information.
592f9852fSVassil Vassilev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
692f9852fSVassil Vassilev //
792f9852fSVassil Vassilev //===----------------------------------------------------------------------===//
892f9852fSVassil Vassilev 
9a871470aSStefan Gränitz #include "InterpreterTestFixture.h"
10a871470aSStefan Gränitz 
1192f9852fSVassil Vassilev #include "clang/AST/ASTConsumer.h"
1292f9852fSVassil Vassilev #include "clang/AST/ASTContext.h"
1392f9852fSVassil Vassilev #include "clang/AST/RecursiveASTVisitor.h"
1492f9852fSVassil Vassilev #include "clang/Basic/TargetInfo.h"
1592f9852fSVassil Vassilev #include "clang/CodeGen/ModuleBuilder.h"
1692f9852fSVassil Vassilev #include "clang/Frontend/CompilerInstance.h"
1792f9852fSVassil Vassilev #include "clang/Interpreter/Interpreter.h"
1892f9852fSVassil Vassilev #include "clang/Lex/Preprocessor.h"
1992f9852fSVassil Vassilev #include "clang/Parse/Parser.h"
2092f9852fSVassil Vassilev #include "clang/Sema/Sema.h"
2198f9bb38SStefan Gränitz 
2292f9852fSVassil Vassilev #include "llvm/IR/LLVMContext.h"
2392f9852fSVassil Vassilev #include "llvm/IR/Module.h"
24d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h"
2562c7f035SArchibald Elliott #include "llvm/TargetParser/Triple.h"
26*647d2728SStefan Gränitz 
2792f9852fSVassil Vassilev #include "gtest/gtest.h"
2892f9852fSVassil Vassilev 
2992f9852fSVassil Vassilev #include <memory>
3092f9852fSVassil Vassilev 
3198f9bb38SStefan Gränitz #if defined(_AIX) || defined(__MVS__)
3298f9bb38SStefan Gränitz #define CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT
3398f9bb38SStefan Gränitz #endif
3498f9bb38SStefan Gränitz 
3592f9852fSVassil Vassilev using namespace llvm;
3692f9852fSVassil Vassilev using namespace clang;
3792f9852fSVassil Vassilev 
3892f9852fSVassil Vassilev namespace {
3992f9852fSVassil Vassilev 
40a871470aSStefan Gränitz class IncrementalProcessingTest : public InterpreterTestBase {};
41a871470aSStefan Gränitz 
4292f9852fSVassil Vassilev // Incremental processing produces several modules, all using the same "main
4392f9852fSVassil Vassilev // file". Make sure CodeGen can cope with that, e.g. for static initializers.
4492f9852fSVassil Vassilev const char TestProgram1[] = "extern \"C\" int funcForProg1() { return 17; }\n"
4592f9852fSVassil Vassilev                             "struct EmitCXXGlobalInitFunc1 {\n"
4692f9852fSVassil Vassilev                             "   EmitCXXGlobalInitFunc1() {}\n"
4792f9852fSVassil Vassilev                             "} test1;";
4892f9852fSVassil Vassilev 
4992f9852fSVassil Vassilev const char TestProgram2[] = "extern \"C\" int funcForProg2() { return 42; }\n"
5092f9852fSVassil Vassilev                             "struct EmitCXXGlobalInitFunc2 {\n"
5192f9852fSVassil Vassilev                             "   EmitCXXGlobalInitFunc2() {}\n"
5292f9852fSVassil Vassilev                             "} test2;";
5392f9852fSVassil Vassilev 
getGlobalInit(llvm::Module * M)5492f9852fSVassil Vassilev const Function *getGlobalInit(llvm::Module *M) {
5592f9852fSVassil Vassilev   for (const auto &Func : *M)
56f3dcc235SKazu Hirata     if (Func.hasName() && Func.getName().starts_with("_GLOBAL__sub_I_"))
5792f9852fSVassil Vassilev       return &Func;
5892f9852fSVassil Vassilev 
5992f9852fSVassil Vassilev   return nullptr;
6092f9852fSVassil Vassilev }
6192f9852fSVassil Vassilev 
TEST_F(IncrementalProcessingTest,EmitCXXGlobalInitFunc)62a871470aSStefan Gränitz TEST_F(IncrementalProcessingTest, EmitCXXGlobalInitFunc) {
6392f9852fSVassil Vassilev   std::vector<const char *> ClangArgv = {"-Xclang", "-emit-llvm-only"};
64ddeab07cSAnubhab Ghosh   auto CB = clang::IncrementalCompilerBuilder();
65ddeab07cSAnubhab Ghosh   CB.SetCompilerArgs(ClangArgv);
66ddeab07cSAnubhab Ghosh   auto CI = cantFail(CB.CreateCpp());
6792f9852fSVassil Vassilev   auto Interp = llvm::cantFail(Interpreter::create(std::move(CI)));
6892f9852fSVassil Vassilev 
6911b47c10SVassil Vassilev   std::array<clang::PartialTranslationUnit *, 2> PTUs;
7092f9852fSVassil Vassilev 
7111b47c10SVassil Vassilev   PTUs[0] = &llvm::cantFail(Interp->Parse(TestProgram1));
7211b47c10SVassil Vassilev   ASSERT_TRUE(PTUs[0]->TheModule);
7311b47c10SVassil Vassilev   ASSERT_TRUE(PTUs[0]->TheModule->getFunction("funcForProg1"));
7492f9852fSVassil Vassilev 
7511b47c10SVassil Vassilev   PTUs[1] = &llvm::cantFail(Interp->Parse(TestProgram2));
7611b47c10SVassil Vassilev   ASSERT_TRUE(PTUs[1]->TheModule);
7711b47c10SVassil Vassilev   ASSERT_TRUE(PTUs[1]->TheModule->getFunction("funcForProg2"));
7892f9852fSVassil Vassilev   // First code should not end up in second module:
7911b47c10SVassil Vassilev   ASSERT_FALSE(PTUs[1]->TheModule->getFunction("funcForProg1"));
8092f9852fSVassil Vassilev 
8192f9852fSVassil Vassilev   // Make sure global inits exist and are unique:
8211b47c10SVassil Vassilev   const Function *GlobalInit1 = getGlobalInit(PTUs[0]->TheModule.get());
8392f9852fSVassil Vassilev   ASSERT_TRUE(GlobalInit1);
8492f9852fSVassil Vassilev 
8511b47c10SVassil Vassilev   const Function *GlobalInit2 = getGlobalInit(PTUs[1]->TheModule.get());
8692f9852fSVassil Vassilev   ASSERT_TRUE(GlobalInit2);
8792f9852fSVassil Vassilev 
8892f9852fSVassil Vassilev   ASSERT_FALSE(GlobalInit1->getName() == GlobalInit2->getName());
8992f9852fSVassil Vassilev }
9092f9852fSVassil Vassilev 
9192f9852fSVassil Vassilev } // end anonymous namespace
92