111 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef CLANG_UNITTESTS_CODEGEN_TESTCOMPILER_H10#define CLANG_UNITTESTS_CODEGEN_TESTCOMPILER_H11 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/VirtualFileSystem.h"24#include "llvm/TargetParser/Host.h"25 26namespace llvm {27 28struct TestCompiler {29 LLVMContext Context;30 clang::CompilerInstance compiler;31 std::unique_ptr<clang::CodeGenerator> CG;32 llvm::Module *M = nullptr;33 unsigned PtrSize = 0;34 35 TestCompiler(clang::LangOptions LO,36 clang::CodeGenOptions CGO = clang::CodeGenOptions()) {37 compiler.getLangOpts() = LO;38 compiler.getCodeGenOpts() = CGO;39 compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem());40 compiler.createDiagnostics();41 42 std::string TrStr = llvm::Triple::normalize(llvm::sys::getProcessTriple());43 llvm::Triple Tr(TrStr);44 Tr.setOS(Triple::Linux);45 Tr.setVendor(Triple::VendorType::UnknownVendor);46 Tr.setEnvironment(Triple::EnvironmentType::UnknownEnvironment);47 compiler.getTargetOpts().Triple = Tr.getTriple();48 compiler.setTarget(clang::TargetInfo::CreateTargetInfo(49 compiler.getDiagnostics(), compiler.getTargetOpts()));50 51 const clang::TargetInfo &TInfo = compiler.getTarget();52 PtrSize = TInfo.getPointerWidth(clang::LangAS::Default) / 8;53 54 compiler.createFileManager();55 compiler.createSourceManager();56 compiler.createPreprocessor(clang::TU_Prefix);57 58 compiler.createASTContext();59 60 CG.reset(CreateLLVMCodeGen(61 compiler.getDiagnostics(), "main-module",62 compiler.getVirtualFileSystemPtr(), compiler.getHeaderSearchOpts(),63 compiler.getPreprocessorOpts(), compiler.getCodeGenOpts(), Context));64 }65 66 void init(const char *TestProgram,67 std::unique_ptr<clang::ASTConsumer> Consumer = nullptr) {68 if (!Consumer)69 Consumer = std::move(CG);70 71 compiler.setASTConsumer(std::move(Consumer));72 73 compiler.createSema(clang::TU_Prefix, nullptr);74 75 clang::SourceManager &sm = compiler.getSourceManager();76 sm.setMainFileID(sm.createFileID(77 llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User));78 }79 80 const BasicBlock *compile() {81 clang::ParseAST(compiler.getSema(), false, false);82 M =83 static_cast<clang::CodeGenerator&>(compiler.getASTConsumer()).GetModule();84 85 // Do not expect more than one function definition.86 auto FuncPtr = M->begin();87 for (; FuncPtr != M->end(); ++FuncPtr)88 if (!FuncPtr->isDeclaration())89 break;90 assert(FuncPtr != M->end());91 const llvm::Function &Func = *FuncPtr;92 ++FuncPtr;93 for (; FuncPtr != M->end(); ++FuncPtr)94 if (!FuncPtr->isDeclaration())95 break;96 assert(FuncPtr == M->end());97 98 // The function must consist of single basic block.99 auto BBPtr = Func.begin();100 assert(Func.begin() != Func.end());101 const BasicBlock &BB = *BBPtr;102 ++BBPtr;103 assert(BBPtr == Func.end());104 105 return &BB;106 }107};108 109} // namespace llvm110#endif // CLANG_UNITTESTS_CODEGEN_TESTCOMPILER_H111