Skip to content

Commit 7e5df5b

Browse files
authored
[SandboxIR] Implement Module (llvm#109716)
This patch implements sandboxir::Module. It provides access to globals.
1 parent 7645d9c commit 7e5df5b

File tree

8 files changed

+259
-2
lines changed

8 files changed

+259
-2
lines changed

llvm/include/llvm/SandboxIR/Module.h

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//===- Module.h -------------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_SANDBOXIR_MODULE_H
10+
#define LLVM_SANDBOXIR_MODULE_H
11+
12+
#include "llvm/ADT/STLExtras.h"
13+
#include "llvm/IR/Module.h"
14+
#include <string>
15+
16+
namespace llvm {
17+
18+
class DataLayout;
19+
20+
namespace sandboxir {
21+
22+
class Context;
23+
class Function;
24+
class GlobalVariable;
25+
class Type;
26+
class Constant;
27+
class GlobalAlias;
28+
class GlobalIFunc;
29+
30+
/// In SandboxIR the Module is mainly used to access the list of global objects.
31+
class Module {
32+
llvm::Module &LLVMM;
33+
Context &Ctx;
34+
35+
Module(llvm::Module &LLVMM, Context &Ctx) : LLVMM(LLVMM), Ctx(Ctx) {}
36+
friend class Context; // For constructor.
37+
38+
public:
39+
Context &getContext() const { return Ctx; }
40+
41+
Function *getFunction(StringRef Name) const;
42+
43+
const DataLayout &getDataLayout() const { return LLVMM.getDataLayout(); }
44+
45+
const std::string &getSourceFileName() const {
46+
return LLVMM.getSourceFileName();
47+
}
48+
49+
/// Look up the specified global variable in the module symbol table. If it
50+
/// does not exist, return null. If AllowInternal is set to true, this
51+
/// function will return types that have InternalLinkage. By default, these
52+
/// types are not returned.
53+
GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal) const;
54+
GlobalVariable *getGlobalVariable(StringRef Name) const {
55+
return getGlobalVariable(Name, /*AllowInternal=*/false);
56+
}
57+
/// Return the global variable in the module with the specified name, of
58+
/// arbitrary type. This method returns null if a global with the specified
59+
/// name is not found.
60+
GlobalVariable *getNamedGlobal(StringRef Name) const {
61+
return getGlobalVariable(Name, true);
62+
}
63+
64+
// TODO: missing getOrInsertGlobal().
65+
66+
/// Return the global alias in the module with the specified name, of
67+
/// arbitrary type. This method returns null if a global with the specified
68+
/// name is not found.
69+
GlobalAlias *getNamedAlias(StringRef Name) const;
70+
71+
/// Return the global ifunc in the module with the specified name, of
72+
/// arbitrary type. This method returns null if a global with the specified
73+
/// name is not found.
74+
GlobalIFunc *getNamedIFunc(StringRef Name) const;
75+
76+
// TODO: Missing removeGlobalVariable() eraseGlobalVariable(),
77+
// insertGlobalVariable()
78+
79+
// TODO: Missing global_begin(), global_end(), globals().
80+
81+
// TODO: Missing many other functions.
82+
83+
#ifndef NDEBUG
84+
void dumpOS(raw_ostream &OS) const;
85+
LLVM_DUMP_METHOD void dump() const;
86+
#endif // NDEBUG
87+
};
88+
89+
} // namespace sandboxir
90+
} // namespace llvm
91+
92+
#endif // LLVM_SANDBOXIR_MODULE_H

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
#include "llvm/IR/PatternMatch.h"
110110
#include "llvm/IR/User.h"
111111
#include "llvm/IR/Value.h"
112+
#include "llvm/SandboxIR/Module.h"
112113
#include "llvm/SandboxIR/Tracker.h"
113114
#include "llvm/SandboxIR/Type.h"
114115
#include "llvm/SandboxIR/Use.h"
@@ -138,6 +139,7 @@ class ConstantPtrAuth;
138139
class ConstantExpr;
139140
class Context;
140141
class Function;
142+
class Module;
141143
class Instruction;
142144
class VAArgInst;
143145
class FreezeInst;
@@ -347,7 +349,7 @@ class Value {
347349
friend class ConstantPtrAuth; // For `Val`.
348350
friend class ConstantExpr; // For `Val`.
349351
friend class Utils; // For `Val`.
350-
352+
friend class Module; // For `Val`.
351353
// Region needs to manipulate metadata in the underlying LLVM Value, we don't
352354
// expose metadata in sandboxir.
353355
friend class Region;
@@ -1322,7 +1324,10 @@ class GlobalWithNodeAPI : public ParentT {
13221324
GlobalWithNodeAPI(Value::ClassID ID, LLVMParentT *C, Context &Ctx)
13231325
: ParentT(ID, C, Ctx) {}
13241326

1325-
// TODO: Missing getParent(). Should be added once Module is available.
1327+
Module *getParent() const {
1328+
llvm::Module *LLVMM = cast<LLVMGlobalT>(this->Val)->getParent();
1329+
return this->Ctx.getModule(LLVMM);
1330+
}
13261331

13271332
using iterator = mapped_iterator<
13281333
decltype(static_cast<LLVMGlobalT *>(nullptr)->getIterator()), LLVMGVToGV>;
@@ -4556,6 +4561,9 @@ class Context {
45564561
DenseMap<llvm::Value *, std::unique_ptr<sandboxir::Value>>
45574562
LLVMValueToValueMap;
45584563

4564+
/// Maps an LLVM Module to the corresponding sandboxir::Module.
4565+
DenseMap<llvm::Module *, std::unique_ptr<Module>> LLVMModuleToModuleMap;
4566+
45594567
/// Type has a protected destructor to prohibit the user from managing the
45604568
/// lifetime of the Type objects. Context is friend of Type, and this custom
45614569
/// deleter can destroy Type.
@@ -4699,6 +4707,10 @@ class Context {
46994707
return getValue(const_cast<llvm::Value *>(V));
47004708
}
47014709

4710+
Module *getModule(llvm::Module *LLVMM) const;
4711+
4712+
Module *getOrCreateModule(llvm::Module *LLVMM);
4713+
47024714
Type *getType(llvm::Type *LLVMTy) {
47034715
if (LLVMTy == nullptr)
47044716
return nullptr;
@@ -4712,8 +4724,13 @@ class Context {
47124724
/// Create a sandboxir::Function for an existing LLVM IR \p F, including all
47134725
/// blocks and instructions.
47144726
/// This is the main API function for creating Sandbox IR.
4727+
/// Note: this will not fully populate its parent module. The only globals
4728+
/// that will be available are those used within the function.
47154729
Function *createFunction(llvm::Function *F);
47164730

4731+
/// Create a sandboxir::Module corresponding to \p LLVMM.
4732+
Module *createModule(llvm::Module *LLVMM);
4733+
47174734
/// \Returns the number of values registered with Context.
47184735
size_t getNumValues() const { return LLVMValueToValueMap.size(); }
47194736
};
@@ -4739,6 +4756,10 @@ class Function : public GlobalWithNodeAPI<Function, llvm::Function,
47394756
return From->getSubclassID() == ClassID::Function;
47404757
}
47414758

4759+
Module *getParent() {
4760+
return Ctx.getModule(cast<llvm::Function>(Val)->getParent());
4761+
}
4762+
47424763
Argument *getArg(unsigned Idx) const {
47434764
llvm::Argument *Arg = cast<llvm::Function>(Val)->getArg(Idx);
47444765
return cast<Argument>(Ctx.getValue(Arg));

llvm/include/llvm/SandboxIR/Tracker.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ class SwitchInst;
6464
class ConstantInt;
6565
class ShuffleVectorInst;
6666
class CmpInst;
67+
class Module;
68+
class GlobalVariable;
69+
6770
/// The base class for IR Change classes.
6871
class IRChangeBase {
6972
protected:

llvm/include/llvm/SandboxIR/Type.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class IntegerType;
3131
class FunctionType;
3232
class ArrayType;
3333
class StructType;
34+
class Module;
3435
#define DEF_INSTR(ID, OPCODE, CLASS) class CLASS;
3536
#define DEF_CONST(ID, CLASS) class CLASS;
3637
#include "llvm/SandboxIR/SandboxIRValues.def"
@@ -57,6 +58,8 @@ class Type {
5758
friend class CmpInst; // For LLVMTy. TODO: Cleanup after
5859
// sandboxir::VectorType is more complete.
5960
friend class Utils; // for LLVMTy
61+
friend class TargetExtType; // For LLVMTy.
62+
friend class Module; // For LLVMTy.
6063

6164
// Friend all instruction classes because `create()` functions use LLVMTy.
6265
#define DEF_INSTR(ID, OPCODE, CLASS) friend class CLASS;

llvm/lib/SandboxIR/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
add_llvm_component_library(LLVMSandboxIR
2+
Module.cpp
23
Pass.cpp
34
PassManager.cpp
45
SandboxIR.cpp

llvm/lib/SandboxIR/Module.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===- Module.cpp ---------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/SandboxIR/Module.h"
10+
#include "llvm/SandboxIR/SandboxIR.h"
11+
12+
using namespace llvm::sandboxir;
13+
14+
Function *Module::getFunction(StringRef Name) const {
15+
llvm::Function *LLVMF = LLVMM.getFunction(Name);
16+
return cast_or_null<Function>(Ctx.getValue(LLVMF));
17+
}
18+
19+
GlobalVariable *Module::getGlobalVariable(StringRef Name,
20+
bool AllowInternal) const {
21+
return cast_or_null<GlobalVariable>(
22+
Ctx.getValue(LLVMM.getGlobalVariable(Name, AllowInternal)));
23+
}
24+
25+
GlobalAlias *Module::getNamedAlias(StringRef Name) const {
26+
return cast_or_null<GlobalAlias>(Ctx.getValue(LLVMM.getNamedAlias(Name)));
27+
}
28+
29+
GlobalIFunc *Module::getNamedIFunc(StringRef Name) const {
30+
return cast_or_null<GlobalIFunc>(Ctx.getValue(LLVMM.getNamedIFunc(Name)));
31+
}
32+
33+
#ifndef NDEBUG
34+
void Module::dumpOS(raw_ostream &OS) const { OS << LLVMM; }
35+
36+
void Module::dump() const {
37+
dumpOS(dbgs());
38+
dbgs() << "\n";
39+
}
40+
#endif // NDEBUG

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3404,8 +3404,29 @@ Value *Context::getValue(llvm::Value *V) const {
34043404
return nullptr;
34053405
}
34063406

3407+
Module *Context::getModule(llvm::Module *LLVMM) const {
3408+
auto It = LLVMModuleToModuleMap.find(LLVMM);
3409+
if (It != LLVMModuleToModuleMap.end())
3410+
return It->second.get();
3411+
return nullptr;
3412+
}
3413+
3414+
Module *Context::getOrCreateModule(llvm::Module *LLVMM) {
3415+
auto Pair = LLVMModuleToModuleMap.insert({LLVMM, nullptr});
3416+
auto It = Pair.first;
3417+
if (!Pair.second)
3418+
return It->second.get();
3419+
It->second = std::unique_ptr<Module>(new Module(*LLVMM, *this));
3420+
return It->second.get();
3421+
}
3422+
34073423
Function *Context::createFunction(llvm::Function *F) {
34083424
assert(getValue(F) == nullptr && "Already exists!");
3425+
// Create the module if needed before we create the new sandboxir::Function.
3426+
// Note: this won't fully populate the module. The only globals that will be
3427+
// available will be the ones being used within the function.
3428+
getOrCreateModule(F->getParent());
3429+
34093430
auto NewFPtr = std::unique_ptr<Function>(new Function(F, *this));
34103431
auto *SBF = cast<Function>(registerValue(std::move(NewFPtr)));
34113432
// Create arguments.
@@ -3417,6 +3438,24 @@ Function *Context::createFunction(llvm::Function *F) {
34173438
return SBF;
34183439
}
34193440

3441+
Module *Context::createModule(llvm::Module *LLVMM) {
3442+
auto *M = getOrCreateModule(LLVMM);
3443+
// Create the functions.
3444+
for (auto &LLVMF : *LLVMM)
3445+
createFunction(&LLVMF);
3446+
// Create globals.
3447+
for (auto &Global : LLVMM->globals())
3448+
getOrCreateValue(&Global);
3449+
// Create aliases.
3450+
for (auto &Alias : LLVMM->aliases())
3451+
getOrCreateValue(&Alias);
3452+
// Create ifuncs.
3453+
for (auto &IFunc : LLVMM->ifuncs())
3454+
getOrCreateValue(&IFunc);
3455+
3456+
return M;
3457+
}
3458+
34203459
Function *BasicBlock::getParent() const {
34213460
auto *BB = cast<llvm::BasicBlock>(Val);
34223461
auto *F = BB->getParent();

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,6 +1685,64 @@ void @foo0(i32 %arg0, i32 %arg1) {
16851685
#endif // NDEBUG
16861686
}
16871687

1688+
TEST_F(SandboxIRTest, Module) {
1689+
parseIR(C, R"IR(
1690+
@glob0 = global i32 42
1691+
@glob1 = global i32 43
1692+
@internal0 = internal global i32 42
1693+
@const0 = constant i32 42
1694+
@alias0 = dso_local alias void(), ptr @foo
1695+
@ifunc = ifunc void(), ptr @foo
1696+
define void @foo() {
1697+
ret void
1698+
}
1699+
define void @bar() {
1700+
ret void
1701+
}
1702+
)IR");
1703+
llvm::Module *LLVMM = &*M;
1704+
llvm::Function *LLVMFFoo = &*M->getFunction("foo");
1705+
llvm::Function *LLVMFBar = &*M->getFunction("bar");
1706+
1707+
sandboxir::Context Ctx(C);
1708+
auto *M = Ctx.createModule(LLVMM);
1709+
// Check getContext().
1710+
EXPECT_EQ(&M->getContext(), &Ctx);
1711+
// Check getFunction().
1712+
auto *FFoo = M->getFunction("foo");
1713+
auto *FBar = M->getFunction("bar");
1714+
EXPECT_EQ(FFoo, Ctx.getValue(LLVMFFoo));
1715+
EXPECT_EQ(FBar, Ctx.getValue(LLVMFBar));
1716+
// Check getDataLayout().
1717+
EXPECT_EQ(&M->getDataLayout(), &LLVMM->getDataLayout());
1718+
// Check getSourceFileName().
1719+
EXPECT_EQ(M->getSourceFileName(), LLVMM->getSourceFileName());
1720+
// Check getGlobalVariable().
1721+
for (const char *Name : {"global0", "global1", "internal0"})
1722+
EXPECT_EQ(M->getGlobalVariable(Name),
1723+
Ctx.getValue(LLVMM->getGlobalVariable(Name)));
1724+
// Check getGlobalVariable(AllowInternal).
1725+
{
1726+
auto *Internal0 = M->getGlobalVariable("internal0", /*AllowInternal=*/true);
1727+
EXPECT_TRUE(Internal0 != nullptr);
1728+
EXPECT_EQ(Internal0, Ctx.getValue(LLVMM->getNamedGlobal("internal0")));
1729+
}
1730+
// Check getNamedGlobal().
1731+
{
1732+
auto *Internal = M->getNamedGlobal("internal0");
1733+
EXPECT_TRUE(Internal != nullptr);
1734+
EXPECT_EQ(Internal, Ctx.getValue(LLVMM->getNamedGlobal("internal0")));
1735+
}
1736+
// Check getNamedAlias().
1737+
auto *Alias0 = M->getNamedAlias("alias0");
1738+
EXPECT_EQ(Alias0, Ctx.getValue(LLVMM->getNamedAlias("alias0")));
1739+
EXPECT_EQ(M->getNamedAlias("aliasFOO"), nullptr);
1740+
// Check getNamedIFunc().
1741+
auto *IFunc0 = M->getNamedIFunc("ifunc0");
1742+
EXPECT_EQ(IFunc0, Ctx.getValue(LLVMM->getNamedAlias("ifunc0")));
1743+
EXPECT_EQ(M->getNamedIFunc("ifuncFOO"), nullptr);
1744+
}
1745+
16881746
TEST_F(SandboxIRTest, BasicBlock) {
16891747
parseIR(C, R"IR(
16901748
define void @foo(i32 %v1) {

0 commit comments

Comments
 (0)