Skip to content

Commit 450399f

Browse files
committed
IRGen: Emitting metadata for function types containing pack expansion parameters
1 parent 0f3c430 commit 450399f

File tree

4 files changed

+139
-1
lines changed

4 files changed

+139
-1
lines changed

lib/IRGen/GenPack.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,3 +1349,73 @@ irgen::emitDynamicTupleTypeLabels(IRGenFunction &IGF,
13491349

13501350
return labelString;
13511351
}
1352+
1353+
/// Mapping type-level parameter flags to ABI parameter flags.
1354+
static ParameterFlags getABIParameterFlags(ParameterTypeFlags flags) {
1355+
return ParameterFlags()
1356+
.withValueOwnership(flags.getValueOwnership())
1357+
.withVariadic(flags.isVariadic())
1358+
.withAutoClosure(flags.isAutoClosure())
1359+
.withNoDerivative(flags.isNoDerivative())
1360+
.withIsolated(flags.isIsolated());
1361+
}
1362+
1363+
StackAddress
1364+
irgen::emitDynamicFunctionParameterFlags(IRGenFunction &IGF,
1365+
AnyFunctionType::CanParamArrayRef params,
1366+
CanPackType packType,
1367+
llvm::Value *shapeExpression) {
1368+
auto array =
1369+
IGF.emitDynamicAlloca(IGF.IGM.Int32Ty, shapeExpression,
1370+
Alignment(4), /*allowTaskAlloc=*/true);
1371+
1372+
unsigned numExpansions = 0;
1373+
1374+
auto visitFn = [&](CanType eltTy,
1375+
unsigned scalarIndex,
1376+
llvm::Value *dynamicIndex,
1377+
llvm::Value *dynamicLength) {
1378+
if (scalarIndex != 0 || dynamicIndex == nullptr) {
1379+
auto *constant = llvm::ConstantInt::get(IGF.IGM.SizeTy, scalarIndex);
1380+
accumulateSum(IGF, dynamicIndex, constant);
1381+
}
1382+
1383+
auto elt = params[scalarIndex + numExpansions];
1384+
auto flags = getABIParameterFlags(elt.getParameterFlags());
1385+
auto flagsVal = llvm::ConstantInt::get(
1386+
IGF.IGM.Int32Ty, flags.getIntValue());
1387+
1388+
assert(eltTy == elt.getPlainType());
1389+
1390+
// If we're looking at a pack expansion, insert the appropriate
1391+
// number of flags fields.
1392+
if (auto expansionTy = dyn_cast<PackExpansionType>(eltTy)) {
1393+
emitPackExpansionPack(IGF, array.getAddress(), expansionTy,
1394+
dynamicIndex, dynamicLength,
1395+
[&](llvm::Value *) -> llvm::Value * {
1396+
return flagsVal;
1397+
});
1398+
1399+
// We consumed an expansion.
1400+
numExpansions += 1;
1401+
1402+
return;
1403+
}
1404+
1405+
// The destination address, where we put the current element's flags field.
1406+
Address eltAddr(
1407+
IGF.Builder.CreateInBoundsGEP(array.getAddress().getElementType(),
1408+
array.getAddressPointer(),
1409+
dynamicIndex),
1410+
array.getAddress().getElementType(),
1411+
array.getAlignment());
1412+
1413+
// Otherwise, we have a single scalar element, which deposits a single
1414+
// flags field.
1415+
IGF.Builder.CreateStore(flagsVal, eltAddr);
1416+
};
1417+
1418+
(void) visitPackExplosion(IGF, packType, visitFn);
1419+
1420+
return array;
1421+
}

lib/IRGen/GenPack.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ emitDynamicTupleTypeLabels(IRGenFunction &IGF,
120120
CanPackType packType,
121121
llvm::Value *shapeExpression);
122122

123+
StackAddress
124+
emitDynamicFunctionParameterFlags(IRGenFunction &IGF,
125+
AnyFunctionType::CanParamArrayRef params,
126+
CanPackType packType,
127+
llvm::Value *shapeExpression);
128+
123129
} // end namespace irgen
124130
} // end namespace swift
125131

lib/IRGen/MetadataRequest.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1489,7 +1489,27 @@ emitDynamicFunctionTypeMetadataParams(IRGenFunction &IGF,
14891489
CanPackType packType,
14901490
DynamicMetadataRequest request,
14911491
SmallVectorImpl<llvm::Value *> &arguments) {
1492-
assert(false);
1492+
assert(!params.empty());
1493+
1494+
FunctionTypeMetadataParamInfo info;
1495+
1496+
llvm::Value *shape;
1497+
std::tie(info.parameters, shape) = emitTypeMetadataPack(
1498+
IGF, packType, MetadataState::Abstract);
1499+
1500+
arguments.push_back(info.parameters.getAddress().getAddress());
1501+
1502+
if (flags.hasParameterFlags()) {
1503+
info.paramFlags = emitDynamicFunctionParameterFlags(
1504+
IGF, params, packType, shape);
1505+
1506+
arguments.push_back(info.paramFlags.getAddress().getAddress());
1507+
} else {
1508+
arguments.push_back(llvm::ConstantPointerNull::get(
1509+
IGF.IGM.Int32Ty->getPointerTo()));
1510+
}
1511+
1512+
return info;
14931513
}
14941514

14951515
static void cleanupFunctionTypeMetadataParams(IRGenFunction &IGF,
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %target-run-simple-swift
2+
3+
// REQUIRES: executable_test
4+
5+
import StdlibUnittest
6+
7+
var funcs = TestSuite("VariadicGenericFuncTypes")
8+
9+
func makeFunctionType1<each T>(_: repeat (each T).Type) -> Any.Type {
10+
return ((repeat each T) -> ()).self
11+
}
12+
13+
func makeFunctionType2<each T>(_: repeat (each T).Type) -> Any.Type {
14+
return ((Character, repeat each T, Bool) -> ()).self
15+
}
16+
17+
func makeFunctionType3<each T>(_: repeat (each T).Type) -> Any.Type {
18+
return ((inout Character, repeat each T, inout Bool) -> ()).self
19+
}
20+
21+
funcs.test("makeFunctionType1") {
22+
expectEqual("() -> ()", _typeName(makeFunctionType1()))
23+
expectEqual("(Int) -> ()", _typeName(makeFunctionType1(Int.self)))
24+
expectEqual("(Int, String) -> ()", _typeName(makeFunctionType1(Int.self, String.self)))
25+
expectEqual("(Int, Float, String) -> ()", _typeName(makeFunctionType1(Int.self, Float.self, String.self)))
26+
}
27+
28+
funcs.test("makeFunctionType2") {
29+
expectEqual("(Character, Bool) -> ()", _typeName(makeFunctionType2()))
30+
expectEqual("(Character, Int, Bool) -> ()", _typeName(makeFunctionType2(Int.self)))
31+
expectEqual("(Character, Int, String, Bool) -> ()", _typeName(makeFunctionType2(Int.self, String.self)))
32+
expectEqual("(Character, Int, Float, String, Bool) -> ()", _typeName(makeFunctionType2(Int.self, Float.self, String.self)))
33+
}
34+
35+
funcs.test("makeFunctionType3") {
36+
expectEqual("(inout Character, inout Bool) -> ()", _typeName(makeFunctionType3()))
37+
expectEqual("(inout Character, Int, inout Bool) -> ()", _typeName(makeFunctionType3(Int.self)))
38+
expectEqual("(inout Character, Int, String, inout Bool) -> ()", _typeName(makeFunctionType3(Int.self, String.self)))
39+
expectEqual("(inout Character, Int, Float, String, inout Bool) -> ()", _typeName(makeFunctionType3(Int.self, Float.self, String.self)))
40+
}
41+
42+
runAllTests()

0 commit comments

Comments
 (0)