Skip to content

Commit 79f2e57

Browse files
committed
[SandboxIR] Adds BasicBlock and adds functionality to Function and Context
We can now create SandboxIR from LLVM IR using the Context::create* functions.
1 parent 4c63672 commit 79f2e57

File tree

4 files changed

+517
-4
lines changed

4 files changed

+517
-4
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,15 @@
6262
#include "llvm/IR/User.h"
6363
#include "llvm/IR/Value.h"
6464
#include "llvm/Support/raw_ostream.h"
65+
#include <iterator>
6566

6667
namespace llvm {
6768

6869
namespace sandboxir {
6970

71+
class Function;
7072
class Context;
73+
class Instruction;
7174

7275
/// A SandboxIR Value has users. This is the base class.
7376
class Value {
@@ -106,6 +109,8 @@ class Value {
106109
/// NOTE: Some SBInstructions, like Packs, may include more than one value.
107110
llvm::Value *Val = nullptr;
108111

112+
friend class Context; // For getting `Val`.
113+
109114
/// All values point to the context.
110115
Context &Ctx;
111116
// This is used by eraseFromParent().
@@ -205,6 +210,53 @@ class Constant : public sandboxir::User {
205210
#endif
206211
};
207212

213+
/// The BasicBlock::iterator.
214+
class BBIterator {
215+
public:
216+
using difference_type = std::ptrdiff_t;
217+
using value_type = Instruction;
218+
using pointer = value_type *;
219+
using reference = value_type &;
220+
using iterator_category = std::bidirectional_iterator_tag;
221+
222+
private:
223+
llvm::BasicBlock *BB;
224+
llvm::BasicBlock::iterator It;
225+
Context *Ctx;
226+
pointer getI(llvm::BasicBlock::iterator It) const;
227+
228+
public:
229+
BBIterator() : BB(nullptr), Ctx(nullptr) {}
230+
BBIterator(llvm::BasicBlock *BB, llvm::BasicBlock::iterator It, Context *Ctx)
231+
: BB(BB), It(It), Ctx(Ctx) {}
232+
reference operator*() const { return *getI(It); }
233+
BBIterator &operator++();
234+
BBIterator operator++(int) {
235+
auto Copy = *this;
236+
++*this;
237+
return Copy;
238+
}
239+
BBIterator &operator--();
240+
BBIterator operator--(int) {
241+
auto Copy = *this;
242+
--*this;
243+
return Copy;
244+
}
245+
bool operator==(const BBIterator &Other) const {
246+
assert(Ctx == Other.Ctx && "BBIterators in different context!");
247+
return It == Other.It;
248+
}
249+
bool operator!=(const BBIterator &Other) const { return !(*this == Other); }
250+
/// \Returns true if the internal iterator is at the beginning of the IR BB.
251+
/// NOTE: This is meant to be used internally, during the construction of a
252+
/// SBBB, during which SBBB->begin() fails due to the missing mapping of
253+
/// BB->begin() to SandboxIR.
254+
bool atBegin() const;
255+
/// \Returns the SBInstruction that corresponds to this iterator, or null if
256+
/// the instruction is not found in the IR-to-SandboxIR tables.
257+
pointer get() const { return getI(It); }
258+
};
259+
208260
/// A sandboxir::User with operands and opcode.
209261
class Instruction : public sandboxir::User {
210262
public:
@@ -231,6 +283,8 @@ class Instruction : public sandboxir::User {
231283
return OS;
232284
}
233285
#endif
286+
/// This is used by BasicBlcok::iterator.
287+
virtual unsigned getNumOfIRInstrs() const = 0;
234288
/// For isa/dyn_cast.
235289
static bool classof(const sandboxir::Value *From);
236290

@@ -256,6 +310,7 @@ class OpaqueInst : public sandboxir::Instruction {
256310
static bool classof(const sandboxir::Value *From) {
257311
return From->getSubclassID() == ClassID::Opaque;
258312
}
313+
unsigned getNumOfIRInstrs() const final { return 1u; }
259314
#ifndef NDEBUG
260315
void verify() const final {
261316
// Nothing to do
@@ -270,6 +325,54 @@ class OpaqueInst : public sandboxir::Instruction {
270325
#endif
271326
};
272327

328+
class BasicBlock : public Value {
329+
/// Builds a graph that contains all values in \p BB in their original form
330+
/// i.e., no vectorization is taking place here.
331+
void buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB);
332+
friend class Context; // For `buildBasicBlockFromIR`
333+
334+
public:
335+
BasicBlock(llvm::BasicBlock *BB, Context &SBCtx)
336+
: Value(ClassID::Block, BB, SBCtx) {
337+
buildBasicBlockFromLLVMIR(BB);
338+
}
339+
~BasicBlock() = default;
340+
/// For isa/dyn_cast.
341+
static bool classof(const Value *From) {
342+
return From->getSubclassID() == Value::ClassID::Block;
343+
}
344+
Function *getParent() const;
345+
using iterator = BBIterator;
346+
iterator begin() const;
347+
iterator end() const {
348+
auto *BB = cast<llvm::BasicBlock>(Val);
349+
return iterator(BB, BB->end(), &Ctx);
350+
}
351+
std::reverse_iterator<iterator> rbegin() const {
352+
return std::make_reverse_iterator(end());
353+
}
354+
std::reverse_iterator<iterator> rend() const {
355+
return std::make_reverse_iterator(begin());
356+
}
357+
Context &getContext() const { return Ctx; }
358+
Instruction *getTerminator() const;
359+
bool empty() const { return begin() == end(); }
360+
Instruction &front() const;
361+
Instruction &back() const;
362+
363+
#ifndef NDEBUG
364+
void verify() const final {
365+
assert(isa<llvm::BasicBlock>(Val) && "Expected BasicBlock!");
366+
}
367+
friend raw_ostream &operator<<(raw_ostream &OS, const BasicBlock &SBBB) {
368+
SBBB.dump(OS);
369+
return OS;
370+
}
371+
void dump(raw_ostream &OS) const final;
372+
LLVM_DUMP_METHOD void dump() const final;
373+
#endif
374+
};
375+
273376
class Context {
274377
protected:
275378
LLVMContext &LLVMCtx;
@@ -278,12 +381,55 @@ class Context {
278381
DenseMap<llvm::Value *, std::unique_ptr<sandboxir::Value>>
279382
LLVMValueToValueMap;
280383

384+
/// Take ownership of VPtr and store it in `LLVMValueToValueMap`.
385+
Value *registerValue(std::unique_ptr<Value> &&VPtr);
386+
387+
/// Helper for avoiding recursion loop when creating SBConstants.
388+
SmallDenseSet<llvm::Constant *, 8> VisitedConstants;
389+
390+
Value *getOrCreateValueInternal(llvm::Value *V, int Depth,
391+
llvm::User *U = nullptr);
392+
393+
template <typename SBT, typename LLVMT>
394+
SBT *getOrCreateGeneric(LLVMT *LLVMV) {
395+
auto Pair = LLVMValueToValueMap.insert({LLVMV, nullptr});
396+
auto It = Pair.first;
397+
if (Pair.second) {
398+
It->second = std::make_unique<SBT>(LLVMV, *this);
399+
return cast<SBT>(It->second.get());
400+
}
401+
return cast<SBT>(It->second.get());
402+
}
403+
404+
Value *getOrCreateValue(llvm::Value *LLVMV) {
405+
return getOrCreateValueInternal(LLVMV, 0);
406+
}
407+
408+
BasicBlock *createBasicBlock(llvm::BasicBlock *BB);
409+
410+
friend class BasicBlock; // For getOrCreateValue().
411+
281412
public:
282413
Context(LLVMContext &LLVMCtx) : LLVMCtx(LLVMCtx) {}
414+
283415
sandboxir::Value *getValue(llvm::Value *V) const;
416+
417+
Function *createFunction(llvm::Function *F, bool CreateBBs = true);
418+
419+
/// \Returns the number of values registered with Context.
420+
size_t getNumValues() const { return LLVMValueToValueMap.size(); }
284421
};
285422

286423
class Function : public sandboxir::Value {
424+
/// Helper for mapped_iterator.
425+
struct LLVMBBToBB {
426+
Context &Ctx;
427+
LLVMBBToBB(Context &Ctx) : Ctx(Ctx) {}
428+
BasicBlock &operator()(llvm::BasicBlock &LLVMBB) const {
429+
return *cast<BasicBlock>(Ctx.getValue(&LLVMBB));
430+
}
431+
};
432+
287433
public:
288434
Function(llvm::Function *F, sandboxir::Context &Ctx)
289435
: sandboxir::Value(ClassID::Function, F, Ctx) {}
@@ -292,6 +438,24 @@ class Function : public sandboxir::Value {
292438
return From->getSubclassID() == ClassID::Function;
293439
}
294440

441+
Argument *getArg(unsigned Idx) const {
442+
llvm::Argument *Arg = cast<llvm::Function>(Val)->getArg(Idx);
443+
return cast<Argument>(Ctx.getValue(Arg));
444+
}
445+
446+
size_t arg_size() const { return cast<llvm::Function>(Val)->arg_size(); }
447+
bool arg_empty() const { return cast<llvm::Function>(Val)->arg_empty(); }
448+
449+
using iterator = mapped_iterator<llvm::Function::iterator, LLVMBBToBB>;
450+
iterator begin() const {
451+
LLVMBBToBB BBGetter(Ctx);
452+
return iterator(cast<llvm::Function>(Val)->begin(), BBGetter);
453+
}
454+
iterator end() const {
455+
LLVMBBToBB BBGetter(Ctx);
456+
return iterator(cast<llvm::Function>(Val)->end(), BBGetter);
457+
}
458+
295459
#ifndef NDEBUG
296460
void verify() const final {
297461
assert(isa<llvm::Function>(Val) && "Expected Function!");

llvm/include/llvm/SandboxIR/SandboxIRValues.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ DEF_VALUE(Argument, Argument)
1717
#define DEF_USER(ID, CLASS)
1818
#endif
1919
DEF_USER(User, User)
20+
DEF_VALUE(Block, BasicBlock)
2021
DEF_USER(Constant, Constant)
2122

2223
#ifndef DEF_INSTR

0 commit comments

Comments
 (0)