Skip to content

Commit fd2da9e

Browse files
authored
[SandboxIR] Implement PoisonValue (#107324)
This patch implements sandboxir::PoisonValue mirroring llvm::PoisonValue.
1 parent c014db4 commit fd2da9e

File tree

4 files changed

+130
-0
lines changed

4 files changed

+130
-0
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ class ConstantInt;
122122
class ConstantFP;
123123
class ConstantAggregateZero;
124124
class ConstantPointerNull;
125+
class PoisonValue;
125126
class Context;
126127
class Function;
127128
class Instruction;
@@ -320,6 +321,7 @@ class Value {
320321
friend class ConstantStruct; // For `Val`.
321322
friend class ConstantAggregateZero; // For `Val`.
322323
friend class ConstantPointerNull; // For `Val`.
324+
friend class PoisonValue; // For `Val`.
323325

324326
/// All values point to the context.
325327
Context &Ctx;
@@ -1018,6 +1020,49 @@ class ConstantPointerNull final : public Constant {
10181020
#endif
10191021
};
10201022

1023+
// TODO: Inherit from UndefValue.
1024+
class PoisonValue final : public Constant {
1025+
PoisonValue(llvm::PoisonValue *C, Context &Ctx)
1026+
: Constant(ClassID::PoisonValue, C, Ctx) {}
1027+
friend class Context; // For constructor.
1028+
1029+
public:
1030+
/// Static factory methods - Return an 'poison' object of the specified type.
1031+
static PoisonValue *get(Type *T);
1032+
1033+
/// If this poison has array or vector type, return a poison with the right
1034+
/// element type.
1035+
PoisonValue *getSequentialElement() const;
1036+
1037+
/// If this poison has struct type, return a poison with the right element
1038+
/// type for the specified element.
1039+
PoisonValue *getStructElement(unsigned Elt) const;
1040+
1041+
/// Return an poison of the right value for the specified GEP index if we can,
1042+
/// otherwise return null (e.g. if C is a ConstantExpr).
1043+
PoisonValue *getElementValue(Constant *C) const;
1044+
1045+
/// Return an poison of the right value for the specified GEP index.
1046+
PoisonValue *getElementValue(unsigned Idx) const;
1047+
1048+
/// For isa/dyn_cast.
1049+
static bool classof(const sandboxir::Value *From) {
1050+
return From->getSubclassID() == ClassID::PoisonValue;
1051+
}
1052+
unsigned getUseOperandNo(const Use &Use) const final {
1053+
llvm_unreachable("PoisonValue has no operands!");
1054+
}
1055+
#ifndef NDEBUG
1056+
void verify() const override {
1057+
assert(isa<llvm::PoisonValue>(Val) && "Expected a PoisonValue!");
1058+
}
1059+
void dumpOS(raw_ostream &OS) const override {
1060+
dumpCommonPrefix(OS);
1061+
dumpCommonSuffix(OS);
1062+
}
1063+
#endif
1064+
};
1065+
10211066
/// Iterator for `Instruction`s in a `BasicBlock.
10221067
/// \Returns an sandboxir::Instruction & when derereferenced.
10231068
class BBIterator {

llvm/include/llvm/SandboxIR/SandboxIRValues.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ DEF_CONST(ConstantStruct, ConstantStruct)
3232
DEF_CONST(ConstantVector, ConstantVector)
3333
DEF_CONST(ConstantAggregateZero, ConstantAggregateZero)
3434
DEF_CONST(ConstantPointerNull, ConstantPointerNull)
35+
DEF_CONST(PoisonValue, PoisonValue)
3536

3637
#ifndef DEF_INSTR
3738
#define DEF_INSTR(ID, OPCODE, CLASS)

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2437,6 +2437,32 @@ PointerType *ConstantPointerNull::getType() const {
24372437
Ctx.getType(cast<llvm::ConstantPointerNull>(Val)->getType()));
24382438
}
24392439

2440+
PoisonValue *PoisonValue::get(Type *T) {
2441+
auto *LLVMC = llvm::PoisonValue::get(T->LLVMTy);
2442+
return cast<PoisonValue>(T->getContext().getOrCreateConstant(LLVMC));
2443+
}
2444+
2445+
PoisonValue *PoisonValue::getSequentialElement() const {
2446+
return cast<PoisonValue>(Ctx.getOrCreateConstant(
2447+
cast<llvm::PoisonValue>(Val)->getSequentialElement()));
2448+
}
2449+
2450+
PoisonValue *PoisonValue::getStructElement(unsigned Elt) const {
2451+
return cast<PoisonValue>(Ctx.getOrCreateConstant(
2452+
cast<llvm::PoisonValue>(Val)->getStructElement(Elt)));
2453+
}
2454+
2455+
PoisonValue *PoisonValue::getElementValue(Constant *C) const {
2456+
return cast<PoisonValue>(
2457+
Ctx.getOrCreateConstant(cast<llvm::PoisonValue>(Val)->getElementValue(
2458+
cast<llvm::Constant>(C->Val))));
2459+
}
2460+
2461+
PoisonValue *PoisonValue::getElementValue(unsigned Idx) const {
2462+
return cast<PoisonValue>(Ctx.getOrCreateConstant(
2463+
cast<llvm::PoisonValue>(Val)->getElementValue(Idx)));
2464+
}
2465+
24402466
FunctionType *Function::getFunctionType() const {
24412467
return cast<FunctionType>(
24422468
Ctx.getType(cast<llvm::Function>(Val)->getFunctionType()));
@@ -2550,6 +2576,10 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
25502576
It->second = std::unique_ptr<ConstantPointerNull>(
25512577
new ConstantPointerNull(cast<llvm::ConstantPointerNull>(C), *this));
25522578
return It->second.get();
2579+
case llvm::Value::PoisonValueVal:
2580+
It->second = std::unique_ptr<PoisonValue>(
2581+
new PoisonValue(cast<llvm::PoisonValue>(C), *this));
2582+
return It->second.get();
25532583
case llvm::Value::ConstantArrayVal:
25542584
It->second = std::unique_ptr<ConstantArray>(
25552585
new ConstantArray(cast<llvm::ConstantArray>(C), *this));

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,60 @@ define ptr @foo() {
616616
EXPECT_EQ(NewCPNull2->getType(), sandboxir::PointerType::get(Ctx, 1u));
617617
}
618618

619+
TEST_F(SandboxIRTest, PoisonValue) {
620+
parseIR(C, R"IR(
621+
define void @foo() {
622+
%i0 = add i32 poison, poison
623+
%i1 = add <2 x i32> poison, poison
624+
%i2 = extractvalue {i32, i8} poison, 0
625+
ret void
626+
}
627+
)IR");
628+
Function &LLVMF = *M->getFunction("foo");
629+
sandboxir::Context Ctx(C);
630+
631+
auto &F = *Ctx.createFunction(&LLVMF);
632+
auto &BB = *F.begin();
633+
auto It = BB.begin();
634+
auto *I0 = &*It++;
635+
auto *I1 = &*It++;
636+
auto *I2 = &*It++;
637+
auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx);
638+
auto *Int8Ty = sandboxir::Type::getInt8Ty(Ctx);
639+
auto *Zero32 = sandboxir::ConstantInt::get(Int32Ty, 0u);
640+
auto *One32 = sandboxir::ConstantInt::get(Int32Ty, 1u);
641+
642+
// Check classof() and creation.
643+
auto *Poison = cast<sandboxir::PoisonValue>(I0->getOperand(0));
644+
EXPECT_EQ(Poison->getType(), Int32Ty);
645+
// Check get().
646+
auto *NewPoison = sandboxir::PoisonValue::get(Int32Ty);
647+
EXPECT_EQ(NewPoison, Poison);
648+
auto *NewPoison2 =
649+
sandboxir::PoisonValue::get(sandboxir::PointerType::get(Ctx, 0u));
650+
EXPECT_NE(NewPoison2, Poison);
651+
// Check getSequentialElement().
652+
auto *PoisonVector = cast<sandboxir::PoisonValue>(I1->getOperand(0));
653+
auto *SeqElm = PoisonVector->getSequentialElement();
654+
EXPECT_EQ(SeqElm->getType(), Int32Ty);
655+
// Check getStructElement().
656+
auto *PoisonStruct = cast<sandboxir::PoisonValue>(I2->getOperand(0));
657+
auto *StrElm0 = PoisonStruct->getStructElement(0);
658+
auto *StrElm1 = PoisonStruct->getStructElement(1);
659+
EXPECT_EQ(StrElm0->getType(), Int32Ty);
660+
EXPECT_EQ(StrElm1->getType(), Int8Ty);
661+
// Check getElementValue(Constant)
662+
EXPECT_EQ(PoisonStruct->getElementValue(Zero32),
663+
sandboxir::PoisonValue::get(Int32Ty));
664+
EXPECT_EQ(PoisonStruct->getElementValue(One32),
665+
sandboxir::PoisonValue::get(Int8Ty));
666+
// Check getElementValue(unsigned)
667+
EXPECT_EQ(PoisonStruct->getElementValue(0u),
668+
sandboxir::PoisonValue::get(Int32Ty));
669+
EXPECT_EQ(PoisonStruct->getElementValue(1u),
670+
sandboxir::PoisonValue::get(Int8Ty));
671+
}
672+
619673
TEST_F(SandboxIRTest, Use) {
620674
parseIR(C, R"IR(
621675
define i32 @foo(i32 %v0, i32 %v1) {

0 commit comments

Comments
 (0)