mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
IRGen: Emitting metadata for function types containing pack expansion parameters
This commit is contained in:
@@ -1349,3 +1349,63 @@ irgen::emitDynamicTupleTypeLabels(IRGenFunction &IGF,
|
||||
|
||||
return labelString;
|
||||
}
|
||||
|
||||
StackAddress
|
||||
irgen::emitDynamicFunctionParameterFlags(IRGenFunction &IGF,
|
||||
AnyFunctionType::CanParamArrayRef params,
|
||||
CanPackType packType,
|
||||
llvm::Value *shapeExpression) {
|
||||
auto array =
|
||||
IGF.emitDynamicAlloca(IGF.IGM.Int32Ty, shapeExpression,
|
||||
Alignment(4), /*allowTaskAlloc=*/true);
|
||||
|
||||
unsigned numExpansions = 0;
|
||||
|
||||
auto visitFn = [&](CanType eltTy,
|
||||
unsigned scalarIndex,
|
||||
llvm::Value *dynamicIndex,
|
||||
llvm::Value *dynamicLength) {
|
||||
if (scalarIndex != 0 || dynamicIndex == nullptr) {
|
||||
auto *constant = llvm::ConstantInt::get(IGF.IGM.SizeTy, scalarIndex);
|
||||
accumulateSum(IGF, dynamicIndex, constant);
|
||||
}
|
||||
|
||||
auto elt = params[scalarIndex + numExpansions];
|
||||
auto flags = getABIParameterFlags(elt.getParameterFlags());
|
||||
auto flagsVal = llvm::ConstantInt::get(
|
||||
IGF.IGM.Int32Ty, flags.getIntValue());
|
||||
|
||||
assert(eltTy == elt.getPlainType());
|
||||
|
||||
// If we're looking at a pack expansion, insert the appropriate
|
||||
// number of flags fields.
|
||||
if (auto expansionTy = dyn_cast<PackExpansionType>(eltTy)) {
|
||||
emitPackExpansionPack(IGF, array.getAddress(), expansionTy,
|
||||
dynamicIndex, dynamicLength,
|
||||
[&](llvm::Value *) -> llvm::Value * {
|
||||
return flagsVal;
|
||||
});
|
||||
|
||||
// We consumed an expansion.
|
||||
numExpansions += 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// The destination address, where we put the current element's flags field.
|
||||
Address eltAddr(
|
||||
IGF.Builder.CreateInBoundsGEP(array.getAddress().getElementType(),
|
||||
array.getAddressPointer(),
|
||||
dynamicIndex),
|
||||
array.getAddress().getElementType(),
|
||||
array.getAlignment());
|
||||
|
||||
// Otherwise, we have a single scalar element, which deposits a single
|
||||
// flags field.
|
||||
IGF.Builder.CreateStore(flagsVal, eltAddr);
|
||||
};
|
||||
|
||||
(void) visitPackExplosion(IGF, packType, visitFn);
|
||||
|
||||
return array;
|
||||
}
|
||||
@@ -120,6 +120,12 @@ emitDynamicTupleTypeLabels(IRGenFunction &IGF,
|
||||
CanPackType packType,
|
||||
llvm::Value *shapeExpression);
|
||||
|
||||
StackAddress
|
||||
emitDynamicFunctionParameterFlags(IRGenFunction &IGF,
|
||||
AnyFunctionType::CanParamArrayRef params,
|
||||
CanPackType packType,
|
||||
llvm::Value *shapeExpression);
|
||||
|
||||
} // end namespace irgen
|
||||
} // end namespace swift
|
||||
|
||||
|
||||
@@ -1371,7 +1371,7 @@ static llvm::Value *getFunctionParameterRef(IRGenFunction &IGF,
|
||||
}
|
||||
|
||||
/// Mapping type-level parameter flags to ABI parameter flags.
|
||||
static ParameterFlags getABIParameterFlags(ParameterTypeFlags flags) {
|
||||
ParameterFlags irgen::getABIParameterFlags(ParameterTypeFlags flags) {
|
||||
return ParameterFlags()
|
||||
.withValueOwnership(flags.getValueOwnership())
|
||||
.withVariadic(flags.isVariadic())
|
||||
@@ -1489,7 +1489,27 @@ emitDynamicFunctionTypeMetadataParams(IRGenFunction &IGF,
|
||||
CanPackType packType,
|
||||
DynamicMetadataRequest request,
|
||||
SmallVectorImpl<llvm::Value *> &arguments) {
|
||||
assert(false);
|
||||
assert(!params.empty());
|
||||
|
||||
FunctionTypeMetadataParamInfo info;
|
||||
|
||||
llvm::Value *shape;
|
||||
std::tie(info.parameters, shape) = emitTypeMetadataPack(
|
||||
IGF, packType, MetadataState::Abstract);
|
||||
|
||||
arguments.push_back(info.parameters.getAddress().getAddress());
|
||||
|
||||
if (flags.hasParameterFlags()) {
|
||||
info.paramFlags = emitDynamicFunctionParameterFlags(
|
||||
IGF, params, packType, shape);
|
||||
|
||||
arguments.push_back(info.paramFlags.getAddress().getAddress());
|
||||
} else {
|
||||
arguments.push_back(llvm::ConstantPointerNull::get(
|
||||
IGF.IGM.Int32Ty->getPointerTo()));
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void cleanupFunctionTypeMetadataParams(IRGenFunction &IGF,
|
||||
|
||||
@@ -709,6 +709,8 @@ MetadataResponse emitCheckTypeMetadataState(IRGenFunction &IGF,
|
||||
OperationCost getCheckTypeMetadataStateCost(DynamicMetadataRequest request,
|
||||
MetadataResponse response);
|
||||
|
||||
ParameterFlags getABIParameterFlags(ParameterTypeFlags flags);
|
||||
|
||||
} // end namespace irgen
|
||||
} // end namespace swift
|
||||
|
||||
|
||||
42
test/Interpreter/variadic_generic_func_types.swift
Normal file
42
test/Interpreter/variadic_generic_func_types.swift
Normal file
@@ -0,0 +1,42 @@
|
||||
// RUN: %target-run-simple-swift
|
||||
|
||||
// REQUIRES: executable_test
|
||||
|
||||
import StdlibUnittest
|
||||
|
||||
var funcs = TestSuite("VariadicGenericFuncTypes")
|
||||
|
||||
func makeFunctionType1<each T>(_: repeat (each T).Type) -> Any.Type {
|
||||
return ((repeat each T) -> ()).self
|
||||
}
|
||||
|
||||
func makeFunctionType2<each T>(_: repeat (each T).Type) -> Any.Type {
|
||||
return ((Character, repeat each T, Bool) -> ()).self
|
||||
}
|
||||
|
||||
func makeFunctionType3<each T>(_: repeat (each T).Type) -> Any.Type {
|
||||
return ((inout Character, repeat each T, inout Bool) -> ()).self
|
||||
}
|
||||
|
||||
funcs.test("makeFunctionType1") {
|
||||
expectEqual("() -> ()", _typeName(makeFunctionType1()))
|
||||
expectEqual("(Swift.Int) -> ()", _typeName(makeFunctionType1(Int.self)))
|
||||
expectEqual("(Swift.Int, Swift.String) -> ()", _typeName(makeFunctionType1(Int.self, String.self)))
|
||||
expectEqual("(Swift.Int, Swift.Float, Swift.String) -> ()", _typeName(makeFunctionType1(Int.self, Float.self, String.self)))
|
||||
}
|
||||
|
||||
funcs.test("makeFunctionType2") {
|
||||
expectEqual("(Swift.Character, Swift.Bool) -> ()", _typeName(makeFunctionType2()))
|
||||
expectEqual("(Swift.Character, Swift.Int, Swift.Bool) -> ()", _typeName(makeFunctionType2(Int.self)))
|
||||
expectEqual("(Swift.Character, Swift.Int, Swift.String, Swift.Bool) -> ()", _typeName(makeFunctionType2(Int.self, String.self)))
|
||||
expectEqual("(Swift.Character, Swift.Int, Swift.Float, Swift.String, Swift.Bool) -> ()", _typeName(makeFunctionType2(Int.self, Float.self, String.self)))
|
||||
}
|
||||
|
||||
funcs.test("makeFunctionType3") {
|
||||
expectEqual("(inout Swift.Character, inout Swift.Bool) -> ()", _typeName(makeFunctionType3()))
|
||||
expectEqual("(inout Swift.Character, Swift.Int, inout Swift.Bool) -> ()", _typeName(makeFunctionType3(Int.self)))
|
||||
expectEqual("(inout Swift.Character, Swift.Int, Swift.String, inout Swift.Bool) -> ()", _typeName(makeFunctionType3(Int.self, String.self)))
|
||||
expectEqual("(inout Swift.Character, Swift.Int, Swift.Float, Swift.String, inout Swift.Bool) -> ()", _typeName(makeFunctionType3(Int.self, Float.self, String.self)))
|
||||
}
|
||||
|
||||
runAllTests()
|
||||
Reference in New Issue
Block a user