mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
* IRGen: EmptyBoxType's representation cannot be nil because of a conflict with extra inhabitant assumption in indirect enums We map nil to the .None case of Optional. Instead use a singleton object. SR-5148 rdar://32618580
582 lines
24 KiB
C++
582 lines
24 KiB
C++
//===--- IRGenFunction.h - IR Generation for Swift Functions ----*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the structure used to generate the IR body of a
|
|
// function.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_IRGEN_IRGENFUNCTION_H
|
|
#define SWIFT_IRGEN_IRGENFUNCTION_H
|
|
|
|
#include "swift/Basic/LLVM.h"
|
|
#include "swift/AST/Type.h"
|
|
#include "swift/SIL/SILLocation.h"
|
|
#include "swift/SIL/SILType.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/IR/CallingConv.h"
|
|
#include "IRBuilder.h"
|
|
#include "LocalTypeDataKind.h"
|
|
#include "DominancePoint.h"
|
|
|
|
namespace llvm {
|
|
class AllocaInst;
|
|
class CallSite;
|
|
class Constant;
|
|
class Function;
|
|
}
|
|
|
|
namespace swift {
|
|
class ArchetypeType;
|
|
class AssociatedTypeDecl;
|
|
class ClassDecl;
|
|
class ConstructorDecl;
|
|
class Decl;
|
|
class ExtensionDecl;
|
|
class FuncDecl;
|
|
class EnumElementDecl;
|
|
class EnumType;
|
|
class Pattern;
|
|
class PatternBindingDecl;
|
|
class SILDebugScope;
|
|
class SILType;
|
|
class KeyPathInst;
|
|
class SourceLoc;
|
|
class StructType;
|
|
class Substitution;
|
|
class ValueDecl;
|
|
class VarDecl;
|
|
|
|
namespace Lowering {
|
|
class TypeConverter;
|
|
}
|
|
|
|
namespace irgen {
|
|
class Explosion;
|
|
class FunctionRef;
|
|
class HeapLayout;
|
|
class HeapNonFixedOffsets;
|
|
class IRGenModule;
|
|
class LinkEntity;
|
|
class LocalTypeDataCache;
|
|
class Scope;
|
|
class TypeInfo;
|
|
enum class ValueWitness : unsigned;
|
|
enum class ReferenceCounting : unsigned char;
|
|
|
|
/// IRGenFunction - Primary class for emitting LLVM instructions for a
|
|
/// specific function.
|
|
class IRGenFunction {
|
|
public:
|
|
IRGenModule &IGM;
|
|
IRBuilder Builder;
|
|
|
|
llvm::Function *CurFn;
|
|
ModuleDecl *getSwiftModule() const;
|
|
SILModule &getSILModule() const;
|
|
Lowering::TypeConverter &getSILTypes() const;
|
|
|
|
IRGenFunction(IRGenModule &IGM, llvm::Function *fn,
|
|
const SILDebugScope *DbgScope = nullptr,
|
|
Optional<SILLocation> DbgLoc = None);
|
|
~IRGenFunction();
|
|
|
|
void unimplemented(SourceLoc Loc, StringRef Message);
|
|
|
|
friend class Scope;
|
|
|
|
//--- Function prologue and epilogue -------------------------------------------
|
|
public:
|
|
Explosion collectParameters();
|
|
void emitScalarReturn(SILType resultTy, Explosion &scalars,
|
|
bool isSwiftCCReturn);
|
|
void emitScalarReturn(llvm::Type *resultTy, Explosion &scalars);
|
|
|
|
void emitBBForReturn();
|
|
bool emitBranchToReturnBB();
|
|
|
|
/// Return the error result slot, given an error type. There's
|
|
/// always only one error type.
|
|
Address getErrorResultSlot(SILType errorType);
|
|
|
|
/// Return the error result slot provided by the caller.
|
|
Address getCallerErrorResultSlot();
|
|
|
|
/// Set the error result slot.
|
|
void setErrorResultSlot(llvm::Value *address);
|
|
|
|
private:
|
|
void emitPrologue();
|
|
void emitEpilogue();
|
|
|
|
Address ReturnSlot;
|
|
llvm::BasicBlock *ReturnBB;
|
|
llvm::Value *ErrorResultSlot = nullptr;
|
|
|
|
//--- Helper methods -----------------------------------------------------------
|
|
public:
|
|
Address createAlloca(llvm::Type *ty, Alignment align,
|
|
const llvm::Twine &name);
|
|
Address createAlloca(llvm::Type *ty, llvm::Value *ArraySize, Alignment align,
|
|
const llvm::Twine &name);
|
|
Address createFixedSizeBufferAlloca(const llvm::Twine &name);
|
|
|
|
llvm::BasicBlock *createBasicBlock(const llvm::Twine &Name);
|
|
const TypeInfo &getTypeInfoForUnlowered(Type subst);
|
|
const TypeInfo &getTypeInfoForUnlowered(AbstractionPattern orig, Type subst);
|
|
const TypeInfo &getTypeInfoForUnlowered(AbstractionPattern orig,
|
|
CanType subst);
|
|
const TypeInfo &getTypeInfoForLowered(CanType T);
|
|
const TypeInfo &getTypeInfo(SILType T);
|
|
void emitMemCpy(llvm::Value *dest, llvm::Value *src,
|
|
Size size, Alignment align);
|
|
void emitMemCpy(llvm::Value *dest, llvm::Value *src,
|
|
llvm::Value *size, Alignment align);
|
|
void emitMemCpy(Address dest, Address src, Size size);
|
|
void emitMemCpy(Address dest, Address src, llvm::Value *size);
|
|
|
|
llvm::Value *emitByteOffsetGEP(llvm::Value *base, llvm::Value *offset,
|
|
llvm::Type *objectType,
|
|
const llvm::Twine &name = "");
|
|
Address emitByteOffsetGEP(llvm::Value *base, llvm::Value *offset,
|
|
const TypeInfo &type,
|
|
const llvm::Twine &name = "");
|
|
|
|
void emitStoreOfRelativeIndirectablePointer(llvm::Value *value,
|
|
Address addr,
|
|
bool isFar);
|
|
|
|
llvm::Value *
|
|
emitLoadOfRelativeIndirectablePointer(Address addr, bool isFar,
|
|
llvm::PointerType *expectedType,
|
|
const llvm::Twine &name = "");
|
|
|
|
|
|
llvm::Value *emitAllocObjectCall(llvm::Value *metadata, llvm::Value *size,
|
|
llvm::Value *alignMask,
|
|
const llvm::Twine &name = "");
|
|
llvm::Value *emitInitStackObjectCall(llvm::Value *metadata,
|
|
llvm::Value *object,
|
|
const llvm::Twine &name = "");
|
|
llvm::Value *emitVerifyEndOfLifetimeCall(llvm::Value *object,
|
|
const llvm::Twine &name = "");
|
|
llvm::Value *emitAllocRawCall(llvm::Value *size, llvm::Value *alignMask,
|
|
const llvm::Twine &name ="");
|
|
void emitDeallocRawCall(llvm::Value *pointer, llvm::Value *size,
|
|
llvm::Value *alignMask);
|
|
|
|
void emitAllocBoxCall(llvm::Value *typeMetadata,
|
|
llvm::Value *&box,
|
|
llvm::Value *&valueAddress);
|
|
|
|
void emitMakeBoxUniqueCall(llvm::Value *box, llvm::Value *typeMetadata,
|
|
llvm::Value *alignMask, llvm::Value *&outBox,
|
|
llvm::Value *&outValueAddress);
|
|
|
|
void emitDeallocBoxCall(llvm::Value *box, llvm::Value *typeMetadata);
|
|
|
|
void emitTSanInoutAccessCall(llvm::Value *address);
|
|
|
|
llvm::Value *emitProjectBoxCall(llvm::Value *box, llvm::Value *typeMetadata);
|
|
|
|
llvm::Value *emitAllocEmptyBoxCall();
|
|
|
|
// Emit a reference to the canonical type metadata record for the given AST
|
|
// type. This can be used to identify the type at runtime. For types with
|
|
// abstraction difference, the metadata contains the layout information for
|
|
// values in the maximally-abstracted representation of the type; this is
|
|
// correct for all uses of reabstractable values in opaque contexts.
|
|
llvm::Value *emitTypeMetadataRef(CanType type);
|
|
|
|
// Emit a reference to a type layout record for the given type. The referenced
|
|
// data is enough to lay out an aggregate containing a value of the type, but
|
|
// can't uniquely represent the type or perform value witness operations on
|
|
// it.
|
|
llvm::Value *emitTypeLayoutRef(SILType type);
|
|
|
|
// Emit a reference to a metadata object that can be used for layout, but
|
|
// cannot be used to identify a type. This will produce a layout appropriate
|
|
// to the abstraction level of the given type. It may be able to avoid runtime
|
|
// calls if there is a standard metadata object with the correct layout for
|
|
// the type.
|
|
//
|
|
// TODO: It might be better to return just a value witness table reference
|
|
// here, since for some types it's easier to get a shared reference to one
|
|
// than a metadata reference, and it would be more type-safe.
|
|
llvm::Value *emitTypeMetadataRefForLayout(SILType type);
|
|
|
|
llvm::Value *emitValueWitnessTableRef(CanType type);
|
|
llvm::Value *emitValueWitnessTableRefForLayout(SILType type);
|
|
llvm::Value *emitValueWitnessTableRefForMetadata(llvm::Value *metadata);
|
|
|
|
llvm::Value *emitValueWitness(CanType type, ValueWitness index);
|
|
llvm::Value *emitValueWitnessForLayout(SILType type, ValueWitness index);
|
|
|
|
/// Emit a load of a reference to the given Objective-C selector.
|
|
llvm::Value *emitObjCSelectorRefLoad(StringRef selector);
|
|
|
|
/// Return the SILDebugScope for this function.
|
|
const SILDebugScope *getDebugScope() const { return DbgScope; }
|
|
llvm::Value *coerceValue(llvm::Value *value, llvm::Type *toTy,
|
|
const llvm::DataLayout &);
|
|
|
|
/// Mark a load as invariant.
|
|
void setInvariantLoad(llvm::LoadInst *load);
|
|
/// Mark a load as dereferenceable to `size` bytes.
|
|
void setDereferenceableLoad(llvm::LoadInst *load, unsigned size);
|
|
|
|
private:
|
|
llvm::Instruction *AllocaIP;
|
|
const SILDebugScope *DbgScope;
|
|
|
|
//--- Reference-counting methods -----------------------------------------------
|
|
public:
|
|
// Returns the default atomicity of the module.
|
|
Atomicity getDefaultAtomicity();
|
|
|
|
llvm::Value *emitUnmanagedAlloc(const HeapLayout &layout,
|
|
const llvm::Twine &name,
|
|
llvm::Constant *captureDescriptor,
|
|
const HeapNonFixedOffsets *offsets = 0);
|
|
|
|
// Functions that don't care about the reference-counting style.
|
|
void emitFixLifetime(llvm::Value *value);
|
|
|
|
// Routines that are generic over the reference-counting style:
|
|
// - strong references
|
|
void emitStrongRetain(llvm::Value *value, ReferenceCounting refcounting,
|
|
Atomicity atomicity);
|
|
void emitStrongRelease(llvm::Value *value, ReferenceCounting refcounting,
|
|
Atomicity atomicity);
|
|
llvm::Value *emitLoadRefcountedPtr(Address addr, ReferenceCounting style);
|
|
|
|
// - unowned references
|
|
void emitUnownedRetain(llvm::Value *value, ReferenceCounting style,
|
|
Atomicity atomicity);
|
|
void emitUnownedRelease(llvm::Value *value, ReferenceCounting style,
|
|
Atomicity atomicity);
|
|
void emitStrongRetainUnowned(llvm::Value *value, ReferenceCounting style,
|
|
Atomicity atomicity);
|
|
void emitStrongRetainAndUnownedRelease(llvm::Value *value,
|
|
ReferenceCounting style,
|
|
Atomicity atomicity);
|
|
void emitUnownedInit(llvm::Value *val, Address dest, ReferenceCounting style);
|
|
void emitUnownedAssign(llvm::Value *value, Address dest,
|
|
ReferenceCounting style);
|
|
void emitUnownedCopyInit(Address destAddr, Address srcAddr,
|
|
ReferenceCounting style);
|
|
void emitUnownedTakeInit(Address destAddr, Address srcAddr,
|
|
ReferenceCounting style);
|
|
void emitUnownedCopyAssign(Address destAddr, Address srcAddr,
|
|
ReferenceCounting style);
|
|
void emitUnownedTakeAssign(Address destAddr, Address srcAddr,
|
|
ReferenceCounting style);
|
|
llvm::Value *emitUnownedLoadStrong(Address src, llvm::Type *resultType,
|
|
ReferenceCounting style);
|
|
llvm::Value *emitUnownedTakeStrong(Address src, llvm::Type *resultType,
|
|
ReferenceCounting style);
|
|
void emitUnownedDestroy(Address addr, ReferenceCounting style);
|
|
llvm::Value *getUnownedExtraInhabitantIndex(Address src,
|
|
ReferenceCounting style);
|
|
void storeUnownedExtraInhabitant(llvm::Value *index, Address dest,
|
|
ReferenceCounting style);
|
|
|
|
// - weak references
|
|
void emitWeakInit(llvm::Value *ref, Address dest, ReferenceCounting style);
|
|
void emitWeakAssign(llvm::Value *ref, Address dest, ReferenceCounting style);
|
|
void emitWeakCopyInit(Address destAddr, Address srcAddr,
|
|
ReferenceCounting style);
|
|
void emitWeakTakeInit(Address destAddr, Address srcAddr,
|
|
ReferenceCounting style);
|
|
void emitWeakCopyAssign(Address destAddr, Address srcAddr,
|
|
ReferenceCounting style);
|
|
void emitWeakTakeAssign(Address destAddr, Address srcAddr,
|
|
ReferenceCounting style);
|
|
llvm::Value *emitWeakLoadStrong(Address src, llvm::Type *resultType,
|
|
ReferenceCounting style);
|
|
llvm::Value *emitWeakTakeStrong(Address src, llvm::Type *resultType,
|
|
ReferenceCounting style);
|
|
void emitWeakDestroy(Address addr, ReferenceCounting style);
|
|
|
|
// Routines for the Swift native reference-counting style.
|
|
// - strong references
|
|
void emitNativeStrongAssign(llvm::Value *value, Address addr);
|
|
void emitNativeStrongInit(llvm::Value *value, Address addr);
|
|
void emitNativeStrongRetain(llvm::Value *value, Atomicity atomicity);
|
|
void emitNativeStrongRelease(llvm::Value *value, Atomicity atomicity);
|
|
void emitNativeSetDeallocating(llvm::Value *value);
|
|
// - unowned references
|
|
void emitNativeUnownedRetain(llvm::Value *value, Atomicity atomicity);
|
|
void emitNativeUnownedRelease(llvm::Value *value, Atomicity atomicity);
|
|
void emitNativeStrongRetainUnowned(llvm::Value *value, Atomicity atomicity);
|
|
void emitNativeStrongRetainAndUnownedRelease(llvm::Value *value,
|
|
Atomicity atomicity);
|
|
void emitNativeUnownedInit(llvm::Value *val, Address dest);
|
|
void emitNativeUnownedAssign(llvm::Value *value, Address dest);
|
|
void emitNativeUnownedCopyInit(Address destAddr, Address srcAddr);
|
|
void emitNativeUnownedTakeInit(Address destAddr, Address srcAddr);
|
|
void emitNativeUnownedCopyAssign(Address destAddr, Address srcAddr);
|
|
void emitNativeUnownedTakeAssign(Address destAddr, Address srcAddr);
|
|
llvm::Value *emitNativeUnownedLoadStrong(Address src, llvm::Type *resultType);
|
|
llvm::Value *emitNativeUnownedTakeStrong(Address src, llvm::Type *resultType);
|
|
void emitNativeUnownedDestroy(Address addr);
|
|
|
|
// - weak references
|
|
void emitNativeWeakInit(llvm::Value *value, Address dest);
|
|
void emitNativeWeakAssign(llvm::Value *value, Address dest);
|
|
llvm::Value *emitNativeWeakLoadStrong(Address src, llvm::Type *type);
|
|
llvm::Value *emitNativeWeakTakeStrong(Address src, llvm::Type *type);
|
|
void emitNativeWeakDestroy(Address addr);
|
|
void emitNativeWeakCopyInit(Address destAddr, Address srcAddr);
|
|
void emitNativeWeakTakeInit(Address destAddr, Address srcAddr);
|
|
void emitNativeWeakCopyAssign(Address destAddr, Address srcAddr);
|
|
void emitNativeWeakTakeAssign(Address destAddr, Address srcAddr);
|
|
// - other operations
|
|
llvm::Value *emitNativeTryPin(llvm::Value *object, Atomicity atomicity);
|
|
void emitNativeUnpin(llvm::Value *handle, Atomicity atomicity);
|
|
|
|
// Routines for the ObjC reference-counting style.
|
|
void emitObjCStrongRetain(llvm::Value *value);
|
|
llvm::Value *emitObjCRetainCall(llvm::Value *value);
|
|
llvm::Value *emitObjCAutoreleaseCall(llvm::Value *value);
|
|
void emitObjCStrongRelease(llvm::Value *value);
|
|
|
|
llvm::Value *emitBlockCopyCall(llvm::Value *value);
|
|
void emitBlockRelease(llvm::Value *value);
|
|
|
|
// Routines for an unknown reference-counting style (meaning,
|
|
// dynamically something compatible with either the ObjC or Swift styles).
|
|
// - strong references
|
|
void emitUnknownStrongRetain(llvm::Value *value, Atomicity atomicity);
|
|
void emitUnknownStrongRelease(llvm::Value *value, Atomicity atomicity);
|
|
// - unowned references
|
|
void emitUnknownUnownedInit(llvm::Value *val, Address dest);
|
|
void emitUnknownUnownedAssign(llvm::Value *value, Address dest);
|
|
void emitUnknownUnownedCopyInit(Address destAddr, Address srcAddr);
|
|
void emitUnknownUnownedTakeInit(Address destAddr, Address srcAddr);
|
|
void emitUnknownUnownedCopyAssign(Address destAddr, Address srcAddr);
|
|
void emitUnknownUnownedTakeAssign(Address destAddr, Address srcAddr);
|
|
llvm::Value *emitUnknownUnownedLoadStrong(Address src, llvm::Type *resultTy);
|
|
llvm::Value *emitUnknownUnownedTakeStrong(Address src, llvm::Type *resultTy);
|
|
void emitUnknownUnownedDestroy(Address addr);
|
|
// - weak references
|
|
void emitUnknownWeakDestroy(Address addr);
|
|
void emitUnknownWeakCopyInit(Address destAddr, Address srcAddr);
|
|
void emitUnknownWeakTakeInit(Address destAddr, Address srcAddr);
|
|
void emitUnknownWeakCopyAssign(Address destAddr, Address srcAddr);
|
|
void emitUnknownWeakTakeAssign(Address destAddr, Address srcAddr);
|
|
void emitUnknownWeakInit(llvm::Value *value, Address dest);
|
|
void emitUnknownWeakAssign(llvm::Value *value, Address dest);
|
|
llvm::Value *emitUnknownWeakLoadStrong(Address src, llvm::Type *type);
|
|
llvm::Value *emitUnknownWeakTakeStrong(Address src, llvm::Type *type);
|
|
|
|
// Routines for the Builtin.NativeObject reference-counting style.
|
|
void emitBridgeStrongRetain(llvm::Value *value, Atomicity atomicity);
|
|
void emitBridgeStrongRelease(llvm::Value *value, Atomicity atomicity);
|
|
|
|
// Routines for the ErrorType reference-counting style.
|
|
void emitErrorStrongRetain(llvm::Value *value);
|
|
void emitErrorStrongRelease(llvm::Value *value);
|
|
|
|
llvm::Value *emitIsUniqueCall(llvm::Value *value, SourceLoc loc,
|
|
bool isNonNull, bool checkPinned);
|
|
|
|
//--- Expression emission ------------------------------------------------------
|
|
public:
|
|
void emitFakeExplosion(const TypeInfo &type, Explosion &explosion);
|
|
|
|
//--- Declaration emission -----------------------------------------------------
|
|
public:
|
|
|
|
void bindArchetype(ArchetypeType *type,
|
|
llvm::Value *metadata,
|
|
ArrayRef<llvm::Value*> wtables);
|
|
|
|
//--- Type emission ------------------------------------------------------------
|
|
public:
|
|
/// Look up a local type data reference, returning null if no entry was
|
|
/// found. This will emit code to materialize the reference if an
|
|
/// "abstract" entry is present.
|
|
llvm::Value *tryGetLocalTypeData(CanType type, LocalTypeDataKind kind) {
|
|
return tryGetLocalTypeData(LocalTypeDataKey{type, kind});
|
|
}
|
|
llvm::Value *tryGetLocalTypeData(LocalTypeDataKey key);
|
|
|
|
/// Look up a local type data reference, returning null if no entry was
|
|
/// found or if the only viable entries are abstract. This will never
|
|
/// emit code.
|
|
llvm::Value *tryGetConcreteLocalTypeData(LocalTypeDataKey key);
|
|
|
|
/// Retrieve a local type data reference which is known to exist.
|
|
llvm::Value *getLocalTypeData(CanType type, LocalTypeDataKind kind);
|
|
|
|
/// Add a local type-metadata reference at a point which definitely
|
|
/// dominates all of its uses.
|
|
void setUnscopedLocalTypeData(CanType type, LocalTypeDataKind kind,
|
|
llvm::Value *data) {
|
|
setUnscopedLocalTypeData(LocalTypeDataKey{type, kind}, data);
|
|
}
|
|
void setUnscopedLocalTypeData(LocalTypeDataKey key, llvm::Value *data);
|
|
|
|
/// Add a local type-metadata reference, valid at the current insertion
|
|
/// point.
|
|
void setScopedLocalTypeData(CanType type, LocalTypeDataKind kind,
|
|
llvm::Value *data) {
|
|
setScopedLocalTypeData(LocalTypeDataKey{type, kind}, data);
|
|
}
|
|
void setScopedLocalTypeData(LocalTypeDataKey key, llvm::Value *data);
|
|
|
|
/// The same as tryGetLocalTypeData, just for the Layout metadata.
|
|
///
|
|
/// We use a separate function name for this to clarify that you should
|
|
/// only ever be looking type metadata for a lowered SILType for the
|
|
/// purposes of local layout (e.g. of a tuple).
|
|
llvm::Value *tryGetLocalTypeDataForLayout(SILType type,
|
|
LocalTypeDataKind kind) {
|
|
return tryGetLocalTypeData(type.getSwiftRValueType(), kind);
|
|
}
|
|
|
|
/// Add a local type-metadata reference, which is valid for the containing
|
|
/// block.
|
|
void setScopedLocalTypeDataForLayout(SILType type, LocalTypeDataKind kind,
|
|
llvm::Value *data) {
|
|
setScopedLocalTypeData(type.getSwiftRValueType(), kind, data);
|
|
}
|
|
|
|
/// Given a concrete type metadata node, add all the local type data
|
|
/// that we can reach from it.
|
|
void bindLocalTypeDataFromTypeMetadata(CanType type, IsExact_t isExact,
|
|
llvm::Value *metadata);
|
|
|
|
void setDominanceResolver(DominanceResolverFunction resolver) {
|
|
assert(DominanceResolver == nullptr);
|
|
DominanceResolver = resolver;
|
|
}
|
|
|
|
bool isActiveDominancePointDominatedBy(DominancePoint point) {
|
|
// If the point is universal, it dominates.
|
|
if (point.isUniversal()) return true;
|
|
|
|
assert(!ActiveDominancePoint.isUniversal() &&
|
|
"active dominance point is universal but there exists a"
|
|
"non-universal point?");
|
|
|
|
// If we don't have a resolver, we're emitting a simple helper
|
|
// function; just assume dominance.
|
|
if (!DominanceResolver) return true;
|
|
|
|
// Otherwise, ask the resolver.
|
|
return DominanceResolver(*this, ActiveDominancePoint, point);
|
|
}
|
|
|
|
/// Is the current dominance point conditional in some way not
|
|
/// tracked by the active dominance point?
|
|
///
|
|
/// This should only be used by the local type data cache code.
|
|
bool isConditionalDominancePoint() const {
|
|
return ConditionalDominance != nullptr;
|
|
}
|
|
|
|
void registerConditionalLocalTypeDataKey(LocalTypeDataKey key) {
|
|
assert(ConditionalDominance != nullptr &&
|
|
"not in a conditional dominance scope");
|
|
ConditionalDominance->registerConditionalLocalTypeDataKey(key);
|
|
}
|
|
|
|
/// Return the currently-active dominance point.
|
|
DominancePoint getActiveDominancePoint() const {
|
|
return ActiveDominancePoint;
|
|
}
|
|
|
|
/// A RAII object for temporarily changing the dominance of the active
|
|
/// definition point.
|
|
class DominanceScope {
|
|
IRGenFunction &IGF;
|
|
DominancePoint OldDominancePoint;
|
|
public:
|
|
explicit DominanceScope(IRGenFunction &IGF, DominancePoint newPoint)
|
|
: IGF(IGF), OldDominancePoint(IGF.ActiveDominancePoint) {
|
|
IGF.ActiveDominancePoint = newPoint;
|
|
assert(!newPoint.isOrdinary() || IGF.DominanceResolver);
|
|
}
|
|
|
|
DominanceScope(const DominanceScope &other) = delete;
|
|
DominanceScope &operator=(const DominanceScope &other) = delete;
|
|
|
|
~DominanceScope() {
|
|
IGF.ActiveDominancePoint = OldDominancePoint;
|
|
}
|
|
};
|
|
|
|
/// A RAII object for temporarily suppressing type-data caching at the
|
|
/// active definition point. Do this if you're adding local control flow
|
|
/// that isn't modeled by the dominance system.
|
|
class ConditionalDominanceScope {
|
|
IRGenFunction &IGF;
|
|
ConditionalDominanceScope *OldScope;
|
|
SmallVector<LocalTypeDataKey, 2> RegisteredKeys;
|
|
|
|
public:
|
|
explicit ConditionalDominanceScope(IRGenFunction &IGF)
|
|
: IGF(IGF), OldScope(IGF.ConditionalDominance) {
|
|
IGF.ConditionalDominance = this;
|
|
}
|
|
|
|
ConditionalDominanceScope(const ConditionalDominanceScope &other) = delete;
|
|
ConditionalDominanceScope &operator=(const ConditionalDominanceScope &other)
|
|
= delete;
|
|
|
|
void registerConditionalLocalTypeDataKey(LocalTypeDataKey key) {
|
|
RegisteredKeys.push_back(key);
|
|
}
|
|
|
|
~ConditionalDominanceScope();
|
|
};
|
|
|
|
/// The kind of value LocalSelf is.
|
|
enum LocalSelfKind {
|
|
/// An object reference.
|
|
ObjectReference,
|
|
/// A Swift metatype.
|
|
SwiftMetatype,
|
|
/// An ObjC metatype.
|
|
ObjCMetatype,
|
|
};
|
|
|
|
llvm::Value *getLocalSelfMetadata();
|
|
void setLocalSelfMetadata(llvm::Value *value, LocalSelfKind kind);
|
|
|
|
private:
|
|
LocalTypeDataCache &getOrCreateLocalTypeData();
|
|
void destroyLocalTypeData();
|
|
|
|
LocalTypeDataCache *LocalTypeData = nullptr;
|
|
|
|
/// The dominance resolver. This can be set at most once; when it's not
|
|
/// set, this emission must never have a non-null active definition point.
|
|
DominanceResolverFunction DominanceResolver = nullptr;
|
|
DominancePoint ActiveDominancePoint = DominancePoint::universal();
|
|
ConditionalDominanceScope *ConditionalDominance = nullptr;
|
|
|
|
/// The value that satisfies metadata lookups for dynamic Self.
|
|
llvm::Value *LocalSelf = nullptr;
|
|
|
|
LocalSelfKind SelfKind;
|
|
};
|
|
|
|
using ConditionalDominanceScope = IRGenFunction::ConditionalDominanceScope;
|
|
|
|
} // end namespace irgen
|
|
} // end namespace swift
|
|
|
|
#endif
|