mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
1520 lines
65 KiB
C++
1520 lines
65 KiB
C++
//===--- SILBuilder.h - Class for creating SIL Constructs -------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_SIL_SILBUILDER_H
|
|
#define SWIFT_SIL_SILBUILDER_H
|
|
|
|
#include "swift/SIL/SILDebugScope.h"
|
|
#include "swift/SIL/SILFunction.h"
|
|
#include "swift/SIL/SILModule.h"
|
|
#include "llvm/ADT/PointerUnion.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
namespace swift {
|
|
|
|
using Atomicity = RefCountingInst::Atomicity;
|
|
|
|
class SILDebugScope;
|
|
|
|
class SILBuilder {
|
|
friend class SILBuilderWithScope;
|
|
|
|
SILFunction &F;
|
|
/// If this is non-null, the instruction is inserted in the specified
|
|
/// basic block, at the specified InsertPt. If null, created instructions
|
|
/// are not auto-inserted.
|
|
SILBasicBlock *BB;
|
|
SILBasicBlock::iterator InsertPt;
|
|
const SILDebugScope *CurDebugScope = nullptr;
|
|
|
|
/// If this pointer is non-null, then any inserted instruction is
|
|
/// recorded in this list.
|
|
SmallVectorImpl<SILInstruction *> *InsertedInstrs = nullptr;
|
|
|
|
public:
|
|
SILBuilder(SILFunction &F) : F(F), BB(0) {}
|
|
|
|
SILBuilder(SILFunction &F, SmallVectorImpl<SILInstruction *> *InsertedInstrs)
|
|
: F(F), BB(0), InsertedInstrs(InsertedInstrs) {}
|
|
|
|
explicit SILBuilder(SILInstruction *I,
|
|
SmallVectorImpl<SILInstruction *> *InsertedInstrs = 0)
|
|
: F(*I->getFunction()), InsertedInstrs(InsertedInstrs) {
|
|
setInsertionPoint(I);
|
|
}
|
|
|
|
explicit SILBuilder(SILBasicBlock::iterator I,
|
|
SmallVectorImpl<SILInstruction *> *InsertedInstrs = 0)
|
|
: SILBuilder(&*I, InsertedInstrs) {}
|
|
|
|
explicit SILBuilder(SILBasicBlock *BB,
|
|
SmallVectorImpl<SILInstruction *> *InsertedInstrs = 0)
|
|
: F(*BB->getParent()), InsertedInstrs(InsertedInstrs) {
|
|
setInsertionPoint(BB);
|
|
}
|
|
|
|
SILBuilder(SILBasicBlock *BB, SILBasicBlock::iterator InsertPt,
|
|
SmallVectorImpl<SILInstruction *> *InsertedInstrs = 0)
|
|
: F(*BB->getParent()), InsertedInstrs(InsertedInstrs) {
|
|
setInsertionPoint(BB, InsertPt);
|
|
}
|
|
|
|
SILFunction &getFunction() const { return F; }
|
|
SILModule &getModule() const { return F.getModule(); }
|
|
ASTContext &getASTContext() const { return F.getASTContext(); }
|
|
const Lowering::TypeLowering &getTypeLowering(SILType T) const {
|
|
return F.getModule().getTypeLowering(T);
|
|
}
|
|
|
|
void setCurrentDebugScope(const SILDebugScope *DS) { CurDebugScope = DS; }
|
|
const SILDebugScope *getCurrentDebugScope() const { return CurDebugScope; }
|
|
|
|
/// Convenience function for building a SILDebugLocation.
|
|
SILDebugLocation getSILDebugLocation(SILLocation Loc) {
|
|
// FIXME: Audit all uses and enable this assertion.
|
|
// assert(getCurrentDebugScope() && "no debug scope");
|
|
auto Scope = getCurrentDebugScope();
|
|
return SILDebugLocation(Loc, Scope ? Scope : getFunction().getDebugScope());
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Insertion Point Management
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
bool hasValidInsertionPoint() const { return BB != nullptr; }
|
|
SILBasicBlock *getInsertionBB() { return BB; }
|
|
SILBasicBlock::iterator getInsertionPoint() { return InsertPt; }
|
|
|
|
/// insertingAtEndOfBlock - Return true if the insertion point is at the end
|
|
/// of the current basic block. False if we're inserting before an existing
|
|
/// instruction.
|
|
bool insertingAtEndOfBlock() const {
|
|
assert(hasValidInsertionPoint() &&
|
|
"Must have insertion point to ask about it");
|
|
return InsertPt == BB->end();
|
|
}
|
|
|
|
/// clearInsertionPoint - Clear the insertion point: created instructions will
|
|
/// not be inserted into a block.
|
|
void clearInsertionPoint() { BB = nullptr; }
|
|
|
|
/// setInsertionPoint - Set the insertion point.
|
|
void setInsertionPoint(SILBasicBlock *BB, SILBasicBlock::iterator InsertPt) {
|
|
this->BB = BB;
|
|
this->InsertPt = InsertPt;
|
|
}
|
|
|
|
/// setInsertionPoint - Set the insertion point to insert before the specified
|
|
/// instruction.
|
|
void setInsertionPoint(SILInstruction *I) {
|
|
setInsertionPoint(I->getParent(), I->getIterator());
|
|
}
|
|
|
|
/// setInsertionPoint - Set the insertion point to insert before the specified
|
|
/// instruction.
|
|
void setInsertionPoint(SILBasicBlock::iterator IIIter) {
|
|
setInsertionPoint(IIIter->getParent(), IIIter);
|
|
}
|
|
|
|
/// setInsertionPoint - Set the insertion point to insert at the end of the
|
|
/// specified block.
|
|
void setInsertionPoint(SILBasicBlock *BB) {
|
|
setInsertionPoint(BB, BB->end());
|
|
}
|
|
|
|
/// setInsertionPoint - Set the insertion point to insert at the end of the
|
|
/// specified block.
|
|
void setInsertionPoint(SILFunction::iterator BBIter) {
|
|
setInsertionPoint(&*BBIter);
|
|
}
|
|
|
|
SILBasicBlock *getInsertionPoint() const { return BB; }
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Instruction Tracking
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
/// Clients of SILBuilder who want to know about any newly created
|
|
/// instructions can install a SmallVector into the builder to collect them.
|
|
void setTrackingList(SmallVectorImpl<SILInstruction *> *II) {
|
|
InsertedInstrs = II;
|
|
}
|
|
|
|
SmallVectorImpl<SILInstruction *> *getTrackingList() {
|
|
return InsertedInstrs;
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Type remapping
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
static SILType getPartialApplyResultType(SILType Ty, unsigned ArgCount,
|
|
SILModule &M,
|
|
ArrayRef<Substitution> subs);
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// CFG Manipulation
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
/// moveBlockTo - Move a block to immediately before the given iterator.
|
|
void moveBlockTo(SILBasicBlock *BB, SILFunction::iterator IP) {
|
|
assert(SILFunction::iterator(BB) != IP && "moving block before itself?");
|
|
SILFunction *F = BB->getParent();
|
|
auto &Blocks = F->getBlocks();
|
|
Blocks.remove(BB);
|
|
Blocks.insert(IP, BB);
|
|
}
|
|
|
|
/// moveBlockTo - Move \p BB to immediately before \p Before.
|
|
void moveBlockTo(SILBasicBlock *BB, SILBasicBlock *Before) {
|
|
moveBlockTo(BB, Before->getIterator());
|
|
}
|
|
|
|
/// moveBlockToEnd - Reorder a block to the end of its containing function.
|
|
void moveBlockToEnd(SILBasicBlock *BB) {
|
|
moveBlockTo(BB, BB->getParent()->end());
|
|
}
|
|
|
|
/// \brief Move the insertion point to the end of the given block.
|
|
///
|
|
/// Assumes that no insertion point is currently active.
|
|
void emitBlock(SILBasicBlock *BB) {
|
|
assert(!hasValidInsertionPoint());
|
|
setInsertionPoint(BB);
|
|
}
|
|
|
|
/// \brief Branch to the given block if there's an active insertion point,
|
|
/// then move the insertion point to the end of that block.
|
|
void emitBlock(SILBasicBlock *BB, SILLocation BranchLoc);
|
|
|
|
/// splitBlockForFallthrough - Prepare for the insertion of a terminator. If
|
|
/// the builder's insertion point is at the end of the current block (as when
|
|
/// SILGen is creating the initial code for a function), just create and
|
|
/// return a new basic block that will be later used for the continue point.
|
|
///
|
|
/// If the insertion point is valid (i.e., pointing to an existing
|
|
/// instruction) then split the block at that instruction and return the
|
|
/// continuation block.
|
|
SILBasicBlock *splitBlockForFallthrough();
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// SILInstruction Creation Methods
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
AllocStackInst *createAllocStack(SILLocation Loc, SILType elementType,
|
|
SILDebugVariable Var = SILDebugVariable()) {
|
|
Loc.markAsPrologue();
|
|
return insert(AllocStackInst::create(getSILDebugLocation(Loc),
|
|
elementType, F, Var));
|
|
}
|
|
|
|
AllocRefInst *createAllocRef(SILLocation Loc, SILType elementType, bool objc,
|
|
bool canAllocOnStack) {
|
|
// AllocRefInsts expand to function calls and can therefore not be
|
|
// counted towards the function prologue.
|
|
assert(!Loc.isInPrologue());
|
|
return insert(new (F.getModule()) AllocRefInst(
|
|
getSILDebugLocation(Loc), elementType, F, objc, canAllocOnStack));
|
|
}
|
|
|
|
AllocRefDynamicInst *createAllocRefDynamic(SILLocation Loc, SILValue operand,
|
|
SILType type, bool objc) {
|
|
// AllocRefDynamicInsts expand to function calls and can therefore
|
|
// not be counted towards the function prologue.
|
|
assert(!Loc.isInPrologue());
|
|
return insert(new (F.getModule()) AllocRefDynamicInst(
|
|
getSILDebugLocation(Loc), operand, type, objc));
|
|
}
|
|
|
|
AllocValueBufferInst *
|
|
createAllocValueBuffer(SILLocation Loc, SILType valueType, SILValue operand) {
|
|
return insert(new (F.getModule()) AllocValueBufferInst(
|
|
getSILDebugLocation(Loc), valueType, operand));
|
|
}
|
|
|
|
AllocBoxInst *createAllocBox(SILLocation Loc, SILType ElementType,
|
|
SILDebugVariable Var = SILDebugVariable()) {
|
|
Loc.markAsPrologue();
|
|
return insert(
|
|
AllocBoxInst::create(getSILDebugLocation(Loc), ElementType, F, Var));
|
|
}
|
|
|
|
AllocExistentialBoxInst *
|
|
createAllocExistentialBox(SILLocation Loc, SILType ExistentialType,
|
|
CanType ConcreteType,
|
|
ArrayRef<ProtocolConformanceRef> Conformances) {
|
|
return insert(AllocExistentialBoxInst::create(
|
|
getSILDebugLocation(Loc), ExistentialType, ConcreteType,
|
|
Conformances, &F));
|
|
}
|
|
|
|
ApplyInst *createApply(SILLocation Loc, SILValue Fn, SILType SubstFnTy,
|
|
SILType Result, ArrayRef<Substitution> Subs,
|
|
ArrayRef<SILValue> Args, bool isNonThrowing) {
|
|
return insert(ApplyInst::create(getSILDebugLocation(Loc), Fn, SubstFnTy,
|
|
Result, Subs, Args, isNonThrowing, F));
|
|
}
|
|
|
|
ApplyInst *createApply(SILLocation Loc, SILValue Fn, ArrayRef<SILValue> Args,
|
|
bool isNonThrowing) {
|
|
auto FnTy = Fn->getType();
|
|
return createApply(Loc, Fn, FnTy,
|
|
FnTy.castTo<SILFunctionType>()->getSILResult(),
|
|
ArrayRef<Substitution>(), Args, isNonThrowing);
|
|
}
|
|
|
|
TryApplyInst *createTryApply(SILLocation Loc, SILValue fn, SILType substFnTy,
|
|
ArrayRef<Substitution> subs,
|
|
ArrayRef<SILValue> args, SILBasicBlock *normalBB,
|
|
SILBasicBlock *errorBB) {
|
|
return insertTerminator(TryApplyInst::create(getSILDebugLocation(Loc),
|
|
fn, substFnTy, subs, args,
|
|
normalBB, errorBB, F));
|
|
}
|
|
|
|
PartialApplyInst *createPartialApply(SILLocation Loc, SILValue Fn,
|
|
SILType SubstFnTy,
|
|
ArrayRef<Substitution> Subs,
|
|
ArrayRef<SILValue> Args,
|
|
SILType ClosureTy) {
|
|
return insert(PartialApplyInst::create(
|
|
getSILDebugLocation(Loc), Fn, SubstFnTy, Subs, Args, ClosureTy, F));
|
|
}
|
|
|
|
BuiltinInst *createBuiltin(SILLocation Loc, Identifier Name, SILType ResultTy,
|
|
ArrayRef<Substitution> Subs,
|
|
ArrayRef<SILValue> Args) {
|
|
return insert(BuiltinInst::create(getSILDebugLocation(Loc), Name,
|
|
ResultTy, Subs, Args, F));
|
|
}
|
|
|
|
/// Create a binary function with the signature: OpdTy, OpdTy -> ResultTy.
|
|
BuiltinInst *createBuiltinBinaryFunction(SILLocation Loc, StringRef Name,
|
|
SILType OpdTy, SILType ResultTy,
|
|
ArrayRef<SILValue> Args) {
|
|
auto &C = getASTContext();
|
|
|
|
llvm::SmallString<16> NameStr = Name;
|
|
if (auto BuiltinIntTy =
|
|
dyn_cast<BuiltinIntegerType>(OpdTy.getSwiftRValueType())) {
|
|
if (BuiltinIntTy == BuiltinIntegerType::getWordType(getASTContext())) {
|
|
NameStr += "_Word";
|
|
} else {
|
|
unsigned NumBits = BuiltinIntTy->getWidth().getFixedWidth();
|
|
NameStr += "_Int" + llvm::utostr(NumBits);
|
|
}
|
|
} else {
|
|
assert(OpdTy.getSwiftRValueType() == C.TheRawPointerType);
|
|
NameStr += "_RawPointer";
|
|
}
|
|
auto Ident = C.getIdentifier(NameStr);
|
|
return insert(BuiltinInst::create(getSILDebugLocation(Loc), Ident,
|
|
ResultTy, {}, Args, F));
|
|
}
|
|
|
|
/// Create a binary function with the signature:
|
|
/// OpdTy, OpdTy, Int1 -> (OpdTy, Int1)
|
|
BuiltinInst *
|
|
createBuiltinBinaryFunctionWithOverflow(SILLocation Loc, StringRef Name,
|
|
ArrayRef<SILValue> Args) {
|
|
assert(Args.size() == 3 && "Need three arguments");
|
|
assert(Args[0]->getType() == Args[1]->getType() &&
|
|
"Binary operands must match");
|
|
assert(Args[2]->getType().is<BuiltinIntegerType>() &&
|
|
Args[2]->getType().getSwiftRValueType()->isBuiltinIntegerType(1) &&
|
|
"Must have a third Int1 operand");
|
|
|
|
SILType OpdTy = Args[0]->getType();
|
|
SILType Int1Ty = Args[2]->getType();
|
|
|
|
TupleTypeElt ResultElts[] = {OpdTy.getSwiftRValueType(),
|
|
Int1Ty.getSwiftRValueType()};
|
|
Type ResultTy = TupleType::get(ResultElts, getASTContext());
|
|
SILType SILResultTy =
|
|
SILType::getPrimitiveObjectType(ResultTy->getCanonicalType());
|
|
|
|
return createBuiltinBinaryFunction(Loc, Name, OpdTy, SILResultTy, Args);
|
|
}
|
|
|
|
FunctionRefInst *createFunctionRef(SILLocation Loc, SILFunction *f) {
|
|
return insert(new (F.getModule())
|
|
FunctionRefInst(getSILDebugLocation(Loc), f));
|
|
}
|
|
AllocGlobalInst *createAllocGlobal(SILLocation Loc, SILGlobalVariable *g) {
|
|
return insert(new (F.getModule())
|
|
AllocGlobalInst(getSILDebugLocation(Loc), g));
|
|
}
|
|
GlobalAddrInst *createGlobalAddr(SILLocation Loc, SILGlobalVariable *g) {
|
|
return insert(new (F.getModule())
|
|
GlobalAddrInst(getSILDebugLocation(Loc), g));
|
|
}
|
|
|
|
IntegerLiteralInst *createIntegerLiteral(IntegerLiteralExpr *E) {
|
|
return insert(IntegerLiteralInst::create(E, getSILDebugLocation(E), F));
|
|
}
|
|
IntegerLiteralInst *createIntegerLiteral(SILLocation Loc, SILType Ty,
|
|
intmax_t Value) {
|
|
return insert(
|
|
IntegerLiteralInst::create(getSILDebugLocation(Loc), Ty, Value, F));
|
|
}
|
|
IntegerLiteralInst *createIntegerLiteral(SILLocation Loc, SILType Ty,
|
|
const APInt &Value) {
|
|
return insert(
|
|
IntegerLiteralInst::create(getSILDebugLocation(Loc), Ty, Value, F));
|
|
}
|
|
|
|
FloatLiteralInst *createFloatLiteral(FloatLiteralExpr *E) {
|
|
return insert(FloatLiteralInst::create(E, getSILDebugLocation(E), F));
|
|
}
|
|
FloatLiteralInst *createFloatLiteral(SILLocation Loc, SILType Ty,
|
|
const APFloat &Value) {
|
|
return insert(
|
|
FloatLiteralInst::create(getSILDebugLocation(Loc), Ty, Value, F));
|
|
}
|
|
|
|
StringLiteralInst *createStringLiteral(SILLocation Loc, StringRef text,
|
|
StringLiteralInst::Encoding encoding) {
|
|
return insert(StringLiteralInst::create(getSILDebugLocation(Loc), text,
|
|
encoding, F));
|
|
}
|
|
|
|
StringLiteralInst *createStringLiteral(SILLocation Loc, const Twine &text,
|
|
StringLiteralInst::Encoding encoding) {
|
|
SmallVector<char, 256> Out;
|
|
return insert(StringLiteralInst::create(
|
|
getSILDebugLocation(Loc), text.toStringRef(Out), encoding, F));
|
|
}
|
|
|
|
LoadInst *createLoad(SILLocation Loc, SILValue LV) {
|
|
return insert(new (F.getModule())
|
|
LoadInst(getSILDebugLocation(Loc), LV));
|
|
}
|
|
|
|
StoreInst *createStore(SILLocation Loc, SILValue Src, SILValue DestAddr) {
|
|
return insert(new (F.getModule())
|
|
StoreInst(getSILDebugLocation(Loc), Src, DestAddr));
|
|
}
|
|
AssignInst *createAssign(SILLocation Loc, SILValue Src, SILValue DestAddr) {
|
|
return insert(new (F.getModule())
|
|
AssignInst(getSILDebugLocation(Loc), Src, DestAddr));
|
|
}
|
|
|
|
MarkUninitializedInst *
|
|
createMarkUninitialized(SILLocation Loc, SILValue src,
|
|
MarkUninitializedInst::Kind k) {
|
|
return insert(new (F.getModule()) MarkUninitializedInst(
|
|
getSILDebugLocation(Loc), src, k));
|
|
}
|
|
MarkUninitializedInst *createMarkUninitializedVar(SILLocation Loc,
|
|
SILValue src) {
|
|
return createMarkUninitialized(Loc, src, MarkUninitializedInst::Var);
|
|
}
|
|
MarkUninitializedInst *createMarkUninitializedRootSelf(SILLocation Loc,
|
|
SILValue src) {
|
|
return createMarkUninitialized(Loc, src, MarkUninitializedInst::RootSelf);
|
|
}
|
|
|
|
MarkUninitializedBehaviorInst *
|
|
createMarkUninitializedBehavior(SILLocation Loc,
|
|
SILValue initStorageFunc,
|
|
ArrayRef<Substitution> initStorageSubs,
|
|
SILValue storage,
|
|
SILValue setterFunc,
|
|
ArrayRef<Substitution> setterSubs,
|
|
SILValue self,
|
|
SILType ty) {
|
|
return insert(MarkUninitializedBehaviorInst::create(F.getModule(),
|
|
getSILDebugLocation(Loc),
|
|
initStorageFunc, initStorageSubs, storage,
|
|
setterFunc, setterSubs, self, ty));
|
|
}
|
|
|
|
MarkFunctionEscapeInst *createMarkFunctionEscape(SILLocation Loc,
|
|
ArrayRef<SILValue> vars) {
|
|
return insert(
|
|
MarkFunctionEscapeInst::create(getSILDebugLocation(Loc), vars, F));
|
|
}
|
|
|
|
DebugValueInst *createDebugValue(SILLocation Loc, SILValue src,
|
|
SILDebugVariable Var = SILDebugVariable()) {
|
|
return insert(DebugValueInst::create(getSILDebugLocation(Loc), src,
|
|
F.getModule(), Var));
|
|
}
|
|
DebugValueAddrInst *
|
|
createDebugValueAddr(SILLocation Loc, SILValue src,
|
|
SILDebugVariable Var = SILDebugVariable()) {
|
|
return insert(DebugValueAddrInst::create(getSILDebugLocation(Loc), src,
|
|
F.getModule(), Var));
|
|
}
|
|
|
|
LoadWeakInst *createLoadWeak(SILLocation Loc, SILValue src, IsTake_t isTake) {
|
|
return insert(new (F.getModule())
|
|
LoadWeakInst(getSILDebugLocation(Loc), src, isTake));
|
|
}
|
|
|
|
StoreWeakInst *createStoreWeak(SILLocation Loc, SILValue value, SILValue dest,
|
|
IsInitialization_t isInit) {
|
|
return insert(new (F.getModule()) StoreWeakInst(getSILDebugLocation(Loc),
|
|
value, dest, isInit));
|
|
}
|
|
|
|
LoadUnownedInst *createLoadUnowned(SILLocation loc, SILValue src,
|
|
IsTake_t isTake) {
|
|
return insert(new (F.getModule())
|
|
LoadUnownedInst(getSILDebugLocation(loc), src, isTake));
|
|
}
|
|
|
|
StoreUnownedInst *createStoreUnowned(SILLocation loc, SILValue value,
|
|
SILValue dest,
|
|
IsInitialization_t isInit) {
|
|
return insert(new (F.getModule())
|
|
StoreUnownedInst(getSILDebugLocation(loc),
|
|
value, dest, isInit));
|
|
}
|
|
|
|
CopyAddrInst *createCopyAddr(SILLocation Loc, SILValue srcAddr,
|
|
SILValue destAddr, IsTake_t isTake,
|
|
IsInitialization_t isInitialize) {
|
|
assert(srcAddr->getType() == destAddr->getType());
|
|
return insert(new (F.getModule()) CopyAddrInst(
|
|
getSILDebugLocation(Loc), srcAddr, destAddr, isTake, isInitialize));
|
|
}
|
|
|
|
ConvertFunctionInst *createConvertFunction(SILLocation Loc, SILValue Op,
|
|
SILType Ty) {
|
|
return insert(new (F.getModule())
|
|
ConvertFunctionInst(getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
ThinFunctionToPointerInst *
|
|
createThinFunctionToPointer(SILLocation Loc, SILValue Op, SILType Ty) {
|
|
return insert(new (F.getModule()) ThinFunctionToPointerInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
PointerToThinFunctionInst *
|
|
createPointerToThinFunction(SILLocation Loc, SILValue Op, SILType Ty) {
|
|
return insert(new (F.getModule()) PointerToThinFunctionInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
UpcastInst *createUpcast(SILLocation Loc, SILValue Op, SILType Ty) {
|
|
return insert(new (F.getModule())
|
|
UpcastInst(getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
AddressToPointerInst *createAddressToPointer(SILLocation Loc, SILValue Op,
|
|
SILType Ty) {
|
|
return insert(new (F.getModule()) AddressToPointerInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
PointerToAddressInst *createPointerToAddress(SILLocation Loc, SILValue Op,
|
|
SILType Ty) {
|
|
return insert(new (F.getModule()) PointerToAddressInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
UncheckedRefCastInst *createUncheckedRefCast(SILLocation Loc, SILValue Op,
|
|
SILType Ty) {
|
|
return insert(new (F.getModule()) UncheckedRefCastInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
UncheckedRefCastAddrInst *
|
|
createUncheckedRefCastAddr(SILLocation Loc, SILValue src, CanType sourceType,
|
|
SILValue dest, CanType targetType) {
|
|
return insert(new (F.getModule()) UncheckedRefCastAddrInst(
|
|
getSILDebugLocation(Loc), src, sourceType, dest, targetType));
|
|
}
|
|
|
|
UncheckedAddrCastInst *createUncheckedAddrCast(SILLocation Loc, SILValue Op,
|
|
SILType Ty) {
|
|
return insert(new (F.getModule()) UncheckedAddrCastInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
UncheckedTrivialBitCastInst *
|
|
createUncheckedTrivialBitCast(SILLocation Loc, SILValue Op, SILType Ty) {
|
|
return insert(new (F.getModule()) UncheckedTrivialBitCastInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
UncheckedBitwiseCastInst *
|
|
createUncheckedBitwiseCast(SILLocation Loc, SILValue Op, SILType Ty) {
|
|
return insert(new (F.getModule()) UncheckedBitwiseCastInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
RefToBridgeObjectInst *createRefToBridgeObject(SILLocation Loc, SILValue Ref,
|
|
SILValue Bits) {
|
|
auto Ty = SILType::getBridgeObjectType(getASTContext());
|
|
return insert(new (F.getModule()) RefToBridgeObjectInst(
|
|
getSILDebugLocation(Loc), Ref, Bits, Ty));
|
|
}
|
|
|
|
BridgeObjectToRefInst *createBridgeObjectToRef(SILLocation Loc, SILValue Op,
|
|
SILType Ty) {
|
|
return insert(new (F.getModule()) BridgeObjectToRefInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
BridgeObjectToWordInst *createBridgeObjectToWord(SILLocation Loc,
|
|
SILValue Op) {
|
|
auto Ty = SILType::getBuiltinWordType(getASTContext());
|
|
return createBridgeObjectToWord(Loc, Op, Ty);
|
|
}
|
|
|
|
BridgeObjectToWordInst *createBridgeObjectToWord(SILLocation Loc, SILValue Op,
|
|
SILType Ty) {
|
|
return insert(new (F.getModule()) BridgeObjectToWordInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
RefToRawPointerInst *createRefToRawPointer(SILLocation Loc, SILValue Op,
|
|
SILType Ty) {
|
|
return insert(new (F.getModule())
|
|
RefToRawPointerInst(getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
RawPointerToRefInst *createRawPointerToRef(SILLocation Loc, SILValue Op,
|
|
SILType Ty) {
|
|
return insert(new (F.getModule())
|
|
RawPointerToRefInst(getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
ThinToThickFunctionInst *createThinToThickFunction(SILLocation Loc,
|
|
SILValue Op, SILType Ty) {
|
|
return insert(new (F.getModule()) ThinToThickFunctionInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
ThickToObjCMetatypeInst *createThickToObjCMetatype(SILLocation Loc,
|
|
SILValue Op, SILType Ty) {
|
|
return insert(new (F.getModule()) ThickToObjCMetatypeInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
ObjCToThickMetatypeInst *createObjCToThickMetatype(SILLocation Loc,
|
|
SILValue Op, SILType Ty) {
|
|
return insert(new (F.getModule()) ObjCToThickMetatypeInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
ObjCProtocolInst *createObjCProtocol(SILLocation Loc, ProtocolDecl *P,
|
|
SILType Ty) {
|
|
return insert(new (F.getModule())
|
|
ObjCProtocolInst(getSILDebugLocation(Loc), P, Ty));
|
|
}
|
|
|
|
UnownedToRefInst *createUnownedToRef(SILLocation Loc, SILValue op,
|
|
SILType ty) {
|
|
return insert(new (F.getModule())
|
|
UnownedToRefInst(getSILDebugLocation(Loc), op, ty));
|
|
}
|
|
|
|
RefToUnownedInst *createRefToUnowned(SILLocation Loc, SILValue op,
|
|
SILType ty) {
|
|
return insert(new (F.getModule())
|
|
RefToUnownedInst(getSILDebugLocation(Loc), op, ty));
|
|
}
|
|
|
|
UnmanagedToRefInst *createUnmanagedToRef(SILLocation Loc, SILValue op,
|
|
SILType ty) {
|
|
return insert(new (F.getModule())
|
|
UnmanagedToRefInst(getSILDebugLocation(Loc), op, ty));
|
|
}
|
|
|
|
RefToUnmanagedInst *createRefToUnmanaged(SILLocation Loc, SILValue op,
|
|
SILType ty) {
|
|
return insert(new (F.getModule())
|
|
RefToUnmanagedInst(getSILDebugLocation(Loc), op, ty));
|
|
}
|
|
|
|
IsNonnullInst *createIsNonnull(SILLocation Loc, SILValue operand) {
|
|
return insert(new (F.getModule()) IsNonnullInst(
|
|
getSILDebugLocation(Loc), operand,
|
|
SILType::getBuiltinIntegerType(1, getASTContext())));
|
|
}
|
|
|
|
UnconditionalCheckedCastInst *
|
|
createUnconditionalCheckedCast(SILLocation Loc, SILValue op, SILType destTy) {
|
|
return insert(new (F.getModule()) UnconditionalCheckedCastInst(
|
|
getSILDebugLocation(Loc), op, destTy));
|
|
}
|
|
|
|
UnconditionalCheckedCastAddrInst *createUnconditionalCheckedCastAddr(
|
|
SILLocation Loc, CastConsumptionKind consumption, SILValue src,
|
|
CanType sourceType, SILValue dest, CanType targetType) {
|
|
return insert(new (F.getModule()) UnconditionalCheckedCastAddrInst(
|
|
getSILDebugLocation(Loc), consumption, src, sourceType, dest,
|
|
targetType));
|
|
}
|
|
|
|
RetainValueInst *createRetainValue(SILLocation Loc, SILValue operand,
|
|
Atomicity atomicity) {
|
|
return insert(new (F.getModule()) RetainValueInst(getSILDebugLocation(Loc),
|
|
operand, atomicity));
|
|
}
|
|
|
|
ReleaseValueInst *createReleaseValue(SILLocation Loc, SILValue operand,
|
|
Atomicity atomicity) {
|
|
return insert(new (F.getModule()) ReleaseValueInst(getSILDebugLocation(Loc),
|
|
operand, atomicity));
|
|
}
|
|
|
|
AutoreleaseValueInst *createAutoreleaseValue(SILLocation Loc,
|
|
SILValue operand,
|
|
Atomicity atomicity) {
|
|
return insert(new (F.getModule()) AutoreleaseValueInst(
|
|
getSILDebugLocation(Loc), operand, atomicity));
|
|
}
|
|
|
|
SetDeallocatingInst *createSetDeallocating(SILLocation Loc,
|
|
SILValue operand,
|
|
Atomicity atomicity) {
|
|
return insert(new (F.getModule()) SetDeallocatingInst(
|
|
getSILDebugLocation(Loc), operand, atomicity));
|
|
}
|
|
|
|
StructInst *createStruct(SILLocation Loc, SILType Ty,
|
|
ArrayRef<SILValue> Elements) {
|
|
return insert(
|
|
StructInst::create(getSILDebugLocation(Loc), Ty, Elements, F));
|
|
}
|
|
|
|
TupleInst *createTuple(SILLocation Loc, SILType Ty,
|
|
ArrayRef<SILValue> Elements) {
|
|
return insert(
|
|
TupleInst::create(getSILDebugLocation(Loc), Ty, Elements, F));
|
|
}
|
|
|
|
TupleInst *createTuple(SILLocation loc, ArrayRef<SILValue> elts);
|
|
|
|
EnumInst *createEnum(SILLocation Loc, SILValue Operand,
|
|
EnumElementDecl *Element, SILType Ty) {
|
|
return insert(new (F.getModule()) EnumInst(getSILDebugLocation(Loc),
|
|
Operand, Element, Ty));
|
|
}
|
|
|
|
/// Inject a loadable value into the corresponding optional type.
|
|
EnumInst *createOptionalSome(SILLocation Loc, SILValue operand, SILType ty) {
|
|
return createOptionalSome(Loc, operand, ty.getOptionalTypeKind(), ty);
|
|
}
|
|
|
|
/// Inject a loadable value into the corresponding optional type.
|
|
EnumInst *createOptionalSome(SILLocation Loc, SILValue operand,
|
|
OptionalTypeKind optKind, SILType ty) {
|
|
assert(ty.getOptionalTypeKind() == optKind);
|
|
auto someDecl = F.getModule().getASTContext().getOptionalSomeDecl(optKind);
|
|
return createEnum(Loc, operand, someDecl, ty);
|
|
}
|
|
|
|
/// Create the nil value of a loadable optional type.
|
|
EnumInst *createOptionalNone(SILLocation Loc, SILType ty) {
|
|
return createOptionalNone(Loc, ty.getOptionalTypeKind(), ty);
|
|
}
|
|
|
|
/// Create the nil value of a loadable optional type.
|
|
EnumInst *createOptionalNone(SILLocation Loc, OptionalTypeKind optKind,
|
|
SILType ty) {
|
|
assert(ty.getOptionalTypeKind() == optKind);
|
|
auto noneDecl = F.getModule().getASTContext().getOptionalNoneDecl(optKind);
|
|
return createEnum(Loc, nullptr, noneDecl, ty);
|
|
}
|
|
|
|
InitEnumDataAddrInst *createInitEnumDataAddr(SILLocation Loc,
|
|
SILValue Operand,
|
|
EnumElementDecl *Element,
|
|
SILType Ty) {
|
|
return insert(new (F.getModule()) InitEnumDataAddrInst(
|
|
getSILDebugLocation(Loc), Operand, Element, Ty));
|
|
}
|
|
|
|
UncheckedEnumDataInst *createUncheckedEnumData(SILLocation Loc,
|
|
SILValue Operand,
|
|
EnumElementDecl *Element,
|
|
SILType Ty) {
|
|
return insert(new (F.getModule()) UncheckedEnumDataInst(
|
|
getSILDebugLocation(Loc), Operand, Element, Ty));
|
|
}
|
|
|
|
UncheckedEnumDataInst *createUncheckedEnumData(SILLocation Loc,
|
|
SILValue Operand,
|
|
EnumElementDecl *Element) {
|
|
SILType EltType =
|
|
Operand->getType().getEnumElementType(Element, getModule());
|
|
return createUncheckedEnumData(Loc, Operand, Element, EltType);
|
|
}
|
|
|
|
UncheckedTakeEnumDataAddrInst *
|
|
createUncheckedTakeEnumDataAddr(SILLocation Loc, SILValue Operand,
|
|
EnumElementDecl *Element, SILType Ty) {
|
|
return insert(new (F.getModule()) UncheckedTakeEnumDataAddrInst(
|
|
getSILDebugLocation(Loc), Operand, Element, Ty));
|
|
}
|
|
|
|
UncheckedTakeEnumDataAddrInst *
|
|
createUncheckedTakeEnumDataAddr(SILLocation Loc, SILValue Operand,
|
|
EnumElementDecl *Element) {
|
|
SILType EltType =
|
|
Operand->getType().getEnumElementType(Element, getModule());
|
|
return createUncheckedTakeEnumDataAddr(Loc, Operand, Element, EltType);
|
|
}
|
|
|
|
InjectEnumAddrInst *createInjectEnumAddr(SILLocation Loc, SILValue Operand,
|
|
EnumElementDecl *Element) {
|
|
return insert(new (F.getModule()) InjectEnumAddrInst(
|
|
getSILDebugLocation(Loc), Operand, Element));
|
|
}
|
|
|
|
SelectEnumInst *createSelectEnum(
|
|
SILLocation Loc, SILValue Operand, SILType Ty, SILValue DefaultValue,
|
|
ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues) {
|
|
return insert(SelectEnumInst::create(getSILDebugLocation(Loc), Operand,
|
|
Ty, DefaultValue, CaseValues, F));
|
|
}
|
|
|
|
SelectEnumAddrInst *createSelectEnumAddr(
|
|
SILLocation Loc, SILValue Operand, SILType Ty, SILValue DefaultValue,
|
|
ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues) {
|
|
return insert(SelectEnumAddrInst::create(
|
|
getSILDebugLocation(Loc), Operand, Ty, DefaultValue, CaseValues, F));
|
|
}
|
|
|
|
SelectValueInst *createSelectValue(
|
|
SILLocation Loc, SILValue Operand, SILType Ty, SILValue DefaultResult,
|
|
ArrayRef<std::pair<SILValue, SILValue>> CaseValuesAndResults) {
|
|
return insert(SelectValueInst::create(getSILDebugLocation(Loc), Operand,
|
|
Ty, DefaultResult,
|
|
CaseValuesAndResults, F));
|
|
}
|
|
|
|
TupleExtractInst *createTupleExtract(SILLocation Loc, SILValue Operand,
|
|
unsigned FieldNo, SILType ResultTy) {
|
|
return insert(new (F.getModule()) TupleExtractInst(
|
|
getSILDebugLocation(Loc), Operand, FieldNo, ResultTy));
|
|
}
|
|
|
|
TupleExtractInst *createTupleExtract(SILLocation Loc, SILValue Operand,
|
|
unsigned FieldNo) {
|
|
auto type = Operand->getType().getTupleElementType(FieldNo);
|
|
return createTupleExtract(Loc, Operand, FieldNo, type);
|
|
}
|
|
|
|
TupleElementAddrInst *createTupleElementAddr(SILLocation Loc,
|
|
SILValue Operand,
|
|
unsigned FieldNo,
|
|
SILType ResultTy) {
|
|
return insert(new (F.getModule()) TupleElementAddrInst(
|
|
getSILDebugLocation(Loc), Operand, FieldNo, ResultTy));
|
|
}
|
|
|
|
TupleElementAddrInst *
|
|
createTupleElementAddr(SILLocation Loc, SILValue Operand, unsigned FieldNo) {
|
|
return insert(new (F.getModule()) TupleElementAddrInst(
|
|
getSILDebugLocation(Loc), Operand, FieldNo,
|
|
Operand->getType().getTupleElementType(FieldNo)));
|
|
}
|
|
|
|
StructExtractInst *createStructExtract(SILLocation Loc, SILValue Operand,
|
|
VarDecl *Field, SILType ResultTy) {
|
|
return insert(new (F.getModule()) StructExtractInst(
|
|
getSILDebugLocation(Loc), Operand, Field, ResultTy));
|
|
}
|
|
|
|
StructExtractInst *createStructExtract(SILLocation Loc, SILValue Operand,
|
|
VarDecl *Field) {
|
|
auto type = Operand->getType().getFieldType(Field, F.getModule());
|
|
return createStructExtract(Loc, Operand, Field, type);
|
|
}
|
|
|
|
StructElementAddrInst *createStructElementAddr(SILLocation Loc,
|
|
SILValue Operand,
|
|
VarDecl *Field,
|
|
SILType ResultTy) {
|
|
return insert(new (F.getModule()) StructElementAddrInst(
|
|
getSILDebugLocation(Loc), Operand, Field, ResultTy));
|
|
}
|
|
|
|
StructElementAddrInst *
|
|
createStructElementAddr(SILLocation Loc, SILValue Operand, VarDecl *Field) {
|
|
auto ResultTy = Operand->getType().getFieldType(Field, F.getModule());
|
|
return createStructElementAddr(Loc, Operand, Field, ResultTy);
|
|
}
|
|
|
|
RefElementAddrInst *createRefElementAddr(SILLocation Loc, SILValue Operand,
|
|
VarDecl *Field, SILType ResultTy) {
|
|
return insert(new (F.getModule()) RefElementAddrInst(
|
|
getSILDebugLocation(Loc), Operand, Field, ResultTy));
|
|
}
|
|
RefElementAddrInst *createRefElementAddr(SILLocation Loc, SILValue Operand,
|
|
VarDecl *Field) {
|
|
auto ResultTy = Operand->getType().getFieldType(Field, F.getModule());
|
|
return createRefElementAddr(Loc, Operand, Field, ResultTy);
|
|
}
|
|
|
|
ClassMethodInst *createClassMethod(SILLocation Loc, SILValue Operand,
|
|
SILDeclRef Member, SILType MethodTy,
|
|
bool Volatile = false) {
|
|
return insert(new (F.getModule()) ClassMethodInst(
|
|
getSILDebugLocation(Loc), Operand, Member, MethodTy, Volatile));
|
|
}
|
|
|
|
ClassMethodInst *createClassMethod(SILLocation Loc, SILValue Operand,
|
|
SILDeclRef Member, bool Volatile = false) {
|
|
auto MethodTy = getModule().Types.getConstantOverrideType(Member);
|
|
return createClassMethod(Loc, Operand, Member,
|
|
SILType::getPrimitiveObjectType(MethodTy),
|
|
Volatile);
|
|
}
|
|
|
|
/// Emit a class_method reference to the least derived overridden decl for
|
|
/// the given method, and upcast the "self" pointer to the matching superclass
|
|
/// type.
|
|
std::pair<ClassMethodInst *, SILValue> emitClassMethod(SILLocation Loc,
|
|
SILValue Self,
|
|
SILDeclRef Member,
|
|
bool Volatile = false);
|
|
|
|
SuperMethodInst *createSuperMethod(SILLocation Loc, SILValue Operand,
|
|
SILDeclRef Member, SILType MethodTy,
|
|
bool Volatile = false) {
|
|
return insert(new (F.getModule()) SuperMethodInst(
|
|
getSILDebugLocation(Loc), Operand, Member, MethodTy, Volatile));
|
|
}
|
|
|
|
WitnessMethodInst *createWitnessMethod(SILLocation Loc, CanType LookupTy,
|
|
ProtocolConformanceRef Conformance,
|
|
SILDeclRef Member, SILType MethodTy,
|
|
SILValue OptionalOpenedExistential,
|
|
bool Volatile = false) {
|
|
return insert(WitnessMethodInst::create(
|
|
getSILDebugLocation(Loc), LookupTy, Conformance, Member, MethodTy,
|
|
&F, OptionalOpenedExistential, Volatile));
|
|
}
|
|
|
|
DynamicMethodInst *createDynamicMethod(SILLocation Loc, SILValue Operand,
|
|
SILDeclRef Member, SILType MethodTy,
|
|
bool Volatile = false) {
|
|
return insert(new (F.getModule()) DynamicMethodInst(
|
|
getSILDebugLocation(Loc), Operand, Member, MethodTy, Volatile));
|
|
}
|
|
|
|
OpenExistentialAddrInst *
|
|
createOpenExistentialAddr(SILLocation Loc, SILValue Operand, SILType SelfTy) {
|
|
return insert(new (F.getModule()) OpenExistentialAddrInst(
|
|
getSILDebugLocation(Loc), Operand, SelfTy));
|
|
}
|
|
|
|
OpenExistentialMetatypeInst *createOpenExistentialMetatype(SILLocation Loc,
|
|
SILValue operand,
|
|
SILType selfTy) {
|
|
return insert(new (F.getModule()) OpenExistentialMetatypeInst(
|
|
getSILDebugLocation(Loc), operand, selfTy));
|
|
}
|
|
|
|
OpenExistentialRefInst *
|
|
createOpenExistentialRef(SILLocation Loc, SILValue Operand, SILType Ty) {
|
|
return insert(new (F.getModule()) OpenExistentialRefInst(
|
|
getSILDebugLocation(Loc), Operand, Ty));
|
|
}
|
|
|
|
OpenExistentialBoxInst *
|
|
createOpenExistentialBox(SILLocation Loc, SILValue Operand, SILType Ty) {
|
|
return insert(new (F.getModule()) OpenExistentialBoxInst(
|
|
getSILDebugLocation(Loc), Operand, Ty));
|
|
}
|
|
|
|
InitExistentialAddrInst *
|
|
createInitExistentialAddr(SILLocation Loc, SILValue Existential,
|
|
CanType FormalConcreteType,
|
|
SILType LoweredConcreteType,
|
|
ArrayRef<ProtocolConformanceRef> Conformances) {
|
|
return insert(InitExistentialAddrInst::create(
|
|
getSILDebugLocation(Loc), Existential, FormalConcreteType,
|
|
LoweredConcreteType, Conformances, &F));
|
|
}
|
|
|
|
InitExistentialMetatypeInst *
|
|
createInitExistentialMetatype(SILLocation Loc, SILValue metatype,
|
|
SILType existentialType,
|
|
ArrayRef<ProtocolConformanceRef> conformances) {
|
|
return insert(InitExistentialMetatypeInst::create(
|
|
getSILDebugLocation(Loc), existentialType, metatype, conformances,
|
|
&F));
|
|
}
|
|
|
|
InitExistentialRefInst *
|
|
createInitExistentialRef(SILLocation Loc, SILType ExistentialType,
|
|
CanType FormalConcreteType, SILValue Concrete,
|
|
ArrayRef<ProtocolConformanceRef> Conformances) {
|
|
return insert(InitExistentialRefInst::create(
|
|
getSILDebugLocation(Loc), ExistentialType, FormalConcreteType,
|
|
Concrete, Conformances, &F));
|
|
}
|
|
|
|
DeinitExistentialAddrInst *createDeinitExistentialAddr(SILLocation Loc,
|
|
SILValue Existential) {
|
|
return insert(new (F.getModule()) DeinitExistentialAddrInst(
|
|
getSILDebugLocation(Loc), Existential));
|
|
}
|
|
|
|
ProjectBlockStorageInst *createProjectBlockStorage(SILLocation Loc,
|
|
SILValue Storage) {
|
|
auto CaptureTy = Storage->getType()
|
|
.castTo<SILBlockStorageType>()
|
|
->getCaptureAddressType();
|
|
return createProjectBlockStorage(Loc, Storage, CaptureTy);
|
|
}
|
|
ProjectBlockStorageInst *createProjectBlockStorage(SILLocation Loc,
|
|
SILValue Storage,
|
|
SILType CaptureTy) {
|
|
return insert(new (F.getModule()) ProjectBlockStorageInst(
|
|
getSILDebugLocation(Loc), Storage, CaptureTy));
|
|
}
|
|
|
|
InitBlockStorageHeaderInst *
|
|
createInitBlockStorageHeader(SILLocation Loc, SILValue BlockStorage,
|
|
SILValue InvokeFunction, SILType BlockType) {
|
|
return insert(new (F.getModule()) InitBlockStorageHeaderInst(
|
|
getSILDebugLocation(Loc), BlockStorage, InvokeFunction, BlockType));
|
|
}
|
|
|
|
MetatypeInst *createMetatype(SILLocation Loc, SILType Metatype) {
|
|
return insert(new (F.getModule())
|
|
MetatypeInst(getSILDebugLocation(Loc), Metatype));
|
|
}
|
|
|
|
ObjCMetatypeToObjectInst *
|
|
createObjCMetatypeToObject(SILLocation Loc, SILValue Op, SILType Ty) {
|
|
return insert(new (F.getModule()) ObjCMetatypeToObjectInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
ObjCExistentialMetatypeToObjectInst *
|
|
createObjCExistentialMetatypeToObject(SILLocation Loc, SILValue Op,
|
|
SILType Ty) {
|
|
return insert(new (F.getModule()) ObjCExistentialMetatypeToObjectInst(
|
|
getSILDebugLocation(Loc), Op, Ty));
|
|
}
|
|
|
|
ValueMetatypeInst *createValueMetatype(SILLocation Loc, SILType Metatype,
|
|
SILValue Base) {
|
|
return insert(new (F.getModule()) ValueMetatypeInst(
|
|
getSILDebugLocation(Loc), Metatype, Base));
|
|
}
|
|
|
|
ExistentialMetatypeInst *
|
|
createExistentialMetatype(SILLocation Loc, SILType Metatype, SILValue Base) {
|
|
return insert(new (F.getModule()) ExistentialMetatypeInst(
|
|
getSILDebugLocation(Loc), Metatype, Base));
|
|
}
|
|
|
|
CopyBlockInst *createCopyBlock(SILLocation Loc, SILValue Operand) {
|
|
return insert(new (F.getModule())
|
|
CopyBlockInst(getSILDebugLocation(Loc), Operand));
|
|
}
|
|
StrongRetainInst *createStrongRetain(SILLocation Loc, SILValue Operand,
|
|
Atomicity atomicity) {
|
|
return insert(new (F.getModule()) StrongRetainInst(getSILDebugLocation(Loc),
|
|
Operand, atomicity));
|
|
}
|
|
StrongReleaseInst *createStrongRelease(SILLocation Loc, SILValue Operand,
|
|
Atomicity atomicity) {
|
|
return insert(new (F.getModule()) StrongReleaseInst(
|
|
getSILDebugLocation(Loc), Operand, atomicity));
|
|
}
|
|
StrongPinInst *createStrongPin(SILLocation Loc, SILValue Operand,
|
|
Atomicity atomicity) {
|
|
return insert(new (F.getModule()) StrongPinInst(getSILDebugLocation(Loc),
|
|
Operand, atomicity));
|
|
}
|
|
StrongUnpinInst *createStrongUnpin(SILLocation Loc, SILValue Operand,
|
|
Atomicity atomicity) {
|
|
return insert(new (F.getModule()) StrongUnpinInst(getSILDebugLocation(Loc),
|
|
Operand, atomicity));
|
|
}
|
|
StrongRetainUnownedInst *createStrongRetainUnowned(SILLocation Loc,
|
|
SILValue Operand,
|
|
Atomicity atomicity) {
|
|
return insert(new (F.getModule()) StrongRetainUnownedInst(
|
|
getSILDebugLocation(Loc), Operand, atomicity));
|
|
}
|
|
UnownedRetainInst *createUnownedRetain(SILLocation Loc, SILValue Operand,
|
|
Atomicity atomicity) {
|
|
return insert(new (F.getModule()) UnownedRetainInst(
|
|
getSILDebugLocation(Loc), Operand, atomicity));
|
|
}
|
|
UnownedReleaseInst *createUnownedRelease(SILLocation Loc, SILValue Operand,
|
|
Atomicity atomicity) {
|
|
return insert(new (F.getModule()) UnownedReleaseInst(
|
|
getSILDebugLocation(Loc), Operand, atomicity));
|
|
}
|
|
|
|
FixLifetimeInst *createFixLifetime(SILLocation Loc, SILValue Operand) {
|
|
return insert(new (F.getModule())
|
|
FixLifetimeInst(getSILDebugLocation(Loc), Operand));
|
|
}
|
|
void emitFixLifetime(SILLocation Loc, SILValue Operand) {
|
|
if (getTypeLowering(Operand->getType()).isTrivial())
|
|
return;
|
|
createFixLifetime(Loc, Operand);
|
|
}
|
|
MarkDependenceInst *createMarkDependence(SILLocation Loc, SILValue value,
|
|
SILValue base) {
|
|
return insert(new (F.getModule()) MarkDependenceInst(
|
|
getSILDebugLocation(Loc), value, base));
|
|
}
|
|
IsUniqueInst *createIsUnique(SILLocation Loc, SILValue operand) {
|
|
auto Int1Ty = SILType::getBuiltinIntegerType(1, getASTContext());
|
|
return insert(new (F.getModule()) IsUniqueInst(getSILDebugLocation(Loc),
|
|
operand, Int1Ty));
|
|
}
|
|
IsUniqueOrPinnedInst *createIsUniqueOrPinned(SILLocation Loc,
|
|
SILValue value) {
|
|
auto Int1Ty = SILType::getBuiltinIntegerType(1, getASTContext());
|
|
return insert(new (F.getModule()) IsUniqueOrPinnedInst(
|
|
getSILDebugLocation(Loc), value, Int1Ty));
|
|
}
|
|
|
|
DeallocStackInst *createDeallocStack(SILLocation Loc, SILValue operand) {
|
|
return insert(new (F.getModule())
|
|
DeallocStackInst(getSILDebugLocation(Loc), operand));
|
|
}
|
|
DeallocRefInst *createDeallocRef(SILLocation Loc, SILValue operand,
|
|
bool canBeOnStack) {
|
|
return insert(new (F.getModule()) DeallocRefInst(
|
|
getSILDebugLocation(Loc), operand, canBeOnStack));
|
|
}
|
|
DeallocPartialRefInst *createDeallocPartialRef(SILLocation Loc,
|
|
SILValue operand,
|
|
SILValue metatype) {
|
|
return insert(new (F.getModule()) DeallocPartialRefInst(
|
|
getSILDebugLocation(Loc), operand, metatype));
|
|
}
|
|
DeallocBoxInst *createDeallocBox(SILLocation Loc, SILType eltType,
|
|
SILValue operand) {
|
|
return insert(new (F.getModule()) DeallocBoxInst(
|
|
getSILDebugLocation(Loc), eltType, operand));
|
|
}
|
|
DeallocBoxInst *createDeallocBox(SILLocation Loc, SILValue operand) {
|
|
auto eltType =
|
|
operand->getType().castTo<SILBoxType>()->getBoxedAddressType();
|
|
return insert(new (F.getModule()) DeallocBoxInst(
|
|
getSILDebugLocation(Loc), eltType, operand));
|
|
}
|
|
DeallocExistentialBoxInst *createDeallocExistentialBox(SILLocation Loc,
|
|
CanType concreteType,
|
|
SILValue operand) {
|
|
return insert(new (F.getModule()) DeallocExistentialBoxInst(
|
|
getSILDebugLocation(Loc), concreteType, operand));
|
|
}
|
|
DeallocValueBufferInst *createDeallocValueBuffer(SILLocation Loc,
|
|
SILType valueType,
|
|
SILValue operand) {
|
|
return insert(new (F.getModule()) DeallocValueBufferInst(
|
|
getSILDebugLocation(Loc), valueType, operand));
|
|
}
|
|
DestroyAddrInst *createDestroyAddr(SILLocation Loc, SILValue Operand) {
|
|
return insert(new (F.getModule())
|
|
DestroyAddrInst(getSILDebugLocation(Loc), Operand));
|
|
}
|
|
|
|
ProjectValueBufferInst *createProjectValueBuffer(SILLocation Loc,
|
|
SILType valueType,
|
|
SILValue operand) {
|
|
return insert(new (F.getModule()) ProjectValueBufferInst(
|
|
getSILDebugLocation(Loc), valueType, operand));
|
|
}
|
|
ProjectBoxInst *createProjectBox(SILLocation Loc, SILValue boxOperand) {
|
|
auto valueTy =
|
|
boxOperand->getType().castTo<SILBoxType>()->getBoxedAddressType();
|
|
|
|
return insert(new (F.getModule()) ProjectBoxInst(
|
|
getSILDebugLocation(Loc), valueTy, boxOperand));
|
|
}
|
|
ProjectBoxInst *createProjectBox(SILLocation Loc, SILType valueTy,
|
|
SILValue boxOperand) {
|
|
return insert(new (F.getModule()) ProjectBoxInst(
|
|
getSILDebugLocation(Loc), valueTy, boxOperand));
|
|
}
|
|
ProjectExistentialBoxInst *createProjectExistentialBox(SILLocation Loc,
|
|
SILType valueTy,
|
|
SILValue boxOperand) {
|
|
return insert(new (F.getModule()) ProjectExistentialBoxInst(
|
|
getSILDebugLocation(Loc), valueTy, boxOperand));
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Unchecked cast helpers
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
// Create an UncheckedRefCast if the source and dest types are legal,
|
|
// otherwise return null.
|
|
// Unwrap or wrap optional types as needed.
|
|
SILInstruction *tryCreateUncheckedRefCast(SILLocation Loc, SILValue Op,
|
|
SILType ResultTy);
|
|
|
|
// Create the appropriate cast instruction based on result type.
|
|
SILInstruction *createUncheckedBitCast(SILLocation Loc, SILValue Op,
|
|
SILType Ty);
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Runtime failure
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
CondFailInst *createCondFail(SILLocation Loc, SILValue Operand) {
|
|
return insert(new (F.getModule())
|
|
CondFailInst(getSILDebugLocation(Loc), Operand));
|
|
}
|
|
|
|
BuiltinInst *createBuiltinTrap(SILLocation Loc) {
|
|
ASTContext &AST = F.getModule().getASTContext();
|
|
auto Id_trap = AST.getIdentifier("int_trap");
|
|
return createBuiltin(Loc, Id_trap, F.getModule().Types.getEmptyTupleType(),
|
|
{}, {});
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Array indexing instructions
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
IndexAddrInst *createIndexAddr(SILLocation Loc, SILValue Operand,
|
|
SILValue Index) {
|
|
return insert(new (F.getModule()) IndexAddrInst(getSILDebugLocation(Loc),
|
|
Operand, Index));
|
|
}
|
|
|
|
IndexRawPointerInst *createIndexRawPointer(SILLocation Loc, SILValue Operand,
|
|
SILValue Index) {
|
|
return insert(new (F.getModule()) IndexRawPointerInst(
|
|
getSILDebugLocation(Loc), Operand, Index));
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Terminator SILInstruction Creation Methods
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
UnreachableInst *createUnreachable(SILLocation Loc) {
|
|
return insertTerminator(new (F.getModule())
|
|
UnreachableInst(getSILDebugLocation(Loc)));
|
|
}
|
|
|
|
ReturnInst *createReturn(SILLocation Loc, SILValue ReturnValue) {
|
|
return insertTerminator(new (F.getModule()) ReturnInst(
|
|
getSILDebugLocation(Loc), ReturnValue));
|
|
}
|
|
|
|
ThrowInst *createThrow(SILLocation Loc, SILValue errorValue) {
|
|
return insertTerminator(
|
|
new (F.getModule()) ThrowInst(getSILDebugLocation(Loc), errorValue));
|
|
}
|
|
|
|
CondBranchInst *createCondBranch(SILLocation Loc, SILValue Cond,
|
|
SILBasicBlock *Target1,
|
|
SILBasicBlock *Target2) {
|
|
return insertTerminator(CondBranchInst::create(getSILDebugLocation(Loc),
|
|
Cond, Target1, Target2, F));
|
|
}
|
|
|
|
CondBranchInst *createCondBranch(SILLocation Loc, SILValue Cond,
|
|
SILBasicBlock *Target1,
|
|
ArrayRef<SILValue> Args1,
|
|
SILBasicBlock *Target2,
|
|
ArrayRef<SILValue> Args2) {
|
|
return insertTerminator(CondBranchInst::create(
|
|
getSILDebugLocation(Loc), Cond, Target1, Args1, Target2, Args2, F));
|
|
}
|
|
|
|
CondBranchInst *createCondBranch(SILLocation Loc, SILValue Cond,
|
|
SILBasicBlock *Target1,
|
|
OperandValueArrayRef Args1,
|
|
SILBasicBlock *Target2,
|
|
OperandValueArrayRef Args2) {
|
|
SmallVector<SILValue, 6> ArgsCopy1;
|
|
SmallVector<SILValue, 6> ArgsCopy2;
|
|
|
|
ArgsCopy1.reserve(Args1.size());
|
|
ArgsCopy2.reserve(Args2.size());
|
|
|
|
for (auto I = Args1.begin(), E = Args1.end(); I != E; ++I)
|
|
ArgsCopy1.push_back(*I);
|
|
for (auto I = Args2.begin(), E = Args2.end(); I != E; ++I)
|
|
ArgsCopy2.push_back(*I);
|
|
|
|
return insertTerminator(CondBranchInst::create(getSILDebugLocation(Loc),
|
|
Cond, Target1, ArgsCopy1,
|
|
Target2, ArgsCopy2, F));
|
|
}
|
|
|
|
BranchInst *createBranch(SILLocation Loc, SILBasicBlock *TargetBlock) {
|
|
return insertTerminator(
|
|
BranchInst::create(getSILDebugLocation(Loc), TargetBlock, F));
|
|
}
|
|
|
|
BranchInst *createBranch(SILLocation Loc, SILBasicBlock *TargetBlock,
|
|
ArrayRef<SILValue> Args) {
|
|
return insertTerminator(
|
|
BranchInst::create(getSILDebugLocation(Loc), TargetBlock, Args, F));
|
|
}
|
|
|
|
BranchInst *createBranch(SILLocation Loc, SILBasicBlock *TargetBlock,
|
|
OperandValueArrayRef Args);
|
|
|
|
SwitchValueInst *
|
|
createSwitchValue(SILLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
|
|
ArrayRef<std::pair<SILValue, SILBasicBlock *>> CaseBBs) {
|
|
return insertTerminator(SwitchValueInst::create(
|
|
getSILDebugLocation(Loc), Operand, DefaultBB, CaseBBs, F));
|
|
}
|
|
|
|
SwitchEnumInst *createSwitchEnum(
|
|
SILLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
|
|
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs) {
|
|
return insertTerminator(SwitchEnumInst::create(
|
|
getSILDebugLocation(Loc), Operand, DefaultBB, CaseBBs, F));
|
|
}
|
|
|
|
SwitchEnumAddrInst *createSwitchEnumAddr(
|
|
SILLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
|
|
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs) {
|
|
return insertTerminator(SwitchEnumAddrInst::create(
|
|
getSILDebugLocation(Loc), Operand, DefaultBB, CaseBBs, F));
|
|
}
|
|
|
|
DynamicMethodBranchInst *
|
|
createDynamicMethodBranch(SILLocation Loc, SILValue Operand,
|
|
SILDeclRef Member, SILBasicBlock *HasMethodBB,
|
|
SILBasicBlock *NoMethodBB) {
|
|
return insertTerminator(
|
|
DynamicMethodBranchInst::create(getSILDebugLocation(Loc), Operand,
|
|
Member, HasMethodBB, NoMethodBB, F));
|
|
}
|
|
|
|
CheckedCastBranchInst *createCheckedCastBranch(SILLocation Loc, bool isExact,
|
|
SILValue op, SILType destTy,
|
|
SILBasicBlock *successBB,
|
|
SILBasicBlock *failureBB) {
|
|
return insertTerminator(new (F.getModule()) CheckedCastBranchInst(
|
|
getSILDebugLocation(Loc), isExact, op, destTy, successBB,
|
|
failureBB));
|
|
}
|
|
|
|
CheckedCastAddrBranchInst *
|
|
createCheckedCastAddrBranch(SILLocation Loc, CastConsumptionKind consumption,
|
|
SILValue src, CanType sourceType, SILValue dest,
|
|
CanType targetType, SILBasicBlock *successBB,
|
|
SILBasicBlock *failureBB) {
|
|
return insertTerminator(new (F.getModule()) CheckedCastAddrBranchInst(
|
|
getSILDebugLocation(Loc), consumption, src, sourceType, dest,
|
|
targetType, successBB, failureBB));
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Memory management helpers
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
/// Try to fold a destroy_addr operation into the previous instructions, or
|
|
/// generate an explicit one if that fails. If this inserts a new
|
|
/// instruction, it returns it, otherwise it returns null.
|
|
DestroyAddrInst *emitDestroyAddrAndFold(SILLocation Loc, SILValue Operand) {
|
|
auto U = emitDestroyAddr(Loc, Operand);
|
|
if (U.isNull() || !U.is<DestroyAddrInst *>())
|
|
return nullptr;
|
|
return U.get<DestroyAddrInst *>();
|
|
}
|
|
|
|
/// Perform a strong_release instruction at the current location, attempting
|
|
/// to fold it locally into nearby retain instructions or emitting an explicit
|
|
/// strong release if necessary. If this inserts a new instruction, it
|
|
/// returns it, otherwise it returns null.
|
|
StrongReleaseInst *emitStrongReleaseAndFold(SILLocation Loc,
|
|
SILValue Operand) {
|
|
auto U = emitStrongRelease(Loc, Operand);
|
|
if (U.isNull())
|
|
return nullptr;
|
|
if (auto *SRI = U.dyn_cast<StrongReleaseInst *>())
|
|
return SRI;
|
|
U.get<StrongRetainInst *>()->eraseFromParent();
|
|
return nullptr;
|
|
}
|
|
|
|
/// Emit a release_value instruction at the current location, attempting to
|
|
/// fold it locally into another nearby retain_value instruction. This
|
|
/// returns the new instruction if it inserts one, otherwise it returns null.
|
|
///
|
|
/// This instruction doesn't handle strength reduction of release_value into
|
|
/// a noop / strong_release / unowned_release. For that, use the
|
|
/// emitReleaseValueOperation method below or use the TypeLowering API.
|
|
ReleaseValueInst *emitReleaseValueAndFold(SILLocation Loc, SILValue Operand) {
|
|
auto U = emitReleaseValue(Loc, Operand);
|
|
if (U.isNull())
|
|
return nullptr;
|
|
if (auto *RVI = U.dyn_cast<ReleaseValueInst *>())
|
|
return RVI;
|
|
U.get<RetainValueInst *>()->eraseFromParent();
|
|
return nullptr;
|
|
}
|
|
|
|
/// Emit a release_value instruction at the current location, attempting to
|
|
/// fold it locally into another nearby retain_value instruction. Returns a
|
|
/// pointer union initialized with a release value inst if it inserts one,
|
|
/// otherwise returns the retain. It is expected that the caller will remove
|
|
/// the retain_value. This allows for the caller to update any state before
|
|
/// the retain_value is destroyed.
|
|
PointerUnion<RetainValueInst *, ReleaseValueInst *>
|
|
emitReleaseValue(SILLocation Loc, SILValue Operand);
|
|
|
|
/// Emit a strong_release instruction at the current location, attempting to
|
|
/// fold it locally into another nearby strong_retain instruction. Returns a
|
|
/// pointer union initialized with a strong_release inst if it inserts one,
|
|
/// otherwise returns the pointer union initialized with the strong_retain. It
|
|
/// is expected that the caller will remove the returned strong_retain. This
|
|
/// allows for the caller to update any state before the release value is
|
|
/// destroyed.
|
|
PointerUnion<StrongRetainInst *, StrongReleaseInst *>
|
|
emitStrongRelease(SILLocation Loc, SILValue Operand);
|
|
|
|
/// Emit a destroy_addr instruction at \p Loc attempting to fold the
|
|
/// destroy_addr locally into a copy_addr instruction. Returns a pointer union
|
|
/// initialized with the folded copy_addr if the destroy_addr was folded into
|
|
/// a copy_addr. Otherwise, returns the newly inserted destroy_addr.
|
|
PointerUnion<CopyAddrInst *, DestroyAddrInst *>
|
|
emitDestroyAddr(SILLocation Loc, SILValue Operand);
|
|
|
|
/// Convenience function for calling emitRetain on the type lowering
|
|
/// for the non-address value.
|
|
void emitRetainValueOperation(SILLocation Loc, SILValue v) {
|
|
assert(!v->getType().isAddress());
|
|
auto &lowering = getTypeLowering(v->getType());
|
|
return lowering.emitRetainValue(*this, Loc, v);
|
|
}
|
|
|
|
/// Convenience function for calling TypeLowering.emitRelease on the type
|
|
/// lowering for the non-address value.
|
|
void emitReleaseValueOperation(SILLocation Loc, SILValue v) {
|
|
assert(!v->getType().isAddress());
|
|
auto &lowering = getTypeLowering(v->getType());
|
|
lowering.emitReleaseValue(*this, Loc, v);
|
|
}
|
|
|
|
SILValue emitTupleExtract(SILLocation Loc, SILValue Operand, unsigned FieldNo,
|
|
SILType ResultTy) {
|
|
// Fold tuple_extract(tuple(x,y,z),2)
|
|
if (auto *TI = dyn_cast<TupleInst>(Operand))
|
|
return TI->getOperand(FieldNo);
|
|
|
|
return createTupleExtract(Loc, Operand, FieldNo, ResultTy);
|
|
}
|
|
|
|
SILValue emitTupleExtract(SILLocation Loc, SILValue Operand,
|
|
unsigned FieldNo) {
|
|
return emitTupleExtract(Loc, Operand, FieldNo,
|
|
Operand->getType().getTupleElementType(FieldNo));
|
|
}
|
|
|
|
SILValue emitStructExtract(SILLocation Loc, SILValue Operand, VarDecl *Field,
|
|
SILType ResultTy) {
|
|
if (auto *SI = dyn_cast<StructInst>(Operand))
|
|
return SI->getFieldValue(Field);
|
|
|
|
return createStructExtract(Loc, Operand, Field, ResultTy);
|
|
}
|
|
|
|
SILValue emitStructExtract(SILLocation Loc, SILValue Operand,
|
|
VarDecl *Field) {
|
|
auto type = Operand->getType().getFieldType(Field, F.getModule());
|
|
return emitStructExtract(Loc, Operand, Field, type);
|
|
}
|
|
|
|
SILValue emitThickToObjCMetatype(SILLocation Loc, SILValue Op, SILType Ty);
|
|
SILValue emitObjCToThickMetatype(SILLocation Loc, SILValue Op, SILType Ty);
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Private Helper Methods
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
private:
|
|
/// insert - This is a template to avoid losing type info on the result.
|
|
template <typename T> T *insert(T *TheInst) {
|
|
insertImpl(TheInst);
|
|
return TheInst;
|
|
}
|
|
|
|
/// insertTerminator - This is the same as insert, but clears the insertion
|
|
/// point after doing the insertion. This is used by terminators, since it
|
|
/// isn't valid to insert something after a terminator.
|
|
template <typename T> T *insertTerminator(T *TheInst) {
|
|
insertImpl(TheInst);
|
|
clearInsertionPoint();
|
|
return TheInst;
|
|
}
|
|
|
|
void insertImpl(SILInstruction *TheInst) {
|
|
if (BB == 0)
|
|
return;
|
|
|
|
// If the SILBuilder client wants to know about new instructions, record
|
|
// this.
|
|
if (InsertedInstrs)
|
|
InsertedInstrs->push_back(TheInst);
|
|
|
|
BB->insert(InsertPt, TheInst);
|
|
}
|
|
};
|
|
|
|
/// An wrapper on top of SILBuilder's constructor that automatically sets the
|
|
/// current SILDebugScope based on the specified insertion point. This is useful
|
|
/// for situations where a single SIL instruction is lowered into a sequence of
|
|
/// SIL instructions.
|
|
class SILBuilderWithScope : public SILBuilder {
|
|
void inheritScopeFrom(SILInstruction *I) {
|
|
assert(I->getDebugScope() && "instruction has no debug scope");
|
|
setCurrentDebugScope(I->getDebugScope());
|
|
}
|
|
|
|
public:
|
|
explicit SILBuilderWithScope(
|
|
SILInstruction *I,
|
|
SmallVectorImpl<SILInstruction *> *InsertedInstrs = nullptr)
|
|
: SILBuilder(I, InsertedInstrs) {
|
|
assert(I->getDebugScope() && "instruction has no debug scope");
|
|
setCurrentDebugScope(I->getDebugScope());
|
|
}
|
|
|
|
explicit SILBuilderWithScope(SILBasicBlock::iterator I)
|
|
: SILBuilderWithScope(&*I) {}
|
|
|
|
explicit SILBuilderWithScope(SILInstruction *I,
|
|
SILInstruction *InheritScopeFrom)
|
|
: SILBuilderWithScope(I) {
|
|
inheritScopeFrom(InheritScopeFrom);
|
|
}
|
|
|
|
explicit SILBuilderWithScope(SILBasicBlock::iterator I,
|
|
SILInstruction *InheritScopeFrom)
|
|
: SILBuilderWithScope(&*I) {
|
|
inheritScopeFrom(InheritScopeFrom);
|
|
}
|
|
|
|
explicit SILBuilderWithScope(SILBasicBlock *BB,
|
|
SILInstruction *InheritScopeFrom)
|
|
: SILBuilder(BB) {
|
|
inheritScopeFrom(InheritScopeFrom);
|
|
}
|
|
};
|
|
|
|
} // end swift namespace
|
|
|
|
#endif
|