lib/IR/IRBuilder.cpp (917 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #include "llvh/Support/Casting.h" #include "llvh/Support/ErrorHandling.h" #include "hermes/AST/Context.h" #include "hermes/IR/IR.h" #include "hermes/IR/IRBuilder.h" using namespace hermes; using llvh::cast; using llvh::dyn_cast; using llvh::isa; BasicBlock *IRBuilder::createBasicBlock(Function *Parent) { assert(Parent && "Invalid insertion point"); return new BasicBlock(Parent); } Function *IRBuilder::createFunction( Identifier OriginalName, Function::DefinitionKind definitionKind, bool strictMode, SourceVisibility sourceVisibility, SMRange sourceRange, bool isGlobal, Function *insertBefore) { // Function must have a name. If the source doesn't provide the function name, // Hermes will try to infer the name from the name of a variable or property // it is assigned to. If there was no inference, an empty string is used. if (!OriginalName.isValid()) { OriginalName = createIdentifier(""); } return new Function( M, OriginalName, definitionKind, strictMode, sourceVisibility, isGlobal, sourceRange, insertBefore); } GeneratorFunction *IRBuilder::createGeneratorFunction( Identifier OriginalName, Function::DefinitionKind definitionKind, bool strictMode, SourceVisibility sourceVisibility, SMRange sourceRange, Function *insertBefore) { if (!OriginalName.isValid()) { // Function must have a name, even it's empty. // Eventually we will give it a properly inferred name. OriginalName = createIdentifier(""); } return new GeneratorFunction( M, OriginalName, definitionKind, strictMode, sourceVisibility, /* isGlobal */ false, sourceRange, insertBefore); } GeneratorInnerFunction *IRBuilder::createGeneratorInnerFunction( Identifier OriginalName, Function::DefinitionKind definitionKind, bool strictMode, SMRange sourceRange, Function *insertBefore) { if (!OriginalName.isValid()) { // Function must have a name, even it's empty. // Eventually we will give it a properly inferred name. OriginalName = createIdentifier(""); } return new GeneratorInnerFunction( M, OriginalName, definitionKind, strictMode, /* isGlobal */ false, sourceRange, insertBefore); } ExternalScope *IRBuilder::createExternalScope( Function *function, int32_t depth) { return new ExternalScope(function, depth); } Function *IRBuilder::createTopLevelFunction( bool strictMode, SourceVisibility sourceVisibility, SMRange sourceRange) { // Notice that this synthesized name is not a legal javascript name and // can't collide with functions in the processed program. return createFunction( "global", Function::DefinitionKind::ES5Function, strictMode, sourceVisibility, sourceRange, true); } Function *IRBuilder::createFunction( StringRef OriginalName, Function::DefinitionKind definitionKind, bool strictMode, SourceVisibility sourceVisibility, SMRange sourceRange, bool isGlobal, Function *insertBefore) { Identifier OrigIden = OriginalName.empty() ? Identifier{} : createIdentifier(OriginalName); return createFunction( OrigIden, definitionKind, strictMode, sourceVisibility, sourceRange, isGlobal, insertBefore); } AsyncFunction *IRBuilder::createAsyncFunction( Identifier OriginalName, Function::DefinitionKind definitionKind, bool strictMode, SourceVisibility sourceVisibility, SMRange sourceRange, Function *insertBefore) { if (!OriginalName.isValid()) { // Function must have a name, even it's empty. // Eventually we will give it a properly inferred name. OriginalName = createIdentifier(""); } return new AsyncFunction( M, OriginalName, definitionKind, strictMode, sourceVisibility, /* isGlobal */ false, sourceRange, insertBefore); } GlobalObjectProperty *IRBuilder::createGlobalObjectProperty( Identifier name, bool declared) { return M->addGlobalProperty(name, declared); } GlobalObjectProperty *IRBuilder::createGlobalObjectProperty( StringRef name, bool declared) { return createGlobalObjectProperty( M->getContext().getIdentifier(name), declared); } Parameter *IRBuilder::createParameter(Function *Parent, Identifier Name) { return new Parameter(Parent, Name); } Parameter *IRBuilder::createParameter(Function *Parent, StringRef Name) { return createParameter(Parent, createIdentifier(Name)); } Variable *IRBuilder::createVariable( VariableScope *Parent, Variable::DeclKind declKind, Identifier Name) { return new Variable(Parent, declKind, Name); } Variable *IRBuilder::createVariable( VariableScope *Parent, Variable::DeclKind declKind, StringRef Name) { return createVariable(Parent, declKind, createIdentifier(Name)); } LiteralNumber *IRBuilder::getLiteralNumber(double value) { return M->getLiteralNumber(value); } // FIXME: use proper language semantics. LiteralNumber *IRBuilder::getLiteralPositiveZero() { return M->getLiteralNumber(+0.0); } LiteralNumber *IRBuilder::getLiteralNegativeZero() { return M->getLiteralNumber(-0.0); } LiteralNumber *IRBuilder::getLiteralNaN() { return M->getLiteralNumber(std::numeric_limits<double>::quiet_NaN()); } LiteralString *IRBuilder::getLiteralString(StringRef value) { Identifier Iden = createIdentifier(value); return getLiteralString(Iden); } LiteralString *IRBuilder::getLiteralString(Identifier value) { return M->getLiteralString(value); } LiteralBool *IRBuilder::getLiteralBool(bool value) { return M->getLiteralBool(value); } LiteralEmpty *IRBuilder::getLiteralEmpty() { return M->getLiteralEmpty(); } LiteralUndefined *IRBuilder::getLiteralUndefined() { return M->getLiteralUndefined(); } LiteralNull *IRBuilder::getLiteralNull() { return M->getLiteralNull(); } GlobalObject *IRBuilder::getGlobalObject() { return M->getGlobalObject(); } EmptySentinel *IRBuilder::getEmptySentinel() { return M->getEmptySentinel(); } Identifier IRBuilder::createIdentifier(StringRef str) { return M->getContext().getIdentifier(str); } BranchInst *IRBuilder::createBranchInst(BasicBlock *Destination) { auto *BI = new BranchInst(getInsertionBlock(), Destination); insert(BI); return BI; } CondBranchInst * IRBuilder::createCondBranchInst(Value *Cond, BasicBlock *T, BasicBlock *F) { auto *CBI = new CondBranchInst(getInsertionBlock(), Cond, T, F); insert(CBI); return CBI; } ReturnInst *IRBuilder::createReturnInst(Value *Val) { auto *RI = new ReturnInst(Val); insert(RI); return RI; } CatchInst *IRBuilder::createCatchInst() { auto *CI = new CatchInst(); insert(CI); return CI; } ThrowInst *IRBuilder::createThrowInst(Value *thrownValue) { auto *TI = new ThrowInst(thrownValue); insert(TI); return TI; } CheckHasInstanceInst *IRBuilder::createCheckHasInstanceInst( AllocStackInst *result, Value *left, Value *right, BasicBlock *onTrue, BasicBlock *onFalse) { auto *TI = new CheckHasInstanceInst(result, left, right, onTrue, onFalse); insert(TI); return TI; } TryStartInst *IRBuilder::createTryStartInst( BasicBlock *tryBodyBlock, BasicBlock *catchTargetBlock) { auto *I = new TryStartInst(tryBodyBlock, catchTargetBlock); insert(I); return I; } TryEndInst *IRBuilder::createTryEndInst() { auto *I = new TryEndInst(); insert(I); return I; } AllocStackInst *IRBuilder::createAllocStackInst(StringRef varName) { Identifier Iden = createIdentifier(varName); return createAllocStackInst(Iden); } AllocStackInst *IRBuilder::createAllocStackInst(Identifier varName) { auto *AHI = new AllocStackInst(varName); insert(AHI); return AHI; } AsNumberInst *IRBuilder::createAsNumberInst(Value *val) { auto *ANI = new AsNumberInst(val); insert(ANI); return ANI; } AsInt32Inst *IRBuilder::createAsInt32Inst(Value *val) { auto *AII = new AsInt32Inst(val); insert(AII); return AII; } AddEmptyStringInst *IRBuilder::createAddEmptyStringInst(Value *val) { auto *I = new AddEmptyStringInst(val); insert(I); return I; } CreateFunctionInst *IRBuilder::createCreateFunctionInst(Function *code) { auto CFI = new CreateFunctionInst(code); insert(CFI); return CFI; } LoadFrameInst *IRBuilder::createLoadFrameInst(Variable *ptr) { auto LI = new LoadFrameInst(ptr); insert(LI); return LI; } LoadStackInst *IRBuilder::createLoadStackInst(AllocStackInst *ptr) { auto LI = new LoadStackInst(ptr); insert(LI); return LI; } StoreFrameInst *IRBuilder::createStoreFrameInst( Value *storedValue, Variable *ptr) { auto SI = new StoreFrameInst(storedValue, ptr); insert(SI); return SI; } StoreStackInst *IRBuilder::createStoreStackInst( Value *storedValue, AllocStackInst *ptr) { auto SI = new StoreStackInst(storedValue, ptr); insert(SI); return SI; } CallInst *IRBuilder::createCallInst( Value *callee, Value *thisValue, ArrayRef<Value *> args) { auto CI = new CallInst(ValueKind::CallInstKind, callee, thisValue, args); insert(CI); return CI; } HBCCallNInst *IRBuilder::createHBCCallNInst( Value *callee, Value *thisValue, ArrayRef<Value *> args) { auto CI = new HBCCallNInst(callee, thisValue, args); insert(CI); return CI; } ConstructInst *IRBuilder::createConstructInst( Value *constructor, ArrayRef<Value *> args) { auto *inst = new ConstructInst(constructor, getLiteralUndefined(), args); insert(inst); return inst; } LoadPropertyInst *IRBuilder::createLoadPropertyInst( Value *object, Value *property) { auto LPI = new LoadPropertyInst(object, property); insert(LPI); return LPI; } TryLoadGlobalPropertyInst *IRBuilder::createTryLoadGlobalPropertyInst( LiteralString *property) { auto *inst = new TryLoadGlobalPropertyInst(getGlobalObject(), property); insert(inst); return inst; } TryLoadGlobalPropertyInst *IRBuilder::createTryLoadGlobalPropertyInst( GlobalObjectProperty *property) { return createTryLoadGlobalPropertyInst(property->getName()); } DeletePropertyInst *IRBuilder::createDeletePropertyInst( Value *object, Value *property) { auto DPI = new DeletePropertyInst(object, property); insert(DPI); return DPI; } StorePropertyInst *IRBuilder::createStorePropertyInst( Value *storedValue, Value *object, Value *property) { auto SPI = new StorePropertyInst(storedValue, object, property); insert(SPI); return SPI; } TryStoreGlobalPropertyInst *IRBuilder::createTryStoreGlobalPropertyInst( Value *storedValue, LiteralString *property) { auto *inst = new TryStoreGlobalPropertyInst(storedValue, getGlobalObject(), property); insert(inst); return inst; } TryStoreGlobalPropertyInst *IRBuilder::createTryStoreGlobalPropertyInst( Value *storedValue, GlobalObjectProperty *property) { return createTryStoreGlobalPropertyInst(storedValue, property->getName()); } StoreOwnPropertyInst *IRBuilder::createStoreOwnPropertyInst( Value *storedValue, Value *object, Value *property, PropEnumerable isEnumerable) { auto SPI = new StoreOwnPropertyInst( storedValue, object, property, getLiteralBool(isEnumerable == PropEnumerable::Yes)); insert(SPI); return SPI; } StoreNewOwnPropertyInst *IRBuilder::createStoreNewOwnPropertyInst( Value *storedValue, Value *object, Literal *property, PropEnumerable isEnumerable) { auto *inst = new StoreNewOwnPropertyInst( storedValue, object, property, getLiteralBool(isEnumerable == PropEnumerable::Yes)); insert(inst); return inst; } StoreGetterSetterInst *IRBuilder::createStoreGetterSetterInst( Value *storedGetter, Value *storedSetter, Value *object, Value *property, PropEnumerable isEnumerable) { auto *SGSI = new StoreGetterSetterInst( storedGetter, storedSetter, object, property, getLiteralBool(isEnumerable == PropEnumerable::Yes)); insert(SGSI); return SGSI; } DeletePropertyInst *IRBuilder::createDeletePropertyInst( Value *object, StringRef property) { Identifier Iden = createIdentifier(property); return createDeletePropertyInst(object, Iden); } LoadPropertyInst *IRBuilder::createLoadPropertyInst( Value *object, StringRef property) { Identifier Iden = createIdentifier(property); return createLoadPropertyInst(object, Iden); } TryLoadGlobalPropertyInst *IRBuilder::createTryLoadGlobalPropertyInst( StringRef property) { return createTryLoadGlobalPropertyInst(createIdentifier(property)); } StorePropertyInst *IRBuilder::createStorePropertyInst( Value *storedValue, Value *object, StringRef property) { Identifier Iden = createIdentifier(property); return createStorePropertyInst(storedValue, object, Iden); } LoadPropertyInst *IRBuilder::createLoadPropertyInst( Value *object, Identifier property) { auto L = getLiteralString(property); return createLoadPropertyInst(object, L); } TryLoadGlobalPropertyInst *IRBuilder::createTryLoadGlobalPropertyInst( Identifier property) { auto *inst = new TryLoadGlobalPropertyInst( getGlobalObject(), getLiteralString(property)); insert(inst); return inst; } DeletePropertyInst *IRBuilder::createDeletePropertyInst( Value *object, Identifier property) { auto L = getLiteralString(property); return createDeletePropertyInst(object, L); } StorePropertyInst *IRBuilder::createStorePropertyInst( Value *storedValue, Value *object, Identifier property) { auto L = getLiteralString(property); return createStorePropertyInst(storedValue, object, L); } TryStoreGlobalPropertyInst *IRBuilder::createTryStoreGlobalPropertyInst( Value *storedValue, Identifier property) { auto *inst = new TryStoreGlobalPropertyInst( storedValue, getGlobalObject(), getLiteralString(property)); insert(inst); return inst; } AllocObjectInst *IRBuilder::createAllocObjectInst( uint32_t size, Value *parent) { auto AOI = new AllocObjectInst( M->getLiteralNumber(size), parent ? parent : getEmptySentinel()); insert(AOI); return AOI; } AllocArrayInst *IRBuilder::createAllocArrayInst( LiteralNumber *sizeHint, AllocArrayInst::ArrayValueList val_list) { auto AAI = new AllocArrayInst(val_list, sizeHint); insert(AAI); return AAI; } AllocArrayInst *IRBuilder::createAllocArrayInst( AllocArrayInst::ArrayValueList val_list, unsigned sizeHint) { return createAllocArrayInst(this->getLiteralNumber(sizeHint), val_list); } CreateArgumentsInst *IRBuilder::createCreateArgumentsInst() { auto CAI = new CreateArgumentsInst(); insert(CAI); return CAI; } GetNewTargetInst *IRBuilder::createGetNewTargetInst() { auto *inst = new GetNewTargetInst(); insert(inst); return inst; } ThrowIfEmptyInst *IRBuilder::createThrowIfEmptyInst(Value *checkedValue) { auto *inst = new ThrowIfEmptyInst(checkedValue); insert(inst); return inst; } HBCGetGlobalObjectInst *IRBuilder::createHBCGetGlobalObjectInst() { auto inst = new HBCGetGlobalObjectInst(); insert(inst); return inst; } CreateRegExpInst *IRBuilder::createRegExpInst( Identifier pattern, Identifier flags) { auto res = new CreateRegExpInst(getLiteralString(pattern), getLiteralString(flags)); insert(res); return res; } UnaryOperatorInst *IRBuilder::createUnaryOperatorInst( Value *value, UnaryOperatorInst::OpKind opKind) { auto UOI = new UnaryOperatorInst(value, opKind); insert(UOI); return UOI; } BinaryOperatorInst *IRBuilder::createBinaryOperatorInst( Value *left, Value *right, BinaryOperatorInst::OpKind opKind) { auto BOI = new BinaryOperatorInst(left, right, opKind); insert(BOI); return BOI; } SwitchInst *IRBuilder::createSwitchInst( Value *input, BasicBlock *defaultBlock, const SwitchInst::ValueListType &values, const SwitchInst::BasicBlockListType &blocks) { auto SI = new SwitchInst(input, defaultBlock, values, blocks); insert(SI); return SI; } PhiInst *IRBuilder::createPhiInst() { PhiInst::ValueListType values; PhiInst::BasicBlockListType blocks; return createPhiInst(values, blocks); } PhiInst *IRBuilder::createPhiInst( const PhiInst::ValueListType &values, const PhiInst::BasicBlockListType &blocks) { auto PI = new PhiInst(values, blocks); insert(PI); return PI; } GetPNamesInst *IRBuilder::createGetPNamesInst( Value *iteratorAddr, Value *baseAddr, Value *indexAddr, Value *sizeAddr, BasicBlock *onEmpty, BasicBlock *onSome) { auto GP = new GetPNamesInst( getInsertionBlock(), iteratorAddr, baseAddr, indexAddr, sizeAddr, onEmpty, onSome); insert(GP); return GP; } GetNextPNameInst *IRBuilder::createGetNextPNameInst( Value *propertyAddr, Value *baseAddr, Value *indexAddr, Value *sizeAddr, Value *iteratorAddr, BasicBlock *onLast, BasicBlock *onSome) { auto GNP = new GetNextPNameInst( getInsertionBlock(), propertyAddr, baseAddr, indexAddr, sizeAddr, iteratorAddr, onLast, onSome); insert(GNP); return GNP; } MovInst *IRBuilder::createMovInst(Value *input) { auto MI = new MovInst(input); insert(MI); return MI; } ImplicitMovInst *IRBuilder::createImplicitMovInst(Value *input) { auto IMI = new ImplicitMovInst(input); insert(IMI); return IMI; } CoerceThisNSInst *IRBuilder::createCoerceThisNSInst(Value *input) { auto *inst = new CoerceThisNSInst(input); insert(inst); return inst; } DebuggerInst *IRBuilder::createDebuggerInst() { auto DI = new DebuggerInst(); insert(DI); return DI; } SaveAndYieldInst *IRBuilder::createSaveAndYieldInst( Value *result, BasicBlock *nextBlock) { auto *I = new SaveAndYieldInst(result, nextBlock); insert(I); return I; } CreateGeneratorInst *IRBuilder::createCreateGeneratorInst(Function *innerFn) { auto *I = new CreateGeneratorInst(innerFn); insert(I); return I; } StartGeneratorInst *IRBuilder::createStartGeneratorInst() { auto *I = new StartGeneratorInst(); insert(I); return I; } ResumeGeneratorInst *IRBuilder::createResumeGeneratorInst(Value *isReturn) { auto *I = new ResumeGeneratorInst(isReturn); insert(I); return I; } HBCResolveEnvironment *IRBuilder::createHBCResolveEnvironment( VariableScope *scope) { auto RSC = new HBCResolveEnvironment(scope); insert(RSC); return RSC; } HBCStoreToEnvironmentInst *IRBuilder::createHBCStoreToEnvironmentInst( Value *env, Value *toPut, Variable *var) { auto PSI = new HBCStoreToEnvironmentInst(env, toPut, var); insert(PSI); return PSI; } HBCLoadFromEnvironmentInst *IRBuilder::createHBCLoadFromEnvironmentInst( Value *env, Variable *var) { auto GSI = new HBCLoadFromEnvironmentInst(env, var); insert(GSI); return GSI; } SwitchImmInst *IRBuilder::createSwitchImmInst( Value *input, BasicBlock *defaultBlock, LiteralNumber *minValue, LiteralNumber *size, const SwitchImmInst::ValueListType &values, const SwitchImmInst::BasicBlockListType &blocks) { auto inst = new SwitchImmInst(input, defaultBlock, minValue, size, values, blocks); insert(inst); return inst; } DirectEvalInst *IRBuilder::createDirectEvalInst(Value *operand) { auto *inst = new DirectEvalInst(operand); insert(inst); return inst; } HBCLoadConstInst *IRBuilder::createHBCLoadConstInst(Literal *value) { auto inst = new HBCLoadConstInst(value); insert(inst); return inst; } HBCLoadParamInst *IRBuilder::createHBCLoadParamInst(LiteralNumber *value) { auto inst = new HBCLoadParamInst(value); insert(inst); return inst; } HBCCreateEnvironmentInst *IRBuilder::createHBCCreateEnvironmentInst() { auto inst = new HBCCreateEnvironmentInst(); insert(inst); return inst; } HBCGetThisNSInst *IRBuilder::createHBCGetThisNSInst() { auto inst = new HBCGetThisNSInst(); insert(inst); return inst; } HBCGetArgumentsPropByValInst *IRBuilder::createHBCGetArgumentsPropByValInst( Value *index, AllocStackInst *lazyReg) { auto inst = new HBCGetArgumentsPropByValInst(index, lazyReg); insert(inst); return inst; } HBCGetArgumentsLengthInst *IRBuilder::createHBCGetArgumentsLengthInst( AllocStackInst *lazyReg) { auto inst = new HBCGetArgumentsLengthInst(lazyReg); insert(inst); return inst; } HBCReifyArgumentsInst *IRBuilder::createHBCReifyArgumentsInst( AllocStackInst *lazyReg) { auto inst = new HBCReifyArgumentsInst(lazyReg); insert(inst); return inst; } HBCCreateThisInst *IRBuilder::createHBCCreateThisInst( Value *prototype, Value *closure) { auto inst = new HBCCreateThisInst(prototype, closure); insert(inst); return inst; } HBCConstructInst *IRBuilder::createHBCConstructInst( Value *closure, Value *thisValue, ArrayRef<Value *> arguments) { auto inst = new HBCConstructInst(closure, thisValue, arguments); insert(inst); return inst; } HBCGetConstructedObjectInst *IRBuilder::createHBCGetConstructedObjectInst( HBCCreateThisInst *thisValue, HBCConstructInst *constructorReturnValue) { auto inst = new HBCGetConstructedObjectInst(thisValue, constructorReturnValue); insert(inst); return inst; } HBCProfilePointInst *IRBuilder::createHBCProfilePointInst(uint16_t pointIndex) { auto inst = new HBCProfilePointInst(pointIndex); insert(inst); return inst; } CallBuiltinInst *IRBuilder::createCallBuiltinInst( BuiltinMethod::Enum builtinIndex, ArrayRef<Value *> arguments) { auto *inst = new CallBuiltinInst( getLiteralNumber(builtinIndex), getLiteralUndefined(), arguments); insert(inst); return inst; } GetBuiltinClosureInst *IRBuilder::createGetBuiltinClosureInst( BuiltinMethod::Enum builtinIndex) { auto *inst = new GetBuiltinClosureInst(getLiteralNumber(builtinIndex)); insert(inst); return inst; } #ifdef HERMES_RUN_WASM CallIntrinsicInst *IRBuilder::createCallIntrinsicInst( WasmIntrinsics::Enum intrinsicsIndex, ArrayRef<Value *> arguments) { auto *inst = new CallIntrinsicInst(getLiteralNumber(intrinsicsIndex), arguments); insert(inst); return inst; } #endif HBCCallDirectInst *IRBuilder::createHBCCallDirectInst( Function *callee, Value *thisValue, ArrayRef<Value *> arguments) { auto *inst = new HBCCallDirectInst(callee, thisValue, arguments); insert(inst); return inst; } HBCCreateFunctionInst *IRBuilder::createHBCCreateFunctionInst( Function *function, Value *env) { auto inst = new HBCCreateFunctionInst(function, env); insert(inst); return inst; } HBCSpillMovInst *IRBuilder::createHBCSpillMovInst(Instruction *value) { auto *inst = new HBCSpillMovInst(value); insert(inst); return inst; } HBCCreateGeneratorInst *IRBuilder::createHBCCreateGeneratorInst( Function *function, Value *env) { auto *inst = new HBCCreateGeneratorInst(function, env); insert(inst); return inst; } HBCAllocObjectFromBufferInst *IRBuilder::createHBCAllocObjectFromBufferInst( HBCAllocObjectFromBufferInst::ObjectPropertyMap prop_map, uint32_t size) { auto *inst = new HBCAllocObjectFromBufferInst(M->getLiteralNumber(size), prop_map); insert(inst); return inst; } AllocObjectLiteralInst *IRBuilder::createAllocObjectLiteralInst( const AllocObjectLiteralInst::ObjectPropertyMap &propMap) { auto *inst = new AllocObjectLiteralInst(propMap); insert(inst); return inst; } CompareBranchInst *IRBuilder::createCompareBranchInst( Value *left, Value *right, BinaryOperatorInst::OpKind opKind, BasicBlock *trueBlock, BasicBlock *falseBlock) { auto *inst = new CompareBranchInst(left, right, opKind, trueBlock, falseBlock); insert(inst); return inst; } IteratorBeginInst *IRBuilder::createIteratorBeginInst( AllocStackInst *sourceOrNext) { auto *I = new IteratorBeginInst(sourceOrNext); insert(I); return I; } IteratorNextInst *IRBuilder::createIteratorNextInst( AllocStackInst *iterator, AllocStackInst *sourceOrNext) { auto *I = new IteratorNextInst(iterator, sourceOrNext); insert(I); return I; } IteratorCloseInst *IRBuilder::createIteratorCloseInst( AllocStackInst *iterator, bool ignoreInnerException) { auto *I = new IteratorCloseInst(iterator, getLiteralBool(ignoreInnerException)); insert(I); return I; } UnreachableInst *IRBuilder::createUnreachableInst() { auto *I = new UnreachableInst(); insert(I); return I; } inline void IRBuilder::justInsert(Instruction *Inst) { assert(!Inst->getParent() && "Instr that's already inserted elsewhere"); Inst->setParent(Block); Block->getInstList().insert(InsertionPoint, Inst); } void IRBuilder::insert(Instruction *Inst) { // Set the statement of the new instruction based on the current function's // statement counter. OptValue<uint32_t> statementOpt = getFunction()->getStatementCount(); uint32_t statement; if (LLVM_LIKELY(statementOpt.hasValue())) { statement = *statementOpt; } else { // If we've cleared the statement count, // then just set the new instruction's statement to the statement of the // instruction we're inserting at (0 if it doesn't exist). statement = InsertionPoint != Block->getInstList().end() ? InsertionPoint->getStatementIndex() : 0; } Inst->setStatementIndex(statement); Inst->setLocation(Location); return justInsert(Inst); } void IRBuilder::setInsertionBlock(BasicBlock *BB) { if (BB) { InsertionPoint = BB->end(); Block = BB; } else { InsertionPoint = BasicBlock::iterator(nullptr); Block = nullptr; } } BasicBlock *IRBuilder::getInsertionBlock() { return Block; } void IRBuilder::setInsertionPointAfter(Instruction *IP) { InsertionPoint = IP->getIterator(); InsertionPoint++; Block = IP->getParent(); } void IRBuilder::setInsertionPoint(Instruction *IP) { InsertionPoint = IP->getIterator(); Block = IP->getParent(); } bool IRBuilder::isInsertionPointValid() { return InsertionPoint.getNodePtr(); } void IRBuilder::resetInsertionPoint() { InsertionPoint = BasicBlock::iterator(); Block = nullptr; } void IRBuilder::transferInstructionToCurrentBlock(Instruction *inst) { auto *oldBlock = inst->getParent(); inst->removeFromParent(); inst->setParent(Block); Block->getInstList().insert(InsertionPoint, inst); if (oldBlock == Block || !llvh::isa<TerminatorInst>(inst)) return; // If we moved the terminator, we want to update all successors' phi-nodes. for (auto *use : oldBlock->getUsers()) { auto *phi = llvh::dyn_cast<PhiInst>(use); if (!phi) continue; for (unsigned i = 0, e = phi->getNumOperands(); i != e; ++i) { if (phi->getOperand(i) == oldBlock) phi->setOperand(Block, i); } } } Instruction *IRBuilder::cloneInst( const Instruction *source, llvh::ArrayRef<Value *> operands) { Instruction *inst; switch (source->getKind()) { #define INCLUDE_ALL_INSTRS #define DEF_VALUE(name, parent) \ case ValueKind::name##Kind: \ inst = new name(cast<name>(source), operands); \ break; #include "hermes/IR/Instrs.def" #undef INCLUDE_ALL_INSTRS default: llvm_unreachable("invalid kind"); } justInsert(inst); return inst; }