[llvm] [SandboxIR] More boilerplate: Function, Argument, Constant, Instruction, OpaqueInst (PR #97343)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 1 12:58:42 PDT 2024


https://github.com/vporpo created https://github.com/llvm/llvm-project/pull/97343

A very basic implementation of sandboxir::
`Fuction`
`Argument`
`Constant`
`Instruction`
`OpaqueInst`

>From f938e82f17a7d629b17b681cf93cf7ce4b970a4a Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Mon, 1 Jul 2024 11:46:55 -0700
Subject: [PATCH] [SandboxIR] More boilerplate: Function, Argument, Constant,
 Instruction, OpaqueInst

A very basic implementation of sandboxir::
`Fuction`
`Argument`
`Constant`
`Instruction`
`OpaqueInst`
---
 llvm/include/llvm/SandboxIR/SandboxIR.h       | 151 ++++++++++++++++++
 .../llvm/SandboxIR/SandboxIRValues.def        |   8 +-
 llvm/lib/SandboxIR/SandboxIR.cpp              |  87 ++++++++++
 llvm/unittests/SandboxIR/SandboxIRTest.cpp    |  19 +++
 4 files changed, 264 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index ec7ec1a268fa7..f8efd24ad58d2 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,137 @@ 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 OPCODES(...) __VA_ARGS__
+#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>>
+      LLVMValueToSBValueMap;
 
 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..32d44fc60d33b 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIRValues.def
+++ b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
@@ -7,7 +7,13 @@
 //===----------------------------------------------------------------------===//
 
 //    ClassID, Class
-DEF_USER(User, sandboxir::User)
+DEF_VALUE(Function, Function)
+DEF_VALUE(Argument, Argument)
+DEF_USER(User, User)
+DEF_USER(Constant, Constant)
+
+//       ClassID, Opcode(s),  Class
+DEF_INSTR(Opaque, OP(Opaque), OpaqueInst)
 
 #ifdef DEF_VALUE
 #undef DEF_VALUE
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 70101ab10ff12..36935dd27438e 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -59,8 +59,95 @@ void sandboxir::Value::printAsOperandCommon(raw_ostream &OS) const {
     OS << "NULL ";
 }
 
+void sandboxir::Argument::printAsOperand(raw_ostream &OS) const {
+  printAsOperandCommon(OS);
+}
+void sandboxir::Argument::dump(raw_ostream &OS) const {
+  dumpCommonPrefix(OS);
+  dumpCommonSuffix(OS);
+}
+void sandboxir::Argument::dump() const {
+  dump(dbgs());
+  dbgs() << "\n";
+}
+
 void sandboxir::User::dumpCommonHeader(raw_ostream &OS) const {
   Value::dumpCommonHeader(OS);
   // TODO: This is incomplete
 }
 #endif // NDEBUG
+
+const char *sandboxir::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 OPCODES(...) __VA_ARGS__
+#define DEF_INSTR(ID, OPC, CLASS) OPC
+#include "llvm/SandboxIR/SandboxIRValues.def"
+  }
+}
+
+#ifndef NDEBUG
+void sandboxir::Instruction::dump(raw_ostream &OS) const {
+  OS << "Unimplemented! Please override dump().";
+}
+void sandboxir::Instruction::dump() const {
+  dump(dbgs());
+  dbgs() << "\n";
+}
+
+void sandboxir::OpaqueInst::dump(raw_ostream &OS) const {
+  dumpCommonPrefix(OS);
+  dumpCommonSuffix(OS);
+}
+
+void sandboxir::OpaqueInst::dump() const {
+  dump(dbgs());
+  dbgs() << "\n";
+}
+
+void sandboxir::Constant::dump(raw_ostream &OS) const {
+  dumpCommonPrefix(OS);
+  dumpCommonSuffix(OS);
+}
+
+void sandboxir::Constant::dump() const {
+  dump(dbgs());
+  dbgs() << "\n";
+}
+
+void sandboxir::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<sandboxir::Argument>(Ctx.getValue(&Arg));
+    if (SBArg == nullptr)
+      OS << "NULL";
+    else
+      SBArg->printAsOperand(OS);
+    if (Idx + 1 < NumArgs)
+      OS << ", ";
+  }
+  OS << ")";
+}
+void sandboxir::Function::dump(raw_ostream &OS) const {
+  dumpNameAndArgs(OS);
+  OS << " {\n";
+  OS << "}\n";
+}
+void sandboxir::Function::dump() const {
+  dump(dbgs());
+  dbgs() << "\n";
+}
+#endif // NDEBUG
+
+sandboxir::Value *sandboxir::Context::getValue(llvm::Value *V) const {
+  auto It = LLVMValueToSBValueMap.find(V);
+  if (It != LLVMValueToSBValueMap.end())
+    return It->second.get();
+  return nullptr;
+}
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index 14e6e745f757a..6662ca001c584 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -40,3 +40,22 @@ 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));
+  sandboxir::Context Ctx(C);
+  auto *LLVMArg0 = LLVMF->getArg(0);
+  [[maybe_unused]] sandboxir::Function F(LLVMF, Ctx);
+  [[maybe_unused]] sandboxir::Argument Arg0(LLVMArg0, Ctx);
+  [[maybe_unused]] sandboxir::Constant Const0(LLVMC, Ctx);
+  [[maybe_unused]] sandboxir::OpaqueInst Opaque(LLVMAdd, Ctx);
+}



More information about the llvm-commits mailing list