Skip to content

introduce @call and remove other builtin calls #3856

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 5 commits into from
Dec 6, 2019
Merged

Conversation

andrewrk
Copy link
Member

@andrewrk andrewrk commented Dec 6, 2019

Implement @call. Closes #3732. This supports more options than were previously available:

pub const CallOptions = struct {
    modifier: Modifier = .auto,
    stack: ?[]align(std.Target.stack_align) u8 = null,

    pub const Modifier = enum {
        /// Prevents tail call optimization. This guarantees that the return
        /// address will point to the callsite, as opposed to the callsite's
        /// callsite. If the call is otherwise required to be tail-called
        /// or inlined, a compile error is emitted instead.
        never_tail,

        /// Guarantees that the call will not be inlined. If the call is
        /// otherwise required to be inlined, a compile error is emitted instead.
        never_inline,

        /// Equivalent to function call syntax.
        auto,

        /// Asserts that the function call will not suspend. This allows a
        /// non-async function to call an async function.
        no_async,

        /// Guarantees that the call will be generated with tail call optimization.
        /// If this is not possible, a compile error is emitted instead.
        always_tail,

        /// Guarantees that the call will inlined at the callsite.
        /// If this is not possible, a compile error is emitted instead.
        always_inline,

        /// Evaluates the call at compile-time. If the call cannot be completed at
        /// compile-time, a compile error is emitted instead.
        compile_time,
    };
};

The order here is interesting:

never_tail <- never_inline <- auto/noasync -> always_tail -> always_inline -> comptime

Zig is allowed to follow the arrows, but going against the arrows is a compile error. For example:

  • if a function is "never_inline", it's allowed for the optimizer to make that a tail call, but not vice versa.
  • if a function is "always_inline", it's allowed for the optimizer to call that at compile-time instead, but not allowed to tail call instead.

This also fixes anonymous struct/tuple literals that had any fields as runtime values.

  • Remove @noInlineCall from the language
  • Remove @inlineCall from the language
  • Remove @newStackCall from the language.

Calling with a new stack, with a runtime-known stack pointer (e.g. not a global variable) is regressed with this branch. It is now a compile-error, due to the Runtime Hint system not being smart enough to mix a compile-time modifier field with a runtime stack field. I'm OK with this regression because this feature is flawed (see #3268) and may be deleted from the language.

@asyncCall will stay for now, and probably will not get removed because the return value has a different meaning than all the rest of the kinds of calls.

This is one of 3 prerequisites until var args can be deleted. The other 2 are:

  • ++ operator for tuples
  • ability for structs to have comptime fields (this allows mixing runtime values and comptime values of comptime types in anon struct/tuple literals without forcing the entire struct/tuple to be comptime)

Calling with a new stack, with a runtime-known stack pointer (e.g.
not a global variable) is regressed with this branch. It is now a
compile-error, due to the Runtime Hint system not being smart enough
to mix a compile-time modifier field with a runtime stack field.
I'm OK with this regression because this feature is flawed (see #3268)
and may be deleted from the language.
@andrewrk andrewrk merged commit 525b1e8 into master Dec 6, 2019
@andrewrk andrewrk added the breaking Implementing this issue could cause existing code to no longer compile or have different behavior. label Dec 6, 2019
@andrewrk andrewrk deleted the builtin-call branch December 6, 2019 20:49
@@ -111,9 +114,11 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round
const m = mem.readIntSliceLittle(u64, b[0..]);
self.v3 ^= m;

// TODO this is a workaround, should be able to supply the value without a separate variable
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a related issue open for this TODO?

Copy link
Member Author

Choose a reason for hiding this comment

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

Only this one 😉 #363

@daurnimator
Copy link
Contributor

no_async could be used in addition to the other modifiers. Shouldn't it be at the CallOptions level and not inside of Modifier?

@andrewrk
Copy link
Member Author

andrewrk commented Dec 7, 2019

no_async could be used in addition to the other modifiers

I don't think this is true. Can you give an example?

@daurnimator
Copy link
Contributor

I don't think this is true. Can you give an example?

Wouldn't e.g. no_async and never_inline work together?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking Implementing this issue could cause existing code to no longer compile or have different behavior.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

NoTailCall option
2 participants