From f12e10b513686a12f20f0c897dcc9ffc00cbce09 Mon Sep 17 00:00:00 2001 From: vporpo Date: Mon, 9 Sep 2024 15:41:30 -0700 Subject: [PATCH] [SandboxVec] Implement Pass class (#107617) This patch implements the Pass base class and the FunctionPass sub-class that operate on Sandbox IR. --- llvm/include/llvm/SandboxIR/Pass.h | 55 ++++++++++++++++ llvm/lib/SandboxIR/CMakeLists.txt | 1 + llvm/lib/SandboxIR/Pass.cpp | 19 ++++++ llvm/unittests/SandboxIR/CMakeLists.txt | 1 + llvm/unittests/SandboxIR/PassTest.cpp | 84 +++++++++++++++++++++++++ 5 files changed, 160 insertions(+) create mode 100644 llvm/include/llvm/SandboxIR/Pass.h create mode 100644 llvm/lib/SandboxIR/Pass.cpp create mode 100644 llvm/unittests/SandboxIR/PassTest.cpp diff --git a/llvm/include/llvm/SandboxIR/Pass.h b/llvm/include/llvm/SandboxIR/Pass.h new file mode 100644 index 00000000000000..d659e968392132 --- /dev/null +++ b/llvm/include/llvm/SandboxIR/Pass.h @@ -0,0 +1,55 @@ +//===- Pass.h ---------------------------------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SANDBOXIR_PASS_H +#define LLVM_SANDBOXIR_PASS_H + +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm::sandboxir { + +class Function; + +/// The base class of a Sandbox IR Pass. +class Pass { +protected: + /// The pass name. This is also used as a command-line flag and should not + /// contain whitespaces. + const std::string Name; + +public: + Pass(StringRef Name) : Name(Name) { + assert(!Name.contains(' ') && + "A pass name should not contain whitespaces!"); + assert(!Name.starts_with('-') && "A pass name should not start with '-'!"); + } + virtual ~Pass() {} + /// \Returns the name of the pass. + StringRef getName() const { return Name; } +#ifndef NDEBUG + friend raw_ostream &operator<<(raw_ostream &OS, const Pass &Pass) { + Pass.print(OS); + return OS; + } + void print(raw_ostream &OS) const { OS << Name; } + LLVM_DUMP_METHOD void dump() const; +#endif +}; + +/// A pass that runs on a sandbox::Function. +class FunctionPass : public Pass { +public: + FunctionPass(StringRef Name) : Pass(Name) {} + /// \Returns true if it modifies \p F. + virtual bool runOnFunction(Function &F) = 0; +}; + +} // namespace llvm::sandboxir + +#endif // LLVM_SANDBOXIR_PASS_H diff --git a/llvm/lib/SandboxIR/CMakeLists.txt b/llvm/lib/SandboxIR/CMakeLists.txt index d94f0642ccc4a1..2f047944e0335e 100644 --- a/llvm/lib/SandboxIR/CMakeLists.txt +++ b/llvm/lib/SandboxIR/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_component_library(LLVMSandboxIR + Pass.cpp SandboxIR.cpp Tracker.cpp Type.cpp diff --git a/llvm/lib/SandboxIR/Pass.cpp b/llvm/lib/SandboxIR/Pass.cpp new file mode 100644 index 00000000000000..64e1b609a9f49d --- /dev/null +++ b/llvm/lib/SandboxIR/Pass.cpp @@ -0,0 +1,19 @@ +//===- Pass.cpp - Passes that operate on Sandbox IR -----------------------===// +// +// 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/SandboxIR/Pass.h" +#include "llvm/Support/Debug.h" + +using namespace llvm::sandboxir; + +#ifndef NDEBUG +void Pass::dump() const { + print(dbgs()); + dbgs() << "\n"; +} +#endif // NDEBUG diff --git a/llvm/unittests/SandboxIR/CMakeLists.txt b/llvm/unittests/SandboxIR/CMakeLists.txt index 2da936bffa02bf..a228637b062a43 100644 --- a/llvm/unittests/SandboxIR/CMakeLists.txt +++ b/llvm/unittests/SandboxIR/CMakeLists.txt @@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS ) add_llvm_unittest(SandboxIRTests + PassTest.cpp SandboxIRTest.cpp TrackerTest.cpp TypesTest.cpp diff --git a/llvm/unittests/SandboxIR/PassTest.cpp b/llvm/unittests/SandboxIR/PassTest.cpp new file mode 100644 index 00000000000000..65992d8cb95ee1 --- /dev/null +++ b/llvm/unittests/SandboxIR/PassTest.cpp @@ -0,0 +1,84 @@ +//===- PassTest.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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/SandboxIR/Pass.h" +#include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Module.h" +#include "llvm/SandboxIR/SandboxIR.h" +#include "llvm/Support/SourceMgr.h" +#include "gtest/gtest.h" + +using namespace llvm::sandboxir; + +struct PassTest : public testing::Test { + llvm::LLVMContext LLVMCtx; + std::unique_ptr LLVMM; + std::unique_ptr Ctx; + + Function *parseFunction(const char *IR, const char *FuncName) { + llvm::SMDiagnostic Err; + LLVMM = parseAssemblyString(IR, Err, LLVMCtx); + if (!LLVMM) + Err.print("PassTest", llvm::errs()); + Ctx = std::make_unique(LLVMCtx); + return Ctx->createFunction(LLVMM->getFunction(FuncName)); + } +}; + +TEST_F(PassTest, FunctionPass) { + auto *F = parseFunction(R"IR( +define void @foo() { + ret void +} +)IR", + "foo"); + class TestPass final : public FunctionPass { + unsigned &BBCnt; + + public: + TestPass(unsigned &BBCnt) : FunctionPass("test-pass"), BBCnt(BBCnt) {} + bool runOnFunction(Function &F) final { + for ([[maybe_unused]] auto &BB : F) + ++BBCnt; + return false; + } + }; + unsigned BBCnt = 0; + TestPass TPass(BBCnt); + // Check getName(), + EXPECT_EQ(TPass.getName(), "test-pass"); + // Check classof(). + EXPECT_TRUE(llvm::isa(TPass)); + // Check runOnFunction(); + TPass.runOnFunction(*F); + EXPECT_EQ(BBCnt, 1u); +#ifndef NDEBUG + { + // Check print(). + std::string Buff; + llvm::raw_string_ostream SS(Buff); + TPass.print(SS); + EXPECT_EQ(Buff, "test-pass"); + } + { + // Check operator<<(). + std::string Buff; + llvm::raw_string_ostream SS(Buff); + SS << TPass; + EXPECT_EQ(Buff, "test-pass"); + } + // Check pass name assertions. + class TestNamePass final : public FunctionPass { + public: + TestNamePass(llvm::StringRef Name) : FunctionPass(Name) {} + bool runOnFunction(Function &F) { return false; } + }; + EXPECT_DEATH(TestNamePass("white space"), ".*whitespace.*"); + EXPECT_DEATH(TestNamePass("-dash"), ".*start with.*"); +#endif +}