Skip to content

Commit f938e82

Browse files
committed
[SandboxIR] More boilerplate: Function, Argument, Constant, Instruction, OpaqueInst
A very basic implementation of sandboxir:: `Fuction` `Argument` `Constant` `Instruction` `OpaqueInst`
1 parent 658c03d commit f938e82

File tree

4 files changed

+264
-1
lines changed

4 files changed

+264
-1
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#ifndef LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
5959
#define LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
6060

61+
#include "llvm/IR/Function.h"
6162
#include "llvm/IR/User.h"
6263
#include "llvm/IR/Value.h"
6364
#include "llvm/Support/raw_ostream.h"
@@ -129,6 +130,35 @@ class Value {
129130
void dumpCommonPrefix(raw_ostream &OS) const;
130131
void dumpCommonSuffix(raw_ostream &OS) const;
131132
void printAsOperandCommon(raw_ostream &OS) const;
133+
friend raw_ostream &operator<<(raw_ostream &OS, const sandboxir::Value &V) {
134+
V.dump(OS);
135+
return OS;
136+
}
137+
virtual void dump(raw_ostream &OS) const = 0;
138+
LLVM_DUMP_METHOD virtual void dump() const = 0;
139+
#endif
140+
};
141+
142+
/// Argument of a sandboxir::Function.
143+
class Argument : public sandboxir::Value {
144+
public:
145+
Argument(llvm::Argument *Arg, sandboxir::Context &Ctx)
146+
: sandboxir::Value(ClassID::Argument, Arg, Ctx) {}
147+
static bool classof(const sandboxir::Value *From) {
148+
return From->getSubclassID() == ClassID::Argument;
149+
}
150+
#ifndef NDEBUG
151+
void verify() const final {
152+
assert(isa<llvm::Argument>(Val) && "Expected Argument!");
153+
}
154+
friend raw_ostream &operator<<(raw_ostream &OS,
155+
const sandboxir::Argument &TArg) {
156+
TArg.dump(OS);
157+
return OS;
158+
}
159+
void printAsOperand(raw_ostream &OS) const;
160+
void dump(raw_ostream &OS) const final;
161+
LLVM_DUMP_METHOD void dump() const final;
132162
#endif
133163
};
134164

@@ -142,16 +172,137 @@ class User : public Value {
142172
assert(isa<llvm::User>(Val) && "Expected User!");
143173
}
144174
void dumpCommonHeader(raw_ostream &OS) const final;
175+
void dump(raw_ostream &OS) const override {
176+
// TODO: Remove this tmp implementation once we get the Instruction classes.
177+
}
178+
LLVM_DUMP_METHOD void dump() const override {
179+
// TODO: Remove this tmp implementation once we get the Instruction classes.
180+
}
181+
#endif
182+
};
183+
184+
class Constant : public sandboxir::User {
185+
public:
186+
Constant(llvm::Constant *C, sandboxir::Context &SBCtx)
187+
: sandboxir::User(ClassID::Constant, C, SBCtx) {}
188+
/// For isa/dyn_cast.
189+
static bool classof(const sandboxir::Value *From) {
190+
return From->getSubclassID() == ClassID::Constant ||
191+
From->getSubclassID() == ClassID::Function;
192+
}
193+
sandboxir::Context &getParent() const { return getContext(); }
194+
#ifndef NDEBUG
195+
void verify() const final {
196+
assert(isa<llvm::Constant>(Val) && "Expected Constant!");
197+
}
198+
friend raw_ostream &operator<<(raw_ostream &OS,
199+
const sandboxir::Constant &SBC) {
200+
SBC.dump(OS);
201+
return OS;
202+
}
203+
void dump(raw_ostream &OS) const override;
204+
LLVM_DUMP_METHOD void dump() const override;
205+
#endif
206+
};
207+
208+
/// A sandboxir::User with operands and opcode.
209+
class Instruction : public sandboxir::User {
210+
public:
211+
enum class Opcode {
212+
#define DEF_VALUE(ID, CLASS)
213+
#define DEF_USER(ID, CLASS)
214+
#define OP(OPC) OPC,
215+
#define OPCODES(...) __VA_ARGS__
216+
#define DEF_INSTR(ID, OPC, CLASS) OPC
217+
#include "llvm/SandboxIR/SandboxIRValues.def"
218+
};
219+
220+
Instruction(ClassID ID, Opcode Opc, llvm::Instruction *I,
221+
sandboxir::Context &SBCtx)
222+
: sandboxir::User(ID, I, SBCtx), Opc(Opc) {}
223+
224+
protected:
225+
Opcode Opc;
226+
227+
public:
228+
static const char *getOpcodeName(Opcode Opc);
229+
#ifndef NDEBUG
230+
friend raw_ostream &operator<<(raw_ostream &OS, Opcode Opc) {
231+
OS << getOpcodeName(Opc);
232+
return OS;
233+
}
234+
#endif
235+
/// For isa/dyn_cast.
236+
static bool classof(const sandboxir::Value *From);
237+
238+
#ifndef NDEBUG
239+
friend raw_ostream &operator<<(raw_ostream &OS,
240+
const sandboxir::Instruction &SBI) {
241+
SBI.dump(OS);
242+
return OS;
243+
}
244+
void dump(raw_ostream &OS) const override;
245+
LLVM_DUMP_METHOD void dump() const override;
246+
#endif
247+
};
248+
249+
/// An LLLVM Instruction that has no SandboxIR equivalent class gets mapped to
250+
/// an OpaqueInstr.
251+
class OpaqueInst : public sandboxir::Instruction {
252+
public:
253+
OpaqueInst(llvm::Instruction *I, sandboxir::Context &Ctx)
254+
: sandboxir::Instruction(ClassID::Opaque, Opcode::Opaque, I, Ctx) {}
255+
OpaqueInst(ClassID SubclassID, llvm::Instruction *I, sandboxir::Context &Ctx)
256+
: sandboxir::Instruction(SubclassID, Opcode::Opaque, I, Ctx) {}
257+
static bool classof(const sandboxir::Value *From) {
258+
return From->getSubclassID() == ClassID::Opaque;
259+
}
260+
#ifndef NDEBUG
261+
void verify() const final {
262+
// Nothing to do
263+
}
264+
friend raw_ostream &operator<<(raw_ostream &OS,
265+
const sandboxir::OpaqueInst &OI) {
266+
OI.dump(OS);
267+
return OS;
268+
}
269+
void dump(raw_ostream &OS) const override;
270+
LLVM_DUMP_METHOD void dump() const override;
145271
#endif
146272
};
147273

148274
class Context {
149275
protected:
150276
LLVMContext &LLVMCtx;
277+
/// Maps LLVM Value to the corresponding sandboxir::Value. Owns all
278+
/// SandboxIR objects.
279+
DenseMap<llvm::Value *, std::unique_ptr<sandboxir::Value>>
280+
LLVMValueToSBValueMap;
151281

152282
public:
153283
Context(LLVMContext &LLVMCtx) : LLVMCtx(LLVMCtx) {}
284+
sandboxir::Value *getValue(llvm::Value *V) const;
285+
};
286+
287+
class Function : public sandboxir::Value {
288+
public:
289+
Function(llvm::Function *F, sandboxir::Context &Ctx)
290+
: sandboxir::Value(ClassID::Function, F, Ctx) {}
291+
/// For isa/dyn_cast.
292+
static bool classof(const sandboxir::Value *From) {
293+
return From->getSubclassID() == ClassID::Function;
294+
}
295+
296+
#ifndef NDEBUG
297+
void verify() const final {
298+
assert(isa<llvm::Function>(Val) && "Expected Function!");
299+
}
300+
void dumpNameAndArgs(raw_ostream &OS) const;
301+
void dump(raw_ostream &OS) const final;
302+
LLVM_DUMP_METHOD void dump() const final;
303+
#endif
154304
};
305+
155306
} // namespace sandboxir
156307
} // namespace llvm
157308

llvm/include/llvm/SandboxIR/SandboxIRValues.def

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@
77
//===----------------------------------------------------------------------===//
88

99
// ClassID, Class
10-
DEF_USER(User, sandboxir::User)
10+
DEF_VALUE(Function, Function)
11+
DEF_VALUE(Argument, Argument)
12+
DEF_USER(User, User)
13+
DEF_USER(Constant, Constant)
14+
15+
// ClassID, Opcode(s), Class
16+
DEF_INSTR(Opaque, OP(Opaque), OpaqueInst)
1117

1218
#ifdef DEF_VALUE
1319
#undef DEF_VALUE

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,95 @@ void sandboxir::Value::printAsOperandCommon(raw_ostream &OS) const {
5959
OS << "NULL ";
6060
}
6161

62+
void sandboxir::Argument::printAsOperand(raw_ostream &OS) const {
63+
printAsOperandCommon(OS);
64+
}
65+
void sandboxir::Argument::dump(raw_ostream &OS) const {
66+
dumpCommonPrefix(OS);
67+
dumpCommonSuffix(OS);
68+
}
69+
void sandboxir::Argument::dump() const {
70+
dump(dbgs());
71+
dbgs() << "\n";
72+
}
73+
6274
void sandboxir::User::dumpCommonHeader(raw_ostream &OS) const {
6375
Value::dumpCommonHeader(OS);
6476
// TODO: This is incomplete
6577
}
6678
#endif // NDEBUG
79+
80+
const char *sandboxir::Instruction::getOpcodeName(Opcode Opc) {
81+
switch (Opc) {
82+
#define DEF_VALUE(ID, CLASS)
83+
#define DEF_USER(ID, CLASS)
84+
#define OP(OPC) \
85+
case Opcode::OPC: \
86+
return #OPC;
87+
#define OPCODES(...) __VA_ARGS__
88+
#define DEF_INSTR(ID, OPC, CLASS) OPC
89+
#include "llvm/SandboxIR/SandboxIRValues.def"
90+
}
91+
}
92+
93+
#ifndef NDEBUG
94+
void sandboxir::Instruction::dump(raw_ostream &OS) const {
95+
OS << "Unimplemented! Please override dump().";
96+
}
97+
void sandboxir::Instruction::dump() const {
98+
dump(dbgs());
99+
dbgs() << "\n";
100+
}
101+
102+
void sandboxir::OpaqueInst::dump(raw_ostream &OS) const {
103+
dumpCommonPrefix(OS);
104+
dumpCommonSuffix(OS);
105+
}
106+
107+
void sandboxir::OpaqueInst::dump() const {
108+
dump(dbgs());
109+
dbgs() << "\n";
110+
}
111+
112+
void sandboxir::Constant::dump(raw_ostream &OS) const {
113+
dumpCommonPrefix(OS);
114+
dumpCommonSuffix(OS);
115+
}
116+
117+
void sandboxir::Constant::dump() const {
118+
dump(dbgs());
119+
dbgs() << "\n";
120+
}
121+
122+
void sandboxir::Function::dumpNameAndArgs(raw_ostream &OS) const {
123+
auto *F = cast<llvm::Function>(Val);
124+
OS << *getType() << " @" << F->getName() << "(";
125+
auto NumArgs = F->arg_size();
126+
for (auto [Idx, Arg] : enumerate(F->args())) {
127+
auto *SBArg = cast_or_null<sandboxir::Argument>(Ctx.getValue(&Arg));
128+
if (SBArg == nullptr)
129+
OS << "NULL";
130+
else
131+
SBArg->printAsOperand(OS);
132+
if (Idx + 1 < NumArgs)
133+
OS << ", ";
134+
}
135+
OS << ")";
136+
}
137+
void sandboxir::Function::dump(raw_ostream &OS) const {
138+
dumpNameAndArgs(OS);
139+
OS << " {\n";
140+
OS << "}\n";
141+
}
142+
void sandboxir::Function::dump() const {
143+
dump(dbgs());
144+
dbgs() << "\n";
145+
}
146+
#endif // NDEBUG
147+
148+
sandboxir::Value *sandboxir::Context::getValue(llvm::Value *V) const {
149+
auto It = LLVMValueToSBValueMap.find(V);
150+
if (It != LLVMValueToSBValueMap.end())
151+
return It->second.get();
152+
return nullptr;
153+
}

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,22 @@ define void @foo(i32 %v1) {
4040
sandboxir::Context Ctx(C);
4141
[[maybe_unused]] sandboxir::User U(sandboxir::Value::ClassID::User, Ret, Ctx);
4242
}
43+
44+
TEST_F(SandboxIRTest, FunctionArgumentConstantAndOpaqueInstInstantiation) {
45+
parseIR(C, R"IR(
46+
define void @foo(i32 %v1) {
47+
%add = add i32 %v1, 42
48+
ret void
49+
}
50+
)IR");
51+
llvm::Function *LLVMF = &*M->getFunction("foo");
52+
llvm::BasicBlock *LLVMBB = &*LLVMF->begin();
53+
llvm::Instruction *LLVMAdd = &*LLVMBB->begin();
54+
auto *LLVMC = cast<llvm::Constant>(LLVMAdd->getOperand(1));
55+
sandboxir::Context Ctx(C);
56+
auto *LLVMArg0 = LLVMF->getArg(0);
57+
[[maybe_unused]] sandboxir::Function F(LLVMF, Ctx);
58+
[[maybe_unused]] sandboxir::Argument Arg0(LLVMArg0, Ctx);
59+
[[maybe_unused]] sandboxir::Constant Const0(LLVMC, Ctx);
60+
[[maybe_unused]] sandboxir::OpaqueInst Opaque(LLVMAdd, Ctx);
61+
}

0 commit comments

Comments
 (0)