[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