
## Purpose This patch is one in a series of code-mods that annotate LLVM’s public interface for export. This patch annotates the remaining LLVM CodeGen and CodeGenTypes library interfaces that were missed in, or modified since, previous patches. The annotations currently have no meaningful impact on the LLVM build; however, they are a prerequisite to support an LLVM Windows DLL (shared library) build. ## Background This effort is tracked in #109483. Additional context is provided in [this discourse](https://discourse.llvm.org/t/psa-annotating-llvm-public-interface/85307), and documentation for `LLVM_ABI` and related annotations is found in the LLVM repo [here](https://github.com/llvm/llvm-project/blob/main/llvm/docs/InterfaceExportAnnotations.rst). ## Overview The bulk of these changes were generated automatically using the [Interface Definition Scanner (IDS)](https://github.com/compnerd/ids) tool, followed formatting with `git clang-format`. The following manual adjustments were also applied after running IDS: - Explicitly instantiate `CallLowering::setArgFlags` template method instances in `CodeGen/GlobalISel/CallLowering.h` and annotate them with `LLVM_ABI`. These methods are already explicitly instantiated in `lib/CodeGen/GlobalISel/CallLowering.cpp` but were not `extern` declared in the header. - Annotate several explicit template instantiations with `LLVM_EXPORT_TEMPLATE`. - Include `llvm/CodeGen/Passes.h` from `llvm/lib/CodeGen/GlobalMergeFunctions.cpp` to pick up the declaration of `llvm::createGlobalMergeFuncPass` with the `LLVM_ABI` annotation (instead of adding `LLVM_ABI` to the function definition in this file) ## Validation Local builds and tests to validate cross-platform compatibility. This included llvm, clang, and lldb on the following configurations: - Windows with MSVC - Windows with Clang - Linux with GCC - Linux with Clang - Darwin with Clang
170 lines
6.5 KiB
C++
170 lines
6.5 KiB
C++
//===---------- MachinePassManager.cpp ------------------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains the pass management machinery for machine functions.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/CodeGen/MachinePassManager.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/PassManagerImpl.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
using namespace llvm;
|
|
|
|
AnalysisKey FunctionAnalysisManagerMachineFunctionProxy::Key;
|
|
|
|
namespace llvm {
|
|
template class LLVM_EXPORT_TEMPLATE AnalysisManager<MachineFunction>;
|
|
template class PassManager<MachineFunction>;
|
|
template class LLVM_EXPORT_TEMPLATE
|
|
InnerAnalysisManagerProxy<MachineFunctionAnalysisManager, Module>;
|
|
template class LLVM_EXPORT_TEMPLATE
|
|
InnerAnalysisManagerProxy<MachineFunctionAnalysisManager, Function>;
|
|
template class LLVM_EXPORT_TEMPLATE
|
|
OuterAnalysisManagerProxy<ModuleAnalysisManager, MachineFunction>;
|
|
} // namespace llvm
|
|
|
|
bool FunctionAnalysisManagerMachineFunctionProxy::Result::invalidate(
|
|
MachineFunction &IR, const PreservedAnalyses &PA,
|
|
MachineFunctionAnalysisManager::Invalidator &Inv) {
|
|
// MachineFunction passes should not invalidate Function analyses.
|
|
// TODO: verify that PA doesn't invalidate Function analyses.
|
|
return false;
|
|
}
|
|
|
|
template <>
|
|
bool MachineFunctionAnalysisManagerModuleProxy::Result::invalidate(
|
|
Module &M, const PreservedAnalyses &PA,
|
|
ModuleAnalysisManager::Invalidator &Inv) {
|
|
// If literally everything is preserved, we're done.
|
|
if (PA.areAllPreserved())
|
|
return false; // This is still a valid proxy.
|
|
|
|
// If this proxy isn't marked as preserved, then even if the result remains
|
|
// valid, the key itself may no longer be valid, so we clear everything.
|
|
//
|
|
// Note that in order to preserve this proxy, a module pass must ensure that
|
|
// the MFAM has been completely updated to handle the deletion of functions.
|
|
// Specifically, any MFAM-cached results for those functions need to have been
|
|
// forcibly cleared. When preserved, this proxy will only invalidate results
|
|
// cached on functions *still in the module* at the end of the module pass.
|
|
auto PAC = PA.getChecker<MachineFunctionAnalysisManagerModuleProxy>();
|
|
if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) {
|
|
InnerAM->clear();
|
|
return true;
|
|
}
|
|
|
|
// FIXME: be more precise, see
|
|
// FunctionAnalysisManagerModuleProxy::Result::invalidate.
|
|
if (!PA.allAnalysesInSetPreserved<AllAnalysesOn<MachineFunction>>()) {
|
|
InnerAM->clear();
|
|
return true;
|
|
}
|
|
|
|
// Return false to indicate that this result is still a valid proxy.
|
|
return false;
|
|
}
|
|
|
|
template <>
|
|
bool MachineFunctionAnalysisManagerFunctionProxy::Result::invalidate(
|
|
Function &F, const PreservedAnalyses &PA,
|
|
FunctionAnalysisManager::Invalidator &Inv) {
|
|
// If literally everything is preserved, we're done.
|
|
if (PA.areAllPreserved())
|
|
return false; // This is still a valid proxy.
|
|
|
|
// If this proxy isn't marked as preserved, then even if the result remains
|
|
// valid, the key itself may no longer be valid, so we clear everything.
|
|
//
|
|
// Note that in order to preserve this proxy, a module pass must ensure that
|
|
// the MFAM has been completely updated to handle the deletion of functions.
|
|
// Specifically, any MFAM-cached results for those functions need to have been
|
|
// forcibly cleared. When preserved, this proxy will only invalidate results
|
|
// cached on functions *still in the module* at the end of the module pass.
|
|
auto PAC = PA.getChecker<MachineFunctionAnalysisManagerFunctionProxy>();
|
|
if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Function>>()) {
|
|
InnerAM->clear();
|
|
return true;
|
|
}
|
|
|
|
// FIXME: be more precise, see
|
|
// FunctionAnalysisManagerModuleProxy::Result::invalidate.
|
|
if (!PA.allAnalysesInSetPreserved<AllAnalysesOn<MachineFunction>>()) {
|
|
InnerAM->clear();
|
|
return true;
|
|
}
|
|
|
|
// Return false to indicate that this result is still a valid proxy.
|
|
return false;
|
|
}
|
|
|
|
PreservedAnalyses
|
|
FunctionToMachineFunctionPassAdaptor::run(Function &F,
|
|
FunctionAnalysisManager &FAM) {
|
|
MachineFunctionAnalysisManager &MFAM =
|
|
FAM.getResult<MachineFunctionAnalysisManagerFunctionProxy>(F)
|
|
.getManager();
|
|
PassInstrumentation PI = FAM.getResult<PassInstrumentationAnalysis>(F);
|
|
PreservedAnalyses PA = PreservedAnalyses::all();
|
|
// Do not codegen any 'available_externally' functions at all, they have
|
|
// definitions outside the translation unit.
|
|
if (F.isDeclaration() || F.hasAvailableExternallyLinkage())
|
|
return PreservedAnalyses::all();
|
|
|
|
MachineFunction &MF = FAM.getResult<MachineFunctionAnalysis>(F).getMF();
|
|
|
|
if (!PI.runBeforePass<MachineFunction>(*Pass, MF))
|
|
return PreservedAnalyses::all();
|
|
PreservedAnalyses PassPA = Pass->run(MF, MFAM);
|
|
MFAM.invalidate(MF, PassPA);
|
|
PI.runAfterPass(*Pass, MF, PassPA);
|
|
PA.intersect(std::move(PassPA));
|
|
|
|
return PA;
|
|
}
|
|
|
|
void FunctionToMachineFunctionPassAdaptor::printPipeline(
|
|
raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
|
|
OS << "machine-function(";
|
|
Pass->printPipeline(OS, MapClassName2PassName);
|
|
OS << ')';
|
|
}
|
|
|
|
template <>
|
|
PreservedAnalyses
|
|
PassManager<MachineFunction>::run(MachineFunction &MF,
|
|
AnalysisManager<MachineFunction> &MFAM) {
|
|
PassInstrumentation PI = MFAM.getResult<PassInstrumentationAnalysis>(MF);
|
|
PreservedAnalyses PA = PreservedAnalyses::all();
|
|
for (auto &Pass : Passes) {
|
|
if (!PI.runBeforePass<MachineFunction>(*Pass, MF))
|
|
continue;
|
|
|
|
PreservedAnalyses PassPA = Pass->run(MF, MFAM);
|
|
MFAM.invalidate(MF, PassPA);
|
|
PI.runAfterPass(*Pass, MF, PassPA);
|
|
PA.intersect(std::move(PassPA));
|
|
}
|
|
PA.preserveSet<AllAnalysesOn<MachineFunction>>();
|
|
return PA;
|
|
}
|
|
|
|
PreservedAnalyses llvm::getMachineFunctionPassPreservedAnalyses() {
|
|
PreservedAnalyses PA;
|
|
// Machine function passes are not allowed to modify the LLVM
|
|
// representation, therefore we should preserve all IR analyses.
|
|
PA.template preserveSet<AllAnalysesOn<Module>>();
|
|
PA.template preserveSet<AllAnalysesOn<Function>>();
|
|
return PA;
|
|
}
|