Skip to content

Commit e5e4e26

Browse files
committed
IRGen: Implement emitPackShapeExpression()
1 parent 09535c3 commit e5e4e26

File tree

4 files changed

+89
-11
lines changed

4 files changed

+89
-11
lines changed

lib/IRGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ add_swift_host_library(swiftIRGen STATIC
3333
GenMeta.cpp
3434
GenObjC.cpp
3535
GenOpaque.cpp
36+
GenPack.cpp
3637
GenPointerAuth.cpp
3738
GenPoly.cpp
3839
GenProto.cpp

lib/IRGen/GenPack.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//===--- GenPack.cpp - Swift IR Generation For Variadic Generics ----------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file implements IR generation for type and value packs in Swift.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#include "swift/AST/Decl.h"
18+
#include "swift/AST/IRGenOptions.h"
19+
#include "swift/AST/Types.h"
20+
#include "swift/SIL/SILModule.h"
21+
#include "swift/SIL/SILType.h"
22+
#include "llvm/IR/DerivedTypes.h"
23+
24+
#include "GenType.h"
25+
#include "IRGenFunction.h"
26+
#include "IRGenModule.h"
27+
28+
using namespace swift;
29+
using namespace irgen;
30+
31+
llvm::Value *IRGenFunction::emitPackShapeExpression(CanType type) {
32+
33+
type = type->getReducedShape()->getCanonicalType();
34+
35+
auto kind = LocalTypeDataKind::forPackShapeExpression();
36+
37+
llvm::Value *result = tryGetLocalTypeData(type, kind);
38+
if (result != nullptr)
39+
return result;
40+
41+
// If shape(T) == t and shape(U) == u, the shape expression for a pack
42+
// {T..., Int, T..., U..., String} becomes 't + t + u + 2'.
43+
unsigned scalarElements = 0;
44+
45+
auto accumulate = [&](llvm::Value *value) {
46+
if (result == nullptr) {
47+
result = value;
48+
return;
49+
}
50+
51+
result = Builder.CreateAdd(result, value);
52+
};
53+
54+
auto packType = cast<PackType>(type);
55+
for (auto elt : packType.getElementTypes()) {
56+
if (auto expansionType = dyn_cast<PackExpansionType>(elt)) {
57+
auto reducedShape = expansionType.getCountType();
58+
accumulate(emitPackShapeExpression(reducedShape));
59+
continue;
60+
}
61+
62+
++scalarElements;
63+
}
64+
65+
if (scalarElements > 0) {
66+
auto *constant = llvm::ConstantInt::get(IGM.SizeTy, scalarElements);
67+
accumulate(constant);
68+
}
69+
70+
setScopedLocalTypeData(type, kind, result);
71+
return result;
72+
}

lib/IRGen/GenProto.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3364,19 +3364,22 @@ irgen::emitGenericRequirementFromSubstitutions(IRGenFunction &IGF,
33643364
CanType depTy = requirement.getTypeParameter();
33653365
CanType argType = depTy.subst(subs)->getCanonicalType();
33663366

3367-
if (requirement.isMetadata()) {
3368-
auto argMetadata = IGF.emitTypeMetadataRef(argType);
3369-
return argMetadata;
3370-
}
3367+
switch (requirement.getKind()) {
3368+
case GenericRequirement::Kind::Shape:
3369+
return IGF.emitPackShapeExpression(argType);
33713370

3372-
assert(requirement.isWitnessTable());
3371+
case GenericRequirement::Kind::Metadata:
3372+
return IGF.emitTypeMetadataRef(argType);
33733373

3374-
auto proto = requirement.getProtocol();
3375-
auto conformance = subs.lookupConformance(depTy, proto);
3376-
assert(conformance.getRequirement() == proto);
3377-
llvm::Value *metadata = nullptr;
3378-
auto wtable = emitWitnessTableRef(IGF, argType, &metadata, conformance);
3379-
return wtable;
3374+
case GenericRequirement::Kind::WitnessTable: {
3375+
auto proto = requirement.getProtocol();
3376+
auto conformance = subs.lookupConformance(depTy, proto);
3377+
assert(conformance.getRequirement() == proto);
3378+
llvm::Value *metadata = nullptr;
3379+
auto wtable = emitWitnessTableRef(IGF, argType, &metadata, conformance);
3380+
return wtable;
3381+
}
3382+
}
33803383
}
33813384

33823385
void GenericTypeRequirements::bindFromBuffer(IRGenFunction &IGF,

lib/IRGen/IRGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,8 @@ class IRGenFunction {
349349
llvm::Value *&metadataSlot,
350350
ValueWitness index);
351351

352+
llvm::Value *emitPackShapeExpression(CanType type);
353+
352354
/// Emit a load of a reference to the given Objective-C selector.
353355
llvm::Value *emitObjCSelectorRefLoad(StringRef selector);
354356

0 commit comments

Comments
 (0)