Skip to content

Commit ff6bd36

Browse files
committed
Add Builtin.packLength
Simplify packCount IRGen Emit pack_length instruction Add space
1 parent 973a506 commit ff6bd36

File tree

5 files changed

+111
-7
lines changed

5 files changed

+111
-7
lines changed

include/swift/AST/Builtins.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,11 @@ BUILTIN_SIL_OPERATION(WithUnsafeThrowingContinuation, "withUnsafeThrowingContinu
538538
/// Force the current task to be rescheduled on the specified actor.
539539
BUILTIN_SIL_OPERATION(HopToActor, "hopToActor", None)
540540

541+
/// packLength: <each T>(_: repeat each T) -> Int
542+
///
543+
/// Returns the number of items in a pack.
544+
BUILTIN_SIL_OPERATION(PackLength, "packLength", Special)
545+
541546
#undef BUILTIN_SIL_OPERATION
542547

543548
// BUILTIN_RUNTIME_CALL - A call into a runtime function.

lib/AST/Builtins.cpp

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -235,21 +235,25 @@ static const char * const GenericParamNames[] = {
235235
};
236236

237237
static GenericTypeParamDecl*
238-
createGenericParam(ASTContext &ctx, const char *name, unsigned index) {
238+
createGenericParam(ASTContext &ctx, const char *name, unsigned index,
239+
bool isParameterPack = false) {
239240
ModuleDecl *M = ctx.TheBuiltinModule;
240241
Identifier ident = ctx.getIdentifier(name);
241242
return GenericTypeParamDecl::createImplicit(
242-
&M->getMainFile(FileUnitKind::Builtin), ident, /*depth*/ 0, index);
243+
&M->getMainFile(FileUnitKind::Builtin), ident, /*depth*/ 0, index,
244+
isParameterPack);
243245
}
244246

245247
/// Create a generic parameter list with multiple generic parameters.
246248
static GenericParamList *getGenericParams(ASTContext &ctx,
247-
unsigned numParameters) {
249+
unsigned numParameters,
250+
bool areParameterPacks = false) {
248251
assert(numParameters <= std::size(GenericParamNames));
249252

250253
SmallVector<GenericTypeParamDecl *, 2> genericParams;
251254
for (unsigned i = 0; i != numParameters; ++i)
252-
genericParams.push_back(createGenericParam(ctx, GenericParamNames[i], i));
255+
genericParams.push_back(createGenericParam(ctx, GenericParamNames[i], i,
256+
areParameterPacks));
253257

254258
auto paramList = GenericParamList::create(ctx, SourceLoc(), genericParams,
255259
SourceLoc());
@@ -678,9 +682,11 @@ namespace {
678682

679683
public:
680684
BuiltinFunctionBuilder(ASTContext &ctx, unsigned numGenericParams = 1,
681-
bool wantsAdditionalAnyObjectRequirement = false)
685+
bool wantsAdditionalAnyObjectRequirement = false,
686+
bool areParametersPacks = false)
682687
: Context(ctx) {
683-
TheGenericParamList = getGenericParams(ctx, numGenericParams);
688+
TheGenericParamList = getGenericParams(ctx, numGenericParams,
689+
areParametersPacks);
684690
if (wantsAdditionalAnyObjectRequirement) {
685691
Requirement req(RequirementKind::Conformance,
686692
TheGenericParamList->getParams()[0]->getInterfaceType(),
@@ -750,7 +756,7 @@ namespace {
750756
unsigned Index;
751757
Type build(BuiltinFunctionBuilder &builder) const {
752758
return builder.TheGenericParamList->getParams()[Index]
753-
->getDeclaredInterfaceType();
759+
->getDeclaredInterfaceType();
754760
}
755761
};
756762
struct LambdaGenerator {
@@ -767,6 +773,16 @@ namespace {
767773
return MetatypeType::get(Object.build(builder), Repr);
768774
}
769775
};
776+
template <class T>
777+
struct PackExpansionGenerator {
778+
T Object;
779+
Type build(BuiltinFunctionBuilder &builder) const {
780+
auto patternTy = Object.build(builder);
781+
SmallVector<Type, 2> packs;
782+
patternTy->getTypeParameterPacks(packs);
783+
return PackExpansionType::get(patternTy, packs[0]);
784+
}
785+
};
770786
};
771787
} // end anonymous namespace
772788

@@ -814,6 +830,12 @@ makeMetatype(const T &object,
814830
return { object, repr };
815831
}
816832

833+
template <class T>
834+
static BuiltinFunctionBuilder::PackExpansionGenerator<T>
835+
makePackExpansion(const T &object) {
836+
return { object };
837+
}
838+
817839
/// Create a function with type <T> T -> ().
818840
static ValueDecl *getRefCountingOperation(ASTContext &ctx, Identifier id) {
819841
return getBuiltinFunction(ctx, id, _thin,
@@ -1934,6 +1956,18 @@ static ValueDecl *getHopToActor(ASTContext &ctx, Identifier id) {
19341956
return builder.build(id);
19351957
}
19361958

1959+
static ValueDecl *getPackLength(ASTContext &ctx, Identifier id) {
1960+
BuiltinFunctionBuilder builder(ctx, /* genericParamCount */ 1,
1961+
/* anyObject */ false,
1962+
/* areParametersPack */ true);
1963+
1964+
auto paramTy = makeMetatype(makeTuple(makePackExpansion(makeGenericParam())));
1965+
builder.addParameter(paramTy);
1966+
builder.setResult(makeConcrete(BuiltinIntegerType::getWordType(ctx)));
1967+
1968+
return builder.build(id);
1969+
}
1970+
19371971
/// An array of the overloaded builtin kinds.
19381972
static const OverloadedBuiltinKind OverloadedBuiltinKinds[] = {
19391973
OverloadedBuiltinKind::None,
@@ -2975,6 +3009,9 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
29753009

29763010
case BuiltinValueKind::AutoDiffAllocateSubcontextWithType:
29773011
return getAutoDiffAllocateSubcontext(Context, Id);
3012+
3013+
case BuiltinValueKind::PackLength:
3014+
return getPackLength(Context, Id);
29783015
}
29793016

29803017
llvm_unreachable("bad builtin value!");

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,6 +1708,19 @@ static ManagedValue emitBuiltinHopToActor(SILGenFunction &SGF, SILLocation loc,
17081708
return ManagedValue::forObjectRValueWithoutOwnership(SGF.emitEmptyTuple(loc));
17091709
}
17101710

1711+
static ManagedValue emitBuiltinPackLength(SILGenFunction &SGF, SILLocation loc,
1712+
SubstitutionMap subs,
1713+
ArrayRef<ManagedValue> args,
1714+
SGFContext C) {
1715+
auto argTy = args[0].getType().getASTType();
1716+
auto tupleTy = CanTupleType(argTy->getMetatypeInstanceType()
1717+
->castTo<TupleType>());
1718+
auto packTy = tupleTy.getInducedPackType();
1719+
1720+
return ManagedValue::forObjectRValueWithoutOwnership(
1721+
SGF.B.createPackLength(loc, packTy));
1722+
}
1723+
17111724
static ManagedValue emitBuiltinAutoDiffCreateLinearMapContextWithType(
17121725
SILGenFunction &SGF, SILLocation loc, SubstitutionMap subs,
17131726
ArrayRef<ManagedValue> args, SGFContext C) {

test/IRGen/builtin_pack_length.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %target-swift-frontend -module-name builtins -enable-builtin-module -Xllvm -sil-disable-pass=target-constant-folding -disable-access-control -primary-file %s -emit-ir -o - -disable-objc-attr-requires-foundation-module -disable-availability-checking -O | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime
2+
3+
// REQUIRES: CPU=x86_64 || CPU=arm64 || CPU=arm64e
4+
5+
import Builtin
6+
7+
// CHECK: define {{.*}} @"$s8builtins9packCountyBwxxQpRvzlF"(ptr {{.*}} %0, i64 {{.*}} [[PACK_COUNT:%.*]], ptr {{.*}} %"each T")
8+
// CHECK: ret i64 [[PACK_COUNT]]
9+
func packCount<each T>(_: repeat each T) -> Builtin.Word {
10+
Builtin.packLength((repeat each T).self)
11+
}
12+
13+
// CHECK: define {{.*}} @"$s8builtins12packCountUseBwyF"()
14+
// CHECK-NEXT: entry:
15+
// CHECK-NEXT: ret i64 4
16+
func packCountUse() -> Builtin.Word {
17+
packCount(123, 321, 456, 654)
18+
}
19+
20+
// CHECK: define {{.*}} @"$s8builtins18weirdPackCountUse0yBwxxQpRvzlF"(ptr {{.*}} %0, i64 [[PACK_COUNT:%.*]], ptr {{.*}} %"each T")
21+
// CHECK: [[ADD:%.*]] = add i64 [[PACK_COUNT]], 2
22+
// CHECK-NEXT: ret i64 [[ADD]]
23+
func weirdPackCountUse0<each T>(_ x: repeat each T) -> Builtin.Word {
24+
Builtin.packLength((String, repeat each T, Int).self)
25+
}
26+
27+
// CHECK: define {{.*}} @"$s8builtins18weirdPackCountUse1yBwxxQpRvzlF"(ptr {{.*}} %0, i64 %1, ptr {{.*}} %"each T")
28+
// CHECK: ret i64 3
29+
func weirdPackCountUse1<each T>(_ x: repeat each T) -> Builtin.Word {
30+
Builtin.packLength((String, (repeat each T), Int).self)
31+
}
32+
33+
struct Pack<each T> {
34+
// CHECK: define {{.*}} @"$s8builtins4PackV5countBwvgZ"(i64 returned [[PACK_COUNT:%.*]], ptr nocapture readnone %"each T")
35+
// CHECK-NEXT: entry:
36+
// CHECK-NEXT: ret i64 [[PACK_COUNT]]
37+
static var count: Builtin.Word {
38+
Builtin.packLength((repeat each T).self)
39+
}
40+
}

test/SILGen/builtins.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,3 +876,12 @@ func assumeTrue(_ x: Builtin.Int1) {
876876
func assumeAlignment(_ p: Builtin.RawPointer, _ x: Builtin.Word) {
877877
Builtin.assumeAlignment(p, x)
878878
}
879+
880+
// CHECK-LABEL: sil hidden [ossa] @$s8builtins9packCountyBwxxQpRvzlF : $@convention(thin) <each T> (@pack_guaranteed Pack{repeat each T}) -> Builtin.Word {
881+
// CHECK: bb0(%0 : $*Pack{repeat each T}):
882+
// CHECK: [[META:%.*]] = metatype $@thin (repeat each T).Type
883+
// CHECK: [[PACK_LENGTH:%.*]] = pack_length $Pack{repeat each T}
884+
// CHECK: return [[PACK_LENGTH]] : $Builtin.Word
885+
func packCount<each T>(_ x: repeat each T) -> Builtin.Word {
886+
Builtin.packLength((repeat each T).self)
887+
}

0 commit comments

Comments
 (0)