10b57cec5SDimitry Andric //===- lib/Passes/PassPluginLoader.cpp - Load Plugins for New PM Passes ---===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "llvm/Passes/PassPlugin.h"
100b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
110b57cec5SDimitry Andric
120b57cec5SDimitry Andric #include <cstdint>
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric using namespace llvm;
150b57cec5SDimitry Andric
Load(const std::string & Filename)160b57cec5SDimitry Andric Expected<PassPlugin> PassPlugin::Load(const std::string &Filename) {
170b57cec5SDimitry Andric std::string Error;
180b57cec5SDimitry Andric auto Library =
190b57cec5SDimitry Andric sys::DynamicLibrary::getPermanentLibrary(Filename.c_str(), &Error);
200b57cec5SDimitry Andric if (!Library.isValid())
210b57cec5SDimitry Andric return make_error<StringError>(Twine("Could not load library '") +
220b57cec5SDimitry Andric Filename + "': " + Error,
230b57cec5SDimitry Andric inconvertibleErrorCode());
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric PassPlugin P{Filename, Library};
26*fe6060f1SDimitry Andric
27*fe6060f1SDimitry Andric // llvmGetPassPluginInfo should be resolved to the definition from the plugin
28*fe6060f1SDimitry Andric // we are currently loading.
290b57cec5SDimitry Andric intptr_t getDetailsFn =
30*fe6060f1SDimitry Andric (intptr_t)Library.getAddressOfSymbol("llvmGetPassPluginInfo");
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric if (!getDetailsFn)
330b57cec5SDimitry Andric // If the symbol isn't found, this is probably a legacy plugin, which is an
340b57cec5SDimitry Andric // error
350b57cec5SDimitry Andric return make_error<StringError>(Twine("Plugin entry point not found in '") +
360b57cec5SDimitry Andric Filename + "'. Is this a legacy plugin?",
370b57cec5SDimitry Andric inconvertibleErrorCode());
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric P.Info = reinterpret_cast<decltype(llvmGetPassPluginInfo) *>(getDetailsFn)();
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric if (P.Info.APIVersion != LLVM_PLUGIN_API_VERSION)
420b57cec5SDimitry Andric return make_error<StringError>(
430b57cec5SDimitry Andric Twine("Wrong API version on plugin '") + Filename + "'. Got version " +
440b57cec5SDimitry Andric Twine(P.Info.APIVersion) + ", supported version is " +
450b57cec5SDimitry Andric Twine(LLVM_PLUGIN_API_VERSION) + ".",
460b57cec5SDimitry Andric inconvertibleErrorCode());
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric if (!P.Info.RegisterPassBuilderCallbacks)
490b57cec5SDimitry Andric return make_error<StringError>(Twine("Empty entry callback in plugin '") +
500b57cec5SDimitry Andric Filename + "'.'",
510b57cec5SDimitry Andric inconvertibleErrorCode());
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric return P;
540b57cec5SDimitry Andric }
55