62
62
#include " llvm/IR/User.h"
63
63
#include " llvm/IR/Value.h"
64
64
#include " llvm/Support/raw_ostream.h"
65
+ #include < iterator>
65
66
66
67
namespace llvm {
67
68
68
69
namespace sandboxir {
69
70
71
+ class Function ;
70
72
class Context ;
73
+ class Instruction ;
71
74
72
75
// / A SandboxIR Value has users. This is the base class.
73
76
class Value {
@@ -106,6 +109,8 @@ class Value {
106
109
// / NOTE: Some SBInstructions, like Packs, may include more than one value.
107
110
llvm::Value *Val = nullptr ;
108
111
112
+ friend class Context ; // For getting `Val`.
113
+
109
114
// / All values point to the context.
110
115
Context &Ctx;
111
116
// This is used by eraseFromParent().
@@ -205,6 +210,48 @@ class Constant : public sandboxir::User {
205
210
#endif
206
211
};
207
212
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 getInstr (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 *getInstr (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 the SBInstruction that corresponds to this iterator, or null if
251
+ // / the instruction is not found in the IR-to-SandboxIR tables.
252
+ pointer get () const { return getInstr (It); }
253
+ };
254
+
208
255
// / A sandboxir::User with operands and opcode.
209
256
class Instruction : public sandboxir ::User {
210
257
public:
@@ -231,6 +278,8 @@ class Instruction : public sandboxir::User {
231
278
return OS;
232
279
}
233
280
#endif
281
+ // / This is used by BasicBlock::iterator.
282
+ virtual unsigned getNumOfIRInstrs () const = 0;
234
283
// / For isa/dyn_cast.
235
284
static bool classof (const sandboxir::Value *From);
236
285
@@ -256,6 +305,7 @@ class OpaqueInst : public sandboxir::Instruction {
256
305
static bool classof (const sandboxir::Value *From) {
257
306
return From->getSubclassID () == ClassID::Opaque;
258
307
}
308
+ unsigned getNumOfIRInstrs () const final { return 1u ; }
259
309
#ifndef NDEBUG
260
310
void verify () const final {
261
311
// Nothing to do
@@ -270,6 +320,54 @@ class OpaqueInst : public sandboxir::Instruction {
270
320
#endif
271
321
};
272
322
323
+ class BasicBlock : public Value {
324
+ // / Builds a graph that contains all values in \p BB in their original form
325
+ // / i.e., no vectorization is taking place here.
326
+ void buildBasicBlockFromLLVMIR (llvm::BasicBlock *LLVMBB);
327
+ friend class Context ; // For `buildBasicBlockFromIR`
328
+
329
+ public:
330
+ BasicBlock (llvm::BasicBlock *BB, Context &SBCtx)
331
+ : Value(ClassID::Block, BB, SBCtx) {
332
+ buildBasicBlockFromLLVMIR (BB);
333
+ }
334
+ ~BasicBlock () = default ;
335
+ // / For isa/dyn_cast.
336
+ static bool classof (const Value *From) {
337
+ return From->getSubclassID () == Value::ClassID::Block;
338
+ }
339
+ Function *getParent () const ;
340
+ using iterator = BBIterator;
341
+ iterator begin () const ;
342
+ iterator end () const {
343
+ auto *BB = cast<llvm::BasicBlock>(Val);
344
+ return iterator (BB, BB->end (), &Ctx);
345
+ }
346
+ std::reverse_iterator<iterator> rbegin () const {
347
+ return std::make_reverse_iterator (end ());
348
+ }
349
+ std::reverse_iterator<iterator> rend () const {
350
+ return std::make_reverse_iterator (begin ());
351
+ }
352
+ Context &getContext () const { return Ctx; }
353
+ Instruction *getTerminator () const ;
354
+ bool empty () const { return begin () == end (); }
355
+ Instruction &front () const ;
356
+ Instruction &back () const ;
357
+
358
+ #ifndef NDEBUG
359
+ void verify () const final {
360
+ assert (isa<llvm::BasicBlock>(Val) && " Expected BasicBlock!" );
361
+ }
362
+ friend raw_ostream &operator <<(raw_ostream &OS, const BasicBlock &SBBB) {
363
+ SBBB.dump (OS);
364
+ return OS;
365
+ }
366
+ void dump (raw_ostream &OS) const final ;
367
+ LLVM_DUMP_METHOD void dump () const final ;
368
+ #endif
369
+ };
370
+
273
371
class Context {
274
372
protected:
275
373
LLVMContext &LLVMCtx;
@@ -278,12 +376,53 @@ class Context {
278
376
DenseMap<llvm::Value *, std::unique_ptr<sandboxir::Value>>
279
377
LLVMValueToValueMap;
280
378
379
+ // / Take ownership of VPtr and store it in `LLVMValueToValueMap`.
380
+ Value *registerValue (std::unique_ptr<Value> &&VPtr);
381
+
382
+ Value *getOrCreateValueInternal (llvm::Value *V, llvm::User *U = nullptr );
383
+
384
+ Argument *getOrCreateArgument (llvm::Argument *LLVMArg) {
385
+ auto Pair = LLVMValueToValueMap.insert ({LLVMArg, nullptr });
386
+ auto It = Pair.first ;
387
+ if (Pair.second ) {
388
+ It->second = std::make_unique<Argument>(LLVMArg, *this );
389
+ return cast<Argument>(It->second .get ());
390
+ }
391
+ return cast<Argument>(It->second .get ());
392
+ }
393
+
394
+ Value *getOrCreateValue (llvm::Value *LLVMV) {
395
+ return getOrCreateValueInternal (LLVMV, 0 );
396
+ }
397
+
398
+ BasicBlock *createBasicBlock (llvm::BasicBlock *BB);
399
+
400
+ friend class BasicBlock ; // For getOrCreateValue().
401
+
281
402
public:
282
403
Context (LLVMContext &LLVMCtx) : LLVMCtx(LLVMCtx) {}
404
+
283
405
sandboxir::Value *getValue (llvm::Value *V) const ;
406
+ const sandboxir::Value *getValue (const llvm::Value *V) const {
407
+ return getValue (const_cast <llvm::Value *>(V));
408
+ }
409
+
410
+ Function *createFunction (llvm::Function *F);
411
+
412
+ // / \Returns the number of values registered with Context.
413
+ size_t getNumValues () const { return LLVMValueToValueMap.size (); }
284
414
};
285
415
286
416
class Function : public sandboxir ::Value {
417
+ // / Helper for mapped_iterator.
418
+ struct LLVMBBToBB {
419
+ Context &Ctx;
420
+ LLVMBBToBB (Context &Ctx) : Ctx(Ctx) {}
421
+ BasicBlock &operator ()(llvm::BasicBlock &LLVMBB) const {
422
+ return *cast<BasicBlock>(Ctx.getValue (&LLVMBB));
423
+ }
424
+ };
425
+
287
426
public:
288
427
Function (llvm::Function *F, sandboxir::Context &Ctx)
289
428
: sandboxir::Value(ClassID::Function, F, Ctx) {}
@@ -292,6 +431,24 @@ class Function : public sandboxir::Value {
292
431
return From->getSubclassID () == ClassID::Function;
293
432
}
294
433
434
+ Argument *getArg (unsigned Idx) const {
435
+ llvm::Argument *Arg = cast<llvm::Function>(Val)->getArg (Idx);
436
+ return cast<Argument>(Ctx.getValue (Arg));
437
+ }
438
+
439
+ size_t arg_size () const { return cast<llvm::Function>(Val)->arg_size (); }
440
+ bool arg_empty () const { return cast<llvm::Function>(Val)->arg_empty (); }
441
+
442
+ using iterator = mapped_iterator<llvm::Function::iterator, LLVMBBToBB>;
443
+ iterator begin () const {
444
+ LLVMBBToBB BBGetter (Ctx);
445
+ return iterator (cast<llvm::Function>(Val)->begin (), BBGetter);
446
+ }
447
+ iterator end () const {
448
+ LLVMBBToBB BBGetter (Ctx);
449
+ return iterator (cast<llvm::Function>(Val)->end (), BBGetter);
450
+ }
451
+
295
452
#ifndef NDEBUG
296
453
void verify () const final {
297
454
assert (isa<llvm::Function>(Val) && " Expected Function!" );
0 commit comments