[llvm] d5f5dc9 - [SandboxIR] More boilerplate: Function, Argument, Constant, Instruction, OpaqueInst (#97343)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 3 12:04:19 PDT 2024
Author: vporpo
Date: 2024-07-03T12:04:16-07:00
New Revision: d5f5dc9dcca427a290a9f454046113afdb6a68ff
URL: https://github.com/llvm/llvm-project/commit/d5f5dc9dcca427a290a9f454046113afdb6a68ff
DIFF: https://github.com/llvm/llvm-project/commit/d5f5dc9dcca427a290a9f454046113afdb6a68ff.diff
LOG: [SandboxIR] More boilerplate: Function, Argument, Constant, Instruction, OpaqueInst (#97343)
A very basic implementation of sandboxir::
`Fuction`
`Argument`
`Constant`
`Instruction`
`OpaqueInst`
Added:
Modified:
llvm/include/llvm/SandboxIR/SandboxIR.h
llvm/include/llvm/SandboxIR/SandboxIRValues.def
llvm/lib/SandboxIR/SandboxIR.cpp
llvm/unittests/SandboxIR/SandboxIRTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index ec7ec1a268fa7..ab6273a7ace66 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -58,6 +58,7 @@
#ifndef LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
#define LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
+#include "llvm/IR/Function.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/raw_ostream.h"
@@ -129,6 +130,35 @@ class Value {
void dumpCommonPrefix(raw_ostream &OS) const;
void dumpCommonSuffix(raw_ostream &OS) const;
void printAsOperandCommon(raw_ostream &OS) const;
+ friend raw_ostream &operator<<(raw_ostream &OS, const sandboxir::Value &V) {
+ V.dump(OS);
+ return OS;
+ }
+ virtual void dump(raw_ostream &OS) const = 0;
+ LLVM_DUMP_METHOD virtual void dump() const = 0;
+#endif
+};
+
+/// Argument of a sandboxir::Function.
+class Argument : public sandboxir::Value {
+public:
+ Argument(llvm::Argument *Arg, sandboxir::Context &Ctx)
+ : sandboxir::Value(ClassID::Argument, Arg, Ctx) {}
+ static bool classof(const sandboxir::Value *From) {
+ return From->getSubclassID() == ClassID::Argument;
+ }
+#ifndef NDEBUG
+ void verify() const final {
+ assert(isa<llvm::Argument>(Val) && "Expected Argument!");
+ }
+ friend raw_ostream &operator<<(raw_ostream &OS,
+ const sandboxir::Argument &TArg) {
+ TArg.dump(OS);
+ return OS;
+ }
+ void printAsOperand(raw_ostream &OS) const;
+ void dump(raw_ostream &OS) const final;
+ LLVM_DUMP_METHOD void dump() const final;
#endif
};
@@ -142,16 +172,136 @@ class User : public Value {
assert(isa<llvm::User>(Val) && "Expected User!");
}
void dumpCommonHeader(raw_ostream &OS) const final;
+ void dump(raw_ostream &OS) const override {
+ // TODO: Remove this tmp implementation once we get the Instruction classes.
+ }
+ LLVM_DUMP_METHOD void dump() const override {
+ // TODO: Remove this tmp implementation once we get the Instruction classes.
+ }
+#endif
+};
+
+class Constant : public sandboxir::User {
+public:
+ Constant(llvm::Constant *C, sandboxir::Context &SBCtx)
+ : sandboxir::User(ClassID::Constant, C, SBCtx) {}
+ /// For isa/dyn_cast.
+ static bool classof(const sandboxir::Value *From) {
+ return From->getSubclassID() == ClassID::Constant ||
+ From->getSubclassID() == ClassID::Function;
+ }
+ sandboxir::Context &getParent() const { return getContext(); }
+#ifndef NDEBUG
+ void verify() const final {
+ assert(isa<llvm::Constant>(Val) && "Expected Constant!");
+ }
+ friend raw_ostream &operator<<(raw_ostream &OS,
+ const sandboxir::Constant &SBC) {
+ SBC.dump(OS);
+ return OS;
+ }
+ void dump(raw_ostream &OS) const override;
+ LLVM_DUMP_METHOD void dump() const override;
+#endif
+};
+
+/// A sandboxir::User with operands and opcode.
+class Instruction : public sandboxir::User {
+public:
+ enum class Opcode {
+#define DEF_VALUE(ID, CLASS)
+#define DEF_USER(ID, CLASS)
+#define OP(OPC) OPC,
+#define DEF_INSTR(ID, OPC, CLASS) OPC
+#include "llvm/SandboxIR/SandboxIRValues.def"
+ };
+
+ Instruction(ClassID ID, Opcode Opc, llvm::Instruction *I,
+ sandboxir::Context &SBCtx)
+ : sandboxir::User(ID, I, SBCtx), Opc(Opc) {}
+
+protected:
+ Opcode Opc;
+
+public:
+ static const char *getOpcodeName(Opcode Opc);
+#ifndef NDEBUG
+ friend raw_ostream &operator<<(raw_ostream &OS, Opcode Opc) {
+ OS << getOpcodeName(Opc);
+ return OS;
+ }
+#endif
+ /// For isa/dyn_cast.
+ static bool classof(const sandboxir::Value *From);
+
+#ifndef NDEBUG
+ friend raw_ostream &operator<<(raw_ostream &OS,
+ const sandboxir::Instruction &SBI) {
+ SBI.dump(OS);
+ return OS;
+ }
+ void dump(raw_ostream &OS) const override;
+ LLVM_DUMP_METHOD void dump() const override;
+#endif
+};
+
+/// An LLLVM Instruction that has no SandboxIR equivalent class gets mapped to
+/// an OpaqueInstr.
+class OpaqueInst : public sandboxir::Instruction {
+public:
+ OpaqueInst(llvm::Instruction *I, sandboxir::Context &Ctx)
+ : sandboxir::Instruction(ClassID::Opaque, Opcode::Opaque, I, Ctx) {}
+ OpaqueInst(ClassID SubclassID, llvm::Instruction *I, sandboxir::Context &Ctx)
+ : sandboxir::Instruction(SubclassID, Opcode::Opaque, I, Ctx) {}
+ static bool classof(const sandboxir::Value *From) {
+ return From->getSubclassID() == ClassID::Opaque;
+ }
+#ifndef NDEBUG
+ void verify() const final {
+ // Nothing to do
+ }
+ friend raw_ostream &operator<<(raw_ostream &OS,
+ const sandboxir::OpaqueInst &OI) {
+ OI.dump(OS);
+ return OS;
+ }
+ void dump(raw_ostream &OS) const override;
+ LLVM_DUMP_METHOD void dump() const override;
#endif
};
class Context {
protected:
LLVMContext &LLVMCtx;
+ /// Maps LLVM Value to the corresponding sandboxir::Value. Owns all
+ /// SandboxIR objects.
+ DenseMap<llvm::Value *, std::unique_ptr<sandboxir::Value>>
+ LLVMValueToValueMap;
public:
Context(LLVMContext &LLVMCtx) : LLVMCtx(LLVMCtx) {}
+ sandboxir::Value *getValue(llvm::Value *V) const;
+};
+
+class Function : public sandboxir::Value {
+public:
+ Function(llvm::Function *F, sandboxir::Context &Ctx)
+ : sandboxir::Value(ClassID::Function, F, Ctx) {}
+ /// For isa/dyn_cast.
+ static bool classof(const sandboxir::Value *From) {
+ return From->getSubclassID() == ClassID::Function;
+ }
+
+#ifndef NDEBUG
+ void verify() const final {
+ assert(isa<llvm::Function>(Val) && "Expected Function!");
+ }
+ void dumpNameAndArgs(raw_ostream &OS) const;
+ void dump(raw_ostream &OS) const final;
+ LLVM_DUMP_METHOD void dump() const final;
+#endif
};
+
} // namespace sandboxir
} // namespace llvm
diff --git a/llvm/include/llvm/SandboxIR/SandboxIRValues.def b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
index d41d8dce56e68..474b151ae03a4 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIRValues.def
+++ b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
@@ -7,7 +7,23 @@
//===----------------------------------------------------------------------===//
// ClassID, Class
-DEF_USER(User, sandboxir::User)
+#ifndef DEF_VALUE
+#define DEF_VALUE(ID, CLASS)
+#endif
+DEF_VALUE(Function, Function)
+DEF_VALUE(Argument, Argument)
+
+#ifndef DEF_USER
+#define DEF_USER(ID, CLASS)
+#endif
+DEF_USER(User, User)
+DEF_USER(Constant, Constant)
+
+#ifndef DEF_INSTR
+#define DEF_INSTR(ID, OPCODE, CLASS)
+#endif
+// ClassID, Opcode(s), Class
+DEF_INSTR(Opaque, OP(Opaque), OpaqueInst)
#ifdef DEF_VALUE
#undef DEF_VALUE
@@ -18,9 +34,6 @@ DEF_USER(User, sandboxir::User)
#ifdef DEF_INSTR
#undef DEF_INSTR
#endif
-#ifdef OPCODES
-#undef OPCODES
-#endif
#ifdef OP
#undef OP
#endif
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 86757029c821c..47e1ae4422c98 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -58,8 +58,122 @@ void Value::printAsOperandCommon(raw_ostream &OS) const {
OS << "NULL ";
}
+void Argument::printAsOperand(raw_ostream &OS) const {
+ printAsOperandCommon(OS);
+}
+void Argument::dump(raw_ostream &OS) const {
+ dumpCommonPrefix(OS);
+ dumpCommonSuffix(OS);
+}
+void Argument::dump() const {
+ dump(dbgs());
+ dbgs() << "\n";
+}
+#endif // NDEBUG
+
+bool User::classof(const Value *From) {
+ switch (From->getSubclassID()) {
+#define DEF_VALUE(ID, CLASS)
+#define DEF_USER(ID, CLASS) \
+ case ClassID::ID: \
+ return true;
+#define DEF_INSTR(ID, OPC, CLASS) \
+ case ClassID::ID: \
+ return true;
+#include "llvm/SandboxIR/SandboxIRValues.def"
+ default:
+ return false;
+ }
+}
+
+#ifndef NDEBUG
void User::dumpCommonHeader(raw_ostream &OS) const {
Value::dumpCommonHeader(OS);
// TODO: This is incomplete
}
#endif // NDEBUG
+
+const char *Instruction::getOpcodeName(Opcode Opc) {
+ switch (Opc) {
+#define DEF_VALUE(ID, CLASS)
+#define DEF_USER(ID, CLASS)
+#define OP(OPC) \
+ case Opcode::OPC: \
+ return #OPC;
+#define DEF_INSTR(ID, OPC, CLASS) OPC
+#include "llvm/SandboxIR/SandboxIRValues.def"
+ }
+}
+
+bool Instruction::classof(const sandboxir::Value *From) {
+ switch (From->getSubclassID()) {
+#define DEF_INSTR(ID, OPC, CLASS) \
+ case ClassID::ID: \
+ return true;
+#include "llvm/SandboxIR/SandboxIRValues.def"
+ default:
+ return false;
+ }
+}
+
+#ifndef NDEBUG
+void Instruction::dump(raw_ostream &OS) const {
+ OS << "Unimplemented! Please override dump().";
+}
+void Instruction::dump() const {
+ dump(dbgs());
+ dbgs() << "\n";
+}
+
+void OpaqueInst::dump(raw_ostream &OS) const {
+ dumpCommonPrefix(OS);
+ dumpCommonSuffix(OS);
+}
+
+void OpaqueInst::dump() const {
+ dump(dbgs());
+ dbgs() << "\n";
+}
+
+void Constant::dump(raw_ostream &OS) const {
+ dumpCommonPrefix(OS);
+ dumpCommonSuffix(OS);
+}
+
+void Constant::dump() const {
+ dump(dbgs());
+ dbgs() << "\n";
+}
+
+void Function::dumpNameAndArgs(raw_ostream &OS) const {
+ auto *F = cast<llvm::Function>(Val);
+ OS << *getType() << " @" << F->getName() << "(";
+ auto NumArgs = F->arg_size();
+ for (auto [Idx, Arg] : enumerate(F->args())) {
+ auto *SBArg = cast_or_null<Argument>(Ctx.getValue(&Arg));
+ if (SBArg == nullptr)
+ OS << "NULL";
+ else
+ SBArg->printAsOperand(OS);
+ if (Idx + 1 < NumArgs)
+ OS << ", ";
+ }
+ OS << ")";
+}
+void Function::dump(raw_ostream &OS) const {
+ dumpNameAndArgs(OS);
+ OS << " {\n";
+ OS << "}\n";
+}
+void Function::dump() const {
+ dump(dbgs());
+ dbgs() << "\n";
+}
+#endif // NDEBUG
+
+Value *Context::getValue(llvm::Value *V) const {
+ auto It = LLVMValueToValueMap.find(V);
+ if (It != LLVMValueToValueMap.end())
+ return It->second.get();
+ return nullptr;
+}
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index 14e6e745f757a..0b0409aa15c4f 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -40,3 +40,53 @@ define void @foo(i32 %v1) {
sandboxir::Context Ctx(C);
[[maybe_unused]] sandboxir::User U(sandboxir::Value::ClassID::User, Ret, Ctx);
}
+
+TEST_F(SandboxIRTest, FunctionArgumentConstantAndOpaqueInstInstantiation) {
+ parseIR(C, R"IR(
+define void @foo(i32 %v1) {
+ %add = add i32 %v1, 42
+ ret void
+}
+)IR");
+ llvm::Function *LLVMF = &*M->getFunction("foo");
+ llvm::BasicBlock *LLVMBB = &*LLVMF->begin();
+ llvm::Instruction *LLVMAdd = &*LLVMBB->begin();
+ auto *LLVMC = cast<llvm::Constant>(LLVMAdd->getOperand(1));
+ auto *LLVMArg0 = LLVMF->getArg(0);
+
+ sandboxir::Context Ctx(C);
+ sandboxir::Function F(LLVMF, Ctx);
+ sandboxir::Argument Arg0(LLVMArg0, Ctx);
+ sandboxir::Constant Const0(LLVMC, Ctx);
+ sandboxir::OpaqueInst OpaqueI(LLVMAdd, Ctx);
+
+ EXPECT_TRUE(isa<sandboxir::Function>(F));
+ EXPECT_FALSE(isa<sandboxir::Function>(Arg0));
+ EXPECT_FALSE(isa<sandboxir::Function>(Const0));
+ EXPECT_FALSE(isa<sandboxir::Function>(OpaqueI));
+
+ EXPECT_FALSE(isa<sandboxir::Argument>(F));
+ EXPECT_TRUE(isa<sandboxir::Argument>(Arg0));
+ EXPECT_FALSE(isa<sandboxir::Argument>(Const0));
+ EXPECT_FALSE(isa<sandboxir::Argument>(OpaqueI));
+
+ EXPECT_TRUE(isa<sandboxir::Constant>(F));
+ EXPECT_FALSE(isa<sandboxir::Constant>(Arg0));
+ EXPECT_TRUE(isa<sandboxir::Constant>(Const0));
+ EXPECT_FALSE(isa<sandboxir::Constant>(OpaqueI));
+
+ EXPECT_FALSE(isa<sandboxir::OpaqueInst>(F));
+ EXPECT_FALSE(isa<sandboxir::OpaqueInst>(Arg0));
+ EXPECT_FALSE(isa<sandboxir::OpaqueInst>(Const0));
+ EXPECT_TRUE(isa<sandboxir::OpaqueInst>(OpaqueI));
+
+ EXPECT_FALSE(isa<sandboxir::Instruction>(F));
+ EXPECT_FALSE(isa<sandboxir::Instruction>(Arg0));
+ EXPECT_FALSE(isa<sandboxir::Instruction>(Const0));
+ EXPECT_TRUE(isa<sandboxir::Instruction>(OpaqueI));
+
+ EXPECT_FALSE(isa<sandboxir::User>(F));
+ EXPECT_FALSE(isa<sandboxir::User>(Arg0));
+ EXPECT_TRUE(isa<sandboxir::User>(Const0));
+ EXPECT_TRUE(isa<sandboxir::User>(OpaqueI));
+}
More information about the llvm-commits
mailing list