Skip to content

Commit

Permalink
Reapply "[SandboxIR] Boilerplate code (#95814)"
Browse files Browse the repository at this point in the history
This reverts commit 2f4f43c.
  • Loading branch information
vporpo committed Jul 1, 2024
1 parent 6b707a8 commit f9efc29
Show file tree
Hide file tree
Showing 8 changed files with 314 additions and 0 deletions.
158 changes: 158 additions & 0 deletions llvm/include/llvm/SandboxIR/SandboxIR.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
//===- SandboxIR.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
//
//===----------------------------------------------------------------------===//
//
// Sandbox IR is a lightweight overlay transactional IR on top of LLVM IR.
// Features:
// - You can save/rollback the state of the IR at any time.
// - Any changes made to Sandbox IR will automatically update the underlying
// LLVM IR so both IRs are always in sync.
// - Feels like LLVM IR, similar API.
//
// SandboxIR forms a class hierarchy that resembles that of LLVM IR
// but is in the `sandboxir` namespace:
//
// namespace sandboxir {
//
// +- Argument +- BinaryOperator
// | |
// Value -+- BasicBlock +- BranchInst
// | |
// +- Function +- Constant +- CastInst
// | | |
// +- User ------+- Instruction -+- CallInst
// |
// +- CmpInst
// |
// +- ExtractElementInst
// |
// +- GetElementPtrInst
// |
// +- InsertElementInst
// |
// +- LoadInst
// |
// +- OpaqueInst
// |
// +- PHINode
// |
// +- RetInst
// |
// +- SelectInst
// |
// +- ShuffleVectorInst
// |
// +- StoreInst
// |
// +- UnaryOperator
//
// Use
//
// } // namespace sandboxir
//

#ifndef LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
#define LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H

#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/raw_ostream.h"

namespace llvm {

namespace sandboxir {

class Context;

/// A SandboxIR Value has users. This is the base class.
class Value {
public:
enum class ClassID : unsigned {
#define DEF_VALUE(ID, CLASS) ID,
#define DEF_USER(ID, CLASS) ID,
#define DEF_INSTR(ID, OPC, CLASS) ID,
#include "llvm/SandboxIR/SandboxIRValues.def"
};

protected:
static const char *getSubclassIDStr(ClassID ID) {
switch (ID) {
#define DEF_VALUE(ID, CLASS) \
case ClassID::ID: \
return #ID;
#define DEF_USER(ID, CLASS) \
case ClassID::ID: \
return #ID;
#define DEF_INSTR(ID, OPC, CLASS) \
case ClassID::ID: \
return #ID;
#include "llvm/SandboxIR/SandboxIRValues.def"
}
llvm_unreachable("Unimplemented ID");
}

/// For isa/dyn_cast.
ClassID SubclassID;
#ifndef NDEBUG
/// A unique ID used for forming the name (used for debugging).
unsigned UID;
#endif
/// The LLVM Value that corresponds to this SandboxIR Value.
/// NOTE: Some SBInstructions, like Packs, may include more than one value.
llvm::Value *Val = nullptr;

/// All values point to the context.
Context &Ctx;
// This is used by eraseFromParent().
void clearValue() { Val = nullptr; }
template <typename ItTy, typename SBTy> friend class LLVMOpUserItToSBTy;

public:
Value(ClassID SubclassID, llvm::Value *Val, Context &Ctx);
virtual ~Value() = default;
ClassID getSubclassID() const { return SubclassID; }

Type *getType() const { return Val->getType(); }

Context &getContext() const;
#ifndef NDEBUG
/// Should crash if there is something wrong with the instruction.
virtual void verify() const = 0;
/// Returns the name in the form 'SB<number>.' like 'SB1.'
std::string getName() const;
virtual void dumpCommonHeader(raw_ostream &OS) const;
void dumpCommonFooter(raw_ostream &OS) const;
void dumpCommonPrefix(raw_ostream &OS) const;
void dumpCommonSuffix(raw_ostream &OS) const;
void printAsOperandCommon(raw_ostream &OS) const;
#endif
};

class User : public Value {
public:
User(ClassID ID, llvm::Value *V, Context &Ctx) : Value(ID, V, Ctx) {}
/// For isa/dyn_cast.
static bool classof(const Value *From);
#ifndef NDEBUG
void verify() const override {
assert(isa<llvm::User>(Val) && "Expected User!");
}
void dumpCommonHeader(raw_ostream &OS) const final;
#endif
};

class Context {
protected:
LLVMContext &LLVMCtx;

public:
Context(LLVMContext &LLVMCtx) : LLVMCtx(LLVMCtx) {}
};
} // namespace sandboxir
} // namespace llvm

#endif // LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
26 changes: 26 additions & 0 deletions llvm/include/llvm/SandboxIR/SandboxIRValues.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===- SandboxIRValues.def --------------------------------------*- 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
//
//===----------------------------------------------------------------------===//

// ClassID, Class
DEF_USER(User, sandboxir::User)

#ifdef DEF_VALUE
#undef DEF_VALUE
#endif
#ifdef DEF_USER
#undef DEF_USER
#endif
#ifdef DEF_INSTR
#undef DEF_INSTR
#endif
#ifdef OPCODES
#undef OPCODES
#endif
#ifdef OP
#undef OP
#endif
1 change: 1 addition & 0 deletions llvm/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ add_subdirectory(DebugInfo)
add_subdirectory(DWP)
add_subdirectory(ExecutionEngine)
add_subdirectory(Target)
add_subdirectory(SandboxIR)
add_subdirectory(AsmParser)
add_subdirectory(LineEditor)
add_subdirectory(ProfileData)
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/SandboxIR/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
add_llvm_component_library(LLVMSandboxIR
SandboxIR.cpp

ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms/SandboxIR

LINK_COMPONENTS
Core
Support
)

66 changes: 66 additions & 0 deletions llvm/lib/SandboxIR/SandboxIR.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//===- SandboxIR.cpp - A transactional overlay IR on top of LLVM 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/SandboxIR.h"
#include "llvm/Support/Debug.h"
#include <sstream>

using namespace llvm;
using namespace sandboxir;

sandboxir::Value::Value(ClassID SubclassID, llvm::Value *Val, Context &Ctx)
: SubclassID(SubclassID), Val(Val), Ctx(Ctx) {
#ifndef NDEBUG
UID = 0; // FIXME: Once SBContext is available.
#endif
}

#ifndef NDEBUG
std::string sandboxir::Value::getName() const {
std::stringstream SS;
SS << "SB" << UID << ".";
return SS.str();
}

void sandboxir::Value::dumpCommonHeader(raw_ostream &OS) const {
OS << getName() << " " << getSubclassIDStr(SubclassID) << " ";
}

void sandboxir::Value::dumpCommonFooter(raw_ostream &OS) const {
OS.indent(2) << "Val: ";
if (Val)
OS << *Val;
else
OS << "NULL";
OS << "\n";
}

void sandboxir::Value::dumpCommonPrefix(raw_ostream &OS) const {
if (Val)
OS << *Val;
else
OS << "NULL ";
}

void sandboxir::Value::dumpCommonSuffix(raw_ostream &OS) const {
OS << " ; " << getName() << " (" << getSubclassIDStr(SubclassID) << ") "
<< this;
}

void sandboxir::Value::printAsOperandCommon(raw_ostream &OS) const {
if (Val)
Val->printAsOperand(OS);
else
OS << "NULL ";
}

void sandboxir::User::dumpCommonHeader(raw_ostream &OS) const {
Value::dumpCommonHeader(OS);
// TODO: This is incomplete
}
#endif // NDEBUG
1 change: 1 addition & 0 deletions llvm/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ add_subdirectory(Option)
add_subdirectory(Remarks)
add_subdirectory(Passes)
add_subdirectory(ProfileData)
add_subdirectory(SandboxIR)
add_subdirectory(Support)
add_subdirectory(TableGen)
add_subdirectory(Target)
Expand Down
9 changes: 9 additions & 0 deletions llvm/unittests/SandboxIR/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
set(LLVM_LINK_COMPONENTS
AsmParser
SandboxIR
Core
)

add_llvm_unittest(SandboxIRTests
SandboxIRTest.cpp
)
42 changes: 42 additions & 0 deletions llvm/unittests/SandboxIR/SandboxIRTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//===- SandboxIRTest.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/SandboxIR.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"

using namespace llvm;

struct SandboxIRTest : public testing::Test {
LLVMContext C;
std::unique_ptr<Module> M;

void parseIR(LLVMContext &C, const char *IR) {
SMDiagnostic Err;
M = parseAssemblyString(IR, Err, C);
if (!M)
Err.print("SandboxIRTest", errs());
}
};

TEST_F(SandboxIRTest, UserInstantiation) {
parseIR(C, R"IR(
define void @foo(i32 %v1) {
ret void
}
)IR");
Function &F = *M->getFunction("foo");
auto *Ret = F.begin()->getTerminator();
sandboxir::Context Ctx(C);
[[maybe_unused]] sandboxir::User U(sandboxir::Value::ClassID::User, Ret, Ctx);
}

0 comments on commit f9efc29

Please sign in to comment.