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