Skip to content

Implement Value generics #75518

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 40 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
75c2cbf
Implement value generics
Azoy Jul 24, 2024
3e9c463
Add some new diagnostics and tests
Azoy Jul 27, 2024
7c85261
Add runtime support
Azoy Jul 28, 2024
71f1bb3
Fix compile error in TypeRefBuilder
Azoy Jul 28, 2024
a029900
Update raw_layout.swift
Azoy Jul 28, 2024
8b773dc
Add an ArrayLayoutEntry and dispatch to that for array raw layout
Azoy Jul 30, 2024
b663a15
Add tests for raw layout vector
Azoy Jul 30, 2024
f66beff
Fix unittest compile error
Azoy Jul 31, 2024
7eb93b8
Update SpecifierDSL.h
Azoy Jul 31, 2024
0df42e9
Lower UDRE to TypeValue if it references a value generic
Azoy Aug 1, 2024
f4f60f4
Remove Value requirement Add GenericTypeParamKind
Azoy Aug 4, 2024
a434126
Disallow referencing a value generic outside of certain contexts
Azoy Aug 4, 2024
1ff1b94
AST: Pick off some usages of GenericTypeParamType::getDecl()
slavapestov Jul 5, 2024
b9b6bb7
AST: Introduce new kind of sugared GenericTypeParamType
slavapestov Jul 5, 2024
71fee06
Requestify GTPD::getValueType
Azoy Aug 6, 2024
7cd4248
Move some value checking to desugaring
Azoy Aug 6, 2024
4f07c06
Future proof the initRawStructMetadata entrypoint
Azoy Aug 6, 2024
e0f2b81
Add serialization and parser tests for SIL
Azoy Aug 6, 2024
19fc174
Don't create fake GTPDs for SIL generic signatures
Azoy Aug 7, 2024
bfffd7e
Set the param kind in ASTGen
Azoy Aug 7, 2024
15db739
Serialize IntegerType
Azoy Aug 7, 2024
b35ac50
Optimize TypeValueInst in Swift
Azoy Aug 8, 2024
f25545b
Add a module interface test
Azoy Aug 8, 2024
bd18bb3
Update ASTDumperTests.cpp
Azoy Aug 8, 2024
4a7fb6f
Some test fixes
Azoy Aug 8, 2024
46a4d56
Bring back the isOpaqueType parameter for deserialization
Azoy Aug 9, 2024
96bfaaf
Update ASTDumperTests.cpp
Azoy Aug 9, 2024
22349bc
Use intptr_t instead of ssize_t and more test fixes
Azoy Aug 9, 2024
9903d71
More changes to get off of ssize_t
Azoy Aug 9, 2024
451e725
Add ValueGenerics experimental feature
Azoy Aug 11, 2024
c1dd957
Use intptr_t more consistently
Azoy Aug 11, 2024
8a9303b
Consistently negate the value from demangling
Azoy Aug 14, 2024
9906db3
Fix closures capturing value generics
Azoy Aug 15, 2024
128a30c
Handle integer types in TypeTransform
Azoy Aug 19, 2024
9faf615
Add runtime availability checking for value generics
Azoy Aug 20, 2024
f2f82a7
Add initRawStructMetadata2 for safety
Azoy Aug 20, 2024
2c703ee
Update raw_layout.swift
Azoy Aug 20, 2024
3d8a9d4
Implement same type checking at runtime
Azoy Aug 21, 2024
f431e00
Fix abi test for new initRaw runtime function
Azoy Aug 24, 2024
17eb973
Update Devirtualize.cpp
Azoy Sep 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ swift_compiler_sources(Optimizer
SimplifyInitEnumDataAddr.swift
SimplifyKeyPath.swift
SimplifyLoad.swift
SimplifyMisc.swift
SimplifyPartialApply.swift
SimplifyPointerToAddress.swift
SimplifyRefCasts.swift
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===--- SimplifyMisc.swift -----------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 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
//
//===----------------------------------------------------------------------===//

import SIL

extension TypeValueInst: OnoneSimplifyable, SILCombineSimplifyable {
func simplify(_ context: SimplifyContext) {
// If our parameter is not known statically, then bail.
guard paramType.isInteger() else {
return
}

// Note: Right now, value generics only support 'Int'. If we ever expand the
// scope of types supported, then this should change.
let fieldType = type.getNominalFields(in: parentFunction)![0]

let builder = Builder(before: self, context)
let intLiteral = builder.createIntegerLiteral(value, type: fieldType)
let structInst = builder.createStruct(type: type, elements: [intLiteral])
uses.replaceAll(with: structInst, context)
context.erase(instruction: self)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ private func registerSwiftPasses() {
registerForSILCombine(DestroyValueInst.self, { run(DestroyValueInst.self, $0) })
registerForSILCombine(DestructureStructInst.self, { run(DestructureStructInst.self, $0) })
registerForSILCombine(DestructureTupleInst.self, { run(DestructureTupleInst.self, $0) })
registerForSILCombine(TypeValueInst.self, { run(TypeValueInst.self, $0) })

// Test passes
registerPass(aliasInfoDumper, { aliasInfoDumper.run($0) })
Expand Down
10 changes: 10 additions & 0 deletions SwiftCompilerSources/Sources/SIL/Instruction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,16 @@ class ExistentialMetatypeInst : SingleValueInstruction, UnaryInstruction {}

final public class ObjCProtocolInst : SingleValueInstruction {}

final public class TypeValueInst: SingleValueInstruction, UnaryInstruction {
public var paramType: BridgedASTType {
bridged.TypeValueInst_getParamType()
}

public var value: Int {
bridged.TypeValueInst_getValue()
}
}

public class GlobalAccessInstruction : SingleValueInstruction {
final public var global: GlobalVariable {
bridged.GlobalAccessInst_getGlobal().globalVar
Expand Down
1 change: 1 addition & 0 deletions SwiftCompilerSources/Sources/SIL/Registration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ public func registerSILClasses() {
register(MetatypeInst.self)
register(ValueMetatypeInst.self)
register(ExistentialMetatypeInst.self)
register(TypeValueInst.self)
register(OpenPackElementInst.self)
register(PackLengthInst.self)
register(DynamicPackIndexInst.self)
Expand Down
15 changes: 13 additions & 2 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,10 @@ Types
type ::= type 'Xm' METATYPE-REPR // existential metatype with representation
type ::= 'Xe' // error or unresolved type

#if SWIFT_RUNTIME_VERSION >= 6.TBD
type ::= '$' 'n'? NATURAL_ZERO // integer type
#endif

bound-generic-type ::= type 'y' (type* '_')* type* retroactive-conformance* 'G' // one type-list per nesting level of type
bound-generic-type ::= substitution

Expand Down Expand Up @@ -1008,11 +1012,18 @@ now codified into the ABI; the index 0 is therefore reserved.

::

generic-signature ::= requirement* generic-param-pack-marker* 'l' // one generic parameter
generic-signature ::= requirement* generic-param-pack-marker* 'r' GENERIC-PARAM-COUNT* 'l'
generic-signature ::= requirement* generic-param-marker 'l' // one generic parameter
generic-signature ::= requirement* generic-param-marker* 'r' GENERIC-PARAM-COUNT* 'l'

generic-param-marker ::= generic-param-pack-marker
generic-param-marker ::= generic-param-value-marker

generic-param-pack-marker ::= 'Rv' GENERIC_PARAM-INDEX // generic parameter pack marker

#if SWIFT_RUNTIME_VERSION >= 6.TBD
generic-param-value-marker ::= type 'RV' GENERIC-PARAM-INDEX // generic parameter value marker
#endif

GENERIC-PARAM-COUNT ::= 'z' // zero parameters
GENERIC-PARAM-COUNT ::= INDEX // N+1 parameters

Expand Down
14 changes: 14 additions & 0 deletions docs/SIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7762,6 +7762,20 @@ element value operand is the projected element type of the pack element
and must be structurally well-typed for the given index and pack type;
see the structural type matching rules for pack indices.

Value Generics
~~~~~~~~~~~~~~~~~

type_value
```````````

::

sil-instruction ::= 'type_value' sil-type 'for' sil-identifier

Produce the dynamic value of the given value generic, which must be a formal
value generic type. The value of the instruction has the type of whatever the
underlying value generic's type is. For right now that is limited to ``Int``.

Unchecked Conversions
~~~~~~~~~~~~~~~~~~~~~

Expand Down
81 changes: 76 additions & 5 deletions include/swift/ABI/GenericContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ struct TargetGenericContextDescriptorHeader {
/// same order as the requirement descriptors which satisfy
/// hasKeyArgument().
///
/// a sequence of values, in the same order as the parameter descriptors
/// which satisify getKind() == GenericParamKind::Value and
/// hasKeyArgument();
///
/// The elements above which are packs are precisely those appearing
/// in the sequence of trailing GenericPackShapeDescriptors.
uint16_t NumKeyArguments;
Expand Down Expand Up @@ -319,6 +323,18 @@ struct ConditionalInvertibleProtocolSet: InvertibleProtocolSet {
template<typename Runtime>
struct TargetConditionalInvertibleProtocolRequirement: TargetGenericRequirementDescriptor<Runtime> { };

struct GenericValueHeader {
/// The total number of generic parameters in this signature where
/// getKind() == GenericParamKind::Value.
uint32_t NumValues;
};

/// The GenericValueHeader is followed by an array of these descriptors,
/// whose length is given by the header's NumValues field.
struct GenericValueDescriptor {
GenericValueType Type;
};

/// An array of generic parameter descriptors, all
/// GenericParamDescriptor::implicit(), which is by far
/// the most common case. Some generic context storage can
Expand Down Expand Up @@ -356,20 +372,26 @@ class RuntimeGenericSignature {
const TargetGenericRequirementDescriptor<Runtime> *Requirements;
GenericPackShapeHeader PackShapeHeader;
const GenericPackShapeDescriptor *PackShapeDescriptors;
GenericValueHeader ValueHeader;
const GenericValueDescriptor *ValueDescriptors;

public:
RuntimeGenericSignature()
: Header{0, 0, 0, GenericContextDescriptorFlags(false, false)},
: Header{0, 0, 0, GenericContextDescriptorFlags(false, false, false)},
Params(nullptr), Requirements(nullptr),
PackShapeHeader{0, 0}, PackShapeDescriptors(nullptr) {}
PackShapeHeader{0, 0}, PackShapeDescriptors(nullptr), ValueHeader{0},
ValueDescriptors(nullptr) {}

RuntimeGenericSignature(const TargetGenericContextDescriptorHeader<Runtime> &header,
const GenericParamDescriptor *params,
const TargetGenericRequirementDescriptor<Runtime> *requirements,
const GenericPackShapeHeader &packShapeHeader,
const GenericPackShapeDescriptor *packShapeDescriptors)
const GenericPackShapeDescriptor *packShapeDescriptors,
const GenericValueHeader &valueHeader,
const GenericValueDescriptor *valueDescriptors)
: Header(header), Params(params), Requirements(requirements),
PackShapeHeader(packShapeHeader), PackShapeDescriptors(packShapeDescriptors) {}
PackShapeHeader(packShapeHeader), PackShapeDescriptors(packShapeDescriptors),
ValueHeader(valueHeader), ValueDescriptors(valueDescriptors) {}

llvm::ArrayRef<GenericParamDescriptor> getParams() const {
return llvm::ArrayRef(Params, Header.NumParams);
Expand All @@ -387,6 +409,14 @@ class RuntimeGenericSignature {
return llvm::ArrayRef(PackShapeDescriptors, PackShapeHeader.NumPacks);
}

const GenericValueHeader &getGenericValueHeader() const {
return ValueHeader;
}

llvm::ArrayRef<GenericValueDescriptor> getGenericValueDescriptors() const {
return llvm::ArrayRef(ValueDescriptors, ValueHeader.NumValues);
}

size_t getArgumentLayoutSizeInWords() const {
return Header.getArgumentLayoutSizeInWords();
}
Expand Down Expand Up @@ -482,6 +512,8 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
ConditionalInvertibleProtocolSet,
ConditionalInvertibleProtocolsRequirementCount,
TargetConditionalInvertibleProtocolRequirement<Runtime>,
GenericValueHeader,
GenericValueDescriptor,
FollowingTrailingObjects...>
{
protected:
Expand All @@ -500,6 +532,8 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
ConditionalInvertibleProtocolSet,
ConditionalInvertibleProtocolsRequirementCount,
GenericConditionalInvertibleProtocolRequirement,
GenericValueHeader,
GenericValueDescriptor,
FollowingTrailingObjects...>;
friend TrailingObjects;

Expand Down Expand Up @@ -648,13 +682,33 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
header.NumPacks};
}

GenericValueHeader getGenericValueHeader() const {
if (!asSelf()->isGeneric())
return {0};
if (!getGenericContextHeader().Flags.hasValues())
return {0};
return *this->template getTrailingObjects<GenericValueHeader>();
}

llvm::ArrayRef<GenericValueDescriptor> getGenericValueDescriptors() const {
auto header = getGenericValueHeader();

if (header.NumValues == 0)
return {};

return {this->template getTrailingObjects<GenericValueDescriptor>(),
header.NumValues};
}

RuntimeGenericSignature<Runtime> getGenericSignature() const {
if (!asSelf()->isGeneric()) return RuntimeGenericSignature<Runtime>();
return {getGenericContextHeader(),
getGenericParams().data(),
getGenericRequirements().data(),
getGenericPackShapeHeader(),
getGenericPackShapeDescriptors().data()};
getGenericPackShapeDescriptors().data(),
getGenericValueHeader(),
getGenericValueDescriptors().data()};
}

protected:
Expand Down Expand Up @@ -713,6 +767,23 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
return counts.empty() ? 0 : counts.back().count;
}

size_t numTrailingObjects(OverloadToken<GenericValueHeader>) const {
if (!asSelf()->isGeneric())
return 0;

return getGenericContextHeader().Flags.hasValues() ? 1 : 0;
}

size_t numTrailingObjects(OverloadToken<GenericValueDescriptor>) const {
if (!asSelf()->isGeneric())
return 0;

if (!getGenericContextHeader().Flags.hasValues())
return 0;

return getGenericValueHeader().NumValues;
}

#if defined(_MSC_VER) && _MSC_VER < 1920
#undef OverloadToken
#endif
Expand Down
5 changes: 3 additions & 2 deletions include/swift/ABI/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -2145,7 +2145,7 @@ struct TargetExtendedExistentialTypeShape

RuntimeGenericSignature<Runtime> getRequirementSignature() const {
return {ReqSigHeader, getReqSigParams(), getReqSigRequirements(),
{0, 0}, nullptr};
{0, 0}, nullptr, {0}, nullptr};
}

unsigned getNumReqSigParams() const {
Expand Down Expand Up @@ -2225,7 +2225,8 @@ struct TargetExtendedExistentialTypeShape
RuntimeGenericSignature<Runtime> getGeneralizationSignature() const {
if (!hasGeneralizationSignature()) return RuntimeGenericSignature<Runtime>();
return {*getGenSigHeader(), getGenSigParams(), getGenSigRequirements(),
getGenSigPackShapeHeader(), getGenSigPackShapeDescriptors()};
getGenSigPackShapeHeader(), getGenSigPackShapeDescriptors(),
{0}, nullptr};
}

unsigned getNumGenSigParams() const {
Expand Down
Loading