1f3d9b488SAdrian Prantl //===- unittests/CodeGen/CodeGenExternalTest.cpp - test external CodeGen -===//
2f3d9b488SAdrian Prantl //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f3d9b488SAdrian Prantl //
7f3d9b488SAdrian Prantl //===----------------------------------------------------------------------===//
8f3d9b488SAdrian Prantl 
9f3d9b488SAdrian Prantl #include "clang/AST/ASTConsumer.h"
10f3d9b488SAdrian Prantl #include "clang/AST/ASTContext.h"
11f3d9b488SAdrian Prantl #include "clang/AST/GlobalDecl.h"
12f3d9b488SAdrian Prantl #include "clang/AST/RecursiveASTVisitor.h"
13f3d9b488SAdrian Prantl #include "clang/Basic/TargetInfo.h"
14f3d9b488SAdrian Prantl #include "clang/CodeGen/CodeGenABITypes.h"
15f3d9b488SAdrian Prantl #include "clang/CodeGen/ModuleBuilder.h"
16f3d9b488SAdrian Prantl #include "clang/Frontend/CompilerInstance.h"
17f3d9b488SAdrian Prantl #include "clang/Lex/Preprocessor.h"
18f3d9b488SAdrian Prantl #include "clang/Parse/ParseAST.h"
19f3d9b488SAdrian Prantl #include "clang/Sema/Sema.h"
20f3d9b488SAdrian Prantl #include "llvm/ADT/Triple.h"
21f3d9b488SAdrian Prantl #include "llvm/IR/Instructions.h"
22f3d9b488SAdrian Prantl #include "llvm/IR/LLVMContext.h"
23f3d9b488SAdrian Prantl #include "llvm/Support/Debug.h"
24f3d9b488SAdrian Prantl #include "llvm/Support/Host.h"
25f3d9b488SAdrian Prantl #include "llvm/Support/MemoryBuffer.h"
26f3d9b488SAdrian Prantl #include "gtest/gtest.h"
27f3d9b488SAdrian Prantl 
28f3d9b488SAdrian Prantl using namespace llvm;
29f3d9b488SAdrian Prantl using namespace clang;
30f3d9b488SAdrian Prantl 
31f3d9b488SAdrian Prantl namespace {
32f3d9b488SAdrian Prantl 
33f3d9b488SAdrian Prantl // Mocks up a language using Clang code generation as a library and
34f3d9b488SAdrian Prantl // tests some basic functionality there.
35f3d9b488SAdrian Prantl //   - CodeGen->GetAddrOfGlobal
36f3d9b488SAdrian Prantl //   - CodeGen::convertTypeForMemory
37f3d9b488SAdrian Prantl //   - CodeGen::getLLVMFieldNumber
38f3d9b488SAdrian Prantl 
39f3d9b488SAdrian Prantl static const bool DebugThisTest = false;
40f3d9b488SAdrian Prantl 
41f3d9b488SAdrian Prantl // forward declarations
42f3d9b488SAdrian Prantl struct MyASTConsumer;
43f3d9b488SAdrian Prantl static void test_codegen_fns(MyASTConsumer *my);
44f3d9b488SAdrian Prantl static bool test_codegen_fns_ran;
45f3d9b488SAdrian Prantl 
46f3d9b488SAdrian Prantl // This forwards the calls to the Clang CodeGenerator
47f3d9b488SAdrian Prantl // so that we can test CodeGen functions while it is open.
48f3d9b488SAdrian Prantl // It accumulates toplevel decls in HandleTopLevelDecl and
49f3d9b488SAdrian Prantl // calls test_codegen_fns() in HandleTranslationUnit
50f3d9b488SAdrian Prantl // before forwarding that function to the CodeGenerator.
51f3d9b488SAdrian Prantl 
52f3d9b488SAdrian Prantl struct MyASTConsumer : public ASTConsumer {
53f3d9b488SAdrian Prantl   std::unique_ptr<CodeGenerator> Builder;
54f3d9b488SAdrian Prantl   std::vector<Decl*> toplevel_decls;
55f3d9b488SAdrian Prantl 
56f3d9b488SAdrian Prantl   MyASTConsumer(std::unique_ptr<CodeGenerator> Builder_in)
57f3d9b488SAdrian Prantl     : ASTConsumer(), Builder(std::move(Builder_in))
58f3d9b488SAdrian Prantl   {
59f3d9b488SAdrian Prantl   }
60f3d9b488SAdrian Prantl 
61f3d9b488SAdrian Prantl   ~MyASTConsumer() { }
62f3d9b488SAdrian Prantl 
63f3d9b488SAdrian Prantl   void Initialize(ASTContext &Context) override;
64f3d9b488SAdrian Prantl   void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override;
65f3d9b488SAdrian Prantl   bool HandleTopLevelDecl(DeclGroupRef D) override;
66f3d9b488SAdrian Prantl   void HandleInlineFunctionDefinition(FunctionDecl *D) override;
67f3d9b488SAdrian Prantl   void HandleInterestingDecl(DeclGroupRef D) override;
68f3d9b488SAdrian Prantl   void HandleTranslationUnit(ASTContext &Ctx) override;
69f3d9b488SAdrian Prantl   void HandleTagDeclDefinition(TagDecl *D) override;
70f3d9b488SAdrian Prantl   void HandleTagDeclRequiredDefinition(const TagDecl *D) override;
71f3d9b488SAdrian Prantl   void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override;
72f3d9b488SAdrian Prantl   void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override;
73f3d9b488SAdrian Prantl   void HandleImplicitImportDecl(ImportDecl *D) override;
74f3d9b488SAdrian Prantl   void CompleteTentativeDefinition(VarDecl *D) override;
75f3d9b488SAdrian Prantl   void AssignInheritanceModel(CXXRecordDecl *RD) override;
76f3d9b488SAdrian Prantl   void HandleVTable(CXXRecordDecl *RD) override;
77f3d9b488SAdrian Prantl   ASTMutationListener *GetASTMutationListener() override;
78f3d9b488SAdrian Prantl   ASTDeserializationListener *GetASTDeserializationListener() override;
79f3d9b488SAdrian Prantl   void PrintStats() override;
80f3d9b488SAdrian Prantl   bool shouldSkipFunctionBody(Decl *D) override;
81f3d9b488SAdrian Prantl };
82f3d9b488SAdrian Prantl 
83f3d9b488SAdrian Prantl void MyASTConsumer::Initialize(ASTContext &Context) {
84f3d9b488SAdrian Prantl   Builder->Initialize(Context);
85f3d9b488SAdrian Prantl }
86f3d9b488SAdrian Prantl 
87f3d9b488SAdrian Prantl bool MyASTConsumer::HandleTopLevelDecl(DeclGroupRef DG) {
88f3d9b488SAdrian Prantl 
89f3d9b488SAdrian Prantl   for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
90f3d9b488SAdrian Prantl     toplevel_decls.push_back(*I);
91f3d9b488SAdrian Prantl   }
92f3d9b488SAdrian Prantl 
93f3d9b488SAdrian Prantl   return Builder->HandleTopLevelDecl(DG);
94f3d9b488SAdrian Prantl }
95f3d9b488SAdrian Prantl 
96f3d9b488SAdrian Prantl void MyASTConsumer::HandleInlineFunctionDefinition(FunctionDecl *D) {
97f3d9b488SAdrian Prantl   Builder->HandleInlineFunctionDefinition(D);
98f3d9b488SAdrian Prantl }
99f3d9b488SAdrian Prantl 
100f3d9b488SAdrian Prantl void MyASTConsumer::HandleInterestingDecl(DeclGroupRef D) {
101f3d9b488SAdrian Prantl   Builder->HandleInterestingDecl(D);
102f3d9b488SAdrian Prantl }
103f3d9b488SAdrian Prantl 
104f3d9b488SAdrian Prantl void MyASTConsumer::HandleTranslationUnit(ASTContext &Context) {
105f3d9b488SAdrian Prantl   test_codegen_fns(this);
106f3d9b488SAdrian Prantl   // HandleTranslationUnit can close the module
107f3d9b488SAdrian Prantl   Builder->HandleTranslationUnit(Context);
108f3d9b488SAdrian Prantl }
109f3d9b488SAdrian Prantl 
110f3d9b488SAdrian Prantl void MyASTConsumer::HandleTagDeclDefinition(TagDecl *D) {
111f3d9b488SAdrian Prantl   Builder->HandleTagDeclDefinition(D);
112f3d9b488SAdrian Prantl }
113f3d9b488SAdrian Prantl 
114f3d9b488SAdrian Prantl void MyASTConsumer::HandleTagDeclRequiredDefinition(const TagDecl *D) {
115f3d9b488SAdrian Prantl   Builder->HandleTagDeclRequiredDefinition(D);
116f3d9b488SAdrian Prantl }
117f3d9b488SAdrian Prantl 
118f3d9b488SAdrian Prantl void MyASTConsumer::HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {
119f3d9b488SAdrian Prantl   Builder->HandleCXXImplicitFunctionInstantiation(D);
120f3d9b488SAdrian Prantl }
121f3d9b488SAdrian Prantl 
122f3d9b488SAdrian Prantl void MyASTConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef D) {
123f3d9b488SAdrian Prantl   Builder->HandleTopLevelDeclInObjCContainer(D);
124f3d9b488SAdrian Prantl }
125f3d9b488SAdrian Prantl 
126f3d9b488SAdrian Prantl void MyASTConsumer::HandleImplicitImportDecl(ImportDecl *D) {
127f3d9b488SAdrian Prantl   Builder->HandleImplicitImportDecl(D);
128f3d9b488SAdrian Prantl }
129f3d9b488SAdrian Prantl 
130f3d9b488SAdrian Prantl void MyASTConsumer::CompleteTentativeDefinition(VarDecl *D) {
131f3d9b488SAdrian Prantl   Builder->CompleteTentativeDefinition(D);
132f3d9b488SAdrian Prantl }
133f3d9b488SAdrian Prantl 
134f3d9b488SAdrian Prantl void MyASTConsumer::AssignInheritanceModel(CXXRecordDecl *RD) {
135f3d9b488SAdrian Prantl   Builder->AssignInheritanceModel(RD);
136f3d9b488SAdrian Prantl }
137f3d9b488SAdrian Prantl 
138f3d9b488SAdrian Prantl void MyASTConsumer::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) {
139f3d9b488SAdrian Prantl    Builder->HandleCXXStaticMemberVarInstantiation(VD);
140f3d9b488SAdrian Prantl }
141f3d9b488SAdrian Prantl 
142f3d9b488SAdrian Prantl void MyASTConsumer::HandleVTable(CXXRecordDecl *RD) {
143f3d9b488SAdrian Prantl    Builder->HandleVTable(RD);
144f3d9b488SAdrian Prantl  }
145f3d9b488SAdrian Prantl 
146f3d9b488SAdrian Prantl ASTMutationListener *MyASTConsumer::GetASTMutationListener() {
147f3d9b488SAdrian Prantl   return Builder->GetASTMutationListener();
148f3d9b488SAdrian Prantl }
149f3d9b488SAdrian Prantl 
150f3d9b488SAdrian Prantl ASTDeserializationListener *MyASTConsumer::GetASTDeserializationListener() {
151f3d9b488SAdrian Prantl   return Builder->GetASTDeserializationListener();
152f3d9b488SAdrian Prantl }
153f3d9b488SAdrian Prantl 
154f3d9b488SAdrian Prantl void MyASTConsumer::PrintStats() {
155f3d9b488SAdrian Prantl   Builder->PrintStats();
156f3d9b488SAdrian Prantl }
157f3d9b488SAdrian Prantl 
158f3d9b488SAdrian Prantl bool MyASTConsumer::shouldSkipFunctionBody(Decl *D) {
159f3d9b488SAdrian Prantl   return Builder->shouldSkipFunctionBody(D);
160f3d9b488SAdrian Prantl }
161f3d9b488SAdrian Prantl 
162f3d9b488SAdrian Prantl const char TestProgram[] =
163f3d9b488SAdrian Prantl     "struct mytest_struct { char x; short y; char p; long z; };\n"
164f3d9b488SAdrian Prantl     "int mytest_fn(int x) { return x; }\n";
165f3d9b488SAdrian Prantl 
166f3d9b488SAdrian Prantl // This function has the real test code here
167f3d9b488SAdrian Prantl static void test_codegen_fns(MyASTConsumer *my) {
168f3d9b488SAdrian Prantl 
169f3d9b488SAdrian Prantl   bool mytest_fn_ok = false;
170f3d9b488SAdrian Prantl   bool mytest_struct_ok = false;
171f3d9b488SAdrian Prantl 
172f3d9b488SAdrian Prantl   CodeGen::CodeGenModule &CGM = my->Builder->CGM();
173f3d9b488SAdrian Prantl 
174f3d9b488SAdrian Prantl   for (auto decl : my->toplevel_decls ) {
175f3d9b488SAdrian Prantl     if (FunctionDecl *fd = dyn_cast<FunctionDecl>(decl)) {
176f3d9b488SAdrian Prantl       if (fd->getName() == "mytest_fn") {
177f3d9b488SAdrian Prantl         Constant *c = my->Builder->GetAddrOfGlobal(GlobalDecl(fd), false);
178f3d9b488SAdrian Prantl         // Verify that we got a function.
179f3d9b488SAdrian Prantl         ASSERT_TRUE(c != NULL);
180f3d9b488SAdrian Prantl         if (DebugThisTest) {
181f3d9b488SAdrian Prantl           c->print(dbgs(), true);
182f3d9b488SAdrian Prantl           dbgs() << "\n";
183f3d9b488SAdrian Prantl         }
184f3d9b488SAdrian Prantl         mytest_fn_ok = true;
185f3d9b488SAdrian Prantl       }
186f3d9b488SAdrian Prantl     } else if(clang::RecordDecl *rd = dyn_cast<RecordDecl>(decl)) {
187f3d9b488SAdrian Prantl       if (rd->getName() == "mytest_struct") {
188f3d9b488SAdrian Prantl         RecordDecl *def = rd->getDefinition();
189f3d9b488SAdrian Prantl         ASSERT_TRUE(def != NULL);
190f3d9b488SAdrian Prantl         const clang::Type *clangTy = rd->getCanonicalDecl()->getTypeForDecl();
191f3d9b488SAdrian Prantl         ASSERT_TRUE(clangTy != NULL);
192f3d9b488SAdrian Prantl         QualType qType = clangTy->getCanonicalTypeInternal();
193f3d9b488SAdrian Prantl 
194f3d9b488SAdrian Prantl         // Check convertTypeForMemory
195f3d9b488SAdrian Prantl         llvm::Type *llvmTy = CodeGen::convertTypeForMemory(CGM, qType);
196f3d9b488SAdrian Prantl         ASSERT_TRUE(llvmTy != NULL);
197f3d9b488SAdrian Prantl         if (DebugThisTest) {
198f3d9b488SAdrian Prantl           llvmTy->print(dbgs(), true);
199f3d9b488SAdrian Prantl           dbgs() << "\n";
200f3d9b488SAdrian Prantl         }
201f3d9b488SAdrian Prantl 
202*e24e95feSEli Friedman         auto* structTy = dyn_cast<llvm::StructType>(llvmTy);
203f3d9b488SAdrian Prantl         ASSERT_TRUE(structTy != NULL);
204f3d9b488SAdrian Prantl 
205f3d9b488SAdrian Prantl         // Check getLLVMFieldNumber
206f3d9b488SAdrian Prantl         FieldDecl *xField = NULL;
207f3d9b488SAdrian Prantl         FieldDecl *yField = NULL;
208f3d9b488SAdrian Prantl         FieldDecl *zField = NULL;
209f3d9b488SAdrian Prantl 
210f3d9b488SAdrian Prantl         for (auto field : rd->fields()) {
211f3d9b488SAdrian Prantl           if (field->getName() == "x") xField = field;
212f3d9b488SAdrian Prantl           if (field->getName() == "y") yField = field;
213f3d9b488SAdrian Prantl           if (field->getName() == "z") zField = field;
214f3d9b488SAdrian Prantl         }
215f3d9b488SAdrian Prantl 
216f3d9b488SAdrian Prantl         ASSERT_TRUE(xField != NULL);
217f3d9b488SAdrian Prantl         ASSERT_TRUE(yField != NULL);
218f3d9b488SAdrian Prantl         ASSERT_TRUE(zField != NULL);
219f3d9b488SAdrian Prantl 
220f3d9b488SAdrian Prantl         unsigned x = CodeGen::getLLVMFieldNumber(CGM, rd, xField);
221f3d9b488SAdrian Prantl         unsigned y = CodeGen::getLLVMFieldNumber(CGM, rd, yField);
222f3d9b488SAdrian Prantl         unsigned z = CodeGen::getLLVMFieldNumber(CGM, rd, zField);
223f3d9b488SAdrian Prantl 
224f3d9b488SAdrian Prantl         ASSERT_NE(x, y);
225f3d9b488SAdrian Prantl         ASSERT_NE(y, z);
226f3d9b488SAdrian Prantl 
227f3d9b488SAdrian Prantl         llvm::Type* xTy = structTy->getTypeAtIndex(x);
228f3d9b488SAdrian Prantl         llvm::Type* yTy = structTy->getTypeAtIndex(y);
229f3d9b488SAdrian Prantl         llvm::Type* zTy = structTy->getTypeAtIndex(z);
230f3d9b488SAdrian Prantl 
231f3d9b488SAdrian Prantl         ASSERT_TRUE(xTy != NULL);
232f3d9b488SAdrian Prantl         ASSERT_TRUE(yTy != NULL);
233f3d9b488SAdrian Prantl         ASSERT_TRUE(zTy != NULL);
234f3d9b488SAdrian Prantl 
235f3d9b488SAdrian Prantl         if (DebugThisTest) {
236f3d9b488SAdrian Prantl           xTy->print(dbgs(), true);
237f3d9b488SAdrian Prantl           dbgs() << "\n";
238f3d9b488SAdrian Prantl           yTy->print(dbgs(), true);
239f3d9b488SAdrian Prantl           dbgs() << "\n";
240f3d9b488SAdrian Prantl           zTy->print(dbgs(), true);
241f3d9b488SAdrian Prantl           dbgs() << "\n";
242f3d9b488SAdrian Prantl         }
243f3d9b488SAdrian Prantl 
244f3d9b488SAdrian Prantl         ASSERT_GE(xTy->getPrimitiveSizeInBits(), 1u);
245f3d9b488SAdrian Prantl         ASSERT_GE(yTy->getPrimitiveSizeInBits(), 16u); // short is at least 16b
246f3d9b488SAdrian Prantl         ASSERT_GE(zTy->getPrimitiveSizeInBits(), 32u); // long is at least 32b
247f3d9b488SAdrian Prantl 
248f3d9b488SAdrian Prantl         mytest_struct_ok = true;
249f3d9b488SAdrian Prantl       }
250f3d9b488SAdrian Prantl     }
251f3d9b488SAdrian Prantl   }
252f3d9b488SAdrian Prantl 
253f3d9b488SAdrian Prantl   ASSERT_TRUE(mytest_fn_ok);
254f3d9b488SAdrian Prantl   ASSERT_TRUE(mytest_struct_ok);
255f3d9b488SAdrian Prantl 
256f3d9b488SAdrian Prantl   test_codegen_fns_ran = true;
257f3d9b488SAdrian Prantl }
258f3d9b488SAdrian Prantl 
259f3d9b488SAdrian Prantl TEST(CodeGenExternalTest, CodeGenExternalTest) {
260f3d9b488SAdrian Prantl     LLVMContext Context;
261f3d9b488SAdrian Prantl     CompilerInstance compiler;
262f3d9b488SAdrian Prantl 
263f3d9b488SAdrian Prantl     compiler.createDiagnostics();
264f3d9b488SAdrian Prantl     compiler.getLangOpts().CPlusPlus = 1;
265f3d9b488SAdrian Prantl     compiler.getLangOpts().CPlusPlus11 = 1;
266f3d9b488SAdrian Prantl 
267f3d9b488SAdrian Prantl     compiler.getTargetOpts().Triple = llvm::Triple::normalize(
268f3d9b488SAdrian Prantl         llvm::sys::getProcessTriple());
269f3d9b488SAdrian Prantl     compiler.setTarget(clang::TargetInfo::CreateTargetInfo(
270f3d9b488SAdrian Prantl       compiler.getDiagnostics(),
271f3d9b488SAdrian Prantl       std::make_shared<clang::TargetOptions>(
272f3d9b488SAdrian Prantl         compiler.getTargetOpts())));
273f3d9b488SAdrian Prantl 
274f3d9b488SAdrian Prantl     compiler.createFileManager();
275f3d9b488SAdrian Prantl     compiler.createSourceManager(compiler.getFileManager());
276f3d9b488SAdrian Prantl     compiler.createPreprocessor(clang::TU_Prefix);
277f3d9b488SAdrian Prantl 
278f3d9b488SAdrian Prantl     compiler.createASTContext();
279f3d9b488SAdrian Prantl 
280f3d9b488SAdrian Prantl 
281f3d9b488SAdrian Prantl     compiler.setASTConsumer(std::unique_ptr<ASTConsumer>(
282f3d9b488SAdrian Prantl           new MyASTConsumer(std::unique_ptr<CodeGenerator>(
283f3d9b488SAdrian Prantl              CreateLLVMCodeGen(compiler.getDiagnostics(),
284f3d9b488SAdrian Prantl                                "MemoryTypesTest",
285f3d9b488SAdrian Prantl                                compiler.getHeaderSearchOpts(),
286f3d9b488SAdrian Prantl                                compiler.getPreprocessorOpts(),
287f3d9b488SAdrian Prantl                                compiler.getCodeGenOpts(),
288f3d9b488SAdrian Prantl                                Context)))));
289f3d9b488SAdrian Prantl 
290f3d9b488SAdrian Prantl     compiler.createSema(clang::TU_Prefix, nullptr);
291f3d9b488SAdrian Prantl 
292f3d9b488SAdrian Prantl     clang::SourceManager &sm = compiler.getSourceManager();
293f3d9b488SAdrian Prantl     sm.setMainFileID(sm.createFileID(
294f3d9b488SAdrian Prantl         llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User));
295f3d9b488SAdrian Prantl 
296f3d9b488SAdrian Prantl     clang::ParseAST(compiler.getSema(), false, false);
297f3d9b488SAdrian Prantl 
298f3d9b488SAdrian Prantl     ASSERT_TRUE(test_codegen_fns_ran);
299f3d9b488SAdrian Prantl }
300f3d9b488SAdrian Prantl 
301f3d9b488SAdrian Prantl } // end anonymous namespace
302