diff --git a/llvm/include/llvm/Support/SsaContext.h b/llvm/include/llvm/Support/SsaContext.h --- a/llvm/include/llvm/Support/SsaContext.h +++ b/llvm/include/llvm/Support/SsaContext.h @@ -12,11 +12,17 @@ /// what is possible from templates via context-free functions like /// \ref llvm::GraphTraits::child_begin()/child_end(). /// +/// Additionally, this file defines the \ref ISsaContext interface class and +/// its implementation that provides a superset of the SsaContext functionality +/// to code that wants to abstract over different IRs without being written as +/// templates. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_SSACONTEXT_H #define LLVM_SUPPORT_SSACONTEXT_H +#include "llvm/Support/Handle.h" #include "llvm/Support/Printable.h" namespace llvm { @@ -73,6 +79,60 @@ template using SsaContextFor = typename SsaContextForImpl::Context; +/// \brief Interface class for type-erased wrapping of SsaContext +/// +/// Do not provide manual implementations of this class. Instead, specialize +/// \ref SsaContextForImpl and rely on \ref ISsaContextImpl. +class ISsaContext { + virtual void anchor(); + +public: + virtual BlockHandle getDefBlock(SsaValueHandle value) const = 0; + + virtual Printable printableName(BlockHandle ref) const = 0; + virtual Printable printable(InstructionHandle ref) const = 0; + virtual Printable printable(SsaValueHandle ref) const = 0; +}; + +/// \brief Implementation of \ref ISsaContext for a context-type +/// +/// Analysis classes that desire a broader interface can have that interface +/// inherit from ISsaContext, with implementations instantiating this template +/// with a custom Base parameter that refers to the broader interface. +template +class ISsaContextImpl : public Base, SsaContextT { +public: + using SsaContext = SsaContextT; + using BlockRef = typename SsaContext::BlockRef; + using InstructionRef = typename SsaContext::InstructionRef; + using ValueRef = typename SsaContext::ValueRef; + using Wrapper = typename SsaContext::Wrapper; + + ISsaContextImpl(BlockRef ref) : SsaContext(ref) {} + ISsaContextImpl(InstructionRef ref) : SsaContext(ref) {} + + const SsaContext &getSsaContext() const { return *this; } + + BlockHandle getDefBlock(SsaValueHandle value) const final { + return Wrapper::wrapRef(SsaContext::getDefBlock(Wrapper::unwrapRef(value))); + } + + Printable printableName(BlockHandle ref) const final { + return SsaContext::printableName(Wrapper::unwrapRef(ref)); + } + + Printable printable(InstructionHandle ref) const final { + return SsaContext::printable(Wrapper::unwrapRef(ref)); + } + + Printable printable(SsaValueHandle ref) const final { + return SsaContext::printable(Wrapper::unwrapRef(ref)); + } +}; + +template +using ISsaContextFor = ISsaContextImpl>; + } // namespace llvm #endif // LLVM_SUPPORT_SSACONTEXT_H diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt --- a/llvm/lib/Support/CMakeLists.txt +++ b/llvm/lib/Support/CMakeLists.txt @@ -162,6 +162,7 @@ SmallVector.cpp SourceMgr.cpp SpecialCaseList.cpp + SsaContext.cpp Statistic.cpp StringExtras.cpp StringMap.cpp diff --git a/llvm/lib/Support/SsaContext.cpp b/llvm/lib/Support/SsaContext.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Support/SsaContext.cpp @@ -0,0 +1,13 @@ +//===- SsaContext.cpp -------------------------------------------*- C++ -*-===// +// +// 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 "llvm/Support/SsaContext.h" + +using namespace llvm; + +void ISsaContext::anchor() {}