blob: 724aac10fa4b0597213ea5e4f92495f9bf8e9cb7 [file] [log] [blame]
//===--- SILBuilder.h - Class for creating SIL Constructs -------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SIL_SILBUILDER_H
#define SWIFT_SIL_SILBUILDER_H
#include "swift/Basic/ProfileCounter.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILOpenedArchetypesTracker.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringExtras.h"
namespace swift {
using Atomicity = RefCountingInst::Atomicity;
class SILDebugScope;
class IntegerLiteralExpr;
class FloatLiteralExpr;
class SILGlobalVariable;
/// Manage the state needed for a SIL pass across multiple, independent
/// SILBuilder invocations.
///
/// A SIL pass can instantiate a SILBuilderContext object to track information
/// across multiple, potentially independent invocations of SILBuilder. This
/// allows utilities used within the pass to construct a new SILBuilder instance
/// whenever it is convenient or appropriate. For example, a separate SILBuilder
/// should be constructed whenever the current debug location or insertion point
/// changed. Reusing the same SILBuilder and calling setInsertionPoint() easily
/// leads to incorrect debug information.
class SILBuilderContext {
friend class SILBuilder;
SILModule &Module;
/// Allow the SIL module conventions to be overriden within the builder.
/// This supports passes that lower SIL to a new stage.
SILModuleConventions silConv = SILModuleConventions(Module);
/// If this pointer is non-null, then any inserted instruction is
/// recorded in this list.
///
/// TODO: Give this ownership of InsertedInstrs and migrate users that
/// currently provide their own InsertedInstrs.
SmallVectorImpl<SILInstruction *> *InsertedInstrs = nullptr;
/// An immutable view on the set of available opened archetypes.
/// It is passed down to SILInstruction constructors and create
/// methods.
SILOpenedArchetypesState OpenedArchetypes;
/// Maps opened archetypes to their definitions. If provided,
/// can be used by the builder. It is supposed to be used
/// only by SILGen or SIL deserializers.
SILOpenedArchetypesTracker *OpenedArchetypesTracker = nullptr;
public:
explicit SILBuilderContext(
SILModule &M, SmallVectorImpl<SILInstruction *> *InsertedInstrs = 0)
: Module(M), InsertedInstrs(InsertedInstrs) {}
SILModule &getModule() { return Module; }
// Allow a pass to override the current SIL module conventions. This should
// only be done by a pass responsible for lowering SIL to a new stage
// (e.g. AddressLowering).
void setSILConventions(SILModuleConventions silConv) {
this->silConv = silConv;
}
void setOpenedArchetypesTracker(SILOpenedArchetypesTracker *Tracker) {
OpenedArchetypesTracker = Tracker;
OpenedArchetypes.setOpenedArchetypesTracker(OpenedArchetypesTracker);
}
SILOpenedArchetypesTracker *getOpenedArchetypesTracker() const {
return OpenedArchetypesTracker;
}
protected:
/// Notify the context of each new instruction after it is inserted in the
/// instruction stream.
void notifyInserted(SILInstruction *Inst) {
// If the SILBuilder client wants to know about new instructions, record
// this.
if (InsertedInstrs)
InsertedInstrs->push_back(Inst);
}
};
class SILBuilder {
friend class SILBuilderWithScope;
/// Temporary context for clients that don't provide their own.
SILBuilderContext TempContext;
/// Reference to the provided SILBuilderContext.
SILBuilderContext &C;
/// The SILFunction that we are currently inserting into if we have one.
///
/// If we are building into a block associated with a SILGlobalVariable this
/// will be a nullptr.
///
/// TODO: This can be made cleaner by using a PointerUnion or the like so we
/// can store the SILGlobalVariable here as well.
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;
Optional<SILLocation> CurDebugLocOverride = None;
public:
explicit SILBuilder(SILFunction &F)
: TempContext(F.getModule()), C(TempContext), F(&F), BB(nullptr) {}
SILBuilder(SILFunction &F, SmallVectorImpl<SILInstruction *> *InsertedInstrs)
: TempContext(F.getModule(), InsertedInstrs), C(TempContext), F(&F),
BB(nullptr) {}
explicit SILBuilder(SILInstruction *I,
SmallVectorImpl<SILInstruction *> *InsertedInstrs = 0)
: TempContext(I->getFunction()->getModule(), InsertedInstrs),
C(TempContext), F(I->getFunction()) {
setInsertionPoint(I);
}
explicit SILBuilder(SILBasicBlock::iterator I,
SmallVectorImpl<SILInstruction *> *InsertedInstrs = 0)
: SILBuilder(&*I, InsertedInstrs) {}
explicit SILBuilder(SILBasicBlock *BB,
SmallVectorImpl<SILInstruction *> *InsertedInstrs = 0)
: TempContext(BB->getParent()->getModule(), InsertedInstrs),
C(TempContext), F(BB->getParent()) {
setInsertionPoint(BB);
}
explicit SILBuilder(SILGlobalVariable *GlobVar,
SmallVectorImpl<SILInstruction *> *InsertedInstrs = 0);
SILBuilder(SILBasicBlock *BB, SILBasicBlock::iterator InsertPt,
SmallVectorImpl<SILInstruction *> *InsertedInstrs = 0)
: TempContext(BB->getParent()->getModule(), InsertedInstrs),
C(TempContext), F(BB->getParent()) {
setInsertionPoint(BB, InsertPt);
}
/// Build instructions before the given insertion point, inheriting the debug
/// location.
///
/// SILBuilderContext must outlive this SILBuilder instance.
SILBuilder(SILInstruction *I, const SILDebugScope *DS, SILBuilderContext &C)
: TempContext(C.getModule()), C(C), F(I->getFunction()) {
assert(DS && "instruction has no debug scope");
setCurrentDebugScope(DS);
setInsertionPoint(I);
}
SILBuilder(SILBasicBlock *BB, const SILDebugScope *DS, SILBuilder &B)
: SILBuilder(BB, DS, B.getBuilderContext()) {}
/// Build instructions before the given insertion point, inheriting the debug
/// location.
///
/// SILBuilderContext must outlive this SILBuilder instance.
SILBuilder(SILBasicBlock *BB, const SILDebugScope *DS, SILBuilderContext &C)
: TempContext(C.getModule()), C(C), F(BB->getParent()) {
assert(DS && "block has no debug scope");
setCurrentDebugScope(DS);
setInsertionPoint(BB);
}
// Allow a pass to override the current SIL module conventions. This should
// only be done by a pass responsible for lowering SIL to a new stage
// (e.g. AddressLowering).
void setSILConventions(SILModuleConventions silConv) { C.silConv = silConv; }
SILFunction &getFunction() const {
assert(F && "cannot create this instruction without a function context");
return *F;
}
bool isInsertingIntoGlobal() const { return F == nullptr; }
TypeExpansionContext getTypeExpansionContext() const {
return TypeExpansionContext(getFunction());
}
SILBuilderContext &getBuilderContext() const { return C; }
SILModule &getModule() const { return C.Module; }
ASTContext &getASTContext() const { return getModule().getASTContext(); }
const Lowering::TypeLowering &getTypeLowering(SILType T) const {
auto expansion = TypeExpansionContext::maximal(getModule().getSwiftModule(),
getModule().isWholeModule());
// If there's no current SILFunction, we're inserting into a global
// variable initializer.
if (F) {
expansion = TypeExpansionContext(getFunction());
}
return getModule().Types.getTypeLowering(T, expansion);
}
void setOpenedArchetypesTracker(SILOpenedArchetypesTracker *Tracker) {
C.setOpenedArchetypesTracker(Tracker);
}
SILOpenedArchetypesTracker *getOpenedArchetypesTracker() const {
return C.getOpenedArchetypesTracker();
}
SILOpenedArchetypesState &getOpenedArchetypes() { return C.OpenedArchetypes; }
void setCurrentDebugScope(const SILDebugScope *DS) { CurDebugScope = DS; }
const SILDebugScope *getCurrentDebugScope() const { return CurDebugScope; }
/// Apply a debug location override. If loc is None, the current override is
/// removed. Otherwise, newly created debug locations use the given location.
/// Note: the override location does not apply to debug_value[_addr].
void applyDebugLocOverride(Optional<SILLocation> loc) {
CurDebugLocOverride = loc;
}
/// Get the current debug location override.
Optional<SILLocation> getCurrentDebugLocOverride() const {
return CurDebugLocOverride;
}
/// 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();
if (!Scope && F)
Scope = F->getDebugScope();
auto overriddenLoc = CurDebugLocOverride ? *CurDebugLocOverride : Loc;
return SILDebugLocation(overriddenLoc, Scope);
}
/// If we have a SILFunction, return SILFunction::hasOwnership(). If we have a
/// SILGlobalVariable, just return false.
bool hasOwnership() const {
if (F)
return F->hasOwnership();
return false;
}
//===--------------------------------------------------------------------===//
// Insertion Point Management
//===--------------------------------------------------------------------===//
bool hasValidInsertionPoint() const { return BB != nullptr; }
SILBasicBlock *getInsertionBB() const { return BB; }
SILBasicBlock::iterator getInsertionPoint() const { return InsertPt; }
SILLocation getInsertionPointLoc() const { return InsertPt->getLoc(); }
/// 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;
if (InsertPt == BB->end())
return;
// Set the opened archetype context from the instruction.
addOpenedArchetypeOperands(&*InsertPt);
}
/// setInsertionPoint - Set the insertion point to insert before the specified
/// instruction.
void setInsertionPoint(SILInstruction *I) {
assert(I && "can't set insertion point to a null instruction");
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) {
assert(BB && "can't set insertion point to a null basic block");
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);
}
//===--------------------------------------------------------------------===//
// 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) {
C.InsertedInstrs = II;
}
SmallVectorImpl<SILInstruction *> *getTrackingList() {
return C.InsertedInstrs;
}
//===--------------------------------------------------------------------===//
// Opened archetypes handling
//===--------------------------------------------------------------------===//
void addOpenedArchetypeOperands(SILInstruction *I);
//===--------------------------------------------------------------------===//
// Type remapping
//===--------------------------------------------------------------------===//
static SILType getPartialApplyResultType(
TypeExpansionContext context, SILType Ty, unsigned ArgCount, SILModule &M,
SubstitutionMap subs, ParameterConvention calleeConvention,
PartialApplyInst::OnStackKind onStack =
PartialApplyInst::OnStackKind::NotOnStack);
//===--------------------------------------------------------------------===//
// 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());
}
/// 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);
}
/// 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();
/// Convenience for creating a fall-through basic block on-the-fly without
/// affecting the insertion point.
SILBasicBlock *createFallthroughBlock(SILLocation loc,
SILBasicBlock *targetBB) {
auto *newBB = F->createBasicBlock();
SILBuilder(newBB, this->getCurrentDebugScope(), this->getBuilderContext())
.createBranch(loc, targetBB);
return newBB;
}
//===--------------------------------------------------------------------===//
// SILInstruction Creation Methods
//===--------------------------------------------------------------------===//
AllocStackInst *createAllocStack(SILLocation Loc, SILType elementType,
Optional<SILDebugVariable> Var = None,
bool hasDynamicLifetime = false) {
Loc.markAsPrologue();
assert((!dyn_cast_or_null<VarDecl>(Loc.getAsASTNode<Decl>()) || Var) &&
"location is a VarDecl, but SILDebugVariable is empty");
return insert(AllocStackInst::create(getSILDebugLocation(Loc), elementType,
getFunction(), C.OpenedArchetypes,
Var, hasDynamicLifetime));
}
AllocRefInst *createAllocRef(SILLocation Loc, SILType ObjectType,
bool objc, bool canAllocOnStack,
ArrayRef<SILType> ElementTypes,
ArrayRef<SILValue> ElementCountOperands) {
// AllocRefInsts expand to function calls and can therefore not be
// counted towards the function prologue.
assert(!Loc.isInPrologue());
return insert(AllocRefInst::create(getSILDebugLocation(Loc), getFunction(),
ObjectType, objc, canAllocOnStack,
ElementTypes, ElementCountOperands,
C.OpenedArchetypes));
}
AllocRefDynamicInst *createAllocRefDynamic(SILLocation Loc, SILValue operand,
SILType type, bool objc,
ArrayRef<SILType> ElementTypes,
ArrayRef<SILValue> ElementCountOperands) {
// AllocRefDynamicInsts expand to function calls and can therefore
// not be counted towards the function prologue.
assert(!Loc.isInPrologue());
return insert(AllocRefDynamicInst::create(
getSILDebugLocation(Loc), *F, operand, type, objc, ElementTypes,
ElementCountOperands, C.OpenedArchetypes));
}
AllocValueBufferInst *
createAllocValueBuffer(SILLocation Loc, SILType valueType, SILValue operand) {
return insert(AllocValueBufferInst::create(
getSILDebugLocation(Loc), valueType, operand, *F, C.OpenedArchetypes));
}
AllocBoxInst *createAllocBox(SILLocation Loc, CanSILBoxType BoxType,
Optional<SILDebugVariable> Var = None,
bool hasDynamicLifetime = false) {
Loc.markAsPrologue();
assert((!dyn_cast_or_null<VarDecl>(Loc.getAsASTNode<Decl>()) || Var) &&
"location is a VarDecl, but SILDebugVariable is empty");
return insert(AllocBoxInst::create(getSILDebugLocation(Loc), BoxType, *F,
C.OpenedArchetypes, Var,
hasDynamicLifetime));
}
AllocExistentialBoxInst *
createAllocExistentialBox(SILLocation Loc, SILType ExistentialType,
CanType ConcreteType,
ArrayRef<ProtocolConformanceRef> Conformances) {
return insert(AllocExistentialBoxInst::create(
getSILDebugLocation(Loc), ExistentialType, ConcreteType, Conformances,
F, C.OpenedArchetypes));
}
ApplyInst *createApply(
SILLocation Loc, SILValue Fn, SubstitutionMap Subs,
ArrayRef<SILValue> Args, bool isNonThrowing = false,
const GenericSpecializationInformation *SpecializationInfo = nullptr) {
return insert(ApplyInst::create(getSILDebugLocation(Loc), Fn, Subs, Args,
isNonThrowing, C.silConv, *F,
C.OpenedArchetypes, SpecializationInfo));
}
TryApplyInst *createTryApply(
SILLocation Loc, SILValue fn, SubstitutionMap subs,
ArrayRef<SILValue> args, SILBasicBlock *normalBB, SILBasicBlock *errorBB,
const GenericSpecializationInformation *SpecializationInfo = nullptr) {
return insertTerminator(TryApplyInst::create(
getSILDebugLocation(Loc), fn, subs, args, normalBB, errorBB, *F,
C.OpenedArchetypes, SpecializationInfo));
}
PartialApplyInst *createPartialApply(
SILLocation Loc, SILValue Fn, SubstitutionMap Subs,
ArrayRef<SILValue> Args, ParameterConvention CalleeConvention,
PartialApplyInst::OnStackKind OnStack =
PartialApplyInst::OnStackKind::NotOnStack,
const GenericSpecializationInformation *SpecializationInfo = nullptr) {
return insert(PartialApplyInst::create(
getSILDebugLocation(Loc), Fn, Args, Subs, CalleeConvention, *F,
C.OpenedArchetypes, SpecializationInfo, OnStack));
}
BeginApplyInst *createBeginApply(
SILLocation Loc, SILValue Fn, SubstitutionMap Subs,
ArrayRef<SILValue> Args, bool isNonThrowing = false,
const GenericSpecializationInformation *SpecializationInfo = nullptr) {
return insert(BeginApplyInst::create(
getSILDebugLocation(Loc), Fn, Subs, Args, isNonThrowing, C.silConv, *F,
C.OpenedArchetypes, SpecializationInfo));
}
AbortApplyInst *createAbortApply(SILLocation loc, SILValue beginApply) {
return insert(new (getModule()) AbortApplyInst(getSILDebugLocation(loc),
beginApply));
}
EndApplyInst *createEndApply(SILLocation loc, SILValue beginApply) {
return insert(new (getModule()) EndApplyInst(getSILDebugLocation(loc),
beginApply));
}
BuiltinInst *createBuiltin(SILLocation Loc, Identifier Name, SILType ResultTy,
SubstitutionMap Subs,
ArrayRef<SILValue> Args) {
return insert(BuiltinInst::create(getSILDebugLocation(Loc), Name,
ResultTy, Subs, Args, getModule()));
}
/// 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;
appendOperandTypeName(OpdTy, NameStr);
auto Ident = C.getIdentifier(NameStr);
return insert(BuiltinInst::create(getSILDebugLocation(Loc), Ident, ResultTy,
{}, Args, getModule()));
}
// Create a binary function with the signature: OpdTy1, OpdTy2 -> ResultTy.
BuiltinInst *createBuiltinBinaryFunctionWithTwoOpTypes(
SILLocation Loc, StringRef Name, SILType OpdTy1, SILType OpdTy2,
SILType ResultTy, ArrayRef<SILValue> Args) {
auto &C = getASTContext();
llvm::SmallString<16> NameStr = Name;
appendOperandTypeName(OpdTy1, NameStr);
appendOperandTypeName(OpdTy2, NameStr);
auto Ident = C.getIdentifier(NameStr);
return insert(BuiltinInst::create(getSILDebugLocation(Loc), Ident,
ResultTy, {}, Args, getModule()));
}
/// 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().getASTType()->isBuiltinIntegerType(1) &&
"Must have a third Int1 operand");
SILType OpdTy = Args[0]->getType();
SILType Int1Ty = Args[2]->getType();
TupleTypeElt ResultElts[] = {OpdTy.getASTType(), Int1Ty.getASTType()};
Type ResultTy = TupleType::get(ResultElts, getASTContext());
SILType SILResultTy =
SILType::getPrimitiveObjectType(ResultTy->getCanonicalType());
return createBuiltinBinaryFunction(Loc, Name, OpdTy, SILResultTy, Args);
}
// Creates a dynamic_function_ref or function_ref depending on whether f is
// dynamically_replaceable.
FunctionRefBaseInst *createFunctionRefFor(SILLocation Loc, SILFunction *f) {
if (f->isDynamicallyReplaceable())
return createDynamicFunctionRef(Loc, f);
else
return createFunctionRef(Loc, f);
}
FunctionRefBaseInst *createFunctionRef(SILLocation Loc, SILFunction *f,
SILInstructionKind kind) {
if (kind == SILInstructionKind::FunctionRefInst)
return createFunctionRef(Loc, f);
else if (kind == SILInstructionKind::DynamicFunctionRefInst)
return createDynamicFunctionRef(Loc, f);
else if (kind == SILInstructionKind::PreviousDynamicFunctionRefInst)
return createPreviousDynamicFunctionRef(Loc, f);
assert(false && "Should not get here");
return nullptr;
}
FunctionRefInst *createFunctionRef(SILLocation Loc, SILFunction *f) {
return insert(new (getModule()) FunctionRefInst(getSILDebugLocation(Loc), f,
getTypeExpansionContext()));
}
DynamicFunctionRefInst *
createDynamicFunctionRef(SILLocation Loc, SILFunction *f) {
return insert(new (getModule()) DynamicFunctionRefInst(
getSILDebugLocation(Loc), f, getTypeExpansionContext()));
}
PreviousDynamicFunctionRefInst *
createPreviousDynamicFunctionRef(SILLocation Loc, SILFunction *f) {
return insert(new (getModule()) PreviousDynamicFunctionRefInst(
getSILDebugLocation(Loc), f, getTypeExpansionContext()));
}
AllocGlobalInst *createAllocGlobal(SILLocation Loc, SILGlobalVariable *g) {
return insert(new (getModule())
AllocGlobalInst(getSILDebugLocation(Loc), g));
}
GlobalAddrInst *createGlobalAddr(SILLocation Loc, SILGlobalVariable *g) {
return insert(new (getModule()) GlobalAddrInst(getSILDebugLocation(Loc), g,
getTypeExpansionContext()));
}
GlobalAddrInst *createGlobalAddr(SILLocation Loc, SILType Ty) {
return insert(new (F->getModule())
GlobalAddrInst(getSILDebugLocation(Loc), Ty));
}
GlobalValueInst *createGlobalValue(SILLocation Loc, SILGlobalVariable *g) {
return insert(new (getModule()) GlobalValueInst(getSILDebugLocation(Loc), g,
getTypeExpansionContext()));
}
BaseAddrForOffsetInst *createBaseAddrForOffset(SILLocation Loc, SILType Ty) {
return insert(new (F->getModule())
BaseAddrForOffsetInst(getSILDebugLocation(Loc), Ty));
}
IntegerLiteralInst *createIntegerLiteral(IntegerLiteralExpr *E);
IntegerLiteralInst *createIntegerLiteral(SILLocation Loc, SILType Ty,
intmax_t Value) {
return insert(
IntegerLiteralInst::create(getSILDebugLocation(Loc), Ty, Value,
getModule()));
}
IntegerLiteralInst *createIntegerLiteral(SILLocation Loc, SILType Ty,
const APInt &Value) {
return insert(
IntegerLiteralInst::create(getSILDebugLocation(Loc), Ty, Value,
getModule()));
}
FloatLiteralInst *createFloatLiteral(FloatLiteralExpr *E);
FloatLiteralInst *createFloatLiteral(SILLocation Loc, SILType Ty,
const APFloat &Value) {
return insert(
FloatLiteralInst::create(getSILDebugLocation(Loc), Ty, Value,
getModule()));
}
StringLiteralInst *createStringLiteral(SILLocation Loc, StringRef text,
StringLiteralInst::Encoding encoding) {
return insert(StringLiteralInst::create(getSILDebugLocation(Loc), text,
encoding, getModule()));
}
StringLiteralInst *createStringLiteral(SILLocation Loc, const Twine &text,
StringLiteralInst::Encoding encoding) {
SmallVector<char, 256> Out;
return insert(StringLiteralInst::create(
getSILDebugLocation(Loc), text.toStringRef(Out), encoding, getModule()));
}
/// If \p LV is non-trivial, return a \p Qualifier load of \p LV. If \p LV is
/// trivial, use trivial instead.
///
/// *NOTE* The SupportUnqualifiedSIL is an option to ease the bring up of
/// Semantic SIL. It enables a pass that must be able to run on both Semantic
/// SIL and non-Semantic SIL. It has a default argument of false, so if this
/// is not necessary for your pass, just ignore the parameter.
LoadInst *createTrivialLoadOr(SILLocation Loc, SILValue LV,
LoadOwnershipQualifier Qualifier,
bool SupportUnqualifiedSIL = false) {
if (SupportUnqualifiedSIL && !hasOwnership()) {
assert(
Qualifier != LoadOwnershipQualifier::Copy &&
"In unqualified SIL, a copy must be done separately form the load");
return createLoad(Loc, LV, LoadOwnershipQualifier::Unqualified);
}
if (LV->getType().isTrivial(getFunction())) {
return createLoad(Loc, LV, LoadOwnershipQualifier::Trivial);
}
return createLoad(Loc, LV, Qualifier);
}
LoadInst *createLoad(SILLocation Loc, SILValue LV,
LoadOwnershipQualifier Qualifier) {
assert((Qualifier != LoadOwnershipQualifier::Unqualified) ||
!hasOwnership() && "Unqualified inst in qualified function");
assert((Qualifier == LoadOwnershipQualifier::Unqualified) ||
hasOwnership() && "Qualified inst in unqualified function");
assert(isLoadableOrOpaque(LV->getType()));
return insert(new (getModule())
LoadInst(getSILDebugLocation(Loc), LV, Qualifier));
}
KeyPathInst *createKeyPath(SILLocation Loc,
KeyPathPattern *Pattern,
SubstitutionMap Subs,
ArrayRef<SILValue> Args,
SILType Ty) {
return insert(KeyPathInst::create(getSILDebugLocation(Loc),
Pattern, Subs, Args,
Ty, getFunction()));
}
/// Convenience function for calling emitLoad on the type lowering for
/// non-address values.
SILValue emitLoadValueOperation(SILLocation Loc, SILValue LV,
LoadOwnershipQualifier Qualifier) {
assert(isLoadableOrOpaque(LV->getType()));
const auto &lowering = getTypeLowering(LV->getType());
return lowering.emitLoad(*this, Loc, LV, Qualifier);
}
/// Convenience function for calling emitLoad on the type lowering for
/// non-address values.
SILValue emitLoweredLoadValueOperation(
SILLocation Loc, SILValue LV, LoadOwnershipQualifier Qualifier,
Lowering::TypeLowering::TypeExpansionKind ExpansionKind) {
assert(isLoadableOrOpaque(LV->getType()));
const auto &lowering = getTypeLowering(LV->getType());
return lowering.emitLoweredLoad(*this, Loc, LV, Qualifier, ExpansionKind);
}
/// Convenience function for calling emitLoweredStore on the type lowering for
/// non-address values.
void emitLoweredStoreValueOperation(
SILLocation Loc, SILValue Value, SILValue Addr,
StoreOwnershipQualifier Qual,
Lowering::TypeLowering::TypeExpansionKind ExpansionKind) {
assert(isLoadableOrOpaque(Value->getType()));
const auto &lowering = getTypeLowering(Value->getType());
lowering.emitLoweredStore(*this, Loc, Value, Addr, Qual, ExpansionKind);
}
LoadBorrowInst *createLoadBorrow(SILLocation Loc, SILValue LV) {
assert(isLoadableOrOpaque(LV->getType()) &&
!LV->getType().isTrivial(getFunction()));
return insert(new (getModule())
LoadBorrowInst(getSILDebugLocation(Loc), LV));
}
BeginBorrowInst *createBeginBorrow(SILLocation Loc, SILValue LV) {
assert(!LV->getType().isAddress());
return insert(new (getModule())
BeginBorrowInst(getSILDebugLocation(Loc), LV));
}
/// Convenience function for creating a load_borrow on non-trivial values and
/// load [trivial] on trivial values. Becomes load unqualified in non-ossa
/// functions.
SILValue emitLoadBorrowOperation(SILLocation loc, SILValue v) {
if (!hasOwnership()) {
return emitLoadValueOperation(loc, v,
LoadOwnershipQualifier::Unqualified);
}
if (v->getType().isTrivial(getFunction())) {
return emitLoadValueOperation(loc, v, LoadOwnershipQualifier::Trivial);
}
return createLoadBorrow(loc, v);
}
SILValue emitBeginBorrowOperation(SILLocation loc, SILValue v) {
if (!hasOwnership() ||
v.getOwnershipKind().isCompatibleWith(OwnershipKind::Guaranteed))
return v;
return createBeginBorrow(loc, v);
}
void emitEndBorrowOperation(SILLocation loc, SILValue v) {
if (!hasOwnership() || v.getOwnershipKind() == OwnershipKind::None)
return;
createEndBorrow(loc, v);
}
// Pass in an address or value, perform a begin_borrow/load_borrow and pass
// the value to the passed in closure. After the closure has finished
// executing, automatically insert the end_borrow. The closure can assume that
// it will receive a loaded loadable value.
void emitScopedBorrowOperation(SILLocation loc, SILValue original,
function_ref<void(SILValue)> &&fun);
/// Utility function that returns a trivial store if the stored type is
/// trivial and a \p Qualifier store if the stored type is non-trivial.
///
/// *NOTE* The SupportUnqualifiedSIL is an option to ease the bring up of
/// Semantic SIL. It enables a pass that must be able to run on both Semantic
/// SIL and non-Semantic SIL. It has a default argument of false, so if this
/// is not necessary for your pass, just ignore the parameter.
StoreInst *createTrivialStoreOr(SILLocation Loc, SILValue Src,
SILValue DestAddr,
StoreOwnershipQualifier Qualifier,
bool SupportUnqualifiedSIL = false) {
if (SupportUnqualifiedSIL && !hasOwnership()) {
assert(
Qualifier != StoreOwnershipQualifier::Assign &&
"In unqualified SIL, assigns must be represented via 2 instructions");
return createStore(Loc, Src, DestAddr,
StoreOwnershipQualifier::Unqualified);
}
if (Src->getType().isTrivial(getFunction())) {
return createStore(Loc, Src, DestAddr, StoreOwnershipQualifier::Trivial);
}
return createStore(Loc, Src, DestAddr, Qualifier);
}
StoreInst *createStore(SILLocation Loc, SILValue Src, SILValue DestAddr,
StoreOwnershipQualifier Qualifier) {
assert((Qualifier != StoreOwnershipQualifier::Unqualified) ||
!hasOwnership() && "Unqualified inst in qualified function");
assert((Qualifier == StoreOwnershipQualifier::Unqualified) ||
hasOwnership() && "Qualified inst in unqualified function");
return insert(new (getModule()) StoreInst(getSILDebugLocation(Loc), Src,
DestAddr, Qualifier));
}
/// Convenience function for calling emitStore on the type lowering for
/// non-address values.
void emitStoreValueOperation(SILLocation Loc, SILValue Src, SILValue DestAddr,
StoreOwnershipQualifier Qualifier) {
assert(!Src->getType().isAddress());
const auto &lowering = getTypeLowering(Src->getType());
return lowering.emitStore(*this, Loc, Src, DestAddr, Qualifier);
}
EndBorrowInst *createEndBorrow(SILLocation loc, SILValue borrowedValue) {
if (auto *arg = dyn_cast<SILPhiArgument>(borrowedValue)) {
if (auto *ti = arg->getSingleTerminator()) {
assert(!ti->isTransformationTerminator() &&
"Transforming terminators do not have end_borrow");
}
}
return insert(new (getModule())
EndBorrowInst(getSILDebugLocation(loc), borrowedValue));
}
BeginAccessInst *createBeginAccess(SILLocation loc, SILValue address,
SILAccessKind accessKind,
SILAccessEnforcement enforcement,
bool noNestedConflict,
bool fromBuiltin) {
return insert(new (getModule()) BeginAccessInst(
getSILDebugLocation(loc), address, accessKind, enforcement,
noNestedConflict, fromBuiltin));
}
EndAccessInst *createEndAccess(SILLocation loc, SILValue address,
bool aborted) {
return insert(new (getModule()) EndAccessInst(
getSILDebugLocation(loc), address, aborted));
}
BeginUnpairedAccessInst *
createBeginUnpairedAccess(SILLocation loc, SILValue address, SILValue buffer,
SILAccessKind accessKind,
SILAccessEnforcement enforcement,
bool noNestedConflict,
bool fromBuiltin) {
return insert(new (getModule()) BeginUnpairedAccessInst(
getSILDebugLocation(loc), address, buffer, accessKind, enforcement,
noNestedConflict, fromBuiltin));
}
EndUnpairedAccessInst *
createEndUnpairedAccess(SILLocation loc, SILValue buffer,
SILAccessEnforcement enforcement, bool aborted,
bool fromBuiltin) {
return insert(new (getModule()) EndUnpairedAccessInst(
getSILDebugLocation(loc), buffer, enforcement, aborted, fromBuiltin));
}
AssignInst *createAssign(SILLocation Loc, SILValue Src, SILValue DestAddr,
AssignOwnershipQualifier Qualifier) {
return insert(new (getModule())
AssignInst(getSILDebugLocation(Loc), Src, DestAddr,
Qualifier));
}
AssignByWrapperInst *createAssignByWrapper(SILLocation Loc,
SILValue Src, SILValue Dest,
SILValue Initializer,
SILValue Setter,
AssignOwnershipQualifier Qualifier) {
return insert(new (getModule())
AssignByWrapperInst(getSILDebugLocation(Loc), Src, Dest,
Initializer, Setter, Qualifier));
}
StoreBorrowInst *createStoreBorrow(SILLocation Loc, SILValue Src,
SILValue DestAddr) {
return insert(new (getModule())
StoreBorrowInst(getSILDebugLocation(Loc), Src, DestAddr));
}
/// A helper function for emitting store_borrow in operations where one must
/// handle both ossa and non-ossa code.
///
/// In words:
///
/// * If the function does not have ownership, this just emits an unqualified
/// store.
///
/// * If the function has ownership, but the type is trivial, use store
/// [trivial].
///
/// * Otherwise, emit an actual store_borrow.
void emitStoreBorrowOperation(SILLocation loc, SILValue src,
SILValue destAddr) {
if (!hasOwnership()) {
return emitStoreValueOperation(loc, src, destAddr,
StoreOwnershipQualifier::Unqualified);
}
if (src->getType().isTrivial(getFunction())) {
return emitStoreValueOperation(loc, src, destAddr,
StoreOwnershipQualifier::Trivial);
}
createStoreBorrow(loc, src, destAddr);
}
MarkUninitializedInst *
createMarkUninitialized(SILLocation Loc, SILValue src,
MarkUninitializedInst::Kind k) {
return insert(new (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);
}
MarkFunctionEscapeInst *createMarkFunctionEscape(SILLocation Loc,
ArrayRef<SILValue> vars) {
return insert(
MarkFunctionEscapeInst::create(getSILDebugLocation(Loc), vars, getFunction()));
}
DebugValueInst *createDebugValue(SILLocation Loc, SILValue src,
SILDebugVariable Var);
DebugValueAddrInst *createDebugValueAddr(SILLocation Loc, SILValue src,
SILDebugVariable Var);
/// Create a debug_value_addr if \p src is an address; a debug_value if not.
SILInstruction *emitDebugDescription(SILLocation Loc, SILValue src,
SILDebugVariable Var) {
if (src->getType().isAddress())
return createDebugValueAddr(Loc, src, Var);
return createDebugValue(Loc, src, Var);
}
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
Load##Name##Inst *createLoad##Name(SILLocation Loc, \
SILValue src, \
IsTake_t isTake) { \
return insert(new (getModule()) \
Load##Name##Inst(getSILDebugLocation(Loc), src, isTake)); \
} \
Store##Name##Inst *createStore##Name(SILLocation Loc, \
SILValue value, \
SILValue dest, \
IsInitialization_t isInit) { \
return insert(new (getModule()) \
Store##Name##Inst(getSILDebugLocation(Loc), value, dest, isInit)); \
}
#define LOADABLE_REF_STORAGE_HELPER(Name) \
Name##ToRefInst *create##Name##ToRef(SILLocation Loc, SILValue op, \
SILType ty) { \
return insert(new (getModule()) \
Name##ToRefInst(getSILDebugLocation(Loc), op, ty)); \
} \
RefTo##Name##Inst *createRefTo##Name(SILLocation Loc, SILValue op, \
SILType ty) { \
return insert(new (getModule()) \
RefTo##Name##Inst(getSILDebugLocation(Loc), op, ty)); \
} \
StrongCopy##Name##ValueInst *createStrongCopy##Name##Value( \
SILLocation Loc, SILValue operand) { \
auto type = getFunction().getLoweredType( \
operand->getType().getASTType().getReferenceStorageReferent()); \
return insert(new (getModule()) StrongCopy##Name##ValueInst( \
getSILDebugLocation(Loc), operand, type)); \
}
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
LOADABLE_REF_STORAGE_HELPER(Name) \
StrongRetain##Name##Inst *createStrongRetain##Name(SILLocation Loc, \
SILValue Operand, \
Atomicity atomicity) { \
return insert(new (getModule()) \
StrongRetain##Name##Inst(getSILDebugLocation(Loc), Operand, atomicity)); \
} \
Name##RetainInst *create##Name##Retain(SILLocation Loc, SILValue Operand, \
Atomicity atomicity) { \
return insert(new (getModule()) \
Name##RetainInst(getSILDebugLocation(Loc), Operand, atomicity)); \
} \
Name##ReleaseInst *create##Name##Release(SILLocation Loc, \
SILValue Operand, \
Atomicity atomicity) { \
return insert(new (getModule()) \
Name##ReleaseInst(getSILDebugLocation(Loc), Operand, atomicity)); \
}
#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, "...") \
ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, "...")
#define UNCHECKED_REF_STORAGE(Name, ...) \
LOADABLE_REF_STORAGE_HELPER(Name)
#include "swift/AST/ReferenceStorage.def"
#undef LOADABLE_REF_STORAGE_HELPER
CopyAddrInst *createCopyAddr(SILLocation Loc, SILValue srcAddr,
SILValue destAddr, IsTake_t isTake,
IsInitialization_t isInitialize) {
assert(srcAddr->getType() == destAddr->getType());
return insert(new (getModule()) CopyAddrInst(
getSILDebugLocation(Loc), srcAddr, destAddr, isTake, isInitialize));
}
BindMemoryInst *createBindMemory(SILLocation Loc, SILValue base,
SILValue index, SILType boundType) {
return insert(BindMemoryInst::create(getSILDebugLocation(Loc), base, index,
boundType, getFunction(),
C.OpenedArchetypes));
}
ConvertFunctionInst *createConvertFunction(SILLocation Loc, SILValue Op,
SILType Ty,
bool WithoutActuallyEscaping) {
return insert(ConvertFunctionInst::create(getSILDebugLocation(Loc), Op, Ty,
getFunction(), C.OpenedArchetypes,
WithoutActuallyEscaping));
}
ConvertEscapeToNoEscapeInst *
createConvertEscapeToNoEscape(SILLocation Loc, SILValue Op, SILType Ty,
bool lifetimeGuaranteed) {
return insert(ConvertEscapeToNoEscapeInst::create(
getSILDebugLocation(Loc), Op, Ty, getFunction(), C.OpenedArchetypes,
lifetimeGuaranteed));
}
ThinFunctionToPointerInst *
createThinFunctionToPointer(SILLocation Loc, SILValue Op, SILType Ty) {
return insert(new (getModule()) ThinFunctionToPointerInst(
getSILDebugLocation(Loc), Op, Ty));
}
PointerToThinFunctionInst *
createPointerToThinFunction(SILLocation Loc, SILValue Op, SILType Ty) {
return insert(PointerToThinFunctionInst::create(
getSILDebugLocation(Loc), Op, Ty, getFunction(), C.OpenedArchetypes));
}
UpcastInst *createUpcast(SILLocation Loc, SILValue Op, SILType Ty) {
return insert(UpcastInst::create(getSILDebugLocation(Loc), Op, Ty,
getFunction(), C.OpenedArchetypes));
}
AddressToPointerInst *createAddressToPointer(SILLocation Loc, SILValue Op,
SILType Ty) {
return insert(new (getModule()) AddressToPointerInst(
getSILDebugLocation(Loc), Op, Ty));
}
PointerToAddressInst *createPointerToAddress(SILLocation Loc, SILValue Op,
SILType Ty,
bool isStrict,
bool isInvariant = false){
return insert(new (getModule()) PointerToAddressInst(
getSILDebugLocation(Loc), Op, Ty, isStrict, isInvariant));
}
UncheckedRefCastInst *createUncheckedRefCast(SILLocation Loc, SILValue Op,
SILType Ty) {
return insert(UncheckedRefCastInst::create(
getSILDebugLocation(Loc), Op, Ty, getFunction(), C.OpenedArchetypes));
}
UncheckedRefCastAddrInst *
createUncheckedRefCastAddr(SILLocation Loc,
SILValue src, CanType sourceFormalType,
SILValue dest, CanType targetFormalType) {
return insert(UncheckedRefCastAddrInst::create(
getSILDebugLocation(Loc), src, sourceFormalType,
dest, targetFormalType, getFunction(), C.OpenedArchetypes));
}
UncheckedAddrCastInst *createUncheckedAddrCast(SILLocation Loc, SILValue Op,
SILType Ty) {
return insert(UncheckedAddrCastInst::create(
getSILDebugLocation(Loc), Op, Ty, getFunction(), C.OpenedArchetypes));
}
UncheckedTrivialBitCastInst *
createUncheckedTrivialBitCast(SILLocation Loc, SILValue Op, SILType Ty) {
return insert(UncheckedTrivialBitCastInst::create(
getSILDebugLocation(Loc), Op, Ty, getFunction(), C.OpenedArchetypes));
}
UncheckedBitwiseCastInst *
createUncheckedBitwiseCast(SILLocation Loc, SILValue Op, SILType Ty) {
return insert(UncheckedBitwiseCastInst::create(
getSILDebugLocation(Loc), Op, Ty, getFunction(), C.OpenedArchetypes));
}
UncheckedValueCastInst *createUncheckedValueCast(SILLocation Loc, SILValue Op,
SILType Ty) {
assert(hasOwnership());
return insert(UncheckedValueCastInst::create(
getSILDebugLocation(Loc), Op, Ty, getFunction(), C.OpenedArchetypes));
}
RefToBridgeObjectInst *createRefToBridgeObject(SILLocation Loc, SILValue Ref,
SILValue Bits) {
auto Ty = SILType::getBridgeObjectType(getASTContext());
return insert(new (getModule()) RefToBridgeObjectInst(
getSILDebugLocation(Loc), Ref, Bits, Ty));
}
BridgeObjectToRefInst *createBridgeObjectToRef(SILLocation Loc, SILValue Op,
SILType Ty) {
return insert(new (getModule()) BridgeObjectToRefInst(
getSILDebugLocation(Loc), Op, Ty));
}
ValueToBridgeObjectInst *createValueToBridgeObject(SILLocation Loc,
SILValue value) {
auto Ty = SILType::getBridgeObjectType(getASTContext());
return insert(new (getModule()) ValueToBridgeObjectInst(
getSILDebugLocation(Loc), value, 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 (getModule()) BridgeObjectToWordInst(
getSILDebugLocation(Loc), Op, Ty));
}
RefToRawPointerInst *createRefToRawPointer(SILLocation Loc, SILValue Op,
SILType Ty) {
return insert(new (getModule())
RefToRawPointerInst(getSILDebugLocation(Loc), Op, Ty));
}
RawPointerToRefInst *createRawPointerToRef(SILLocation Loc, SILValue Op,
SILType Ty) {
return insert(new (getModule())
RawPointerToRefInst(getSILDebugLocation(Loc), Op, Ty));
}
ThinToThickFunctionInst *createThinToThickFunction(SILLocation Loc,
SILValue Op, SILType Ty) {
return insert(ThinToThickFunctionInst::create(
getSILDebugLocation(Loc), Op, Ty, getFunction(), C.OpenedArchetypes));
}
ThickToObjCMetatypeInst *createThickToObjCMetatype(SILLocation Loc,
SILValue Op, SILType Ty) {
return insert(new (getModule()) ThickToObjCMetatypeInst(
getSILDebugLocation(Loc), Op, Ty));
}
ObjCToThickMetatypeInst *createObjCToThickMetatype(SILLocation Loc,
SILValue Op, SILType Ty) {
return insert(new (getModule()) ObjCToThickMetatypeInst(
getSILDebugLocation(Loc), Op, Ty));
}
ObjCProtocolInst *createObjCProtocol(SILLocation Loc, ProtocolDecl *P,
SILType Ty) {
return insert(new (getModule())
ObjCProtocolInst(getSILDebugLocation(Loc), P, Ty));
}
CopyValueInst *createCopyValue(SILLocation Loc, SILValue operand) {
assert(!operand->getType().isTrivial(getFunction()) &&
"Should not be passing trivial values to this api. Use instead "
"emitCopyValueOperation");
return insert(new (getModule())
CopyValueInst(getSILDebugLocation(Loc), operand));
}
DestroyValueInst *createDestroyValue(SILLocation Loc, SILValue operand) {
assert(isLoadableOrOpaque(operand->getType()));
assert(!operand->getType().isTrivial(getFunction()) &&
"Should not be passing trivial values to this api. Use instead "
"emitDestroyValueOperation");
return insert(new (getModule())
DestroyValueInst(getSILDebugLocation(Loc), operand));
}
UnconditionalCheckedCastInst *
createUnconditionalCheckedCast(SILLocation Loc, SILValue op,
SILType destLoweredTy,
CanType destFormalTy) {
return insert(UnconditionalCheckedCastInst::create(
getSILDebugLocation(Loc), op, destLoweredTy, destFormalTy,
getFunction(), C.OpenedArchetypes));
}
UnconditionalCheckedCastAddrInst *
createUnconditionalCheckedCastAddr(SILLocation Loc,
SILValue src, CanType sourceFormalType,
SILValue dest, CanType targetFormalType) {
return insert(UnconditionalCheckedCastAddrInst::create(
getSILDebugLocation(Loc), src, sourceFormalType,
dest, targetFormalType, getFunction(), C.OpenedArchetypes));
}
UnconditionalCheckedCastValueInst *
createUnconditionalCheckedCastValue(SILLocation Loc,
SILValue op, CanType srcFormalTy,
SILType destLoweredTy,
CanType destFormalTy) {
return insert(UnconditionalCheckedCastValueInst::create(
getSILDebugLocation(Loc), op, srcFormalTy,
destLoweredTy, destFormalTy,
getFunction(), C.OpenedArchetypes));
}
RetainValueInst *createRetainValue(SILLocation Loc, SILValue operand,
Atomicity atomicity) {
assert(!hasOwnership());
assert(isLoadableOrOpaque(operand->getType()));
return insert(new (getModule()) RetainValueInst(getSILDebugLocation(Loc),
operand, atomicity));
}
RetainValueAddrInst *createRetainValueAddr(SILLocation Loc, SILValue operand,
Atomicity atomicity) {
assert(!hasOwnership());
return insert(new (getModule()) RetainValueAddrInst(
getSILDebugLocation(Loc), operand, atomicity));
}
ReleaseValueInst *createReleaseValue(SILLocation Loc, SILValue operand,
Atomicity atomicity) {
assert(!hasOwnership());
assert(isLoadableOrOpaque(operand->getType()));
return insert(new (getModule()) ReleaseValueInst(getSILDebugLocation(Loc),
operand, atomicity));
}
ReleaseValueAddrInst *createReleaseValueAddr(SILLocation Loc,
SILValue operand,
Atomicity atomicity) {
assert(!hasOwnership());
return insert(new (getModule()) ReleaseValueAddrInst(
getSILDebugLocation(Loc), operand, atomicity));
}
UnmanagedRetainValueInst *createUnmanagedRetainValue(SILLocation Loc,
SILValue operand,
Atomicity atomicity) {
assert(hasOwnership());
assert(isLoadableOrOpaque(operand->getType()));
return insert(new (getModule()) UnmanagedRetainValueInst(
getSILDebugLocation(Loc), operand, atomicity));
}
UnmanagedReleaseValueInst *createUnmanagedReleaseValue(SILLocation Loc,
SILValue operand,
Atomicity atomicity) {
assert(hasOwnership());
assert(isLoadableOrOpaque(operand->getType()));
return insert(new (getModule()) UnmanagedReleaseValueInst(
getSILDebugLocation(Loc), operand, atomicity));
}
AutoreleaseValueInst *createAutoreleaseValue(SILLocation Loc,
SILValue operand,
Atomicity atomicity) {
return insert(new (getModule()) AutoreleaseValueInst(
getSILDebugLocation(Loc), operand, atomicity));
}
UnmanagedAutoreleaseValueInst *
createUnmanagedAutoreleaseValue(SILLocation Loc, SILValue operand,
Atomicity atomicity) {
return insert(new (getModule()) UnmanagedAutoreleaseValueInst(
getSILDebugLocation(Loc), operand, atomicity));
}
SetDeallocatingInst *createSetDeallocating(SILLocation Loc,
SILValue operand,
Atomicity atomicity) {
return insert(new (getModule()) SetDeallocatingInst(
getSILDebugLocation(Loc), operand, atomicity));
}
ObjectInst *createObject(SILLocation Loc, SILType Ty,
ArrayRef<SILValue> Elements,
unsigned NumBaseElements) {
return insert(ObjectInst::create(getSILDebugLocation(Loc), Ty, Elements,
NumBaseElements, getModule(),
hasOwnership()));
}
StructInst *createStruct(SILLocation Loc, SILType Ty,
ArrayRef<SILValue> Elements) {
assert(isLoadableOrOpaque(Ty));
return insert(StructInst::create(getSILDebugLocation(Loc), Ty, Elements,
getModule(), hasOwnership()));
}
TupleInst *createTuple(SILLocation Loc, SILType Ty,
ArrayRef<SILValue> Elements) {
assert(isLoadableOrOpaque(Ty));
return insert(TupleInst::create(getSILDebugLocation(Loc), Ty, Elements,
getModule(), hasOwnership()));
}
TupleInst *createTuple(SILLocation loc, ArrayRef<SILValue> elts);
EnumInst *createEnum(SILLocation Loc, SILValue Operand,
EnumElementDecl *Element, SILType Ty) {
assert(isLoadableOrOpaque(Ty));
return insert(new (getModule()) EnumInst(getSILDebugLocation(Loc),
Operand, Element, Ty));
}
/// Inject a loadable value into the corresponding optional type.
EnumInst *createOptionalSome(SILLocation Loc, SILValue operand, SILType ty) {
assert(isLoadableOrOpaque(ty));
auto someDecl = getModule().getASTContext().getOptionalSomeDecl();
return createEnum(Loc, operand, someDecl, ty);
}
/// Create the nil value of a loadable optional type.
EnumInst *createOptionalNone(SILLocation Loc, SILType ty) {
assert(isLoadableOrOpaque(ty));
auto noneDecl = getModule().getASTContext().getOptionalNoneDecl();
return createEnum(Loc, nullptr, noneDecl, ty);
}
InitEnumDataAddrInst *createInitEnumDataAddr(SILLocation Loc,
SILValue Operand,
EnumElementDecl *Element,
SILType Ty) {
return insert(new (getModule()) InitEnumDataAddrInst(
getSILDebugLocation(Loc), Operand, Element, Ty));
}
UncheckedEnumDataInst *createUncheckedEnumData(SILLocation Loc,
SILValue Operand,
EnumElementDecl *Element,
SILType Ty) {
assert(isLoadableOrOpaque(Ty));
return insert(new (getModule()) UncheckedEnumDataInst(
getSILDebugLocation(Loc), Operand, Element, Ty));
}
UncheckedEnumDataInst *createUncheckedEnumData(SILLocation Loc,
SILValue Operand,
EnumElementDecl *Element) {
SILType EltType = Operand->getType().getEnumElementType(
Element, getModule(), getTypeExpansionContext());
return createUncheckedEnumData(Loc, Operand, Element, EltType);
}
/// Return unchecked_enum_data %Operand, #Optional<T>.some.
SILValue emitExtractOptionalPayloadOperation(SILLocation Loc,
SILValue Operand) {
auto *Decl = F->getASTContext().getOptionalSomeDecl();
return createUncheckedEnumData(Loc, Operand, Decl);
}
UncheckedTakeEnumDataAddrInst *
createUncheckedTakeEnumDataAddr(SILLocation Loc, SILValue Operand,
EnumElementDecl *Element, SILType Ty) {
return insert(new (getModule()) UncheckedTakeEnumDataAddrInst(
getSILDebugLocation(Loc), Operand, Element, Ty));
}
UncheckedTakeEnumDataAddrInst *
createUncheckedTakeEnumDataAddr(SILLocation Loc, SILValue Operand,
EnumElementDecl *Element) {
SILType EltType = Operand->getType().getEnumElementType(
Element, getModule(), getTypeExpansionContext());
return createUncheckedTakeEnumDataAddr(Loc, Operand, Element, EltType);
}
InjectEnumAddrInst *createInjectEnumAddr(SILLocation Loc, SILValue Operand,
EnumElementDecl *Element) {
return insert(new (getModule()) InjectEnumAddrInst(
getSILDebugLocation(Loc), Operand, Element));
}
SelectEnumInst *
createSelectEnum(SILLocation Loc, SILValue Operand, SILType Ty,
SILValue DefaultValue,
ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
Optional<ArrayRef<ProfileCounter>> CaseCounts = None,
ProfileCounter DefaultCount = ProfileCounter()) {
assert(isLoadableOrOpaque(Ty));
return insert(SelectEnumInst::create(
getSILDebugLocation(Loc), Operand, Ty, DefaultValue, CaseValues,
getModule(), CaseCounts, DefaultCount, hasOwnership()));
}
SelectEnumAddrInst *createSelectEnumAddr(
SILLocation Loc, SILValue Operand, SILType Ty, SILValue DefaultValue,
ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
Optional<ArrayRef<ProfileCounter>> CaseCounts = None,
ProfileCounter DefaultCount = ProfileCounter()) {
return insert(SelectEnumAddrInst::create(
getSILDebugLocation(Loc), Operand, Ty, DefaultValue, CaseValues,
getModule(), CaseCounts, DefaultCount));
}
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,
getModule(), hasOwnership()));
}
TupleExtractInst *createTupleExtract(SILLocation Loc, SILValue Operand,
unsigned FieldNo, SILType ResultTy) {
return insert(new (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 (getModule()) TupleElementAddrInst(
getSILDebugLocation(Loc), Operand, FieldNo, ResultTy));
}
TupleElementAddrInst *
createTupleElementAddr(SILLocation Loc, SILValue Operand, unsigned FieldNo) {
return insert(new (getModule()) TupleElementAddrInst(
getSILDebugLocation(Loc), Operand, FieldNo,
Operand->getType().getTupleElementType(FieldNo)));
}
StructExtractInst *createStructExtract(SILLocation Loc, SILValue Operand,
VarDecl *Field, SILType ResultTy) {
return insert(new (getModule()) StructExtractInst(
getSILDebugLocation(Loc), Operand, Field, ResultTy));
}
StructExtractInst *createStructExtract(SILLocation Loc, SILValue Operand,
VarDecl *Field) {
auto type = Operand->getType().getFieldType(Field, getModule(),
getTypeExpansionContext());
return createStructExtract(Loc, Operand, Field, type);
}
StructElementAddrInst *createStructElementAddr(SILLocation Loc,
SILValue Operand,
VarDecl *Field,
SILType ResultTy) {
return insert(new (getModule()) StructElementAddrInst(
getSILDebugLocation(Loc), Operand, Field, ResultTy));
}
StructElementAddrInst *
createStructElementAddr(SILLocation Loc, SILValue Operand, VarDecl *Field) {
auto ResultTy = Operand->getType().getFieldType(Field, getModule(),
getTypeExpansionContext());
return createStructElementAddr(Loc, Operand, Field, ResultTy);
}
RefElementAddrInst *createRefElementAddr(SILLocation Loc, SILValue Operand,
VarDecl *Field, SILType ResultTy,
bool IsImmutable = false) {
return insert(new (getModule()) RefElementAddrInst(
getSILDebugLocation(Loc), Operand, Field, ResultTy, IsImmutable));
}
RefElementAddrInst *createRefElementAddr(SILLocation Loc, SILValue Operand,
VarDecl *Field) {
auto ResultTy = Operand->getType().getFieldType(Field, getModule(),
getTypeExpansionContext());
return createRefElementAddr(Loc, Operand, Field, ResultTy);
}
RefTailAddrInst *createRefTailAddr(SILLocation Loc, SILValue Ref,
SILType ResultTy,
bool IsImmutable = false) {
return insert(new (getModule()) RefTailAddrInst(getSILDebugLocation(Loc),
Ref, ResultTy, IsImmutable));
}
DestructureStructInst *createDestructureStruct(SILLocation Loc,
SILValue Operand) {
return insert(DestructureStructInst::create(
getFunction(), getSILDebugLocation(Loc), Operand));
}
DestructureTupleInst *createDestructureTuple(SILLocation Loc,
SILValue Operand) {
return insert(DestructureTupleInst::create(
getFunction(), getSILDebugLocation(Loc), Operand));
}
MultipleValueInstruction *emitDestructureValueOperation(SILLocation loc,
SILValue operand) {
// If you hit this assert, you are using the wrong method. Use instead:
//
// emitDestructureValueOperation(SILLocation, SILValue,
// SmallVectorImpl<SILValue> &);
assert(hasOwnership() && "Expected to be called in ownership code only.");
SILType opTy = operand->getType();
if (opTy.is<TupleType>())
return createDestructureTuple(loc, operand);
if (opTy.getStructOrBoundGenericStruct())
return createDestructureStruct(loc, operand);
llvm_unreachable("Can not emit a destructure for this type of operand.");
}
void
emitDestructureValueOperation(SILLocation loc, SILValue operand,
function_ref<void(unsigned, SILValue)> func);
void emitDestructureValueOperation(SILLocation loc, SILValue operand,
SmallVectorImpl<SILValue> &result);
void emitDestructureAddressOperation(SILLocation loc, SILValue operand,
SmallVectorImpl<SILValue> &result);
ClassMethodInst *createClassMethod(SILLocation Loc, SILValue Operand,
SILDeclRef Member, SILType MethodTy) {
return insert(new (getModule()) ClassMethodInst(
getSILDebugLocation(Loc), Operand, Member, MethodTy));
}
SuperMethodInst *createSuperMethod(SILLocation Loc, SILValue Operand,
SILDeclRef Member, SILType MethodTy) {
return insert(new (getModule()) SuperMethodInst(
getSILDebugLocation(Loc), Operand, Member, MethodTy));
}
ObjCMethodInst *createObjCMethod(SILLocation Loc, SILValue Operand,
SILDeclRef Member, SILType MethodTy) {
return insert(ObjCMethodInst::create(getSILDebugLocation(Loc), Operand,
Member, MethodTy, &getFunction(),
C.OpenedArchetypes));
}
ObjCSuperMethodInst *createObjCSuperMethod(SILLocation Loc, SILValue Operand,
SILDeclRef Member, SILType MethodTy) {
return insert(new (getModule()) ObjCSuperMethodInst(
getSILDebugLocation(Loc), Operand, Member, MethodTy));
}
WitnessMethodInst *createWitnessMethod(SILLocation Loc, CanType LookupTy,
ProtocolConformanceRef Conformance,
SILDeclRef Member, SILType MethodTy) {
return insert(WitnessMethodInst::create(
getSILDebugLocation(Loc), LookupTy, Conformance, Member, MethodTy,
&getFunction(), C.OpenedArchetypes));
}
OpenExistentialAddrInst *
createOpenExistentialAddr(SILLocation Loc, SILValue Operand, SILType SelfTy,
OpenedExistentialAccess ForAccess) {
auto *I = insert(new (getModule()) OpenExistentialAddrInst(
getSILDebugLocation(Loc), Operand, SelfTy, ForAccess));
if (C.OpenedArchetypesTracker)
C.OpenedArchetypesTracker->registerOpenedArchetypes(I);
return I;
}
OpenExistentialValueInst *createOpenExistentialValue(SILLocation Loc,
SILValue Operand,
SILType SelfTy) {
auto *I = insert(new (getModule()) OpenExistentialValueInst(
getSILDebugLocation(Loc), Operand, SelfTy));
if (C.OpenedArchetypesTracker)
C.OpenedArchetypesTracker->registerOpenedArchetypes(I);
return I;
}
OpenExistentialMetatypeInst *createOpenExistentialMetatype(SILLocation Loc,
SILValue operand,
SILType selfTy) {
auto *I = insert(new (getModule()) OpenExistentialMetatypeInst(
getSILDebugLocation(Loc), operand, selfTy));
if (C.OpenedArchetypesTracker)
C.OpenedArchetypesTracker->registerOpenedArchetypes(I);
return I;
}
OpenExistentialRefInst *
createOpenExistentialRef(SILLocation Loc, SILValue Operand, SILType Ty) {
auto *I = insert(new (getModule()) OpenExistentialRefInst(
getSILDebugLocation(Loc), Operand, Ty, hasOwnership()));
if (C.OpenedArchetypesTracker)
C.OpenedArchetypesTracker->registerOpenedArchetypes(I);
return I;
}
OpenExistentialBoxInst *
createOpenExistentialBox(SILLocation Loc, SILValue Operand, SILType Ty) {
auto *I = insert(new (getModule()) OpenExistentialBoxInst(
getSILDebugLocation(Loc), Operand, Ty));
if (C.OpenedArchetypesTracker)
C.OpenedArchetypesTracker->registerOpenedArchetypes(I);
return I;
}
OpenExistentialBoxValueInst *
createOpenExistentialBoxValue(SILLocation Loc, SILValue Operand, SILType Ty) {
auto *I = insert(new (getModule()) OpenExistentialBoxValueInst(
getSILDebugLocation(Loc), Operand, Ty));
if (C.OpenedArchetypesTracker)
C.OpenedArchetypesTracker->registerOpenedArchetypes(I);
return I;
}
InitExistentialAddrInst *
createInitExistentialAddr(SILLocation Loc, SILValue Existential,
CanType FormalConcreteType,
SILType LoweredConcreteType,
ArrayRef<ProtocolConformanceRef> Conformances) {
return insert(InitExistentialAddrInst::create(
getSILDebugLocation(Loc), Existential, FormalConcreteType,
LoweredConcreteType, Conformances, &getFunction(), C.OpenedArchetypes));
}
InitExistentialValueInst *
createInitExistentialValue(SILLocation Loc, SILType ExistentialType,
CanType FormalConcreteType, SILValue Concrete,
ArrayRef<ProtocolConformanceRef> Conformances) {
return insert(InitExistentialValueInst::create(
getSILDebugLocation(Loc), ExistentialType, FormalConcreteType, Concrete,
Conformances, &getFunction(), C.OpenedArchetypes));
}
InitExistentialMetatypeInst *
createInitExistentialMetatype(SILLocation Loc, SILValue metatype,
SILType existentialType,
ArrayRef<ProtocolConformanceRef> conformances) {
return insert(InitExistentialMetatypeInst::create(
getSILDebugLocation(Loc), existentialType, metatype, conformances,
&getFunction(), C.OpenedArchetypes));
}
InitExistentialRefInst *
createInitExistentialRef(SILLocation Loc, SILType ExistentialType,
CanType FormalConcreteType, SILValue Concrete,
ArrayRef<ProtocolConformanceRef> Conformances) {
return insert(InitExistentialRefInst::create(
getSILDebugLocation(Loc), ExistentialType, FormalConcreteType, Concrete,
Conformances, &getFunction(), C.OpenedArchetypes));
}
DeinitExistentialAddrInst *createDeinitExistentialAddr(SILLocation Loc,
SILValue Existential) {
return insert(new (getModule()) DeinitExistentialAddrInst(
getSILDebugLocation(Loc), Existential));
}
DeinitExistentialValueInst *
createDeinitExistentialValue(SILLocation Loc, SILValue Existential) {
return insert(new (getModule()) DeinitExistentialValueInst(
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 (getModule()) ProjectBlockStorageInst(
getSILDebugLocation(Loc), Storage, CaptureTy));
}
InitBlockStorageHeaderInst *
createInitBlockStorageHeader(SILLocation Loc, SILValue BlockStorage,
SILValue InvokeFunction, SILType BlockType,
SubstitutionMap Subs) {
return insert(InitBlockStorageHeaderInst::create(getFunction(),
getSILDebugLocation(Loc), BlockStorage, InvokeFunction, BlockType, Subs));
}
MetatypeInst *createMetatype(SILLocation Loc, SILType Metatype) {
return insert(MetatypeInst::create(getSILDebugLocation(Loc), Metatype,
&getFunction(), C.OpenedArchetypes));
}
ObjCMetatypeToObjectInst *
createObjCMetatypeToObject(SILLocation Loc, SILValue Op, SILType Ty) {
return insert(new (getModule()) ObjCMetatypeToObjectInst(
getSILDebugLocation(Loc), Op, Ty));
}
ObjCExistentialMetatypeToObjectInst *
createObjCExistentialMetatypeToObject(SILLocation Loc, SILValue Op,
SILType Ty) {
return insert(new (getModule()) ObjCExistentialMetatypeToObjectInst(
getSILDebugLocation(Loc), Op, Ty));
}
ValueMetatypeInst *createValueMetatype(SILLocation Loc, SILType Metatype,
SILValue Base);
ExistentialMetatypeInst *
createExistentialMetatype(SILLocation Loc, SILType Metatype, SILValue Base) {
return insert(new (getModule()) ExistentialMetatypeInst(
getSILDebugLocation(Loc), Metatype, Base));
}
CopyBlockInst *createCopyBlock(SILLocation Loc, SILValue Operand) {
return insert(new (getModule())
CopyBlockInst(getSILDebugLocation(Loc), Operand));
}
CopyBlockWithoutEscapingInst *
createCopyBlockWithoutEscaping(SILLocation Loc, SILValue Block,
SILValue Closure) {
return insert(new (getModule()) CopyBlockWithoutEscapingInst(
getSILDebugLocation(Loc), Block, Closure));
}
StrongRetainInst *createStrongRetain(SILLocation Loc, SILValue Operand,
Atomicity atomicity) {
assert(!hasOwnership());
return insert(new (getModule()) StrongRetainInst(getSILDebugLocation(Loc),
Operand, atomicity));
}
StrongReleaseInst *createStrongRelease(SILLocation Loc, SILValue Operand,
Atomicity atomicity) {
assert(!hasOwnership());
return insert(new (getModule()) StrongReleaseInst(
getSILDebugLocation(Loc), Operand, atomicity));
}
EndLifetimeInst *createEndLifetime(SILLocation Loc, SILValue Operand) {
return insert(new (getModule())
EndLifetimeInst(getSILDebugLocation(Loc), Operand));
}
UncheckedOwnershipConversionInst *
createUncheckedOwnershipConversion(SILLocation Loc, SILValue Operand,
ValueOwnershipKind Kind) {
return insert(new (getModule()) UncheckedOwnershipConversionInst(
getSILDebugLocation(Loc), Operand, Kind));
}
FixLifetimeInst *createFixLifetime(SILLocation Loc, SILValue Operand) {
return insert(new (getModule())
FixLifetimeInst(getSILDebugLocation(Loc), Operand));
}
void emitFixLifetime(SILLocation Loc, SILValue Operand) {
if (getTypeLowering(Operand->getType()).isTrivial())
return;
createFixLifetime(Loc, Operand);
}
ClassifyBridgeObjectInst *createClassifyBridgeObject(SILLocation Loc,
SILValue value);
MarkDependenceInst *createMarkDependence(SILLocation Loc, SILValue value,
SILValue base) {
return insert(new (getModule()) MarkDependenceInst(
getSILDebugLocation(Loc), value, base));
}
IsUniqueInst *createIsUnique(SILLocation Loc, SILValue operand) {
auto Int1Ty = SILType::getBuiltinIntegerType(1, getASTContext());
return insert(new (getModule()) IsUniqueInst(getSILDebugLocation(Loc),
operand, Int1Ty));
}
BeginCOWMutationInst *createBeginCOWMutation(SILLocation Loc,
SILValue operand, bool isNative) {
auto Int1Ty = SILType::getBuiltinIntegerType(1, getASTContext());
return insert(BeginCOWMutationInst::create(getSILDebugLocation(Loc), operand,
Int1Ty, getFunction(), isNative));
}
EndCOWMutationInst *createEndCOWMutation(SILLocation Loc, SILValue operand,
bool keepUnique = false) {
return insert(new (getModule()) EndCOWMutationInst(getSILDebugLocation(Loc),
operand, keepUnique));
}
IsEscapingClosureInst *createIsEscapingClosure(SILLocation Loc,
SILValue operand,
unsigned VerificationType) {
auto Int1Ty = SILType::getBuiltinIntegerType(1, getASTContext());
return insert(new (getModule()) IsEscapingClosureInst(
getSILDebugLocation(Loc), operand, Int1Ty, VerificationType));
}
DeallocStackInst *createDeallocStack(SILLocation Loc, SILValue operand) {
return insert(new (getModule())
DeallocStackInst(getSILDebugLocation(Loc), operand));
}
DeallocRefInst *createDeallocRef(SILLocation Loc, SILValue operand,
bool canBeOnStack) {
return insert(new (getModule()) DeallocRefInst(
getSILDebugLocation(Loc), operand, canBeOnStack));
}
DeallocPartialRefInst *createDeallocPartialRef(SILLocation Loc,
SILValue operand,
SILValue metatype) {
return insert(new (getModule()) DeallocPartialRefInst(
getSILDebugLocation(Loc), operand, metatype));
}
DeallocBoxInst *createDeallocBox(SILLocation Loc,
SILValue operand) {
return insert(new (getModule()) DeallocBoxInst(
getSILDebugLocation(Loc), operand));
}
DeallocExistentialBoxInst *createDeallocExistentialBox(SILLocation Loc,
CanType concreteType,
SILValue operand) {
return insert(new (getModule()) DeallocExistentialBoxInst(
getSILDebugLocation(Loc), concreteType, operand));
}
DeallocValueBufferInst *createDeallocValueBuffer(SILLocation Loc,
SILType valueType,
SILValue operand) {
return insert(new (getModule()) DeallocValueBufferInst(
getSILDebugLocation(Loc), valueType, operand));
}
DestroyAddrInst *createDestroyAddr(SILLocation Loc, SILValue Operand) {
return insert(new (getModule())
DestroyAddrInst(getSILDebugLocation(Loc), Operand));
}
ProjectValueBufferInst *createProjectValueBuffer(SILLocation Loc,
SILType valueType,
SILValue operand) {
return insert(new (getModule()) ProjectValueBufferInst(
getSILDebugLocation(Loc), valueType, operand));
}
ProjectBoxInst *createProjectBox(SILLocation Loc, SILValue boxOperand,
unsigned index);
ProjectExistentialBoxInst *createProjectExistentialBox(SILLocation Loc,
SILType valueTy,
SILValue boxOperand) {
return insert(new (getModule()) ProjectExistentialBoxInst(
getSILDebugLocation(Loc), valueTy, boxOperand));
}
//===--------------------------------------------------------------------===//
// Unchecked cast helpers
//===--------------------------------------------------------------------===//
/// Create the appropriate cast instruction based on result type.
///
/// NOTE: We allow for non-layout compatible casts that shrink the underlying
/// type we are bit casting!
SingleValueInstruction *
createUncheckedReinterpretCast(SILLocation Loc, SILValue Op, SILType Ty);
/// Create an appropriate cast instruction based on result type.
///
/// NOTE: This assumes that the input and the result cast are layout
/// compatible. Reduces to createUncheckedReinterpretCast when ownership is
/// disabled.
SingleValueInstruction *createUncheckedBitCast(SILLocation Loc, SILValue Op,
SILType Ty);
//===--------------------------------------------------------------------===//
// Runtime failure
//===--------------------------------------------------------------------===//
CondFailInst *createCondFail(SILLocation Loc, SILValue Operand,
StringRef Message, bool Inverted = false) {
if (Inverted) {
SILType Ty = Operand->getType();
SILValue True(createIntegerLiteral(Loc, Ty, 1));
Operand =
createBuiltinBinaryFunction(Loc, "xor", Ty, Ty, {Operand, True});
}
return insert(CondFailInst::create(getSILDebugLocation(Loc), Operand,
Message, getModule()));
}
BuiltinInst *createBuiltinTrap(SILLocation Loc) {
ASTContext &AST = getASTContext();
auto Id_trap = AST.getIdentifier("int_trap");
return createBuiltin(Loc, Id_trap, getModule().Types.getEmptyTupleType(),
{}, {});
}
//===--------------------------------------------------------------------===//
// Array indexing instructions
//===--------------------------------------------------------------------===//
IndexAddrInst *createIndexAddr(SILLocation Loc, SILValue Operand,
SILValue Index) {
return insert(new (getModule()) IndexAddrInst(getSILDebugLocation(Loc),
Operand, Index));
}
TailAddrInst *createTailAddr(SILLocation Loc, SILValue Operand,
SILValue Count, SILType ResultTy) {
return insert(new (getModule()) TailAddrInst(getSILDebugLocation(Loc),
Operand, Count, ResultTy));
}
IndexRawPointerInst *createIndexRawPointer(SILLocation Loc, SILValue Operand,
SILValue Index) {
return insert(new (getModule()) IndexRawPointerInst(
getSILDebugLocation(Loc), Operand, Index));
}
//===--------------------------------------------------------------------===//
// Concurrency instructions
//===--------------------------------------------------------------------===//
GetAsyncContinuationInst *createGetAsyncContinuation(SILLocation Loc,
CanType ResumeType,
bool Throws) {
auto ContinuationType = SILType::getPrimitiveObjectType(
getASTContext().TheRawUnsafeContinuationType);
return insert(new (getModule()) GetAsyncContinuationInst(getSILDebugLocation(Loc),
ContinuationType,
ResumeType,
Throws));
}
GetAsyncContinuationAddrInst *createGetAsyncContinuationAddr(SILLocation Loc,
SILValue Operand,
CanType ResumeType,
bool Throws) {
auto ContinuationType = SILType::getPrimitiveObjectType(
getASTContext().TheRawUnsafeContinuationType);
return insert(new (getModule()) GetAsyncContinuationAddrInst(getSILDebugLocation(Loc),
Operand,
ContinuationType,
ResumeType,
Throws));
}
HopToExecutorInst *createHopToExecutor(SILLocation Loc, SILValue Actor) {
return insert(new (getModule()) HopToExecutorInst(getSILDebugLocation(Loc),
Actor, hasOwnership()));
}
//===--------------------------------------------------------------------===//
// Terminator SILInstruction Creation Methods
//===--------------------------------------------------------------------===//
UnreachableInst *createUnreachable(SILLocation Loc) {
return insertTerminator(new (getModule())
UnreachableInst(getSILDebugLocation(Loc)));
}
ReturnInst *createReturn(SILLocation Loc, SILValue ReturnValue) {
return insertTerminator(new (getModule()) ReturnInst(
getFunction(), getSILDebugLocation(Loc), ReturnValue));
}
ThrowInst *createThrow(SILLocation Loc, SILValue errorValue) {
return insertTerminator(
new (getModule()) ThrowInst(getSILDebugLocation(Loc), errorValue));
}
UnwindInst *createUnwind(SILLocation loc) {
return insertTerminator(
new (getModule()) UnwindInst(getSILDebugLocation(loc)));
}
YieldInst *createYield(SILLocation loc, ArrayRef<SILValue> yieldedValues,
SILBasicBlock *resumeBB, SILBasicBlock *unwindBB) {
return insertTerminator(
YieldInst::create(getSILDebugLocation(loc), yieldedValues,
resumeBB, unwindBB, getFunction()));
}
AwaitAsyncContinuationInst *createAwaitAsyncContinuation(SILLocation loc,
SILValue continuation,
SILBasicBlock *resumeBB,
SILBasicBlock *errorBB) {
return insertTerminator(
new (getModule()) AwaitAsyncContinuationInst(getSILDebugLocation(loc),
continuation,
resumeBB, errorBB));
}
CondBranchInst *
createCondBranch(SILLocation Loc, SILValue Cond, SILBasicBlock *Target1,
SILBasicBlock *Target2,
ProfileCounter Target1Count = ProfileCounter(),
ProfileCounter Target2Count = ProfileCounter()) {
return insertTerminator(
CondBranchInst::create(getSILDebugLocation(Loc), Cond, Target1, Target2,
Target1Count, Target2Count, getFunction()));
}
CondBranchInst *
createCondBranch(SILLocation Loc, SILValue Cond, SILBasicBlock *Target1,
ArrayRef<SILValue> Args1, SILBasicBlock *Target2,
ArrayRef<SILValue> Args2,
ProfileCounter Target1Count = ProfileCounter(),
ProfileCounter Target2Count = ProfileCounter()) {
return insertTerminator(
CondBranchInst::create(getSILDebugLocation(Loc), Cond, Target1, Args1,
Target2, Args2, Target1Count, Target2Count, getFunction()));
}
CondBranchInst *
createCondBranch(SILLocation Loc, SILValue Cond, SILBasicBlock *Target1,
OperandValueArrayRef Args1, SILBasicBlock *Target2,
OperandValueArrayRef Args2,
ProfileCounter Target1Count = ProfileCounter(),
ProfileCounter Target2Count = ProfileCounter()) {
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,
Target1Count, Target2Count, getFunction()));
}
BranchInst *createBranch(SILLocation Loc, SILBasicBlock *TargetBlock) {
return insertTerminator(
BranchInst::create(getSILDebugLocation(Loc), TargetBlock, getFunction()));
}
BranchInst *createBranch(SILLocation Loc, SILBasicBlock *TargetBlock,
ArrayRef<SILValue> Args) {
return insertTerminator(
BranchInst::create(getSILDebugLocation(Loc), TargetBlock, Args,
getFunction()));
}
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, getFunction()));
}
SwitchEnumInst *createSwitchEnum(
SILLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
Optional<ArrayRef<ProfileCounter>> CaseCounts = None,
ProfileCounter DefaultCount = ProfileCounter()) {
return insertTerminator(SwitchEnumInst::create(
getSILDebugLocation(Loc), Operand, DefaultBB, CaseBBs, getFunction(),
CaseCounts, DefaultCount));
}
SwitchEnumAddrInst *createSwitchEnumAddr(
SILLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
Optional<ArrayRef<ProfileCounter>> CaseCounts = None,
ProfileCounter DefaultCount = ProfileCounter()) {
return insertTerminator(SwitchEnumAddrInst::create(
getSILDebugLocation(Loc), Operand, DefaultBB, CaseBBs, getFunction(),
CaseCounts, DefaultCount));
}
DynamicMethodBranchInst *
createDynamicMethodBranch(SILLocation Loc, SILValue Operand,
SILDeclRef Member, SILBasicBlock *HasMethodBB,
SILBasicBlock *NoMethodBB) {
return insertTerminator(
DynamicMethodBranchInst::create(getSILDebugLocation(Loc), Operand,
Member, HasMethodBB, NoMethodBB, getFunction()));
}
CheckedCastBranchInst *
createCheckedCastBranch(SILLocation Loc, bool isExact, SILValue op,
SILType destLoweredTy, CanType destFormalTy,
SILBasicBlock *successBB,
SILBasicBlock *failureBB,
ProfileCounter Target1Count = ProfileCounter(),
ProfileCounter Target2Count = ProfileCounter());
CheckedCastValueBranchInst *
createCheckedCastValueBranch(SILLocation Loc,
SILValue op, CanType srcFormalTy,
SILType destLoweredTy,
CanType destFormalTy,
SILBasicBlock *successBB,
SILBasicBlock *failureBB) {
return insertTerminator(CheckedCastValueBranchInst::create(
getSILDebugLocation(Loc), op, srcFormalTy,
destLoweredTy, destFormalTy,
successBB, failureBB, getFunction(), C.OpenedArchetypes));
}
CheckedCastAddrBranchInst *
createCheckedCastAddrBranch(SILLocation Loc, CastConsumptionKind consumption,
SILValue src, CanType sourceFormalType,
SILValue dest, CanType targetFormalType,
SILBasicBlock *successBB,
SILBasicBlock *failureBB,
ProfileCounter Target1Count = ProfileCounter(),
ProfileCounter Target2Count = ProfileCounter()) {
return insertTerminator(CheckedCastAddrBranchInst::create(
getSILDebugLocation(Loc), consumption, src, sourceFormalType, dest,
targetFormalType, successBB, failureBB, Target1Count, Target2Count,
getFunction(), C.OpenedArchetypes));
}
//===--------------------------------------------------------------------===//
// Memory management helpers
//===--------------------------------------------------------------------===//
/// Returns the default atomicity of the module.
Atomicity getDefaultAtomicity() {
return getModule().isDefaultAtomic() ? Atomicity::Atomic : Atomicity::NonAtomic;
}
/// 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. 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.
DestroyValueInst *emitDestroyValueAndFold(SILLocation Loc, SILValue Operand) {
auto U = emitDestroyValue(Loc, Operand);
if (U.isNull())
return nullptr;
if (auto *DVI = U.dyn_cast<DestroyValueInst *>())
return DVI;
auto *CVI = U.get<CopyValueInst *>();
CVI->replaceAllUsesWith(CVI->getOperand());
CVI->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);
/// Emit a destroy_value instruction at the current location, attempting to
/// fold it locally into another nearby copy_value instruction. Returns a
/// pointer union initialized with a destroy_value inst if it inserts one,
/// otherwise returns the copy_value. It is expected that the caller will
/// remove the copy_value. This allows for the caller to update any state
/// before the copy_value is destroyed.
PointerUnion<CopyValueInst *, DestroyValueInst *>
emitDestroyValue(SILLocation Loc, SILValue Operand);
/// Convenience function for calling emitCopy on the type lowering
/// for the non-address value.
SILValue emitCopyValueOperation(SILLocation Loc, SILValue v) {
assert(!v->getType().isAddress());
auto &lowering = getTypeLowering(v->getType());
return lowering.emitCopyValue(*this, Loc, v);
}
/// Convenience function for calling emitCopy on the type lowering
/// for the non-address value.
SILValue emitLoweredCopyValueOperation(
SILLocation Loc, SILValue v,
Lowering::TypeLowering::TypeExpansionKind expansionKind) {
assert(!v->getType().isAddress());
auto &lowering = getTypeLowering(v->getType());
return lowering.emitLoweredCopyValue(*this, Loc, v, expansionKind);
}
/// Convenience function for calling TypeLowering.emitDestroy on the type
/// lowering for the non-address value.
void emitDestroyValueOperation(SILLocation Loc, SILValue v) {
assert(!v->getType().isAddress());
if (F->hasOwnership() && v.getOwnershipKind() == OwnershipKind::None)
return;
auto &lowering = getTypeLowering(v->getType());
lowering.emitDestroyValue(*this, Loc, v);
}
/// Convenience function for calling TypeLowering.emitDestroy on the type
/// lowering for the non-address value.
void emitLoweredDestroyValueOperation(
SILLocation Loc, SILValue v,
Lowering::TypeLowering::TypeExpansionKind expansionKind) {
assert(!v->getType().isAddress());
if (F->hasOwnership() && v.getOwnershipKind() == OwnershipKind::None)
return;
auto &lowering = getTypeLowering(v->getType());
lowering.emitLoweredDestroyValue(*this, Loc, v, expansionKind);
}
/// Convenience function for destroying objects and addresses.
///
/// Objects are destroyed using emitDestroyValueOperation and addresses by
/// emitting destroy_addr.
void emitDestroyOperation(SILLocation loc, SILValue v) {
if (v->getType().isObject())
return emitDestroyValueOperation(loc, v);
createDestroyAddr(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, getModule(),
getTypeExpansionContext());
return emitStructExtract(Loc, Operand, Field, type);
}
SILValue emitThickToObjCMetatype(SILLocation Loc, SILValue Op, SILType Ty);
SILValue emitObjCToThickMetatype(SILLocation Loc, SILValue Op, SILType Ty);
//===--------------------------------------------------------------------===//
// Differentiable programming instructions
//===--------------------------------------------------------------------===//
DifferentiableFunctionInst *createDifferentiableFunction(
SILLocation Loc, IndexSubset *ParameterIndices,
IndexSubset *ResultIndices, SILValue OriginalFunction,
Optional<std::pair<SILValue, SILValue>> JVPAndVJPFunctions = None) {
return insert(DifferentiableFunctionInst::create(
getModule(), getSILDebugLocation(Loc), ParameterIndices, ResultIndices,
OriginalFunction, JVPAndVJPFunctions, hasOwnership()));
}
LinearFunctionInst *createLinearFunction(
SILLocation Loc, IndexSubset *ParameterIndices, SILValue OriginalFunction,
Optional<SILValue> TransposeFunction = None) {
return insert(LinearFunctionInst::create(
getModule(), getSILDebugLocation(Loc), ParameterIndices,
OriginalFunction, TransposeFunction, hasOwnership()));
}
/// Note: explicit extractee type may be specified only in lowered SIL.
DifferentiableFunctionExtractInst *createDifferentiableFunctionExtract(
SILLocation Loc, NormalDifferentiableFunctionTypeComponent Extractee,
SILValue Function, Optional<SILType> ExtracteeType = None) {
return insert(new (getModule()) DifferentiableFunctionExtractInst(
getModule(), getSILDebugLocation(Loc), Extractee, Function,
ExtracteeType));
}
DifferentiableFunctionExtractInst *
createDifferentiableFunctionExtractOriginal(SILLocation Loc,
SILValue TheFunction) {
return insert(new (getModule()) DifferentiableFunctionExtractInst(
getModule(), getSILDebugLocation(Loc),
NormalDifferentiableFunctionTypeComponent::Original, TheFunction));
}
LinearFunctionExtractInst *createLinearFunctionExtract(
SILLocation Loc, LinearDifferentiableFunctionTypeComponent Extractee,
SILValue TheFunction) {
return insert(new (getModule()) LinearFunctionExtractInst(
getModule(), getSILDebugLocation(Loc), Extractee, TheFunction));
}
/// Note: explicit function type may be specified only in lowered SIL.
DifferentiabilityWitnessFunctionInst *createDifferentiabilityWitnessFunction(
SILLocation Loc, DifferentiabilityWitnessFunctionKind WitnessKind,
SILDifferentiabilityWitness *Witness,
Optional<SILType> FunctionType = None) {
return insert(new (getModule()) DifferentiabilityWitnessFunctionInst(
getModule(), getSILDebugLocation(Loc), WitnessKind, Witness,
FunctionType));
}
//===--------------------------------------------------------------------===//
// 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) {
assert(hasValidInsertionPoint());
BB->insert(InsertPt, TheInst);
C.notifyInserted(TheInst);
#ifndef NDEBUG
TheInst->verifyOperandOwnership();
#endif
}
bool isLoadableOrOpaque(SILType Ty) {
auto &M = C.Module;
if (!SILModuleConventions(M).useLoweredAddresses())
return true;
return getTypeLowering(Ty).isLoadable();
}
void appendOperandTypeName(SILType OpdTy, llvm::SmallString<16> &Name) {
if (auto BuiltinIntTy =
dyn_cast<BuiltinIntegerType>(OpdTy.getASTType())) {
if (BuiltinIntTy == BuiltinIntegerType::getWordType(getASTContext())) {
Name += "_Word";
} else {
unsigned NumBits = BuiltinIntTy->getWidth().getFixedWidth();
Name += "_Int" + llvm::utostr(NumBits);
}
} else if (auto BuiltinFloatTy =
dyn_cast<BuiltinFloatType>(OpdTy.getASTType())) {
Name += "_FP";
switch (BuiltinFloatTy->getFPKind()) {
case BuiltinFloatType::IEEE16: Name += "IEEE16"; break;
case BuiltinFloatType::IEEE32: Name += "IEEE32"; break;
case BuiltinFloatType::IEEE64: Name += "IEEE64"; break;
case BuiltinFloatType::IEEE80: Name += "IEEE80"; break;
case BuiltinFloatType::IEEE128: Name += "IEEE128"; break;
case BuiltinFloatType::PPC128: Name += "PPC128"; break;
}
} else {
assert(OpdTy.getASTType() == getASTContext().TheRawPointerType);
Name += "_RawPointer";
}
}
};
/// 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:
/// Build instructions before the given insertion point, inheriting the debug
/// location.
///
/// Clients should prefer this constructor.
SILBuilderWithScope(SILInstruction *I, SILBuilderContext &C)
: SILBuilder(I, I->getDebugScope(), C)
{}
/// Build instructions before the given insertion point, inheriting the debug
/// location and using the context from the passed in builder.
///
/// Clients should prefer this constructor.
SILBuilderWithScope(SILInstruction *I, SILBuilder &B)
: SILBuilder(I, I->getDebugScope(), B.getBuilderContext()) {}
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(SILBasicBlock::iterator I, SILBuilder &B)
: SILBuilder(&*I, &*I->getDebugScope(), B.getBuilderContext()) {}
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);
}
explicit SILBuilderWithScope(SILBasicBlock *BB, SILBuilder &B,
SILInstruction *InheritScopeFrom)
: SILBuilder(BB, InheritScopeFrom->getDebugScope(),
B.getBuilderContext()) {}
explicit SILBuilderWithScope(SILBasicBlock *BB, SILBuilderContext &C,
const SILDebugScope *debugScope)
: SILBuilder(BB, debugScope, C) {}
/// Creates a new SILBuilder with an insertion point at the
/// beginning of BB and the debug scope from the first
/// non-metainstruction in the BB.
explicit SILBuilderWithScope(SILBasicBlock *BB) : SILBuilder(BB->begin()) {
const SILDebugScope *DS = BB->getScopeOfFirstNonMetaInstruction();
assert(DS && "Instruction without debug scope associated!");
setCurrentDebugScope(DS);
}
/// If \p inst is a terminator apply site, then pass a builder to insert at
/// the first instruction of each successor to \p func. Otherwise, pass a
/// builder to insert at std::next(inst).
///
/// The intention is that this abstraction will enable the compiler writer to
/// ignore whether or not \p inst is a terminator when inserting instructions
/// after \p inst.
///
/// Precondition: It's the responsibility of the caller to ensure that if
/// \p inst is a terminator, all successor blocks have only a single
/// predecessor block: the parent of \p inst.
static void insertAfter(SILInstruction *inst,
function_ref<void(SILBuilder &)> func);
/// If \p is an inst, then this is equivalent to insertAfter(inst). If a
/// SILArgument is passed in, we use the first instruction in its parent
/// block. We assert on undef.
static void insertAfter(SILValue value,
function_ref<void(SILBuilder &)> func) {
if (auto *i = dyn_cast<SingleValueInstruction>(value))
return insertAfter(i, func);
if (auto *mvir = dyn_cast<MultipleValueInstructionResult>(value))
return insertAfter(mvir->getParent(), func);
if (auto *arg = dyn_cast<SILArgument>(value))
return insertAfter(&*arg->getParent()->begin(), func);
assert(!isa<SILUndef>(value) && "This API can not use undef");
llvm_unreachable("Unhandled case?!");
}
};
class SavedInsertionPointRAII {
SILBuilder &builder;
PointerUnion<SILInstruction *, SILBasicBlock *> savedInsertionPoint;
public:
/// Constructor that saves a Builder's insertion point without changing the
/// builder's underlying insertion point.
SavedInsertionPointRAII(SILBuilder &B) : builder(B), savedInsertionPoint() {
// If our builder does not have a valid insertion point, just put nullptr
// into SavedIP.
if (!builder.hasValidInsertionPoint()) {
savedInsertionPoint = static_cast<SILBasicBlock *>(nullptr);
return;
}
// If we are inserting into the end of the block, stash the insertion block.
if (builder.insertingAtEndOfBlock()) {
savedInsertionPoint = builder.getInsertionBB();
return;
}
// Otherwise, stash the instruction.
SILInstruction *i = &*builder.getInsertionPoint();
savedInsertionPoint = i;
}
SavedInsertionPointRAII(SILBuilder &b, SILInstruction *insertionPoint)
: SavedInsertionPointRAII(b) {
builder.setInsertionPoint(insertionPoint);
}
SavedInsertionPointRAII(SILBuilder &b, SILBasicBlock *block,
SILBasicBlock::iterator iter)
: SavedInsertionPointRAII(b) {
builder.setInsertionPoint(block, iter);
}
SavedInsertionPointRAII(SILBuilder &b, SILBasicBlock *insertionBlock)
: SavedInsertionPointRAII(b) {
builder.setInsertionPoint(insertionBlock);
}
SavedInsertionPointRAII(const SavedInsertionPointRAII &) = delete;
SavedInsertionPointRAII &operator=(const SavedInsertionPointRAII &) = delete;
SavedInsertionPointRAII(SavedInsertionPointRAII &&) = delete;
SavedInsertionPointRAII &operator=(SavedInsertionPointRAII &&) = delete;
~SavedInsertionPointRAII() {
if (savedInsertionPoint.isNull()) {
builder.clearInsertionPoint();
} else if (savedInsertionPoint.is<SILInstruction *>()) {
builder.setInsertionPoint(savedInsertionPoint.get<SILInstruction *>());
} else {
builder.setInsertionPoint(savedInsertionPoint.get<SILBasicBlock *>());
}
}
};
/// Apply a debug location override for the duration of the current scope.
class DebugLocOverrideRAII {
SILBuilder &Builder;
Optional<SILLocation> oldOverride;
#ifndef NDEBUG
Optional<SILLocation> installedOverride;
#endif
public:
DebugLocOverrideRAII(SILBuilder &B, Optional<SILLocation> Loc) : Builder(B) {
oldOverride = B.getCurrentDebugLocOverride();
Builder.applyDebugLocOverride(Loc);
#ifndef NDEBUG
installedOverride = Loc;
#endif
}
~DebugLocOverrideRAII() {
assert(Builder.getCurrentDebugLocOverride() == installedOverride &&
"Restoring debug location override to an unexpected state");
Builder.applyDebugLocOverride(oldOverride);
}
DebugLocOverrideRAII(const DebugLocOverrideRAII &) = delete;
DebugLocOverrideRAII &operator=(const DebugLocOverrideRAII &) = delete;
DebugLocOverrideRAII(DebugLocOverrideRAII &&) = delete;
DebugLocOverrideRAII &operator=(DebugLocOverrideRAII &&) = delete;
};
} // end swift namespace
#endif