xref: /llvm-project/clang/unittests/CodeGen/CodeGenExternalTest.cpp (revision d768bf994f508d7eaf9541a568be3d71096febf5)
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 
954e655b3SVassil Vassilev #include "TestCompiler.h"
1054e655b3SVassil Vassilev 
11f3d9b488SAdrian Prantl #include "clang/AST/ASTConsumer.h"
12f3d9b488SAdrian Prantl #include "clang/AST/ASTContext.h"
13f3d9b488SAdrian Prantl #include "clang/AST/GlobalDecl.h"
14f3d9b488SAdrian Prantl #include "clang/AST/RecursiveASTVisitor.h"
15f3d9b488SAdrian Prantl #include "clang/Basic/TargetInfo.h"
16f3d9b488SAdrian Prantl #include "clang/CodeGen/CodeGenABITypes.h"
17f3d9b488SAdrian Prantl #include "clang/CodeGen/ModuleBuilder.h"
18f3d9b488SAdrian Prantl #include "clang/Frontend/CompilerInstance.h"
19f3d9b488SAdrian Prantl #include "clang/Lex/Preprocessor.h"
20f3d9b488SAdrian Prantl #include "clang/Parse/ParseAST.h"
21f3d9b488SAdrian Prantl #include "clang/Sema/Sema.h"
22f3d9b488SAdrian Prantl #include "llvm/IR/Instructions.h"
23f3d9b488SAdrian Prantl #include "llvm/IR/LLVMContext.h"
24f3d9b488SAdrian Prantl #include "llvm/Support/Debug.h"
25f3d9b488SAdrian Prantl #include "llvm/Support/MemoryBuffer.h"
26*d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h"
2762c7f035SArchibald Elliott #include "llvm/TargetParser/Triple.h"
28f3d9b488SAdrian Prantl #include "gtest/gtest.h"
29f3d9b488SAdrian Prantl 
30f3d9b488SAdrian Prantl using namespace llvm;
31f3d9b488SAdrian Prantl using namespace clang;
32f3d9b488SAdrian Prantl 
33f3d9b488SAdrian Prantl namespace {
34f3d9b488SAdrian Prantl 
35f3d9b488SAdrian Prantl // Mocks up a language using Clang code generation as a library and
36f3d9b488SAdrian Prantl // tests some basic functionality there.
37f3d9b488SAdrian Prantl //   - CodeGen->GetAddrOfGlobal
38f3d9b488SAdrian Prantl //   - CodeGen::convertTypeForMemory
39f3d9b488SAdrian Prantl //   - CodeGen::getLLVMFieldNumber
40f3d9b488SAdrian Prantl 
41f3d9b488SAdrian Prantl static const bool DebugThisTest = false;
42f3d9b488SAdrian Prantl 
43f3d9b488SAdrian Prantl // forward declarations
44f3d9b488SAdrian Prantl struct MyASTConsumer;
45f3d9b488SAdrian Prantl static void test_codegen_fns(MyASTConsumer *my);
46f3d9b488SAdrian Prantl static bool test_codegen_fns_ran;
47f3d9b488SAdrian Prantl 
48f3d9b488SAdrian Prantl // This forwards the calls to the Clang CodeGenerator
49f3d9b488SAdrian Prantl // so that we can test CodeGen functions while it is open.
50f3d9b488SAdrian Prantl // It accumulates toplevel decls in HandleTopLevelDecl and
51f3d9b488SAdrian Prantl // calls test_codegen_fns() in HandleTranslationUnit
52f3d9b488SAdrian Prantl // before forwarding that function to the CodeGenerator.
53f3d9b488SAdrian Prantl 
54f3d9b488SAdrian Prantl struct MyASTConsumer : public ASTConsumer {
556c185acfSVitaly Buka   std::unique_ptr<CodeGenerator> Builder;
56f3d9b488SAdrian Prantl   std::vector<Decl*> toplevel_decls;
57f3d9b488SAdrian Prantl 
MyASTConsumer__anonc824fae50111::MyASTConsumer586c185acfSVitaly Buka   MyASTConsumer(std::unique_ptr<CodeGenerator> Builder_in)
596c185acfSVitaly Buka     : ASTConsumer(), Builder(std::move(Builder_in))
60f3d9b488SAdrian Prantl   {
61f3d9b488SAdrian Prantl   }
62f3d9b488SAdrian Prantl 
~MyASTConsumer__anonc824fae50111::MyASTConsumer63f3d9b488SAdrian Prantl   ~MyASTConsumer() { }
64f3d9b488SAdrian Prantl 
65f3d9b488SAdrian Prantl   void Initialize(ASTContext &Context) override;
66f3d9b488SAdrian Prantl   void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override;
67f3d9b488SAdrian Prantl   bool HandleTopLevelDecl(DeclGroupRef D) override;
68f3d9b488SAdrian Prantl   void HandleInlineFunctionDefinition(FunctionDecl *D) override;
69f3d9b488SAdrian Prantl   void HandleInterestingDecl(DeclGroupRef D) override;
70f3d9b488SAdrian Prantl   void HandleTranslationUnit(ASTContext &Ctx) override;
71f3d9b488SAdrian Prantl   void HandleTagDeclDefinition(TagDecl *D) override;
72f3d9b488SAdrian Prantl   void HandleTagDeclRequiredDefinition(const TagDecl *D) override;
73f3d9b488SAdrian Prantl   void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override;
74f3d9b488SAdrian Prantl   void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override;
75f3d9b488SAdrian Prantl   void HandleImplicitImportDecl(ImportDecl *D) override;
76f3d9b488SAdrian Prantl   void CompleteTentativeDefinition(VarDecl *D) override;
77f3d9b488SAdrian Prantl   void AssignInheritanceModel(CXXRecordDecl *RD) override;
78f3d9b488SAdrian Prantl   void HandleVTable(CXXRecordDecl *RD) override;
79f3d9b488SAdrian Prantl   ASTMutationListener *GetASTMutationListener() override;
80f3d9b488SAdrian Prantl   ASTDeserializationListener *GetASTDeserializationListener() override;
81f3d9b488SAdrian Prantl   void PrintStats() override;
82f3d9b488SAdrian Prantl   bool shouldSkipFunctionBody(Decl *D) override;
83f3d9b488SAdrian Prantl };
84f3d9b488SAdrian Prantl 
Initialize(ASTContext & Context)85f3d9b488SAdrian Prantl void MyASTConsumer::Initialize(ASTContext &Context) {
86f3d9b488SAdrian Prantl   Builder->Initialize(Context);
87f3d9b488SAdrian Prantl }
88f3d9b488SAdrian Prantl 
HandleTopLevelDecl(DeclGroupRef DG)89f3d9b488SAdrian Prantl bool MyASTConsumer::HandleTopLevelDecl(DeclGroupRef DG) {
90f3d9b488SAdrian Prantl 
91f3d9b488SAdrian Prantl   for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
92f3d9b488SAdrian Prantl     toplevel_decls.push_back(*I);
93f3d9b488SAdrian Prantl   }
94f3d9b488SAdrian Prantl 
95f3d9b488SAdrian Prantl   return Builder->HandleTopLevelDecl(DG);
96f3d9b488SAdrian Prantl }
97f3d9b488SAdrian Prantl 
HandleInlineFunctionDefinition(FunctionDecl * D)98f3d9b488SAdrian Prantl void MyASTConsumer::HandleInlineFunctionDefinition(FunctionDecl *D) {
99f3d9b488SAdrian Prantl   Builder->HandleInlineFunctionDefinition(D);
100f3d9b488SAdrian Prantl }
101f3d9b488SAdrian Prantl 
HandleInterestingDecl(DeclGroupRef D)102f3d9b488SAdrian Prantl void MyASTConsumer::HandleInterestingDecl(DeclGroupRef D) {
103f3d9b488SAdrian Prantl   Builder->HandleInterestingDecl(D);
104f3d9b488SAdrian Prantl }
105f3d9b488SAdrian Prantl 
HandleTranslationUnit(ASTContext & Context)106f3d9b488SAdrian Prantl void MyASTConsumer::HandleTranslationUnit(ASTContext &Context) {
107f3d9b488SAdrian Prantl   test_codegen_fns(this);
108f3d9b488SAdrian Prantl   // HandleTranslationUnit can close the module
109f3d9b488SAdrian Prantl   Builder->HandleTranslationUnit(Context);
110f3d9b488SAdrian Prantl }
111f3d9b488SAdrian Prantl 
HandleTagDeclDefinition(TagDecl * D)112f3d9b488SAdrian Prantl void MyASTConsumer::HandleTagDeclDefinition(TagDecl *D) {
113f3d9b488SAdrian Prantl   Builder->HandleTagDeclDefinition(D);
114f3d9b488SAdrian Prantl }
115f3d9b488SAdrian Prantl 
HandleTagDeclRequiredDefinition(const TagDecl * D)116f3d9b488SAdrian Prantl void MyASTConsumer::HandleTagDeclRequiredDefinition(const TagDecl *D) {
117f3d9b488SAdrian Prantl   Builder->HandleTagDeclRequiredDefinition(D);
118f3d9b488SAdrian Prantl }
119f3d9b488SAdrian Prantl 
HandleCXXImplicitFunctionInstantiation(FunctionDecl * D)120f3d9b488SAdrian Prantl void MyASTConsumer::HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {
121f3d9b488SAdrian Prantl   Builder->HandleCXXImplicitFunctionInstantiation(D);
122f3d9b488SAdrian Prantl }
123f3d9b488SAdrian Prantl 
HandleTopLevelDeclInObjCContainer(DeclGroupRef D)124f3d9b488SAdrian Prantl void MyASTConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef D) {
125f3d9b488SAdrian Prantl   Builder->HandleTopLevelDeclInObjCContainer(D);
126f3d9b488SAdrian Prantl }
127f3d9b488SAdrian Prantl 
HandleImplicitImportDecl(ImportDecl * D)128f3d9b488SAdrian Prantl void MyASTConsumer::HandleImplicitImportDecl(ImportDecl *D) {
129f3d9b488SAdrian Prantl   Builder->HandleImplicitImportDecl(D);
130f3d9b488SAdrian Prantl }
131f3d9b488SAdrian Prantl 
CompleteTentativeDefinition(VarDecl * D)132f3d9b488SAdrian Prantl void MyASTConsumer::CompleteTentativeDefinition(VarDecl *D) {
133f3d9b488SAdrian Prantl   Builder->CompleteTentativeDefinition(D);
134f3d9b488SAdrian Prantl }
135f3d9b488SAdrian Prantl 
AssignInheritanceModel(CXXRecordDecl * RD)136f3d9b488SAdrian Prantl void MyASTConsumer::AssignInheritanceModel(CXXRecordDecl *RD) {
137f3d9b488SAdrian Prantl   Builder->AssignInheritanceModel(RD);
138f3d9b488SAdrian Prantl }
139f3d9b488SAdrian Prantl 
HandleCXXStaticMemberVarInstantiation(VarDecl * VD)140f3d9b488SAdrian Prantl void MyASTConsumer::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) {
141f3d9b488SAdrian Prantl    Builder->HandleCXXStaticMemberVarInstantiation(VD);
142f3d9b488SAdrian Prantl }
143f3d9b488SAdrian Prantl 
HandleVTable(CXXRecordDecl * RD)144f3d9b488SAdrian Prantl void MyASTConsumer::HandleVTable(CXXRecordDecl *RD) {
145f3d9b488SAdrian Prantl    Builder->HandleVTable(RD);
146f3d9b488SAdrian Prantl  }
147f3d9b488SAdrian Prantl 
GetASTMutationListener()148f3d9b488SAdrian Prantl ASTMutationListener *MyASTConsumer::GetASTMutationListener() {
149f3d9b488SAdrian Prantl   return Builder->GetASTMutationListener();
150f3d9b488SAdrian Prantl }
151f3d9b488SAdrian Prantl 
GetASTDeserializationListener()152f3d9b488SAdrian Prantl ASTDeserializationListener *MyASTConsumer::GetASTDeserializationListener() {
153f3d9b488SAdrian Prantl   return Builder->GetASTDeserializationListener();
154f3d9b488SAdrian Prantl }
155f3d9b488SAdrian Prantl 
PrintStats()156f3d9b488SAdrian Prantl void MyASTConsumer::PrintStats() {
157f3d9b488SAdrian Prantl   Builder->PrintStats();
158f3d9b488SAdrian Prantl }
159f3d9b488SAdrian Prantl 
shouldSkipFunctionBody(Decl * D)160f3d9b488SAdrian Prantl bool MyASTConsumer::shouldSkipFunctionBody(Decl *D) {
161f3d9b488SAdrian Prantl   return Builder->shouldSkipFunctionBody(D);
162f3d9b488SAdrian Prantl }
163f3d9b488SAdrian Prantl 
164f3d9b488SAdrian Prantl const char TestProgram[] =
165f3d9b488SAdrian Prantl     "struct mytest_struct { char x; short y; char p; long z; };\n"
166f3d9b488SAdrian Prantl     "int mytest_fn(int x) { return x; }\n";
167f3d9b488SAdrian Prantl 
168f3d9b488SAdrian Prantl // This function has the real test code here
test_codegen_fns(MyASTConsumer * my)169f3d9b488SAdrian Prantl static void test_codegen_fns(MyASTConsumer *my) {
170f3d9b488SAdrian Prantl 
171f3d9b488SAdrian Prantl   bool mytest_fn_ok = false;
172f3d9b488SAdrian Prantl   bool mytest_struct_ok = false;
173f3d9b488SAdrian Prantl 
174f3d9b488SAdrian Prantl   CodeGen::CodeGenModule &CGM = my->Builder->CGM();
175f3d9b488SAdrian Prantl 
176f3d9b488SAdrian Prantl   for (auto decl : my->toplevel_decls ) {
177f3d9b488SAdrian Prantl     if (FunctionDecl *fd = dyn_cast<FunctionDecl>(decl)) {
178f3d9b488SAdrian Prantl       if (fd->getName() == "mytest_fn") {
179f3d9b488SAdrian Prantl         Constant *c = my->Builder->GetAddrOfGlobal(GlobalDecl(fd), false);
180f3d9b488SAdrian Prantl         // Verify that we got a function.
181f3d9b488SAdrian Prantl         ASSERT_TRUE(c != NULL);
182f3d9b488SAdrian Prantl         if (DebugThisTest) {
183f3d9b488SAdrian Prantl           c->print(dbgs(), true);
184f3d9b488SAdrian Prantl           dbgs() << "\n";
185f3d9b488SAdrian Prantl         }
186f3d9b488SAdrian Prantl         mytest_fn_ok = true;
187f3d9b488SAdrian Prantl       }
188f3d9b488SAdrian Prantl     } else if(clang::RecordDecl *rd = dyn_cast<RecordDecl>(decl)) {
189f3d9b488SAdrian Prantl       if (rd->getName() == "mytest_struct") {
190f3d9b488SAdrian Prantl         RecordDecl *def = rd->getDefinition();
191f3d9b488SAdrian Prantl         ASSERT_TRUE(def != NULL);
192f3d9b488SAdrian Prantl         const clang::Type *clangTy = rd->getCanonicalDecl()->getTypeForDecl();
193f3d9b488SAdrian Prantl         ASSERT_TRUE(clangTy != NULL);
194f3d9b488SAdrian Prantl         QualType qType = clangTy->getCanonicalTypeInternal();
195f3d9b488SAdrian Prantl 
196f3d9b488SAdrian Prantl         // Check convertTypeForMemory
197f3d9b488SAdrian Prantl         llvm::Type *llvmTy = CodeGen::convertTypeForMemory(CGM, qType);
198f3d9b488SAdrian Prantl         ASSERT_TRUE(llvmTy != NULL);
199f3d9b488SAdrian Prantl         if (DebugThisTest) {
200f3d9b488SAdrian Prantl           llvmTy->print(dbgs(), true);
201f3d9b488SAdrian Prantl           dbgs() << "\n";
202f3d9b488SAdrian Prantl         }
203f3d9b488SAdrian Prantl 
204e24e95feSEli Friedman         auto* structTy = dyn_cast<llvm::StructType>(llvmTy);
205f3d9b488SAdrian Prantl         ASSERT_TRUE(structTy != NULL);
206f3d9b488SAdrian Prantl 
207f3d9b488SAdrian Prantl         // Check getLLVMFieldNumber
208f3d9b488SAdrian Prantl         FieldDecl *xField = NULL;
209f3d9b488SAdrian Prantl         FieldDecl *yField = NULL;
210f3d9b488SAdrian Prantl         FieldDecl *zField = NULL;
211f3d9b488SAdrian Prantl 
212f3d9b488SAdrian Prantl         for (auto field : rd->fields()) {
213f3d9b488SAdrian Prantl           if (field->getName() == "x") xField = field;
214f3d9b488SAdrian Prantl           if (field->getName() == "y") yField = field;
215f3d9b488SAdrian Prantl           if (field->getName() == "z") zField = field;
216f3d9b488SAdrian Prantl         }
217f3d9b488SAdrian Prantl 
218f3d9b488SAdrian Prantl         ASSERT_TRUE(xField != NULL);
219f3d9b488SAdrian Prantl         ASSERT_TRUE(yField != NULL);
220f3d9b488SAdrian Prantl         ASSERT_TRUE(zField != NULL);
221f3d9b488SAdrian Prantl 
222f3d9b488SAdrian Prantl         unsigned x = CodeGen::getLLVMFieldNumber(CGM, rd, xField);
223f3d9b488SAdrian Prantl         unsigned y = CodeGen::getLLVMFieldNumber(CGM, rd, yField);
224f3d9b488SAdrian Prantl         unsigned z = CodeGen::getLLVMFieldNumber(CGM, rd, zField);
225f3d9b488SAdrian Prantl 
226f3d9b488SAdrian Prantl         ASSERT_NE(x, y);
227f3d9b488SAdrian Prantl         ASSERT_NE(y, z);
228f3d9b488SAdrian Prantl 
229f3d9b488SAdrian Prantl         llvm::Type* xTy = structTy->getTypeAtIndex(x);
230f3d9b488SAdrian Prantl         llvm::Type* yTy = structTy->getTypeAtIndex(y);
231f3d9b488SAdrian Prantl         llvm::Type* zTy = structTy->getTypeAtIndex(z);
232f3d9b488SAdrian Prantl 
233f3d9b488SAdrian Prantl         ASSERT_TRUE(xTy != NULL);
234f3d9b488SAdrian Prantl         ASSERT_TRUE(yTy != NULL);
235f3d9b488SAdrian Prantl         ASSERT_TRUE(zTy != NULL);
236f3d9b488SAdrian Prantl 
237f3d9b488SAdrian Prantl         if (DebugThisTest) {
238f3d9b488SAdrian Prantl           xTy->print(dbgs(), true);
239f3d9b488SAdrian Prantl           dbgs() << "\n";
240f3d9b488SAdrian Prantl           yTy->print(dbgs(), true);
241f3d9b488SAdrian Prantl           dbgs() << "\n";
242f3d9b488SAdrian Prantl           zTy->print(dbgs(), true);
243f3d9b488SAdrian Prantl           dbgs() << "\n";
244f3d9b488SAdrian Prantl         }
245f3d9b488SAdrian Prantl 
246f3d9b488SAdrian Prantl         ASSERT_GE(xTy->getPrimitiveSizeInBits(), 1u);
247f3d9b488SAdrian Prantl         ASSERT_GE(yTy->getPrimitiveSizeInBits(), 16u); // short is at least 16b
248f3d9b488SAdrian Prantl         ASSERT_GE(zTy->getPrimitiveSizeInBits(), 32u); // long is at least 32b
249f3d9b488SAdrian Prantl 
250f3d9b488SAdrian Prantl         mytest_struct_ok = true;
251f3d9b488SAdrian Prantl       }
252f3d9b488SAdrian Prantl     }
253f3d9b488SAdrian Prantl   }
254f3d9b488SAdrian Prantl 
255f3d9b488SAdrian Prantl   ASSERT_TRUE(mytest_fn_ok);
256f3d9b488SAdrian Prantl   ASSERT_TRUE(mytest_struct_ok);
257f3d9b488SAdrian Prantl 
258f3d9b488SAdrian Prantl   test_codegen_fns_ran = true;
259f3d9b488SAdrian Prantl }
260f3d9b488SAdrian Prantl 
TEST(CodeGenExternalTest,CodeGenExternalTest)261f3d9b488SAdrian Prantl TEST(CodeGenExternalTest, CodeGenExternalTest) {
26254e655b3SVassil Vassilev   clang::LangOptions LO;
26354e655b3SVassil Vassilev   LO.CPlusPlus = 1;
26454e655b3SVassil Vassilev   LO.CPlusPlus11 = 1;
26554e655b3SVassil Vassilev   TestCompiler Compiler(LO);
26654e655b3SVassil Vassilev   auto CustomASTConsumer
26754e655b3SVassil Vassilev     = std::make_unique<MyASTConsumer>(std::move(Compiler.CG));
268f3d9b488SAdrian Prantl 
26954e655b3SVassil Vassilev   Compiler.init(TestProgram, std::move(CustomASTConsumer));
270f3d9b488SAdrian Prantl 
27154e655b3SVassil Vassilev   clang::ParseAST(Compiler.compiler.getSema(), false, false);
272f3d9b488SAdrian Prantl 
273f3d9b488SAdrian Prantl   ASSERT_TRUE(test_codegen_fns_ran);
274f3d9b488SAdrian Prantl }
275f3d9b488SAdrian Prantl 
276f3d9b488SAdrian Prantl } // end anonymous namespace
277