From 3cdd30ec1fe1d48fd6591aebe3c3ba106e7752f1 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 14 Mar 2014 17:31:03 -0700 Subject: [PATCH 1/2] Add RFC for new intrinsic design --- active/0000-new-intrinsics.md | 68 +++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 active/0000-new-intrinsics.md diff --git a/active/0000-new-intrinsics.md b/active/0000-new-intrinsics.md new file mode 100644 index 00000000000..97a3ff2470d --- /dev/null +++ b/active/0000-new-intrinsics.md @@ -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; +} +``` + +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. + +# 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. \ No newline at end of file From ef22d548abb5b85b08a5858cca2781e20e44f4bd Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 7 Apr 2014 15:16:36 -0700 Subject: [PATCH 2/2] Address comments on intrinsic RFC --- active/0000-new-intrinsics.md | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/active/0000-new-intrinsics.md b/active/0000-new-intrinsics.md index 97a3ff2470d..5b99aa14eb2 100644 --- a/active/0000-new-intrinsics.md +++ b/active/0000-new-intrinsics.md @@ -41,11 +41,11 @@ directly as part of the public API. 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: +and identified as intrinsics with the `#[lang = "..."]` attribute: ``` extern "Rust" { - #[intrinsic] + #[lang = "transmute"] fn transmute(T) -> U; } ``` @@ -54,13 +54,24 @@ 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. +Because intrinsics will be lang items, they can no longer be redeclared +arbitrary number of times. This will require a small amount of existing +library code to be refactored, and all intrinsics to be exposed through public +abstractions. + +Currently, "Rust" foreign functions may not be generic; this change +will require a special case that allows intrinsics to be generic. + # 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. +1. Instead of making intrinsics lang items we could create a slightly +different mechanism, like an `#[intrinsic]` attribute, that would +continue letting intrinsics to be redeclared. + +2. While using lang items to identify intrinsics, intrinsic lang items +*could* be allowed to be redeclared. -2. We could also make "rust-intrinsic" coerce or otherwise be the same +3. We could also make "rust-intrinsic" coerce or otherwise be the same as "Rust" externs and normal Rust functions. # Unresolved questions