[ABI/Metadata] Add @autoclosure to function parameter flags

Add `@autoclosure` to parameter flags associated with
function type metadata, which makes it possible to correctly
round-trip mangled name <-> metadata of function types which
have parameters marked as `@autoclosure`.

Resolves: rdar://problem/45489901
This commit is contained in:
Pavel Yaskevich
2018-10-24 00:24:04 -07:00
parent f85d8ae216
commit 621b970b53
7 changed files with 57 additions and 6 deletions

View File

@@ -880,7 +880,11 @@ using FunctionTypeFlags = TargetFunctionTypeFlags<size_t>;
template <typename int_type>
class TargetParameterTypeFlags {
enum : int_type { ValueOwnershipMask = 0x7F, VariadicMask = 0x80 };
enum : int_type {
ValueOwnershipMask = 0x7F,
VariadicMask = 0x80,
AutoClosureMask = 0x100,
};
int_type Data;
constexpr TargetParameterTypeFlags(int_type Data) : Data(Data) {}
@@ -900,8 +904,15 @@ public:
(isVariadic ? VariadicMask : 0));
}
constexpr TargetParameterTypeFlags<int_type>
withAutoClosure(bool isAutoClosure) const {
return TargetParameterTypeFlags<int_type>(
(Data & ~AutoClosureMask) | (isAutoClosure ? AutoClosureMask : 0));
}
bool isNone() const { return Data == 0; }
bool isVariadic() const { return Data & VariadicMask; }
bool isAutoClosure() const { return Data & AutoClosureMask; }
ValueOwnership getValueOwnership() const {
return (ValueOwnership)(Data & ValueOwnershipMask);

View File

@@ -1726,6 +1726,12 @@ public:
| ParameterFlags(uint8_t(ownership) << OwnershipShift);
}
ParameterTypeFlags withAutoClosure(bool isAutoClosure) const {
return ParameterTypeFlags(isAutoClosure
? value | ParameterTypeFlags::AutoClosure
: value - ParameterTypeFlags::AutoClosure);
}
bool operator ==(const ParameterTypeFlags &other) const {
return value.toRaw() == other.value.toRaw();
}

View File

@@ -56,6 +56,7 @@ public:
void setType(BuiltType type) { Type = type; }
void setVariadic() { Flags = Flags.withVariadic(true); }
void setAutoClosure() { Flags = Flags.withAutoClosure(true); }
void setValueOwnership(ValueOwnership ownership) {
Flags = Flags.withValueOwnership(ownership);
}
@@ -252,7 +253,6 @@ class TypeDecoder {
if (Node->getNumChildren() < 2)
return BuiltType();
// FIXME: autoclosure is not represented in function metadata
FunctionTypeFlags flags;
if (Node->getKind() == NodeKind::ObjCBlock) {
flags = flags.withConvention(FunctionMetadataConvention::Block);
@@ -564,6 +564,13 @@ private:
setOwnership(ValueOwnership::Owned);
break;
case NodeKind::AutoClosureType:
case NodeKind::EscapingAutoClosureType: {
param.setAutoClosure();
hasParamFlags = true;
break;
}
default:
break;
}

View File

@@ -928,8 +928,9 @@ namespace {
// flags.
auto getABIParameterFlags = [](ParameterTypeFlags flags) {
return ParameterFlags()
.withValueOwnership(flags.getValueOwnership())
.withVariadic(flags.isVariadic());
.withValueOwnership(flags.getValueOwnership())
.withVariadic(flags.isVariadic())
.withAutoClosure(flags.isAutoClosure());
};
bool hasFlags = false;

View File

@@ -365,7 +365,8 @@ public:
auto ownership = flags.getValueOwnership();
auto parameterFlags = ParameterTypeFlags()
.withValueOwnership(ownership)
.withVariadic(flags.isVariadic());
.withVariadic(flags.isVariadic())
.withAutoClosure(flags.isAutoClosure());
funcParams.push_back(AnyFunctionType::Param(type, label, parameterFlags));
}

View File

@@ -55,6 +55,8 @@ let k: (Int, inout Int) -> Void = { _,_ in }
let l: (inout Int, Float, inout String) -> Void = { _,_,_ in }
let m: (__shared Int, String, inout Float, Double) -> Void = { _,_,_,_ in }
let n: () -> Int = { 42 }
let o: (@autoclosure () -> Int) -> Void = { (x: @autoclosure () -> Int) -> Void in }
let p: (@autoclosure @escaping () -> Int) -> Void = { (x: @autoclosure @escaping () -> Int) -> Void in }
let i_any: Any = i
let j_any: Any = j
@@ -62,6 +64,8 @@ let k_any: Any = k
let l_any: Any = l
let m_any: Any = m
let n_any: Any = n
let o_any: Any = o
let p_any: Any = p
// CHECK: ok
print((i_any as? (Int) -> Void) != nil ? "fail" : "ok")
@@ -125,3 +129,20 @@ print((n_any as? () -> Int) != nil ? "ok" : "fail")
print((n_any as? () -> Void) != nil ? "fail" : "ok")
// CHECK: ok
print((n_any as? (Int) -> Int) != nil ? "fail" : "ok")
// CHECK: ok
print((o_any as? (() -> Int) -> Void) != nil ? "fail" : "ok")
// CHECK: ok
print((o_any as? (inout () -> Int) -> Void) != nil ? "fail" : "ok")
// CHECK: ok
print((o_any as? (@escaping () -> Int) -> Void) != nil ? "fail" : "ok")
// CHECK: ok
print((o_any as? (@autoclosure () -> Int) -> Void) != nil ? "ok" : "fail")
// CHECK: ok
print((o_any as? (@autoclosure @escaping () -> Int) -> Void) != nil ? "fail" : "ok")
// CHECK: ok
print((p_any as? (@escaping () -> Int) -> Void) != nil ? "fail" : "ok")
// CHECK: ok
print((p_any as? (@autoclosure () -> Int) -> Void) != nil ? "fail" : "ok")
// CHECK: ok
print((p_any as? (@autoclosure @escaping () -> Int) -> Void) == nil ? "fail" : "ok")

View File

@@ -53,6 +53,10 @@ func test_arch() {
arch({(x: inout Int, y: Double, z: String, w: Int8) -> () in })
// CHECK-LABEL: define{{( protected)?}} linkonce_odr hidden swiftcc %swift.metadata_response @"$syyyccMa"
// CHECK: call %swift.type* @swift_getFunctionTypeMetadata1({{i(32|64)}} 67108865
// CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 67108865
arch({(x: @escaping () -> ()) -> () in })
// CHECK-LABEL: define{{( protected)?}} linkonce_odr hidden swiftcc %swift.metadata_response @"$sySiyXKcMa"
// CHECK: call %swift.type* @swift_getFunctionTypeMetadata([[WORD]] 100663297
arch({(x: @autoclosure () -> Int) -> Void in })
}