Skip to content

Commit fa0dd8e

Browse files
committed
[SandboxIR] Boilerplate code
This is the first patch in a series of patches for the Sandbox Vectorizer project. SandboxIR is not tightly coupled to the Sandbox Vectorizer and could be used independently as a transactional layer on top of LLVM IR. For a more detailed description of the project please refer to the RFC: https://discourse.llvm.org/t/rfc-sandbox-vectorizer-an-experimental-modular-vectorizer/79059 This patch adds some basic boilerplate code for the SandboxIR which includes parts of the SandboxIR `Value` class.
1 parent d1a4f0c commit fa0dd8e

File tree

8 files changed

+315
-0
lines changed

8 files changed

+315
-0
lines changed
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
//===- SandboxIR.h ----------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Sandbox IR is a lightweight overlay transactional IR on top of LLVM IR.
10+
// Features:
11+
// - You can save/rollback the state of the IR at any time.
12+
// - Any changes made to Sandbox IR will automatically update the underlying
13+
// LLVM IR so both IRs are always in sync.
14+
// - Feels like LLVM IR, similar API.
15+
//
16+
// SandboxIR forms a class hierarchy that resembles that of LLVM IR
17+
// but is in the `sandboxir` namespace:
18+
//
19+
// namespace sandboxir {
20+
//
21+
// +- Argument +- BinaryOperator
22+
// | |
23+
// Value -+- BasicBlock +- BranchInst
24+
// | |
25+
// +- Function +- Constant +- CastInst
26+
// | | |
27+
// +- User ------+- Instruction -+- CallInst
28+
// |
29+
// +- CmpInst
30+
// |
31+
// +- ExtractElementInst
32+
// |
33+
// +- GetElementPtrInst
34+
// |
35+
// +- InsertElementInst
36+
// |
37+
// +- LoadInst
38+
// |
39+
// +- OpaqueInst
40+
// |
41+
// +- PHINode
42+
// |
43+
// +- RetInst
44+
// |
45+
// +- SelectInst
46+
// |
47+
// +- ShuffleVectorInst
48+
// |
49+
// +- StoreInst
50+
// |
51+
// +- UnaryOperator
52+
//
53+
// Use
54+
//
55+
// } // namespace sandboxir
56+
//
57+
58+
#ifndef LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
59+
#define LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
60+
61+
#include "llvm/IR/User.h"
62+
#include "llvm/IR/Value.h"
63+
#include "llvm/Support/raw_ostream.h"
64+
65+
namespace llvm {
66+
67+
namespace sandboxir {
68+
69+
class Context;
70+
71+
/// A SandboxIR Value has users. This is the base class.
72+
class Value {
73+
public:
74+
enum class ClassID : unsigned {
75+
#define DEF_VALUE(ID, CLASS) ID,
76+
#define DEF_USER(ID, CLASS) ID,
77+
#define DEF_INSTR(ID, OPC, CLASS) ID,
78+
#include "llvm/SandboxIR/SandboxIRValues.def"
79+
};
80+
81+
protected:
82+
static const char *getSubclassIDStr(ClassID ID) {
83+
switch (ID) {
84+
#define DEF_VALUE(ID, CLASS) \
85+
case ClassID::ID: \
86+
return #ID;
87+
#define DEF_USER(ID, CLASS) \
88+
case ClassID::ID: \
89+
return #ID;
90+
#define DEF_INSTR(ID, OPC, CLASS) \
91+
case ClassID::ID: \
92+
return #ID;
93+
#include "llvm/SandboxIR/SandboxIRValues.def"
94+
}
95+
llvm_unreachable("Unimplemented ID");
96+
}
97+
98+
/// For isa/dyn_cast.
99+
ClassID SubclassID;
100+
#ifndef NDEBUG
101+
/// A unique ID used for forming the name (used for debugging).
102+
unsigned UID;
103+
#endif
104+
/// The LLVM Value that corresponds to this SandboxIR Value.
105+
/// NOTE: Some SBInstructions, like Packs, may include more than one value.
106+
llvm::Value *Val = nullptr;
107+
108+
/// All values point to the context.
109+
Context &Ctx;
110+
// This is used by eraseFromParent().
111+
void clearValue() { Val = nullptr; }
112+
template <typename ItTy, typename SBTy> friend class LLVMOpUserItToSBTy;
113+
114+
public:
115+
Value(ClassID SubclassID, llvm::Value *Val, Context &Ctx);
116+
virtual ~Value() = default;
117+
ClassID getSubclassID() const { return SubclassID; }
118+
119+
Type *getType() const { return Val->getType(); }
120+
121+
Context &getContext() const;
122+
#ifndef NDEBUG
123+
/// Should crash if there is something wrong with the instruction.
124+
virtual void verify() const = 0;
125+
/// Returns the name in the form 'SB<number>.' like 'SB1.'
126+
std::string getName() const;
127+
virtual void dumpCommonHeader(raw_ostream &OS) const;
128+
void dumpCommonFooter(raw_ostream &OS) const;
129+
void dumpCommonPrefix(raw_ostream &OS) const;
130+
void dumpCommonSuffix(raw_ostream &OS) const;
131+
void printAsOperandCommon(raw_ostream &OS) const;
132+
#endif
133+
};
134+
135+
class User : public Value {
136+
public:
137+
User(ClassID ID, llvm::Value *V, Context &Ctx) : Value(ID, V, Ctx) {}
138+
/// For isa/dyn_cast.
139+
static bool classof(const Value *From);
140+
#ifndef NDEBUG
141+
void verify() const override {
142+
assert(isa<llvm::User>(Val) && "Expected User!");
143+
}
144+
void dumpCommonHeader(raw_ostream &OS) const final;
145+
#endif
146+
};
147+
148+
class Context {
149+
protected:
150+
LLVMContext &LLVMCtx;
151+
152+
public:
153+
Context(LLVMContext &LLVMCtx) : LLVMCtx(LLVMCtx) {}
154+
};
155+
} // namespace sandboxir
156+
} // namespace llvm
157+
158+
#endif // LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===- SandboxIRValues.def --------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// ClassID, Class
10+
DEF_USER(User, sandboxir::User)
11+
12+
#ifdef DEF_VALUE
13+
#undef DEF_VALUE
14+
#endif
15+
#ifdef DEF_USER
16+
#undef DEF_USER
17+
#endif
18+
#ifdef DEF_INSTR
19+
#undef DEF_INSTR
20+
#endif
21+
#ifdef OPCODES
22+
#undef OPCODES
23+
#endif
24+
#ifdef OP
25+
#undef OP
26+
#endif

llvm/lib/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ add_subdirectory(DebugInfo)
3333
add_subdirectory(DWP)
3434
add_subdirectory(ExecutionEngine)
3535
add_subdirectory(Target)
36+
add_subdirectory(SandboxIR)
3637
add_subdirectory(AsmParser)
3738
add_subdirectory(LineEditor)
3839
add_subdirectory(ProfileData)

llvm/lib/SandboxIR/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
add_llvm_component_library(LLVMSandboxIR
2+
SandboxIR.cpp
3+
4+
ADDITIONAL_HEADER_DIRS
5+
${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms/SandboxIR
6+
7+
LINK_COMPONENTS
8+
Core
9+
Support
10+
)
11+

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===- SandboxIR.cpp - A transactional overlay IR on top of LLVM IR -------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/SandboxIR/SandboxIR.h"
10+
#include "llvm/Support/Debug.h"
11+
#include <sstream>
12+
13+
using namespace llvm;
14+
using namespace sandboxir;
15+
16+
sandboxir::Value::Value(ClassID SubclassID, llvm::Value *Val, Context &Ctx)
17+
: SubclassID(SubclassID), Val(Val), Ctx(Ctx) {
18+
#ifndef NDEBUG
19+
UID = 0; // FIXME: Once SBContext is available.
20+
#endif
21+
}
22+
23+
#ifndef NDEBUG
24+
std::string sandboxir::Value::getName() const {
25+
std::stringstream SS;
26+
SS << "SB" << UID << ".";
27+
return SS.str();
28+
}
29+
30+
void sandboxir::Value::dumpCommonHeader(raw_ostream &OS) const {
31+
OS << getName() << " " << getSubclassIDStr(SubclassID) << " ";
32+
}
33+
34+
void sandboxir::Value::dumpCommonFooter(raw_ostream &OS) const {
35+
OS.indent(2) << "Val: ";
36+
if (Val)
37+
OS << *Val;
38+
else
39+
OS << "NULL";
40+
OS << "\n";
41+
}
42+
43+
void sandboxir::Value::dumpCommonPrefix(raw_ostream &OS) const {
44+
if (Val)
45+
OS << *Val;
46+
else
47+
OS << "NULL ";
48+
}
49+
50+
void sandboxir::Value::dumpCommonSuffix(raw_ostream &OS) const {
51+
OS << " ; " << getName() << " (" << getSubclassIDStr(SubclassID) << ") "
52+
<< this;
53+
}
54+
55+
void sandboxir::Value::printAsOperandCommon(raw_ostream &OS) const {
56+
if (Val)
57+
Val->printAsOperand(OS);
58+
else
59+
OS << "NULL ";
60+
}
61+
62+
void sandboxir::User::dumpCommonHeader(raw_ostream &OS) const {
63+
Value::dumpCommonHeader(OS);
64+
// TODO: This is incomplete
65+
}
66+
#endif // NDEBUG

llvm/unittests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ add_subdirectory(Option)
4343
add_subdirectory(Remarks)
4444
add_subdirectory(Passes)
4545
add_subdirectory(ProfileData)
46+
add_subdirectory(SandboxIR)
4647
add_subdirectory(Support)
4748
add_subdirectory(TableGen)
4849
add_subdirectory(Target)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
set(LLVM_LINK_COMPONENTS
2+
AsmParser
3+
SandboxIR
4+
)
5+
6+
add_llvm_unittest(SandboxIRTests
7+
SandboxIRTest.cpp
8+
)
9+
10+
set_property(TARGET SandboxIRTests PROPERTY FOLDER "Tests/UnitTests/TransformsTests")
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===- SandboxIRTest.cpp --------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/SandboxIR/SandboxIR.h"
10+
#include "llvm/AsmParser/Parser.h"
11+
#include "llvm/IR/BasicBlock.h"
12+
#include "llvm/IR/Function.h"
13+
#include "llvm/IR/Instruction.h"
14+
#include "llvm/IR/Module.h"
15+
#include "llvm/Support/SourceMgr.h"
16+
#include "gtest/gtest.h"
17+
18+
using namespace llvm;
19+
20+
struct SandboxIRTest : public testing::Test {
21+
LLVMContext C;
22+
std::unique_ptr<Module> M;
23+
24+
void parseIR(LLVMContext &C, const char *IR) {
25+
SMDiagnostic Err;
26+
M = parseAssemblyString(IR, Err, C);
27+
if (!M)
28+
Err.print("SandboxIRTest", errs());
29+
}
30+
};
31+
32+
TEST_F(SandboxIRTest, UserInstantiation) {
33+
parseIR(C, R"IR(
34+
define void @foo(i32 %v1) {
35+
ret void
36+
}
37+
)IR");
38+
Function &F = *M->getFunction("foo");
39+
auto *Ret = F.begin()->getTerminator();
40+
sandboxir::Context Ctx(C);
41+
[[maybe_unused]] sandboxir::User U(sandboxir::Value::ClassID::User, Ret, Ctx);
42+
}

0 commit comments

Comments
 (0)