1 //=== unittests/CodeGen/TestCompiler.h - Match on the LLVM IR ---*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef CLANG_UNITTESTS_CODEGEN_TESTCOMPILER_H 10 #define CLANG_UNITTESTS_CODEGEN_TESTCOMPILER_H 11 12 13 #include "clang/AST/ASTConsumer.h" 14 #include "clang/Basic/TargetInfo.h" 15 #include "clang/Basic/TargetOptions.h" 16 #include "clang/CodeGen/ModuleBuilder.h" 17 #include "clang/Frontend/CompilerInstance.h" 18 #include "clang/Parse/ParseAST.h" 19 20 #include "llvm/IR/Constants.h" 21 #include "llvm/IR/LLVMContext.h" 22 #include "llvm/IR/Module.h" 23 #include "llvm/Support/Host.h" 24 25 namespace llvm { 26 27 struct TestCompiler { 28 LLVMContext Context; 29 clang::CompilerInstance compiler; 30 std::unique_ptr<clang::CodeGenerator> CG; 31 llvm::Module *M = nullptr; 32 unsigned PtrSize = 0; 33 34 TestCompiler(clang::LangOptions LO, 35 clang::CodeGenOptions CGO = clang::CodeGenOptions()) { 36 compiler.getLangOpts() = LO; 37 compiler.getCodeGenOpts() = CGO; 38 compiler.createDiagnostics(); 39 40 std::string TrStr = llvm::Triple::normalize(llvm::sys::getProcessTriple()); 41 llvm::Triple Tr(TrStr); 42 Tr.setOS(Triple::Linux); 43 Tr.setVendor(Triple::VendorType::UnknownVendor); 44 Tr.setEnvironment(Triple::EnvironmentType::UnknownEnvironment); 45 compiler.getTargetOpts().Triple = Tr.getTriple(); 46 compiler.setTarget(clang::TargetInfo::CreateTargetInfo( 47 compiler.getDiagnostics(), 48 std::make_shared<clang::TargetOptions>(compiler.getTargetOpts()))); 49 50 const clang::TargetInfo &TInfo = compiler.getTarget(); 51 PtrSize = TInfo.getPointerWidth(0) / 8; 52 53 compiler.createFileManager(); 54 compiler.createSourceManager(compiler.getFileManager()); 55 compiler.createPreprocessor(clang::TU_Prefix); 56 57 compiler.createASTContext(); 58 59 CG.reset(CreateLLVMCodeGen( 60 compiler.getDiagnostics(), "main-module", 61 &compiler.getVirtualFileSystem(), compiler.getHeaderSearchOpts(), 62 compiler.getPreprocessorOpts(), compiler.getCodeGenOpts(), Context)); 63 } 64 65 void init(const char *TestProgram, 66 std::unique_ptr<clang::ASTConsumer> Consumer = nullptr) { 67 if (!Consumer) 68 Consumer = std::move(CG); 69 70 compiler.setASTConsumer(std::move(Consumer)); 71 72 compiler.createSema(clang::TU_Prefix, nullptr); 73 74 clang::SourceManager &sm = compiler.getSourceManager(); 75 sm.setMainFileID(sm.createFileID( 76 llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User)); 77 } 78 compileTestCompiler79 const BasicBlock *compile() { 80 clang::ParseAST(compiler.getSema(), false, false); 81 M = 82 static_cast<clang::CodeGenerator&>(compiler.getASTConsumer()).GetModule(); 83 84 // Do not expect more than one function definition. 85 auto FuncPtr = M->begin(); 86 for (; FuncPtr != M->end(); ++FuncPtr) 87 if (!FuncPtr->isDeclaration()) 88 break; 89 assert(FuncPtr != M->end()); 90 const llvm::Function &Func = *FuncPtr; 91 ++FuncPtr; 92 for (; FuncPtr != M->end(); ++FuncPtr) 93 if (!FuncPtr->isDeclaration()) 94 break; 95 assert(FuncPtr == M->end()); 96 97 // The function must consist of single basic block. 98 auto BBPtr = Func.begin(); 99 assert(Func.begin() != Func.end()); 100 const BasicBlock &BB = *BBPtr; 101 ++BBPtr; 102 assert(BBPtr == Func.end()); 103 104 return &BB; 105 } 106 }; 107 108 } // namespace llvm 109 #endif // CLANG_UNITTESTS_CODEGEN_TESTCOMPILER_H 110