Skip to content

SIL: Type lowering for function values with substituted SIL function types. #28065

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 5, 2019

Conversation

jckarter
Copy link
Contributor

@jckarter jckarter commented Nov 4, 2019

After converting a function type to its corresponding SIL type by our usual rules, extract
the substituted generic signature and common interface type for all concrete function types
that the function could be called as. We don't currently have any use cases for distinguishing
types at finer granularity than generic class-constrained/generic unconstrained/not-generic, so
to reduce the amount of conversion noise in SIL, generate the most general generic signature
possible, by extracting every position with a dependent generic parameter or associated type thereof
into a separate generic parameter in the substituted signature, discarding all constraints except
for AnyObject layout constraints. This way, if foo<T>(x: (T, T) -> ()) calls
bar<T, U>(x: (T, U) -> ()) and forwards x along, the two closures that only vary in genericity
don't need a conversion even with substituted function types, because they'll both have the same
abstract lowering <A, B> (A, B) -> () with different substitutions.

@jckarter
Copy link
Contributor Author

jckarter commented Nov 4, 2019

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Nov 5, 2019

Build failed
Swift Test Linux Platform
Git Sha - 1a9ebbd

@swift-ci
Copy link
Contributor

swift-ci commented Nov 5, 2019

Build failed
Swift Test OS X Platform
Git Sha - 1a9ebbd

@jckarter
Copy link
Contributor Author

jckarter commented Nov 5, 2019

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Nov 5, 2019

Build failed
Swift Test OS X Platform
Git Sha - 1a9ebbd

@swift-ci
Copy link
Contributor

swift-ci commented Nov 5, 2019

Build failed
Swift Test Linux Platform
Git Sha - 1a9ebbd

->castTo<ArchetypeType>();

// Replace every dependent type we see with a fresh type variable in
// the substituted signature.
Copy link
Contributor

@rjmccall rjmccall Nov 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is covered correctly in the code, but please clarify in the comment that this also includes opaque types. And that should be tested.

Copy link
Contributor Author

@jckarter jckarter Nov 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't include opaque types, because subst won't substitute them unless explicitly asked to, and I don't think we need to include them because they aren't arbitrarily substitutable by call sites. I can clarify that in the comment, and add a test.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, but they are sometimes substituted, right? On the implementation side of an opaque type, we know that OpaqueType == Int. If we make opaque-type identity part of the ABI, presumably that means that at some point in SIL on the implementation side we'll need to represent function types where the original type is expressed in terms of OpaqueType but the concrete type is known to be Int. Feels easier to me to just define this away.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The opaque type is never formally substituted; we at best do a convert_function or bitcast in places we know the underlying type. Arnold's work on #28044 should more thoroughly handle the relationship between opaque types and their underlying type as part of type lowering, so the difference would only manifest at boundaries between differently-resilient function bodies.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, the ABI of a specific function has to be consistent, so it matters if the representation would say that they're ABI-different on different sides of the resilience boundary. Concretely, if we're going to give () -> (@out Opaque) a different ptrauth discriminator from () -> (@out Int), we need to remember that the function signature was actually written as the former, which is what this work is all about; Arnold's work can't just rewrite it on one side of the boundary and in doing so implicitly change the discriminator.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, good point. I'll change it to substitute them out.

Copy link
Contributor Author

@jckarter jckarter Nov 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, doing that correctly in the face of #28044 might require sinking this more deeply into the type lowering logic than I was hoping to start out with, instead of doing it as a post-pass, since the lowered argument and return types would already have the opaque archetypes substituted out of them. If you don't mind, I can do that in a follow up patch after Arnold lands his.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine, it just needs to happen before we can make ptrauth discriminator tighter.

if (archetype->requiresClass()) {
substRequirements.push_back(Requirement(RequirementKind::Layout,param,
LayoutConstraint::getLayoutConstraint(LayoutConstraintKind::Class)));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we don't really support any other layout constraints in the language right now, but is there a reason for this not to preserve an arbitrary layout constraint?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had it that way originally, but we apparently do have distinct layout constraints for _NativeClass and _SingleRefcounted, which don't seem like useful distinctions from AnyObject at this level. Maybe it'd be better to specifically canonicalize those internal constraints, though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, some of the other layout constraints definitely seem useful to distinguish ABI-wise, and I'm not sure there's harm in just preserving all the original layout constraints. If we specialized an implementation, presumably function arguments would (by default) preserve the original constraints of the function, and it would just be the substitution with the specialized constraint.

Copy link
Contributor Author

@jckarter jckarter Nov 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main issue I see with that is that base class constraints imply _NativeClass instead of AnyObject as their layout constraint when the base class has no ObjC ancestry, and that seems like it could introduce a lot of spurious type mismatches. I can make it so it more selectively generalizes layout constraints, though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I hadn't thought of that. Yeah, maybe doing it selectively would make more sense.

…types.

After converting a function type to its corresponding SIL type by our usual rules, extract
the substituted generic signature and common interface type for all concrete function types
that the function could be called as. We don't currently have any use cases for distinguishing
types at finer granularity than generic class-constrained/generic unconstrained/not-generic, so
to reduce the amount of conversion noise in SIL, generate the most general generic signature
possible, by extracting every position with a dependent generic parameter or associated type thereof
into a separate generic parameter in the substituted signature, discarding all constraints except
for `AnyObject` layout constraints. This way, if `foo<T>(x: (T, T) -> ())` calls
`bar<T, U>(x: (T, U) -> ())` and forwards `x` along, the two closures that only vary in genericity
don't need a conversion even with substituted function types, because they'll both have the same
abstract lowering `<A, B> (A, B) -> ()` with different substitutions.
@jckarter jckarter force-pushed the subst-function-type-value-lowering branch from 1a9ebbd to 27d7117 Compare November 5, 2019 20:50
layout->getAlignmentInBits(),
TC.Context);
break;
}
Copy link
Contributor Author

@jckarter jckarter Nov 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rjmccall Here's some logic I added to fold up our existing layout constraints into what seemed like the appropriate ABI buckets to me. How's this look?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@jckarter
Copy link
Contributor Author

jckarter commented Nov 5, 2019

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Nov 5, 2019

Build failed
Swift Test Linux Platform
Git Sha - 1a9ebbd

@swift-ci
Copy link
Contributor

swift-ci commented Nov 5, 2019

Build failed
Swift Test OS X Platform
Git Sha - 1a9ebbd

@jckarter jckarter merged commit 0fc8377 into master Nov 5, 2019
@compnerd compnerd deleted the subst-function-type-value-lowering branch May 31, 2025 20:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants