mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
SwiftCompilerSources: add a few enum related APIs in Type and Builder
* `Type.getEnumCases` * `Builder.createUncheckedTakeEnumDataAddr` * `Builder.createSwitchEnumAddr`
This commit is contained in:
@@ -215,6 +215,12 @@ public struct Builder {
|
||||
return notifyNew(ued.getAs(UncheckedEnumDataInst.self))
|
||||
}
|
||||
|
||||
public func createUncheckedTakeEnumDataAddr(enumAddress: Value,
|
||||
caseIndex: Int) -> UncheckedTakeEnumDataAddrInst {
|
||||
let uteda = bridged.createUncheckedTakeEnumDataAddr(enumAddress.bridged, caseIndex)
|
||||
return notifyNew(uteda.getAs(UncheckedTakeEnumDataAddrInst.self))
|
||||
}
|
||||
|
||||
public func createEnum(caseIndex: Int, payload: Value?, enumType: Type) -> EnumInst {
|
||||
let enumInst = bridged.createEnum(caseIndex, payload.bridged, enumType.bridged)
|
||||
return notifyNew(enumInst.getAs(EnumInst.self))
|
||||
@@ -236,6 +242,17 @@ public struct Builder {
|
||||
return notifyNew(se.getAs(SwitchEnumInst.self))
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func createSwitchEnumAddr(enumAddress: Value,
|
||||
cases: [(Int, BasicBlock)],
|
||||
defaultBlock: BasicBlock? = nil) -> SwitchEnumAddrInst {
|
||||
let se = cases.withUnsafeBufferPointer { caseBuffer in
|
||||
bridged.createSwitchEnumAddrInst(enumAddress.bridged, defaultBlock.bridged,
|
||||
caseBuffer.baseAddress, caseBuffer.count)
|
||||
}
|
||||
return notifyNew(se.getAs(SwitchEnumAddrInst.self))
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func createBranch(to destBlock: BasicBlock, arguments: [Value] = []) -> BranchInst {
|
||||
return arguments.withBridgedValues { valuesRef in
|
||||
|
||||
@@ -100,6 +100,16 @@ public struct Type : CustomStringConvertible, NoReflectionChildren {
|
||||
return NominalFieldsArray(type: self, function: function)
|
||||
}
|
||||
|
||||
/// Can only be used if the type is in fact an enum type.
|
||||
/// Returns nil if the enum is a resilient type because in this case the complete list
|
||||
/// of cases is not known.
|
||||
public func getEnumCases(in function: Function) -> EnumCases? {
|
||||
if nominal.isResilient(in: function) {
|
||||
return nil
|
||||
}
|
||||
return EnumCases(enumType: self, function: function)
|
||||
}
|
||||
|
||||
public typealias MetatypeRepresentation = BridgedType.MetatypeRepresentation
|
||||
|
||||
public func instanceTypeOfMetatype(in function: Function) -> Type {
|
||||
@@ -199,6 +209,36 @@ public struct NominalFieldsArray : RandomAccessCollection, FormattedLikeArray {
|
||||
}
|
||||
}
|
||||
|
||||
public struct EnumCase {
|
||||
public let payload: Type?
|
||||
public let index: Int
|
||||
}
|
||||
|
||||
public struct EnumCases : CollectionLikeSequence, IteratorProtocol {
|
||||
fileprivate let enumType: Type
|
||||
fileprivate let function: Function
|
||||
private var caseIterator: BridgedType.EnumElementIterator
|
||||
private var caseIndex = 0
|
||||
|
||||
fileprivate init(enumType: Type, function: Function) {
|
||||
self.enumType = enumType
|
||||
self.function = function
|
||||
self.caseIterator = enumType.bridged.getFirstEnumCaseIterator()
|
||||
}
|
||||
|
||||
public mutating func next() -> EnumCase? {
|
||||
if !enumType.bridged.isEndCaseIterator(caseIterator) {
|
||||
defer {
|
||||
caseIterator = caseIterator.getNext()
|
||||
caseIndex += 1
|
||||
}
|
||||
return EnumCase(payload: enumType.bridged.getEnumCasePayload(caseIterator, function.bridged).typeOrNil,
|
||||
index: caseIndex)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public struct TupleElementArray : RandomAccessCollection, FormattedLikeArray {
|
||||
fileprivate let type: Type
|
||||
|
||||
|
||||
@@ -78,6 +78,22 @@ struct BridgedType {
|
||||
Is
|
||||
};
|
||||
|
||||
struct EnumElementIterator {
|
||||
uint64_t storage[4];
|
||||
|
||||
#ifdef USED_IN_CPP_SOURCE
|
||||
EnumElementIterator(swift::EnumDecl::ElementRange::iterator i) {
|
||||
static_assert(sizeof(EnumElementIterator) >= sizeof(swift::EnumDecl::ElementRange::iterator));
|
||||
*reinterpret_cast<swift::EnumDecl::ElementRange::iterator *>(&storage) = i;
|
||||
}
|
||||
swift::EnumDecl::ElementRange::iterator unbridged() const {
|
||||
return *reinterpret_cast<const swift::EnumDecl::ElementRange::iterator *>(&storage);
|
||||
}
|
||||
#endif
|
||||
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE EnumElementIterator getNext() const;
|
||||
};
|
||||
|
||||
#ifdef USED_IN_CPP_SOURCE
|
||||
BridgedType(swift::SILType t) : opaqueValue(t.getOpaqueValue()) {}
|
||||
|
||||
@@ -128,6 +144,9 @@ struct BridgedType {
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedType getFieldType(SwiftInt idx, BridgedFunction f) const;
|
||||
BRIDGED_INLINE SwiftInt getFieldIdxOfNominalType(BridgedStringRef name) const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedStringRef getFieldName(SwiftInt idx) const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE EnumElementIterator getFirstEnumCaseIterator() const;
|
||||
BRIDGED_INLINE bool isEndCaseIterator(EnumElementIterator i) const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedType getEnumCasePayload(EnumElementIterator i, BridgedFunction f) const;
|
||||
BRIDGED_INLINE SwiftInt getNumTupleElements() const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedType getTupleElementType(SwiftInt idx) const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedType getFunctionTypeWithNoEscape(bool withNoEscape) const;
|
||||
@@ -898,11 +917,16 @@ struct BridgedBuilder{
|
||||
BridgedSubstitutionMap subMap,
|
||||
BridgedValueArray arguments, bool isNonThrowing, bool isNonAsync,
|
||||
BridgedGenericSpecializationInformation specInfo) const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createSwitchEnumInst(BridgedValue enumVal,
|
||||
SWIFT_IMPORT_UNSAFE BridgedInstruction createSwitchEnumInst(BridgedValue enumVal,
|
||||
OptionalBridgedBasicBlock defaultBlock,
|
||||
const void * _Nullable enumCases, SwiftInt numEnumCases) const;
|
||||
SWIFT_IMPORT_UNSAFE BridgedInstruction createSwitchEnumAddrInst(BridgedValue enumAddr,
|
||||
OptionalBridgedBasicBlock defaultBlock,
|
||||
const void * _Nullable enumCases, SwiftInt numEnumCases) const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createUncheckedEnumData(BridgedValue enumVal,
|
||||
SwiftInt caseIdx, BridgedType resultType) const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createUncheckedTakeEnumDataAddr(BridgedValue enumAddr,
|
||||
SwiftInt caseIdx) const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createEnum(SwiftInt caseIdx, OptionalBridgedValue payload,
|
||||
BridgedType resultType) const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createThinToThickFunction(BridgedValue fn,
|
||||
|
||||
@@ -44,6 +44,10 @@ SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
|
||||
// BridgedType
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
BridgedType::EnumElementIterator BridgedType::EnumElementIterator::getNext() const {
|
||||
return EnumElementIterator(std::next(unbridged()));
|
||||
}
|
||||
|
||||
BridgedOwnedString BridgedType::getDebugDescription() const {
|
||||
return BridgedOwnedString(unbridged().getDebugDescription());
|
||||
}
|
||||
@@ -216,6 +220,23 @@ BridgedStringRef BridgedType::getFieldName(SwiftInt idx) const {
|
||||
return unbridged().getFieldName(idx);
|
||||
}
|
||||
|
||||
BridgedType::EnumElementIterator BridgedType::getFirstEnumCaseIterator() const {
|
||||
swift::EnumDecl *enumDecl = unbridged().getEnumOrBoundGenericEnum();
|
||||
return EnumElementIterator(enumDecl->getAllElements().begin());
|
||||
}
|
||||
|
||||
bool BridgedType::isEndCaseIterator(EnumElementIterator i) const {
|
||||
swift::EnumDecl *enumDecl = unbridged().getEnumOrBoundGenericEnum();
|
||||
return i.unbridged() == enumDecl->getAllElements().end();
|
||||
}
|
||||
|
||||
BridgedType BridgedType::getEnumCasePayload(EnumElementIterator i, BridgedFunction f) const {
|
||||
swift::EnumElementDecl *elt = *i.unbridged();
|
||||
if (elt->hasAssociatedValues())
|
||||
return unbridged().getEnumElementType(elt, f.getFunction());
|
||||
return swift::SILType();
|
||||
}
|
||||
|
||||
SwiftInt BridgedType::getNumTupleElements() const {
|
||||
return unbridged().getNumTupleElements();
|
||||
}
|
||||
@@ -1338,27 +1359,6 @@ BridgedInstruction BridgedBuilder::createApply(BridgedValue function, BridgedSub
|
||||
arguments.getValues(argValues), applyOpts, specInfo.data)};
|
||||
}
|
||||
|
||||
BridgedInstruction BridgedBuilder::createSwitchEnumInst(BridgedValue enumVal, OptionalBridgedBasicBlock defaultBlock,
|
||||
const void * _Nullable enumCases, SwiftInt numEnumCases) const {
|
||||
using BridgedCase = const std::pair<SwiftInt, BridgedBasicBlock>;
|
||||
llvm::ArrayRef<BridgedCase> cases(static_cast<BridgedCase *>(enumCases),
|
||||
(unsigned)numEnumCases);
|
||||
llvm::SmallDenseMap<SwiftInt, swift::EnumElementDecl *> mappedElements;
|
||||
swift::SILValue en = enumVal.getSILValue();
|
||||
swift::EnumDecl *enumDecl = en->getType().getEnumOrBoundGenericEnum();
|
||||
for (auto elemWithIndex : llvm::enumerate(enumDecl->getAllElements())) {
|
||||
mappedElements[elemWithIndex.index()] = elemWithIndex.value();
|
||||
}
|
||||
llvm::SmallVector<std::pair<swift::EnumElementDecl *, swift::SILBasicBlock *>, 16> convertedCases;
|
||||
for (auto c : cases) {
|
||||
assert(mappedElements.count(c.first) && "wrong enum element index");
|
||||
convertedCases.push_back({mappedElements[c.first], c.second.unbridged()});
|
||||
}
|
||||
return {unbridged().createSwitchEnum(regularLoc(), enumVal.getSILValue(),
|
||||
defaultBlock.unbridged(),
|
||||
convertedCases)};
|
||||
}
|
||||
|
||||
BridgedInstruction BridgedBuilder::createUncheckedEnumData(BridgedValue enumVal, SwiftInt caseIdx,
|
||||
BridgedType resultType) const {
|
||||
swift::SILValue en = enumVal.getSILValue();
|
||||
@@ -1367,6 +1367,11 @@ BridgedInstruction BridgedBuilder::createUncheckedEnumData(BridgedValue enumVal,
|
||||
en->getType().getEnumElement(caseIdx), resultType.unbridged())};
|
||||
}
|
||||
|
||||
BridgedInstruction BridgedBuilder::createUncheckedTakeEnumDataAddr(BridgedValue enumAddr, SwiftInt caseIdx) const {
|
||||
swift::SILValue en = enumAddr.getSILValue();
|
||||
return {unbridged().createUncheckedTakeEnumDataAddr(regularLoc(), en, en->getType().getEnumElement(caseIdx))};
|
||||
}
|
||||
|
||||
BridgedInstruction BridgedBuilder::createEnum(SwiftInt caseIdx, OptionalBridgedValue payload,
|
||||
BridgedType resultType) const {
|
||||
swift::EnumElementDecl *caseDecl =
|
||||
|
||||
@@ -444,3 +444,42 @@ bool BridgedInstruction::mayBeDeinitBarrierNotConsideringSideEffects() const {
|
||||
return ::mayBeDeinitBarrierNotConsideringSideEffects(unbridged());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// BridgedBuilder
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static llvm::SmallVector<std::pair<swift::EnumElementDecl *, swift::SILBasicBlock *>, 16>
|
||||
convertCases(SILType enumTy, const void * _Nullable enumCases, SwiftInt numEnumCases) {
|
||||
using BridgedCase = const std::pair<SwiftInt, BridgedBasicBlock>;
|
||||
llvm::ArrayRef<BridgedCase> cases(static_cast<BridgedCase *>(enumCases),
|
||||
(unsigned)numEnumCases);
|
||||
llvm::SmallDenseMap<SwiftInt, swift::EnumElementDecl *> mappedElements;
|
||||
swift::EnumDecl *enumDecl = enumTy.getEnumOrBoundGenericEnum();
|
||||
for (auto elemWithIndex : llvm::enumerate(enumDecl->getAllElements())) {
|
||||
mappedElements[elemWithIndex.index()] = elemWithIndex.value();
|
||||
}
|
||||
llvm::SmallVector<std::pair<swift::EnumElementDecl *, swift::SILBasicBlock *>, 16> convertedCases;
|
||||
for (auto c : cases) {
|
||||
assert(mappedElements.count(c.first) && "wrong enum element index");
|
||||
convertedCases.push_back({mappedElements[c.first], c.second.unbridged()});
|
||||
}
|
||||
return convertedCases;
|
||||
}
|
||||
|
||||
BridgedInstruction BridgedBuilder::createSwitchEnumInst(BridgedValue enumVal, OptionalBridgedBasicBlock defaultBlock,
|
||||
const void * _Nullable enumCases, SwiftInt numEnumCases) const {
|
||||
return {unbridged().createSwitchEnum(regularLoc(),
|
||||
enumVal.getSILValue(),
|
||||
defaultBlock.unbridged(),
|
||||
convertCases(enumVal.getSILValue()->getType(), enumCases, numEnumCases))};
|
||||
}
|
||||
|
||||
BridgedInstruction BridgedBuilder::createSwitchEnumAddrInst(BridgedValue enumAddr,
|
||||
OptionalBridgedBasicBlock defaultBlock,
|
||||
const void * _Nullable enumCases,
|
||||
SwiftInt numEnumCases) const {
|
||||
return {unbridged().createSwitchEnumAddr(regularLoc(),
|
||||
enumAddr.getSILValue(),
|
||||
defaultBlock.unbridged(),
|
||||
convertCases(enumAddr.getSILValue()->getType(), enumCases, numEnumCases))};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user