[SandboxIR] OpaqueValue (#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.
This commit is contained in:
parent
4a411eb4ee
commit
1987f93d03
@ -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 @@ public:
|
||||
#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
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
DEF_CONST(Function, Function)
|
||||
DEF_VALUE(Argument, Argument)
|
||||
DEF_VALUE(OpaqueValue, OpaqueValue)
|
||||
|
||||
DEF_USER(User, User)
|
||||
DEF_VALUE(Block, BasicBlock)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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()) {
|
||||
|
@ -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));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user