Skip to content
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

Add RFC for new intrinsic design #8

Merged
merged 2 commits into from
Apr 7, 2014
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions active/0000-new-intrinsics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
- Start Date: 2014-03-14
- RFC PR #: (leave this empty)
- Rust Issue #: (leave this empty)

# Summary

They way our intrinsics work forces them to be wrapped in order to
behave like normal functions. As a result, rustc is forced to inline a
great number of tiny intrinsic wrappers, which is bad for both
compile-time performance and runtime performance without
optimizations. This proposal changes the way intrinsics are surfaced
in the language so that they behave the same as normal Rust functions
by removing the "rust-intrinsic" foreign ABI and reusing the "Rust"
ABI.

# Motivation

A number of commonly-used intrinsics, including `transmute`, `forget`,
`init`, `uninit`, and `move_val_init`, are accessed through wrappers
whose only purpose is to present the intrinsics as normal functions.
As a result, rustc is forced to inline a great number of tiny
intrinsic wrappers, which is bad for both compile-time performance and
runtime performance without optimizations.

Intrinsics have a differently-named ABI from Rust functions
("rust-intrinsic" vs. "Rust") though the actual ABI implementation is
identical. As a result one can't take the value of an intrinsic as a
function:

```
// error: the type of transmute is `extern "rust-intrinsic" fn ...`
let transmute: fn(int) -> uint = intrinsics::transmute;
```

This incongruity means that we can't just expose the intrinsics
directly as part of the public API.

# Detailed design

`extern "Rust" fn` is already equivalent to `fn`, so if intrinsics
have the "Rust" ABI then the problem is solved.

Under this scheme intrinsics will be declared as `extern "Rust"` functions
and identified as intrinsics with the `#[intrinsic]` attribute:

```
extern "Rust" {
#[intrinsic]
fn transmute<T, U>(T) -> U;
}
```

The compiler will type check and translate intrinsics the same as today.
Additionally, when trans sees a "Rust" extern tagged as an intrinsic
it will not emit a function declaration to LLVM bitcode.

Choose a reason for hiding this comment

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

Maybe this could paragraph could mention that forced inlining is done in the front-end. That wasn't obvious (to me at least) until @brson clarified it.


# Alternatives

1. Instead of the new `#[intrinsic]` attribute we could make intrinsics
lang items. This would require either forcing them to be 'singletons'
or create a new type of lang item that can be multiply-declared.

2. We could also make "rust-intrinsic" coerce or otherwise be the same
as "Rust" externs and normal Rust functions.

# Unresolved questions

None.