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,53 @@ 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 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
+
208
260
// / A sandboxir::User with operands and opcode.
209
261
class Instruction : public sandboxir ::User {
210
262
public:
@@ -231,6 +283,8 @@ class Instruction : public sandboxir::User {
231
283
return OS;
232
284
}
233
285
#endif
286
+ // / This is used by BasicBlcok::iterator.
287
+ virtual unsigned getNumOfIRInstrs () const = 0;
234
288
// / For isa/dyn_cast.
235
289
static bool classof (const sandboxir::Value *From);
236
290
@@ -256,6 +310,7 @@ class OpaqueInst : public sandboxir::Instruction {
256
310
static bool classof (const sandboxir::Value *From) {
257
311
return From->getSubclassID () == ClassID::Opaque;
258
312
}
313
+ unsigned getNumOfIRInstrs () const final { return 1u ; }
259
314
#ifndef NDEBUG
260
315
void verify () const final {
261
316
// Nothing to do
@@ -270,6 +325,54 @@ class OpaqueInst : public sandboxir::Instruction {
270
325
#endif
271
326
};
272
327
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
+
273
376
class Context {
274
377
protected:
275
378
LLVMContext &LLVMCtx;
@@ -278,12 +381,55 @@ class Context {
278
381
DenseMap<llvm::Value *, std::unique_ptr<sandboxir::Value>>
279
382
LLVMValueToValueMap;
280
383
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
+
281
412
public:
282
413
Context (LLVMContext &LLVMCtx) : LLVMCtx(LLVMCtx) {}
414
+
283
415
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 (); }
284
421
};
285
422
286
423
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
+
287
433
public:
288
434
Function (llvm::Function *F, sandboxir::Context &Ctx)
289
435
: sandboxir::Value(ClassID::Function, F, Ctx) {}
@@ -292,6 +438,24 @@ class Function : public sandboxir::Value {
292
438
return From->getSubclassID () == ClassID::Function;
293
439
}
294
440
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
+
295
459
#ifndef NDEBUG
296
460
void verify () const final {
297
461
assert (isa<llvm::Function>(Val) && " Expected Function!" );
0 commit comments