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(compiler.getDiagnostics(), 60 "main-module", 61 compiler.getHeaderSearchOpts(), 62 compiler.getPreprocessorOpts(), 63 compiler.getCodeGenOpts(), 64 Context)); 65 } 66 67 void init(const char *TestProgram, 68 std::unique_ptr<clang::ASTConsumer> Consumer = nullptr) { 69 if (!Consumer) 70 Consumer = std::move(CG); 71 72 compiler.setASTConsumer(std::move(Consumer)); 73 74 compiler.createSema(clang::TU_Prefix, nullptr); 75 76 clang::SourceManager &sm = compiler.getSourceManager(); 77 sm.setMainFileID(sm.createFileID( 78 llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User)); 79 } 80 compileTestCompiler81 const BasicBlock *compile() { 82 clang::ParseAST(compiler.getSema(), false, false); 83 M = 84 static_cast<clang::CodeGenerator&>(compiler.getASTConsumer()).GetModule(); 85 86 // Do not expect more than one function definition. 87 auto FuncPtr = M->begin(); 88 for (; FuncPtr != M->end(); ++FuncPtr) 89 if (!FuncPtr->isDeclaration()) 90 break; 91 assert(FuncPtr != M->end()); 92 const llvm::Function &Func = *FuncPtr; 93 ++FuncPtr; 94 for (; FuncPtr != M->end(); ++FuncPtr) 95 if (!FuncPtr->isDeclaration()) 96 break; 97 assert(FuncPtr == M->end()); 98 99 // The function must consist of single basic block. 100 auto BBPtr = Func.begin(); 101 assert(Func.begin() != Func.end()); 102 const BasicBlock &BB = *BBPtr; 103 ++BBPtr; 104 assert(BBPtr == Func.end()); 105 106 return &BB; 107 } 108 }; 109 110 } // namespace llvm 111 #endif // CLANG_UNITTESTS_CODEGEN_TESTCOMPILER_H 112