xref: /llvm-project/clang/unittests/CodeGen/TestCompiler.h (revision df9a14d7bbf1180e4f1474254c9d7ed6bcb4ce55)
154e655b3SVassil Vassilev //=== unittests/CodeGen/TestCompiler.h - Match on the LLVM IR ---*- C++ -*-===//
254e655b3SVassil Vassilev //
354e655b3SVassil Vassilev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
454e655b3SVassil Vassilev // See https://llvm.org/LICENSE.txt for license information.
554e655b3SVassil Vassilev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
654e655b3SVassil Vassilev //
754e655b3SVassil Vassilev //===----------------------------------------------------------------------===//
854e655b3SVassil Vassilev 
954e655b3SVassil Vassilev #ifndef CLANG_UNITTESTS_CODEGEN_TESTCOMPILER_H
1054e655b3SVassil Vassilev #define CLANG_UNITTESTS_CODEGEN_TESTCOMPILER_H
1154e655b3SVassil Vassilev 
1254e655b3SVassil Vassilev 
1354e655b3SVassil Vassilev #include "clang/AST/ASTConsumer.h"
1454e655b3SVassil Vassilev #include "clang/Basic/TargetInfo.h"
1554e655b3SVassil Vassilev #include "clang/Basic/TargetOptions.h"
1654e655b3SVassil Vassilev #include "clang/CodeGen/ModuleBuilder.h"
1754e655b3SVassil Vassilev #include "clang/Frontend/CompilerInstance.h"
1854e655b3SVassil Vassilev #include "clang/Parse/ParseAST.h"
1954e655b3SVassil Vassilev 
2054e655b3SVassil Vassilev #include "llvm/IR/Constants.h"
2154e655b3SVassil Vassilev #include "llvm/IR/LLVMContext.h"
2254e655b3SVassil Vassilev #include "llvm/IR/Module.h"
23*df9a14d7SKadir Cetinkaya #include "llvm/Support/VirtualFileSystem.h"
24d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h"
2554e655b3SVassil Vassilev 
2654e655b3SVassil Vassilev namespace llvm {
2754e655b3SVassil Vassilev 
2854e655b3SVassil Vassilev struct TestCompiler {
2954e655b3SVassil Vassilev   LLVMContext Context;
3054e655b3SVassil Vassilev   clang::CompilerInstance compiler;
3154e655b3SVassil Vassilev   std::unique_ptr<clang::CodeGenerator> CG;
3254e655b3SVassil Vassilev   llvm::Module *M = nullptr;
3354e655b3SVassil Vassilev   unsigned PtrSize = 0;
3454e655b3SVassil Vassilev 
3554e655b3SVassil Vassilev   TestCompiler(clang::LangOptions LO,
3654e655b3SVassil Vassilev                clang::CodeGenOptions CGO = clang::CodeGenOptions()) {
3754e655b3SVassil Vassilev     compiler.getLangOpts() = LO;
3854e655b3SVassil Vassilev     compiler.getCodeGenOpts() = CGO;
39*df9a14d7SKadir Cetinkaya     compiler.createDiagnostics(*llvm::vfs::getRealFileSystem());
4054e655b3SVassil Vassilev 
4154e655b3SVassil Vassilev     std::string TrStr = llvm::Triple::normalize(llvm::sys::getProcessTriple());
4254e655b3SVassil Vassilev     llvm::Triple Tr(TrStr);
4354e655b3SVassil Vassilev     Tr.setOS(Triple::Linux);
4454e655b3SVassil Vassilev     Tr.setVendor(Triple::VendorType::UnknownVendor);
4554e655b3SVassil Vassilev     Tr.setEnvironment(Triple::EnvironmentType::UnknownEnvironment);
4654e655b3SVassil Vassilev     compiler.getTargetOpts().Triple = Tr.getTriple();
4754e655b3SVassil Vassilev     compiler.setTarget(clang::TargetInfo::CreateTargetInfo(
4854e655b3SVassil Vassilev         compiler.getDiagnostics(),
4954e655b3SVassil Vassilev         std::make_shared<clang::TargetOptions>(compiler.getTargetOpts())));
5054e655b3SVassil Vassilev 
5154e655b3SVassil Vassilev     const clang::TargetInfo &TInfo = compiler.getTarget();
52a602f76aSAlex Richardson     PtrSize = TInfo.getPointerWidth(clang::LangAS::Default) / 8;
5354e655b3SVassil Vassilev 
5454e655b3SVassil Vassilev     compiler.createFileManager();
5554e655b3SVassil Vassilev     compiler.createSourceManager(compiler.getFileManager());
5654e655b3SVassil Vassilev     compiler.createPreprocessor(clang::TU_Prefix);
5754e655b3SVassil Vassilev 
5854e655b3SVassil Vassilev     compiler.createASTContext();
5954e655b3SVassil Vassilev 
608dfaecc4SArgyrios Kyrtzidis     CG.reset(CreateLLVMCodeGen(
618dfaecc4SArgyrios Kyrtzidis         compiler.getDiagnostics(), "main-module",
628dfaecc4SArgyrios Kyrtzidis         &compiler.getVirtualFileSystem(), compiler.getHeaderSearchOpts(),
638dfaecc4SArgyrios Kyrtzidis         compiler.getPreprocessorOpts(), compiler.getCodeGenOpts(), Context));
6454e655b3SVassil Vassilev   }
6554e655b3SVassil Vassilev 
6654e655b3SVassil Vassilev   void init(const char *TestProgram,
6754e655b3SVassil Vassilev             std::unique_ptr<clang::ASTConsumer> Consumer = nullptr) {
6854e655b3SVassil Vassilev     if (!Consumer)
6954e655b3SVassil Vassilev       Consumer = std::move(CG);
7054e655b3SVassil Vassilev 
7154e655b3SVassil Vassilev     compiler.setASTConsumer(std::move(Consumer));
7254e655b3SVassil Vassilev 
7354e655b3SVassil Vassilev     compiler.createSema(clang::TU_Prefix, nullptr);
7454e655b3SVassil Vassilev 
7554e655b3SVassil Vassilev     clang::SourceManager &sm = compiler.getSourceManager();
7654e655b3SVassil Vassilev     sm.setMainFileID(sm.createFileID(
7754e655b3SVassil Vassilev         llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User));
7854e655b3SVassil Vassilev   }
7954e655b3SVassil Vassilev 
8054e655b3SVassil Vassilev   const BasicBlock *compile() {
8154e655b3SVassil Vassilev     clang::ParseAST(compiler.getSema(), false, false);
8254e655b3SVassil Vassilev     M =
8354e655b3SVassil Vassilev       static_cast<clang::CodeGenerator&>(compiler.getASTConsumer()).GetModule();
8454e655b3SVassil Vassilev 
8554e655b3SVassil Vassilev     // Do not expect more than one function definition.
8654e655b3SVassil Vassilev     auto FuncPtr = M->begin();
8754e655b3SVassil Vassilev     for (; FuncPtr != M->end(); ++FuncPtr)
8854e655b3SVassil Vassilev       if (!FuncPtr->isDeclaration())
8954e655b3SVassil Vassilev         break;
9054e655b3SVassil Vassilev     assert(FuncPtr != M->end());
9154e655b3SVassil Vassilev     const llvm::Function &Func = *FuncPtr;
9254e655b3SVassil Vassilev     ++FuncPtr;
9354e655b3SVassil Vassilev     for (; FuncPtr != M->end(); ++FuncPtr)
9454e655b3SVassil Vassilev       if (!FuncPtr->isDeclaration())
9554e655b3SVassil Vassilev         break;
9654e655b3SVassil Vassilev     assert(FuncPtr == M->end());
9754e655b3SVassil Vassilev 
9854e655b3SVassil Vassilev     // The function must consist of single basic block.
9954e655b3SVassil Vassilev     auto BBPtr = Func.begin();
10054e655b3SVassil Vassilev     assert(Func.begin() != Func.end());
10154e655b3SVassil Vassilev     const BasicBlock &BB = *BBPtr;
10254e655b3SVassil Vassilev     ++BBPtr;
10354e655b3SVassil Vassilev     assert(BBPtr == Func.end());
10454e655b3SVassil Vassilev 
10554e655b3SVassil Vassilev     return &BB;
10654e655b3SVassil Vassilev   }
10754e655b3SVassil Vassilev };
10854e655b3SVassil Vassilev 
10954e655b3SVassil Vassilev } // namespace llvm
11054e655b3SVassil Vassilev #endif // CLANG_UNITTESTS_CODEGEN_TESTCOMPILER_H
111