[llvm] [SandboxIR] OpaqueValue (PR #127699)

via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 18 13:41:42 PST 2025


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

This patch implements a new subclass of the Value class used for Sandbox IR Values that we don't support, like metadata or inline asm. The goal is to never have null sandboxir::Value objects, because this is not the expected behavior.

>From b8e2d0d1e16afae7331b0efc817c0fca44367186 Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Fri, 14 Feb 2025 15:20:48 -0800
Subject: [PATCH] [SandboxIR] OpaqueValue

This patch implements a new subclass of the Value class used for Sandbox IR
Values that we don't support, like metadata or inline asm.
The goal is to never have null sandboxir::Value objects, because this is not
the expected behavior.
---
 llvm/include/llvm/SandboxIR/Value.h        | 23 ++++++++++++++++++++++
 llvm/include/llvm/SandboxIR/Values.def     |  1 +
 llvm/lib/SandboxIR/BasicBlock.cpp          |  6 ------
 llvm/lib/SandboxIR/Context.cpp             | 10 ++++++++++
 llvm/unittests/SandboxIR/SandboxIRTest.cpp | 23 ++++++++++++++++++++++
 5 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/llvm/include/llvm/SandboxIR/Value.h b/llvm/include/llvm/SandboxIR/Value.h
index 28e33ca0f2312..2e91b96bb22e6 100644
--- a/llvm/include/llvm/SandboxIR/Value.h
+++ b/llvm/include/llvm/SandboxIR/Value.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_SANDBOXIR_VALUE_H
 #define LLVM_SANDBOXIR_VALUE_H
 
+#include "llvm/IR/Metadata.h"
 #include "llvm/IR/Value.h"
 #include "llvm/SandboxIR/Use.h"
 
@@ -282,6 +283,28 @@ class Value {
 #endif
 };
 
+class OpaqueValue : public Value {
+protected:
+  OpaqueValue(llvm::Value *V, Context &Ctx)
+      : Value(ClassID::OpaqueValue, V, Ctx) {}
+  friend class Context; // For constructor.
+
+public:
+  static bool classof(const Value *From) {
+    return From->getSubclassID() == ClassID::OpaqueValue;
+  }
+#ifndef NDEBUG
+  void verify() const override {
+    assert((isa<llvm::MetadataAsValue>(Val) || isa<llvm::InlineAsm>(Val)) &&
+           "Expected Metadata or InlineAssembly!");
+  }
+  void dumpOS(raw_ostream &OS) const override {
+    dumpCommonPrefix(OS);
+    dumpCommonSuffix(OS);
+  }
+#endif // NDEBUG
+};
+
 } // namespace llvm::sandboxir
 
 #endif // LLVM_SANDBOXIR_VALUE_H
diff --git a/llvm/include/llvm/SandboxIR/Values.def b/llvm/include/llvm/SandboxIR/Values.def
index 3d8ad6ce197f4..f5ead54a08e10 100644
--- a/llvm/include/llvm/SandboxIR/Values.def
+++ b/llvm/include/llvm/SandboxIR/Values.def
@@ -21,6 +21,7 @@
 
 DEF_CONST(Function, Function)
 DEF_VALUE(Argument, Argument)
+DEF_VALUE(OpaqueValue, OpaqueValue)
 
 DEF_USER(User, User)
 DEF_VALUE(Block, BasicBlock)
diff --git a/llvm/lib/SandboxIR/BasicBlock.cpp b/llvm/lib/SandboxIR/BasicBlock.cpp
index 983a5e8b8825e..b45c046402487 100644
--- a/llvm/lib/SandboxIR/BasicBlock.cpp
+++ b/llvm/lib/SandboxIR/BasicBlock.cpp
@@ -67,12 +67,6 @@ void BasicBlock::buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB) {
       // Skip instruction's label operands
       if (isa<llvm::BasicBlock>(Op))
         continue;
-      // Skip metadata
-      if (isa<llvm::MetadataAsValue>(Op))
-        continue;
-      // Skip asm
-      if (isa<llvm::InlineAsm>(Op))
-        continue;
       Ctx.getOrCreateValue(Op);
     }
   }
diff --git a/llvm/lib/SandboxIR/Context.cpp b/llvm/lib/SandboxIR/Context.cpp
index 6a397b02d6bde..38ca60cfac3ec 100644
--- a/llvm/lib/SandboxIR/Context.cpp
+++ b/llvm/lib/SandboxIR/Context.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/SandboxIR/Context.h"
+#include "llvm/IR/InlineAsm.h"
 #include "llvm/SandboxIR/Function.h"
 #include "llvm/SandboxIR/Instruction.h"
 #include "llvm/SandboxIR/Module.h"
@@ -169,6 +170,15 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
       return SBBB;
     return nullptr;
   }
+  // TODO: Move these checks after more common Values, like after Instruction.
+  if (auto *MD = dyn_cast<llvm::MetadataAsValue>(LLVMV)) {
+    It->second = std::unique_ptr<OpaqueValue>(new OpaqueValue(MD, *this));
+    return It->second.get();
+  }
+  if (auto *Asm = dyn_cast<llvm::InlineAsm>(LLVMV)) {
+    It->second = std::unique_ptr<OpaqueValue>(new OpaqueValue(Asm, *this));
+    return It->second.get();
+  }
   assert(isa<llvm::Instruction>(LLVMV) && "Expected Instruction");
 
   switch (cast<llvm::Instruction>(LLVMV)->getOpcode()) {
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index 2ad33659c609b..088264e0429fd 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -6166,3 +6166,26 @@ define void @bar() {
   // This should not crash, even though there is already a value for LLVMBar.
   Ctx.createFunction(&LLVMBar);
 }
+
+TEST_F(SandboxIRTest, OpaqueValue) {
+  parseIR(C, R"IR(
+declare void @bar(metadata)
+define void @foo() {
+  call void @bar(metadata !1)
+  call void asm "asm", ""()
+  ret void
+}
+!1 = !{}
+)IR");
+  Function &LLVMFoo = *M->getFunction("foo");
+  sandboxir::Context Ctx(C);
+  auto *F = Ctx.createFunction(&LLVMFoo);
+  auto *BB = &*F->begin();
+  auto It = BB->begin();
+  auto *Call = cast<sandboxir::CallInst>(&*It++);
+  auto *Op0 = Call->getOperand(0);
+  EXPECT_TRUE(isa<sandboxir::OpaqueValue>(Op0));
+  auto *Asm = cast<sandboxir::CallInst>(&*It++);
+  auto *AsmOp0 = Asm->getOperand(0);
+  EXPECT_TRUE(isa<sandboxir::OpaqueValue>(AsmOp0));
+}



More information about the llvm-commits mailing list