Coverage Report

Created: 2025-12-11 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hermes/include/hermes/IR/IRBuilder.h
Line
Count
Source
1
/*
2
 * Copyright (c) Meta Platforms, Inc. and affiliates.
3
 *
4
 * This source code is licensed under the MIT license found in the
5
 * LICENSE file in the root directory of this source tree.
6
 */
7
8
#ifndef HERMES_IR_IRBUILDER_H
9
#define HERMES_IR_IRBUILDER_H
10
11
#include <string>
12
#include <utility>
13
14
#include "llvh/ADT/SmallVector.h"
15
#include "llvh/ADT/StringRef.h"
16
17
#include "hermes/AST/Context.h"
18
#include "hermes/FrontEndDefs/Builtins.h"
19
#include "hermes/IR/IR.h"
20
#include "hermes/IR/Instrs.h"
21
#include "hermes/Optimizer/Wasm/WasmIntrinsics.h"
22
23
namespace hermes {
24
25
/// The IRBuilder is used for creating IR. The builder APIs is split into two
26
/// parts. First, APIs for creating blocks and functions. These APIs are
27
/// stateless and do not affect the second kind of APIs which are used for
28
/// creating new instructions. The Instruction creation APIS are stateful and
29
/// follow an insertion point that can be saved, restored and manipulated.
30
class IRBuilder {
31
  IRBuilder(const IRBuilder &) = delete;
32
  void operator=(const IRBuilder &) = delete;
33
34
  /// The module is the root of the program that we are building.
35
  Module *M;
36
  /// This is where the next instruction will be inserted.
37
  BasicBlock::iterator InsertionPoint{};
38
  // The iterator must point into this block:
39
  BasicBlock *Block{};
40
41
  SMLoc Location{};
42
  ScopeDesc *CurrentSourceLevelScope{};
43
44
 public:
45
2.05k
  explicit IRBuilder(Module *Mod) : M(Mod), InsertionPoint(nullptr) {}
46
  explicit IRBuilder(Function *F)
47
23.0k
      : M(F->getParent()), InsertionPoint(nullptr) {}
48
49
  //--------------------------------------------------------------------------//
50
  //                          Stateless APIs.                                 //
51
  //--------------------------------------------------------------------------//
52
53
  enum class PropEnumerable { No = 0, Yes = 1 };
54
55
1.21k
  Module *getModule() {
56
1.21k
    return M;
57
1.21k
  }
58
59
  /// Create a new BasicBlock and add it to a function \p Parent.
60
  BasicBlock *createBasicBlock(Function *Parent);
61
62
  /// Create a new Function and add it to the Module.
63
  /// \param OriginalName the original name specified by the user.
64
  /// \param insertBefore Another function in the module where this function
65
  ///   should be inserted before. If null, appends to the end of the module.
66
  Function *createFunction(
67
      ScopeDesc *scopeDesc,
68
      Identifier OriginalName,
69
      Function::DefinitionKind definitionKind,
70
      bool strictMode,
71
      SourceVisibility sourceVisibility = SourceVisibility::Default,
72
      SMRange sourceRange = SMRange{},
73
      bool isGlobal = false,
74
      Function *insertBefore = nullptr);
75
76
  /// Create a new Function and add it to the Module.
77
  Function *createFunction(
78
      ScopeDesc *scopeDesc,
79
      llvh::StringRef OriginalName,
80
      Function::DefinitionKind definitionKind,
81
      bool strictMode,
82
      SourceVisibility sourceVisibility = SourceVisibility::Default,
83
      SMRange sourceRange = SMRange{},
84
      bool isGlobal = false,
85
      Function *insertBefore = nullptr);
86
87
  /// Create a new AsyncFunction and add it to the Module.
88
  /// \param OriginalName the original name specified by the user.
89
  /// \param insertBefore Another function in the module where this function
90
  ///   should be inserted before. If null, appends to the end of the module.
91
  AsyncFunction *createAsyncFunction(
92
      ScopeDesc *scopeDesc,
93
      Identifier OriginalName,
94
      Function::DefinitionKind definitionKind,
95
      bool strictMode,
96
      SourceVisibility sourceVisibility,
97
      SMRange sourceRange = SMRange{},
98
      Function *insertBefore = nullptr);
99
100
  /// Create a new GeneratorFunction and add it to the Module.
101
  /// \param OriginalName the original name specified by the user.
102
  /// \param insertBefore Another function in the module where this function
103
  ///   should be inserted before. If null, appends to the end of the module.
104
  GeneratorFunction *createGeneratorFunction(
105
      ScopeDesc *scopeDesc,
106
      Identifier OriginalName,
107
      Function::DefinitionKind definitionKind,
108
      bool strictMode,
109
      SourceVisibility sourceVisibility,
110
      SMRange sourceRange = SMRange{},
111
      Function *insertBefore = nullptr);
112
113
  /// Create a new GeneratorInnerFunction and add it to the Module.
114
  /// \param OriginalName the original name specified by the user.
115
  /// \param insertBefore Another function in the module where this function
116
  ///   should be inserted before. If null, appends to the end of the module.
117
  GeneratorInnerFunction *createGeneratorInnerFunction(
118
      ScopeDesc *scopeDesc,
119
      Identifier OriginalName,
120
      Function::DefinitionKind definitionKind,
121
      bool strictMode,
122
      SMRange sourceRange = SMRange{},
123
      Function *insertBefore = nullptr);
124
125
  /// Create the top level function representing the global scope.
126
  Function *createTopLevelFunction(
127
      ScopeDesc *scopeDesc,
128
      bool strictMode,
129
      SourceVisibility sourceVisibility = SourceVisibility::Default,
130
      SMRange sourceRange = SMRange{});
131
132
  /// Create a new global object property.
133
  GlobalObjectProperty *createGlobalObjectProperty(
134
      Identifier name,
135
      bool declared);
136
  /// Create a new global object property.
137
  GlobalObjectProperty *createGlobalObjectProperty(
138
      llvh::StringRef name,
139
      bool declared);
140
141
  /// Add a new non-this parameter to function \p Parent.
142
  Parameter *createParameter(Function *Parent, Identifier Name);
143
144
  /// Add a new non-this parameter to function \p Parent.
145
  Parameter *createParameter(Function *Parent, llvh::StringRef Name);
146
147
  /// Add the 'this' parameter to function \p Parent.
148
  /// Must only be done once per function.
149
  Parameter *createThisParameter(Function *Parent);
150
151
  /// Add a new variable to scope \p Parent.
152
  Variable *createVariable(
153
      ScopeDesc *Parent,
154
      Variable::DeclKind declKind,
155
      Identifier Name);
156
157
  /// Add a new variable to scope \p Parent.
158
  Variable *createVariable(
159
      ScopeDesc *Parent,
160
      Variable::DeclKind declKind,
161
      llvh::StringRef Name);
162
163
  /// Create a new literal number of value \p value.
164
  LiteralNumber *getLiteralNumber(double value);
165
166
  /// Create a new literal positive zero.
167
  LiteralNumber *getLiteralPositiveZero();
168
169
  /// Create a new literal negative zero.
170
  LiteralNumber *getLiteralNegativeZero();
171
172
  /// Create a new literal NaN.
173
  LiteralNumber *getLiteralNaN();
174
175
  /// Create a new literal BitInt of value \p value.
176
  LiteralBigInt *getLiteralBigInt(UniqueString *value);
177
178
  /// Create a new literal string of value \p value.
179
  LiteralString *getLiteralString(llvh::StringRef value);
180
181
  /// Create a new literal string of value \p value.
182
  LiteralString *getLiteralString(Identifier value);
183
184
  /// Create a new literal bool of value \p value.
185
  LiteralBool *getLiteralBool(bool value);
186
187
  /// Create a new literal 'empty'.
188
  LiteralEmpty *getLiteralEmpty();
189
190
  /// Create a new literal 'undefined'.
191
  LiteralUndefined *getLiteralUndefined();
192
193
  /// Create a new literal null.
194
  LiteralNull *getLiteralNull();
195
196
  /// Return the GlobalObject value.
197
  GlobalObject *getGlobalObject();
198
199
  /// Return the EmptySentinel value.
200
  EmptySentinel *getEmptySentinel();
201
202
  /// Convert llvh::StringRef to Identifier.
203
  Identifier createIdentifier(llvh::StringRef str);
204
205
  //--------------------------------------------------------------------------//
206
  //                          Statefull APIs.                                 //
207
  //--------------------------------------------------------------------------//
208
209
 private:
210
  /// Insert the newly created instruction \p Inst into the basic block without
211
  /// touching its location or statement index.
212
  void justInsert(Instruction *Inst);
213
214
  /// Insert the newly created instruction \p Inst into the basic block and
215
  /// populate its location and statement index.
216
  void insert(Instruction *Inst);
217
218
 public:
219
  /// Set the insertion point of the builder. The next instruction will be
220
  /// inserted at the end of \p BB.
221
  void setInsertionBlock(BasicBlock *BB);
222
223
  /// Return the current insertion block.
224
  BasicBlock *getInsertionBlock();
225
226
  /// Return the current function.
227
3.96M
  Function *getFunction() {
228
3.96M
    assert(Block && "Builder has no current function");
229
3.96M
    return Block->getParent();
230
3.96M
  }
231
232
  /// Set the insertion point of the builder. The next instruction will be
233
  /// inserted after \p IP.
234
  void setInsertionPointAfter(Instruction *IP);
235
236
  /// Set the insertion point of the builder. The next instruction will be
237
  /// inserted where the current \p IP is (thereby pushing it down).
238
  void setInsertionPoint(Instruction *IP);
239
240
  /// \returns true if the insertion point is set.
241
  bool isInsertionPointValid();
242
243
  /// Clear the insertion point. New instructions must not be created until the
244
  /// insertion point it set.
245
  void resetInsertionPoint();
246
247
5.59M
  void setLocation(SMLoc loc) {
248
5.59M
    Location = loc;
249
5.59M
  }
250
2.18k
  void clearLocation() {
251
2.18k
    Location = SMLoc{};
252
2.18k
  }
253
1.31M
  SMLoc getLocation() const {
254
1.31M
    return Location;
255
1.31M
  }
256
257
2.85M
  void setCurrentSourceLevelScope(ScopeDesc *sourceLevelScope) {
258
2.85M
    CurrentSourceLevelScope = sourceLevelScope;
259
2.85M
  }
260
261
  /// Move instruction \p inst from its block to the insertion point in the
262
  /// current block. If the instruction is a terminator, correctly update the
263
  /// phi-nodes that refer to the old block and point then to the current one.
264
  void transferInstructionToCurrentBlock(Instruction *inst);
265
266
  //--------------------------------------------------------------------------//
267
  //                    Instruction Creation methods                          //
268
  //--------------------------------------------------------------------------//
269
270
  /// Insert a clone of the instruction at the current insertion point. The
271
  /// location and statement index are preserved but the operands are recreated.
272
  /// \param source the original instruction.
273
  /// \param operands the (updated) operands to use in the new instruction.
274
  Instruction *cloneInst(
275
      const Instruction *source,
276
      llvh::ArrayRef<Value *> operands);
277
278
  BranchInst *createBranchInst(BasicBlock *Destination);
279
280
  CondBranchInst *
281
  createCondBranchInst(Value *Cond, BasicBlock *T, BasicBlock *F);
282
283
  ReturnInst *createReturnInst(Value *Val);
284
285
  AllocStackInst *createAllocStackInst(llvh::StringRef varName);
286
287
  AllocStackInst *createAllocStackInst(Identifier varName);
288
289
  AsNumberInst *createAsNumberInst(Value *val);
290
291
  AsNumericInst *createAsNumericInst(Value *val);
292
293
  AsInt32Inst *createAsInt32Inst(Value *val);
294
295
  AddEmptyStringInst *createAddEmptyStringInst(Value *val);
296
297
  ThrowIfHasRestrictedGlobalPropertyInst *
298
  createThrowIfHasRestrictedGlobalPropertyInst(llvh::StringRef property);
299
300
  CreateScopeInst *createCreateScopeInst(ScopeDesc *scopeDesc);
301
302
  CreateInnerScopeInst *createCreateInnerScopeInst(
303
      ScopeCreationInst *parentScope,
304
      ScopeDesc *scopeDesc);
305
306
  CreateFunctionInst *createCreateFunctionInst(
307
      Function *code,
308
      ScopeCreationInst *environment);
309
310
  LoadStackInst *createLoadStackInst(AllocStackInst *ptr);
311
312
  LoadFrameInst *createLoadFrameInst(Variable *ptr, ScopeCreationInst *scope);
313
314
  StoreStackInst *createStoreStackInst(Value *storedValue, AllocStackInst *ptr);
315
316
  StoreFrameInst *createStoreFrameInst(
317
      Value *storedValue,
318
      Variable *ptr,
319
      ScopeCreationInst *scope);
320
321
  CallInst *createCallInst(
322
      LiteralString *textifiedCallee,
323
      Value *callee,
324
      Value *thisValue,
325
      ArrayRef<Value *> args);
326
327
  HBCCallNInst *createHBCCallNInst(
328
      LiteralString *textifiedCallee,
329
      Value *callee,
330
      Value *thisValue,
331
      ArrayRef<Value *> args);
332
333
  ConstructInst *createConstructInst(
334
      Value *constructor,
335
      Value *newTarget,
336
      ArrayRef<Value *> args);
337
338
  CatchInst *createCatchInst();
339
340
  ThrowInst *createThrowInst(Value *thrownValue);
341
342
  CheckHasInstanceInst *createCheckHasInstanceInst(
343
      AllocStackInst *result,
344
      Value *left,
345
      Value *right,
346
      BasicBlock *onTrue,
347
      BasicBlock *onFalse);
348
349
  TryStartInst *createTryStartInst(
350
      BasicBlock *tryBodyBlock,
351
      BasicBlock *catchTargetBlock);
352
353
  TryEndInst *createTryEndInst();
354
355
  DeletePropertyInst *createDeletePropertyInst(Value *object, Value *property);
356
357
  LoadPropertyInst *createLoadPropertyInst(Value *object, Value *property);
358
  TryLoadGlobalPropertyInst *createTryLoadGlobalPropertyInst(
359
      LiteralString *property);
360
  TryLoadGlobalPropertyInst *createTryLoadGlobalPropertyInst(
361
      GlobalObjectProperty *property);
362
363
  StorePropertyInst *
364
  createStorePropertyInst(Value *storedValue, Value *object, Value *property);
365
  TryStoreGlobalPropertyInst *createTryStoreGlobalPropertyInst(
366
      Value *storedValue,
367
      LiteralString *property);
368
  TryStoreGlobalPropertyInst *createTryStoreGlobalPropertyInst(
369
      Value *storedValue,
370
      GlobalObjectProperty *property);
371
  StoreOwnPropertyInst *createStoreOwnPropertyInst(
372
      Value *storedValue,
373
      Value *object,
374
      Value *property,
375
      PropEnumerable isEnumerable);
376
  StoreNewOwnPropertyInst *createStoreNewOwnPropertyInst(
377
      Value *storedValue,
378
      Value *object,
379
      Literal *property,
380
      PropEnumerable isEnumerable);
381
382
  StoreGetterSetterInst *createStoreGetterSetterInst(
383
      Value *storedGetter,
384
      Value *storedSetter,
385
      Value *object,
386
      Value *property,
387
      PropEnumerable isEnumerable);
388
  DeletePropertyInst *createDeletePropertyInst(
389
      Value *object,
390
      llvh::StringRef property);
391
392
  LoadPropertyInst *createLoadPropertyInst(
393
      Value *object,
394
      llvh::StringRef property);
395
  TryLoadGlobalPropertyInst *createTryLoadGlobalPropertyInst(
396
      llvh::StringRef property);
397
398
  StorePropertyInst *createStorePropertyInst(
399
      Value *storedValue,
400
      Value *object,
401
      llvh::StringRef property);
402
403
  DeletePropertyInst *createDeletePropertyInst(
404
      Value *object,
405
      Identifier property);
406
407
  LoadPropertyInst *createLoadPropertyInst(Value *object, Identifier property);
408
  TryLoadGlobalPropertyInst *createTryLoadGlobalPropertyInst(
409
      Identifier property);
410
411
  StorePropertyInst *createStorePropertyInst(
412
      Value *storedValue,
413
      Value *object,
414
      Identifier property);
415
  TryStoreGlobalPropertyInst *createTryStoreGlobalPropertyInst(
416
      Value *storedValue,
417
      Identifier property);
418
419
  AllocObjectInst *createAllocObjectInst(
420
      uint32_t size,
421
      Value *parent = nullptr);
422
423
  AllocArrayInst *createAllocArrayInst(
424
      LiteralNumber *sizeHint,
425
      AllocArrayInst::ArrayValueList val_list);
426
427
  AllocArrayInst *createAllocArrayInst(
428
      AllocArrayInst::ArrayValueList val_list,
429
      unsigned sizeHint);
430
431
  CreateArgumentsInst *createCreateArgumentsInst();
432
433
  GetNewTargetInst *createGetNewTargetInst();
434
435
  ThrowIfEmptyInst *createThrowIfEmptyInst(Value *checkedValue);
436
437
  HBCGetGlobalObjectInst *createHBCGetGlobalObjectInst();
438
439
  CreateRegExpInst *createRegExpInst(Identifier pattern, Identifier flags);
440
441
  UnaryOperatorInst *createUnaryOperatorInst(
442
      Value *value,
443
      UnaryOperatorInst::OpKind opKind);
444
445
  DirectEvalInst *createDirectEvalInst(Value *operand, LiteralBool *isStrict);
446
447
  SwitchInst *createSwitchInst(
448
      Value *input,
449
      BasicBlock *defaultBlock,
450
      const SwitchInst::ValueListType &values,
451
      const SwitchInst::BasicBlockListType &blocks);
452
453
  PhiInst *createPhiInst(
454
      const PhiInst::ValueListType &values,
455
      const PhiInst::BasicBlockListType &blocks);
456
457
  PhiInst *createPhiInst();
458
459
  BinaryOperatorInst *createBinaryOperatorInst(
460
      Value *left,
461
      Value *right,
462
      BinaryOperatorInst::OpKind opKind);
463
464
  GetPNamesInst *createGetPNamesInst(
465
      Value *iteratorAddr,
466
      Value *baseAddr,
467
      Value *indexAddr,
468
      Value *sizeAddr,
469
      BasicBlock *onEmpty,
470
      BasicBlock *onSome);
471
472
  GetNextPNameInst *createGetNextPNameInst(
473
      Value *propertyAddr,
474
      Value *baseAddr,
475
      Value *indexAddr,
476
      Value *sizeAddr,
477
      Value *iteratorAddr,
478
      BasicBlock *onLast,
479
      BasicBlock *onSome);
480
481
  MovInst *createMovInst(Value *input);
482
483
  ImplicitMovInst *createImplicitMovInst(Value *input);
484
485
  CoerceThisNSInst *createCoerceThisNSInst(Value *input);
486
487
  DebuggerInst *createDebuggerInst();
488
489
  SaveAndYieldInst *createSaveAndYieldInst(
490
      Value *result,
491
      BasicBlock *nextBlock);
492
493
  CreateGeneratorInst *createCreateGeneratorInst(
494
      Function *innerFn,
495
      ScopeCreationInst *environment);
496
497
  StartGeneratorInst *createStartGeneratorInst();
498
499
  ResumeGeneratorInst *createResumeGeneratorInst(Value *isReturn);
500
501
  //--------------------------------------------------------------------------//
502
  //                  Target specific insertions                              //
503
  //--------------------------------------------------------------------------//
504
505
  HBCResolveEnvironment *createHBCResolveEnvironment(
506
      ScopeDesc *originScopeDesc,
507
      ScopeDesc *targetScopeDesc);
508
  HBCStoreToEnvironmentInst *
509
  createHBCStoreToEnvironmentInst(Value *env, Value *toPut, Variable *var);
510
  HBCLoadFromEnvironmentInst *createHBCLoadFromEnvironmentInst(
511
      Value *env,
512
      Variable *var);
513
514
  SwitchImmInst *createSwitchImmInst(
515
      Value *input,
516
      BasicBlock *defaultBlock,
517
      LiteralNumber *minValue,
518
      LiteralNumber *size,
519
      const SwitchImmInst::ValueListType &values,
520
      const SwitchImmInst::BasicBlockListType &blocks);
521
522
  HBCLoadConstInst *createHBCLoadConstInst(Literal *value);
523
524
  HBCLoadParamInst *createHBCLoadParamInst(LiteralNumber *value);
525
526
  HBCCreateEnvironmentInst *createHBCCreateEnvironmentInst(
527
      ScopeDesc *scopeDesc);
528
529
  HBCCreateInnerEnvironmentInst *createHBCCreateInnerEnvironmentInst(
530
      ScopeCreationInst *parentScope,
531
      ScopeDesc *scopeDesc);
532
533
  HBCGetThisNSInst *createHBCGetThisNSInst();
534
535
  HBCGetArgumentsPropByValInst *createHBCGetArgumentsPropByValInst(
536
      Value *index,
537
      AllocStackInst *lazyReg);
538
539
  HBCGetArgumentsLengthInst *createHBCGetArgumentsLengthInst(
540
      AllocStackInst *lazyReg);
541
542
  HBCReifyArgumentsInst *createHBCReifyArgumentsInst(AllocStackInst *lazyReg);
543
544
  HBCCreateThisInst *createHBCCreateThisInst(Value *prototype, Value *closure);
545
546
  HBCConstructInst *createHBCConstructInst(
547
      Value *closure,
548
      Value *newTarget,
549
      Value *thisValue,
550
      ArrayRef<Value *> arguments);
551
  HBCGetConstructedObjectInst *createHBCGetConstructedObjectInst(
552
      HBCCreateThisInst *thisValue,
553
      HBCConstructInst *constructorReturnValue);
554
  HBCProfilePointInst *createHBCProfilePointInst(uint16_t pointIndex);
555
556
  CallBuiltinInst *createCallBuiltinInst(
557
      BuiltinMethod::Enum builtinIndex,
558
      ArrayRef<Value *> arguments);
559
560
  CallBuiltinInst *createCallBuiltinInstWithNewTarget(
561
      BuiltinMethod::Enum builtinIndex,
562
      Value *newTarget,
563
      ArrayRef<Value *> arguments);
564
565
  GetBuiltinClosureInst *createGetBuiltinClosureInst(
566
      BuiltinMethod::Enum builtinIndex);
567
568
#ifdef HERMES_RUN_WASM
569
  CallIntrinsicInst *createCallIntrinsicInst(
570
      WasmIntrinsics::Enum intrinsicsIndex,
571
      ArrayRef<Value *> arguments);
572
#endif
573
574
  HBCCallDirectInst *createHBCCallDirectInst(
575
      LiteralString *textifiedCallee,
576
      Function *callee,
577
      Value *thisValue,
578
      ArrayRef<Value *> arguments);
579
580
  HBCCreateFunctionInst *createHBCCreateFunctionInst(
581
      Function *function,
582
      Value *env);
583
  HBCSpillMovInst *createHBCSpillMovInst(Instruction *value);
584
585
  HBCCreateGeneratorInst *createHBCCreateGeneratorInst(
586
      Function *function,
587
      Value *env);
588
589
  HBCAllocObjectFromBufferInst *createHBCAllocObjectFromBufferInst(
590
      HBCAllocObjectFromBufferInst::ObjectPropertyMap prop_map,
591
      uint32_t size);
592
593
  CompareBranchInst *createCompareBranchInst(
594
      Value *left,
595
      Value *right,
596
      BinaryOperatorInst::OpKind opKind,
597
      BasicBlock *trueBlock,
598
      BasicBlock *falseBlock);
599
600
  IteratorBeginInst *createIteratorBeginInst(AllocStackInst *sourceOrNext);
601
602
  IteratorNextInst *createIteratorNextInst(
603
      AllocStackInst *iterator,
604
      AllocStackInst *sourceOrNext);
605
606
  IteratorCloseInst *createIteratorCloseInst(
607
      AllocStackInst *iterator,
608
      bool ignoreInnerException);
609
610
  UnreachableInst *createUnreachableInst();
611
612
  /// This is an RAII object that saves and restores the source location of the
613
  /// IRBuilder.
614
  class ScopedLocationChange {
615
    ScopedLocationChange(const ScopedLocationChange &) = delete;
616
    void operator=(const ScopedLocationChange &) = delete;
617
618
    IRBuilder &builder_;
619
    SMLoc oldLocation_;
620
621
   public:
622
    /// Save the builder source location when constructing the object.
623
    explicit ScopedLocationChange(IRBuilder &builder, SMLoc location)
624
1.31M
        : builder_(builder), oldLocation_(builder.getLocation()) {
625
1.31M
      builder_.setLocation(location);
626
1.31M
    }
627
628
    /// Resotre source location when the object is destroyed.
629
1.31M
    ~ScopedLocationChange() {
630
1.31M
      builder_.setLocation(oldLocation_);
631
1.31M
    }
632
  };
633
634
  //--------------------------------------------------------------------------//
635
  //                  Insertion point Save and Restore                        //
636
  //--------------------------------------------------------------------------//
637
638
  /// This is an RAII object that saves and restores the insertion point of the
639
  /// IRBuilder.
640
  class SaveRestore {
641
    SaveRestore(const SaveRestore &) = delete;
642
    void operator=(const SaveRestore &) = delete;
643
644
    IRBuilder &Builder;
645
    BasicBlock *BB;
646
    SMLoc Location;
647
648
   public:
649
    // Save the builder insertion point when constructing the object.
650
    explicit SaveRestore(IRBuilder &builder)
651
2.18k
        : Builder(builder),
652
2.18k
          BB(builder.getInsertionBlock()),
653
2.18k
          Location(builder.getLocation()) {
654
2.18k
      builder.clearLocation();
655
2.18k
    }
656
657
    // Restore insertion point when the object is destroyed.
658
2.18k
    ~SaveRestore() {
659
2.18k
      Builder.setInsertionBlock(BB);
660
2.18k
      Builder.setLocation(Location);
661
2.18k
    }
662
  };
663
664
  /// This is an RAII object that destroys instructions when it is destroyed.
665
  class InstructionDestroyer {
666
    InstructionDestroyer(const InstructionDestroyer &) = delete;
667
    void operator=(const InstructionDestroyer &) = delete;
668
669
    llvh::SmallVector<Instruction *, 8> list{};
670
671
   public:
672
66.3k
    explicit InstructionDestroyer() = default;
673
674
    /// \returns true if the instruction \p A is already in the destruction
675
    /// queue. Notice that this is an O(n) search and should only be used for
676
    /// debugging.
677
195k
    bool hasInstruction(Instruction *A) {
678
195k
      return std::find(list.begin(), list.end(), A) != list.end();
679
195k
    }
680
681
    /// Add the instruction \p  A to the list of instructions to delete.
682
195k
    void add(Instruction *A) {
683
195k
#ifndef NDEBUG
684
195k
      assert(!hasInstruction(A) && "Instruction already in list!");
685
195k
#endif
686
195k
      list.push_back(A);
687
195k
    }
688
689
66.3k
    ~InstructionDestroyer() {
690
195k
      for (auto *I : list) {
691
195k
        I->eraseFromParent();
692
195k
      }
693
66.3k
    }
694
  };
695
};
696
697
} // end namespace hermes
698
699
#endif