//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "Plugin/CodeGenTestPass.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/Config/config.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Target/RegisterTargetPassConfigCallback.h" #include "llvm/Target/TargetMachine.h" #include "gtest/gtest.h" using namespace llvm; namespace { void anchor() {} std::string libPath(const std::string &Name) { const auto &Argvs = testing::internal::GetArgvs(); const char *Argv0 = Argvs.size() > 0 ? Argvs[0].c_str() : "CGPluginTest"; void *Ptr = (void *)(intptr_t)anchor; std::string Path = sys::fs::getMainExecutable(Argv0, Ptr); SmallString<256> Buf{sys::path::parent_path(Path)}; sys::path::append(Buf, (Name + LLVM_PLUGIN_EXT).c_str()); return std::string(Buf.str()); } } // namespace namespace llvm { class CGPluginTests : public testing::Test { protected: static void SetUpTestCase() { InitializeAllTargetMCs(); InitializeAllTargetInfos(); InitializeAllTargets(); } }; } // namespace llvm TEST_F(CGPluginTests, LoadPlugin) { #if !defined(LLVM_ENABLE_PLUGINS) // Skip the test if plugins are disabled. GTEST_SKIP(); #endif auto PluginPath = libPath("CGTestPlugin"); ASSERT_NE("", PluginPath); std::string Error; auto Library = sys::DynamicLibrary::getLibrary(PluginPath.c_str(), &Error); ASSERT_TRUE(Library.isValid()) << Error; sys::DynamicLibrary::closeLibrary(Library); } TEST_F(CGPluginTests, ExecuteCallback) { #if !defined(LLVM_ENABLE_PLUGINS) // Skip the test if plugins are disabled. GTEST_SKIP(); #endif volatile bool CallbackExecuted = false; volatile bool MPassExecuted = false; RegisterTargetPassConfigCallback X{[&](auto &TM, auto &PM, auto *TPC) { CallbackExecuted = true; TPC->insertPass(&GCLoweringID, &CodeGenTest::ID); }}; CodeGenTest::RunCallback = [&] { MPassExecuted = true; }; TargetOptions Options; std::unique_ptr MCC; for (auto T : TargetRegistry::targets()) { if (!T.hasTargetMachine()) continue; Triple TT{T.getName(), "", ""}; auto *TM = T.createTargetMachine(TT, "", "", Options, std::nullopt, std::nullopt, CodeGenOptLevel::Default); ASSERT_TRUE(TM); legacy::PassManager PM; MCC.reset(new MCContext(TT, TM->getMCAsmInfo(), TM->getMCRegisterInfo(), TM->getMCSubtargetInfo())); auto *PtrMCC = MCC.get(); CallbackExecuted = false; MPassExecuted = false; if (TM->addPassesToEmitMC(PM, PtrMCC, outs()) == true) continue; ASSERT_TRUE(CallbackExecuted) << T.getName() << " callback failed"; ASSERT_TRUE(MPassExecuted) << T.getName() << " MachinePass failed"; } }