From b8e2d0d1e16afae7331b0efc817c0fca44367186 Mon Sep 17 00:00:00 2001 From: Vasileios Porpodas 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(Val) || isa(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(Op)) continue; - // Skip metadata - if (isa(Op)) - continue; - // Skip asm - if (isa(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(LLVMV)) { + It->second = std::unique_ptr(new OpaqueValue(MD, *this)); + return It->second.get(); + } + if (auto *Asm = dyn_cast(LLVMV)) { + It->second = std::unique_ptr(new OpaqueValue(Asm, *this)); + return It->second.get(); + } assert(isa(LLVMV) && "Expected Instruction"); switch (cast(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(&*It++); + auto *Op0 = Call->getOperand(0); + EXPECT_TRUE(isa(Op0)); + auto *Asm = cast(&*It++); + auto *AsmOp0 = Asm->getOperand(0); + EXPECT_TRUE(isa(AsmOp0)); +}