Skip to content

Commit ec7fe87

Browse files
vporpotmsri
authored andcommitted
[SandboxIR] Implement GlobalVariable (llvm#108642)
This patch implements sandboxir::GlobalVariable mirroring llvm::GlobalVariable.
1 parent d0bac04 commit ec7fe87

File tree

4 files changed

+359
-0
lines changed

4 files changed

+359
-0
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ class ConstantTokenNone;
129129
class GlobalValue;
130130
class GlobalObject;
131131
class GlobalIFunc;
132+
class GlobalVariable;
132133
class Context;
133134
class Function;
134135
class Instruction;
@@ -334,6 +335,7 @@ class Value {
334335
friend class DSOLocalEquivalent; // For `Val`.
335336
friend class GlobalObject; // For `Val`.
336337
friend class GlobalIFunc; // For `Val`.
338+
friend class GlobalVariable; // For `Val`.
337339

338340
/// All values point to the context.
339341
Context &Ctx;
@@ -1370,6 +1372,162 @@ class GlobalIFunc final
13701372
#endif
13711373
};
13721374

1375+
class GlobalVariable final
1376+
: public GlobalWithNodeAPI<GlobalVariable, llvm::GlobalVariable,
1377+
GlobalObject, llvm::GlobalObject> {
1378+
GlobalVariable(llvm::GlobalObject *C, Context &Ctx)
1379+
: GlobalWithNodeAPI(ClassID::GlobalVariable, C, Ctx) {}
1380+
friend class Context; // For constructor.
1381+
1382+
/// Helper for mapped_iterator.
1383+
struct LLVMGVToGV {
1384+
Context &Ctx;
1385+
LLVMGVToGV(Context &Ctx) : Ctx(Ctx) {}
1386+
GlobalVariable &operator()(llvm::GlobalVariable &LLVMGV) const;
1387+
};
1388+
1389+
public:
1390+
/// For isa/dyn_cast.
1391+
static bool classof(const sandboxir::Value *From) {
1392+
return From->getSubclassID() == ClassID::GlobalVariable;
1393+
}
1394+
1395+
/// Definitions have initializers, declarations don't.
1396+
///
1397+
inline bool hasInitializer() const {
1398+
return cast<llvm::GlobalVariable>(Val)->hasInitializer();
1399+
}
1400+
1401+
/// hasDefinitiveInitializer - Whether the global variable has an initializer,
1402+
/// and any other instances of the global (this can happen due to weak
1403+
/// linkage) are guaranteed to have the same initializer.
1404+
///
1405+
/// Note that if you want to transform a global, you must use
1406+
/// hasUniqueInitializer() instead, because of the *_odr linkage type.
1407+
///
1408+
/// Example:
1409+
///
1410+
/// @a = global SomeType* null - Initializer is both definitive and unique.
1411+
///
1412+
/// @b = global weak SomeType* null - Initializer is neither definitive nor
1413+
/// unique.
1414+
///
1415+
/// @c = global weak_odr SomeType* null - Initializer is definitive, but not
1416+
/// unique.
1417+
inline bool hasDefinitiveInitializer() const {
1418+
return cast<llvm::GlobalVariable>(Val)->hasDefinitiveInitializer();
1419+
}
1420+
1421+
/// hasUniqueInitializer - Whether the global variable has an initializer, and
1422+
/// any changes made to the initializer will turn up in the final executable.
1423+
inline bool hasUniqueInitializer() const {
1424+
return cast<llvm::GlobalVariable>(Val)->hasUniqueInitializer();
1425+
}
1426+
1427+
/// getInitializer - Return the initializer for this global variable. It is
1428+
/// illegal to call this method if the global is external, because we cannot
1429+
/// tell what the value is initialized to!
1430+
///
1431+
Constant *getInitializer() const;
1432+
/// setInitializer - Sets the initializer for this global variable, removing
1433+
/// any existing initializer if InitVal==NULL. The initializer must have the
1434+
/// type getValueType().
1435+
void setInitializer(Constant *InitVal);
1436+
1437+
// TODO: Add missing replaceInitializer(). Requires special tracker
1438+
1439+
/// If the value is a global constant, its value is immutable throughout the
1440+
/// runtime execution of the program. Assigning a value into the constant
1441+
/// leads to undefined behavior.
1442+
///
1443+
bool isConstant() const {
1444+
return cast<llvm::GlobalVariable>(Val)->isConstant();
1445+
}
1446+
void setConstant(bool V);
1447+
1448+
bool isExternallyInitialized() const {
1449+
return cast<llvm::GlobalVariable>(Val)->isExternallyInitialized();
1450+
}
1451+
void setExternallyInitialized(bool Val);
1452+
1453+
// TODO: Missing copyAttributesFrom()
1454+
1455+
// TODO: Missing removeFromParent(), eraseFromParent(), dropAllReferences()
1456+
1457+
// TODO: Missing addDebugInfo(), getDebugInfo()
1458+
1459+
// TODO: Missing attribute setter functions: addAttribute(), setAttributes().
1460+
// There seems to be no removeAttribute() so we can't undo them.
1461+
1462+
/// Return true if the attribute exists.
1463+
bool hasAttribute(Attribute::AttrKind Kind) const {
1464+
return cast<llvm::GlobalVariable>(Val)->hasAttribute(Kind);
1465+
}
1466+
1467+
/// Return true if the attribute exists.
1468+
bool hasAttribute(StringRef Kind) const {
1469+
return cast<llvm::GlobalVariable>(Val)->hasAttribute(Kind);
1470+
}
1471+
1472+
/// Return true if any attributes exist.
1473+
bool hasAttributes() const {
1474+
return cast<llvm::GlobalVariable>(Val)->hasAttributes();
1475+
}
1476+
1477+
/// Return the attribute object.
1478+
Attribute getAttribute(Attribute::AttrKind Kind) const {
1479+
return cast<llvm::GlobalVariable>(Val)->getAttribute(Kind);
1480+
}
1481+
1482+
/// Return the attribute object.
1483+
Attribute getAttribute(StringRef Kind) const {
1484+
return cast<llvm::GlobalVariable>(Val)->getAttribute(Kind);
1485+
}
1486+
1487+
/// Return the attribute set for this global
1488+
AttributeSet getAttributes() const {
1489+
return cast<llvm::GlobalVariable>(Val)->getAttributes();
1490+
}
1491+
1492+
/// Return attribute set as list with index.
1493+
/// FIXME: This may not be required once ValueEnumerators
1494+
/// in bitcode-writer can enumerate attribute-set.
1495+
AttributeList getAttributesAsList(unsigned Index) const {
1496+
return cast<llvm::GlobalVariable>(Val)->getAttributesAsList(Index);
1497+
}
1498+
1499+
/// Check if section name is present
1500+
bool hasImplicitSection() const {
1501+
return cast<llvm::GlobalVariable>(Val)->hasImplicitSection();
1502+
}
1503+
1504+
/// Get the custom code model raw value of this global.
1505+
///
1506+
unsigned getCodeModelRaw() const {
1507+
return cast<llvm::GlobalVariable>(Val)->getCodeModelRaw();
1508+
}
1509+
1510+
/// Get the custom code model of this global if it has one.
1511+
///
1512+
/// If this global does not have a custom code model, the empty instance
1513+
/// will be returned.
1514+
std::optional<CodeModel::Model> getCodeModel() const {
1515+
return cast<llvm::GlobalVariable>(Val)->getCodeModel();
1516+
}
1517+
1518+
// TODO: Missing setCodeModel(). Requires custom tracker.
1519+
1520+
#ifndef NDEBUG
1521+
void verify() const override {
1522+
assert(isa<llvm::GlobalVariable>(Val) && "Expected a GlobalVariable!");
1523+
}
1524+
void dumpOS(raw_ostream &OS) const override {
1525+
dumpCommonPrefix(OS);
1526+
dumpCommonSuffix(OS);
1527+
}
1528+
#endif
1529+
};
1530+
13731531
class BlockAddress final : public Constant {
13741532
BlockAddress(llvm::BlockAddress *C, Context &Ctx)
13751533
: Constant(ClassID::BlockAddress, C, Ctx) {}

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2532,6 +2532,8 @@ template class GlobalWithNodeAPI<GlobalIFunc, llvm::GlobalIFunc, GlobalObject,
25322532
llvm::GlobalObject>;
25332533
template class GlobalWithNodeAPI<Function, llvm::Function, GlobalObject,
25342534
llvm::GlobalObject>;
2535+
template class GlobalWithNodeAPI<GlobalVariable, llvm::GlobalVariable,
2536+
GlobalObject, llvm::GlobalObject>;
25352537
} // namespace llvm::sandboxir
25362538

25372539
void GlobalIFunc::setResolver(Constant *Resolver) {
@@ -2552,6 +2554,39 @@ Function *GlobalIFunc::getResolverFunction() {
25522554
cast<llvm::GlobalIFunc>(Val)->getResolverFunction()));
25532555
}
25542556

2557+
GlobalVariable &
2558+
GlobalVariable::LLVMGVToGV::operator()(llvm::GlobalVariable &LLVMGV) const {
2559+
return cast<GlobalVariable>(*Ctx.getValue(&LLVMGV));
2560+
}
2561+
2562+
Constant *GlobalVariable::getInitializer() const {
2563+
return Ctx.getOrCreateConstant(
2564+
cast<llvm::GlobalVariable>(Val)->getInitializer());
2565+
}
2566+
2567+
void GlobalVariable::setInitializer(Constant *InitVal) {
2568+
Ctx.getTracker()
2569+
.emplaceIfTracking<GenericSetter<&GlobalVariable::getInitializer,
2570+
&GlobalVariable::setInitializer>>(this);
2571+
cast<llvm::GlobalVariable>(Val)->setInitializer(
2572+
cast<llvm::Constant>(InitVal->Val));
2573+
}
2574+
2575+
void GlobalVariable::setConstant(bool V) {
2576+
Ctx.getTracker()
2577+
.emplaceIfTracking<GenericSetter<&GlobalVariable::isConstant,
2578+
&GlobalVariable::setConstant>>(this);
2579+
cast<llvm::GlobalVariable>(Val)->setConstant(V);
2580+
}
2581+
2582+
void GlobalVariable::setExternallyInitialized(bool V) {
2583+
Ctx.getTracker()
2584+
.emplaceIfTracking<
2585+
GenericSetter<&GlobalVariable::isExternallyInitialized,
2586+
&GlobalVariable::setExternallyInitialized>>(this);
2587+
cast<llvm::GlobalVariable>(Val)->setExternallyInitialized(V);
2588+
}
2589+
25552590
void GlobalValue::setUnnamedAddr(UnnamedAddr V) {
25562591
Ctx.getTracker()
25572592
.emplaceIfTracking<GenericSetter<&GlobalValue::getUnnamedAddr,
@@ -2764,6 +2799,10 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
27642799
It->second = std::unique_ptr<GlobalIFunc>(
27652800
new GlobalIFunc(cast<llvm::GlobalIFunc>(C), *this));
27662801
break;
2802+
case llvm::Value::GlobalVariableVal:
2803+
It->second = std::unique_ptr<GlobalVariable>(
2804+
new GlobalVariable(cast<llvm::GlobalVariable>(C), *this));
2805+
break;
27672806
default:
27682807
It->second = std::unique_ptr<Constant>(new Constant(C, *this));
27692808
break;

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,120 @@ define void @foo() {
937937
}
938938
}
939939

940+
TEST_F(SandboxIRTest, GlobalVariable) {
941+
parseIR(C, R"IR(
942+
@glob0 = global i32 42
943+
@glob1 = global i32 43
944+
define void @foo() {
945+
%ld0 = load i32, ptr @glob0
946+
%ld1 = load i32, ptr @glob1
947+
ret void
948+
}
949+
)IR");
950+
Function &LLVMF = *M->getFunction("foo");
951+
auto *LLVMBB = &*LLVMF.begin();
952+
auto LLVMIt = LLVMBB->begin();
953+
auto *LLVMLd0 = cast<llvm::LoadInst>(&*LLVMIt++);
954+
auto *LLVMGV0 = cast<llvm::GlobalVariable>(LLVMLd0->getPointerOperand());
955+
sandboxir::Context Ctx(C);
956+
957+
auto &F = *Ctx.createFunction(&LLVMF);
958+
auto *BB = &*F.begin();
959+
auto It = BB->begin();
960+
auto *Ld0 = cast<sandboxir::LoadInst>(&*It++);
961+
auto *Ld1 = cast<sandboxir::LoadInst>(&*It++);
962+
// Check classof(), creation.
963+
auto *GV0 = cast<sandboxir::GlobalVariable>(Ld0->getPointerOperand());
964+
auto *GV1 = cast<sandboxir::GlobalVariable>(Ld1->getPointerOperand());
965+
// Check getIterator().
966+
{
967+
auto It0 = GV0->getIterator();
968+
auto It1 = GV1->getIterator();
969+
EXPECT_EQ(&*It0, GV0);
970+
EXPECT_EQ(&*It1, GV1);
971+
EXPECT_EQ(std::next(It0), It1);
972+
EXPECT_EQ(std::prev(It1), It0);
973+
EXPECT_EQ(&*std::next(It0), GV1);
974+
EXPECT_EQ(&*std::prev(It1), GV0);
975+
}
976+
// Check getReverseIterator().
977+
{
978+
auto RevIt0 = GV0->getReverseIterator();
979+
auto RevIt1 = GV1->getReverseIterator();
980+
EXPECT_EQ(&*RevIt0, GV0);
981+
EXPECT_EQ(&*RevIt1, GV1);
982+
EXPECT_EQ(std::prev(RevIt0), RevIt1);
983+
EXPECT_EQ(std::next(RevIt1), RevIt0);
984+
EXPECT_EQ(&*std::prev(RevIt0), GV1);
985+
EXPECT_EQ(&*std::next(RevIt1), GV0);
986+
}
987+
// Check hasInitializer().
988+
EXPECT_EQ(GV0->hasInitializer(), LLVMGV0->hasInitializer());
989+
// Check hasDefinitiveInitializer().
990+
EXPECT_EQ(GV0->hasDefinitiveInitializer(),
991+
LLVMGV0->hasDefinitiveInitializer());
992+
// Check hasUniqueInitializer().
993+
EXPECT_EQ(GV0->hasUniqueInitializer(), LLVMGV0->hasUniqueInitializer());
994+
// Check getInitializer().
995+
EXPECT_EQ(GV0->getInitializer(), Ctx.getValue(LLVMGV0->getInitializer()));
996+
// Check setInitializer().
997+
auto *OrigInitializer = GV0->getInitializer();
998+
auto *NewInitializer = GV1->getInitializer();
999+
EXPECT_NE(NewInitializer, OrigInitializer);
1000+
GV0->setInitializer(NewInitializer);
1001+
EXPECT_EQ(GV0->getInitializer(), NewInitializer);
1002+
GV0->setInitializer(OrigInitializer);
1003+
EXPECT_EQ(GV0->getInitializer(), OrigInitializer);
1004+
// Check isConstant().
1005+
EXPECT_EQ(GV0->isConstant(), LLVMGV0->isConstant());
1006+
// Check setConstant().
1007+
bool OrigIsConstant = GV0->isConstant();
1008+
bool NewIsConstant = !OrigIsConstant;
1009+
GV0->setConstant(NewIsConstant);
1010+
EXPECT_EQ(GV0->isConstant(), NewIsConstant);
1011+
GV0->setConstant(OrigIsConstant);
1012+
EXPECT_EQ(GV0->isConstant(), OrigIsConstant);
1013+
// Check isExternallyInitialized().
1014+
EXPECT_EQ(GV0->isExternallyInitialized(), LLVMGV0->isExternallyInitialized());
1015+
// Check setExternallyInitialized().
1016+
bool OrigIsExtInit = GV0->isExternallyInitialized();
1017+
bool NewIsExtInit = !OrigIsExtInit;
1018+
GV0->setExternallyInitialized(NewIsExtInit);
1019+
EXPECT_EQ(GV0->isExternallyInitialized(), NewIsExtInit);
1020+
GV0->setExternallyInitialized(OrigIsExtInit);
1021+
EXPECT_EQ(GV0->isExternallyInitialized(), OrigIsExtInit);
1022+
for (auto KindIdx : seq<int>(0, Attribute::AttrKind::EndAttrKinds)) {
1023+
// Check hasAttribute(AttrKind).
1024+
auto Kind = static_cast<Attribute::AttrKind>(KindIdx);
1025+
EXPECT_EQ(GV0->hasAttribute(Kind), LLVMGV0->hasAttribute(Kind));
1026+
// Check hasAttribute(StringRef).
1027+
StringRef KindStr = Attribute::getNameFromAttrKind(Kind);
1028+
EXPECT_EQ(GV0->hasAttribute(KindStr), LLVMGV0->hasAttribute(KindStr));
1029+
}
1030+
// Check hasAttributes().
1031+
EXPECT_EQ(GV0->hasAttributes(), LLVMGV0->hasAttributes());
1032+
1033+
for (auto KindIdx : seq<int>(0, Attribute::AttrKind::EndAttrKinds)) {
1034+
// Check getAttribute(AttrKind).
1035+
auto Kind = static_cast<Attribute::AttrKind>(KindIdx);
1036+
EXPECT_EQ(GV0->getAttribute(Kind), LLVMGV0->getAttribute(Kind));
1037+
// Check getAttribute(StringRef).
1038+
StringRef KindStr = Attribute::getNameFromAttrKind(Kind);
1039+
EXPECT_EQ(GV0->getAttribute(KindStr), LLVMGV0->getAttribute(KindStr));
1040+
}
1041+
// Check getAttributes().
1042+
EXPECT_EQ(GV0->getAttributes(), LLVMGV0->getAttributes());
1043+
// Check getAttributesAsList().
1044+
EXPECT_THAT(GV0->getAttributesAsList(0u),
1045+
testing::ContainerEq(LLVMGV0->getAttributesAsList(0u)));
1046+
// Check hasImplicitSection().
1047+
EXPECT_EQ(GV0->hasImplicitSection(), LLVMGV0->hasImplicitSection());
1048+
// Check getCodeModelRaw().
1049+
EXPECT_EQ(GV0->getCodeModelRaw(), LLVMGV0->getCodeModelRaw());
1050+
// Check getCodeModel().
1051+
EXPECT_EQ(GV0->getCodeModel(), LLVMGV0->getCodeModel());
1052+
}
1053+
9401054
TEST_F(SandboxIRTest, BlockAddress) {
9411055
parseIR(C, R"IR(
9421056
define void @foo(ptr %ptr) {

0 commit comments

Comments
 (0)