From 525343189672095bafac6510e748b1ca28ec1847 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Tue, 3 Jun 2014 19:40:57 -0700 Subject: [PATCH 1/4] RFC: Flexible target specification --- active/0000-target-specification.md | 84 +++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 active/0000-target-specification.md diff --git a/active/0000-target-specification.md b/active/0000-target-specification.md new file mode 100644 index 00000000000..8d29d183a79 --- /dev/null +++ b/active/0000-target-specification.md @@ -0,0 +1,84 @@ +- Start Date: 2014-06-18 +- RFC PR #: (leave this empty) +- Rust Issue #: (leave this empty) + +# Summary + +*Note:* This RFC discusses the behavior of `rustc`, and not any changes to the +language. + +Change how target specification is done to be more flexible for unexpected +usecases. Additionally, add support for the "unknown" OS in target triples, +providing a minimum set of target specifications that is valid for bare-metal +situations. + +# Motivation + +One of Rust's important use cases is embedded, OS, or otherwise "bare metal" +software. At the moment, we still depend on LLVM's split-stack prologue for +stack safety. In certain situations, it is impossible or undesirable to +support what LLVM requires to enable this (on x86, a certain thread-local +storage setup). + +# Detailed design + +A target triple consists of three strings separated by a hyphen, with a +possible fourth string at the end preceded by a hyphen. The first is the +architecture, the second is the "vendor", the third is the OS type, and the +optional fourth is environment type. In theory, this specifies precisely what +platform the generated binary will be able to run on. All of this is +determined not by us but by LLVM and other tools. When on bare metal or a +similar environment, there essentially is no OS, and to handle this there is +the concept of "unknown" in the target triple. When the OS is "unknown", +no runtime environment is assumed to be present (including things such as +dynamic linking, threads/thread-local storage, IO, etc). + +Rather than listing specific targets for special treatment, introduce a +general mechanism for specifying certain characteristics of a target triple. +Redesign how targets are handled around this specification, including for the +built-in targets. Add a `T` family of flags, similar to `C`, for target +specification, as well as `-T from-file=targ.json` which will load the +configuration from a JSON file. A table of the flags and their meaning: + +* `data-layout`: The [LLVM data +layout](http://llvm.org/docs/LangRef.html#data-layout) to use. Mostly included +for completeness; changing this is unlikely to be used. +* `link-args`: Arguments to pass to the linker, unconditionally. +* `cpu`: Default CPU to use for the target, overridable with `-C target-cpu` +* `features`: Default target features to enable, augmentable with `-C + target-features`. +* `dynamic-linking-available`: Whether the `dylib` crate type is allowed. +* `split-stacks-supported`: Whether there is runtime support that will allow + LLVM's split stack prologue to function as intended. +* `target-name`: What name to use for `targ_os` for use in `cfg`. + +Rather than hardcoding a specific set of behaviors per-target, with no +recourse for escaping them, the compiler would also use this mechanism when +deciding how to build for a given target. The process would look like: + +1. Look up the target triple in an internal map, and load that configuration + if it exists. +2. If `-T from-file` is given, load any options from that file. +3. For every other `-T` flag, let it override both of the above. +4. If `-C target-cpu` is specified, replace the `cpu` with it. +5. If `-C features` is specified, add those to the ones specified by `-T`. + +Then during compilation, this information is used at the proper places rather +than matching against an enum listing the OSes we recognize. + +# Drawbacks + +More complexity. However, this is very flexible and allows one to use Rust on +a new or non-standard target *incredibly easy*, without having to modify the +compiler. rustc is the only compiler I know of that would allow that. + +# Alternatives + +One possible extension is to load `.json` from some directory, rather +than having to require `-T from-file`. + +A less holistic approach would be to just allow disabling split stacks on a +per-crate basis. Another solution could be adding a family of targets, +`-unknown-unknown`, which omits all of the above complexity but does not +allow extending to new targets easily. `-T` can easily be extended for the +future needs of other targets. From e0f80608560636afc4801a087f9adfaa766565eb Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Thu, 19 Jun 2014 07:53:21 -0700 Subject: [PATCH 2/4] Load from files only, remove `-T` Also add `relocation-model`. --- active/0000-target-specification.md | 34 ++++++++++++++++++----------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/active/0000-target-specification.md b/active/0000-target-specification.md index 8d29d183a79..2d48a0722bf 100644 --- a/active/0000-target-specification.md +++ b/active/0000-target-specification.md @@ -18,7 +18,8 @@ One of Rust's important use cases is embedded, OS, or otherwise "bare metal" software. At the moment, we still depend on LLVM's split-stack prologue for stack safety. In certain situations, it is impossible or undesirable to support what LLVM requires to enable this (on x86, a certain thread-local -storage setup). +storage setup). Additionally, porting `rustc` to a new platform requires +modifying the compiler, adding a new OS manually. # Detailed design @@ -36,9 +37,8 @@ dynamic linking, threads/thread-local storage, IO, etc). Rather than listing specific targets for special treatment, introduce a general mechanism for specifying certain characteristics of a target triple. Redesign how targets are handled around this specification, including for the -built-in targets. Add a `T` family of flags, similar to `C`, for target -specification, as well as `-T from-file=targ.json` which will load the -configuration from a JSON file. A table of the flags and their meaning: +built-in targets. Extend the `--target` flag to accept a file name of a target +specificatoin. A table of the target specification flags and their meaning: * `data-layout`: The [LLVM data layout](http://llvm.org/docs/LangRef.html#data-layout) to use. Mostly included @@ -50,22 +50,33 @@ for completeness; changing this is unlikely to be used. * `dynamic-linking-available`: Whether the `dylib` crate type is allowed. * `split-stacks-supported`: Whether there is runtime support that will allow LLVM's split stack prologue to function as intended. -* `target-name`: What name to use for `targ_os` for use in `cfg`. +* `target-name`: What name to use for `targ_os` for use in `cfg` and for + passing to LLVM. +* `relocation-model`: What relocation model to use by default. Rather than hardcoding a specific set of behaviors per-target, with no recourse for escaping them, the compiler would also use this mechanism when deciding how to build for a given target. The process would look like: 1. Look up the target triple in an internal map, and load that configuration - if it exists. -2. If `-T from-file` is given, load any options from that file. -3. For every other `-T` flag, let it override both of the above. -4. If `-C target-cpu` is specified, replace the `cpu` with it. -5. If `-C features` is specified, add those to the ones specified by `-T`. + if it exists. If that fails, check if the target name exists as a file, and + try loading that. +2. If `-C linker` is specified, use that instead of the target-specified + linker. +3. If `-C link-args` is given, add those to the ones specified by the target. +4. If `-C target-cpu` is specified, replace the target `cpu` with it. +5. If `-C target-feature` is specified, add those to the ones specified by the + target. +6. If `-C relocation-model` is specified, replace the target + `relocation-model` with it. + Then during compilation, this information is used at the proper places rather than matching against an enum listing the OSes we recognize. +The complete set of target configuration flags would be mixed into the SVH +for that crate, but would not include modifications given with `-C`. + # Drawbacks More complexity. However, this is very flexible and allows one to use Rust on @@ -74,9 +85,6 @@ compiler. rustc is the only compiler I know of that would allow that. # Alternatives -One possible extension is to load `.json` from some directory, rather -than having to require `-T from-file`. - A less holistic approach would be to just allow disabling split stacks on a per-crate basis. Another solution could be adding a family of targets, `-unknown-unknown`, which omits all of the above complexity but does not From d065a1229b81ccda2dad6165609975aed40c9af8 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Thu, 19 Jun 2014 07:57:42 -0700 Subject: [PATCH 3/4] Add RUST_TARGET_PATH --- active/0000-target-specification.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/active/0000-target-specification.md b/active/0000-target-specification.md index 2d48a0722bf..2cfe927e593 100644 --- a/active/0000-target-specification.md +++ b/active/0000-target-specification.md @@ -60,7 +60,9 @@ deciding how to build for a given target. The process would look like: 1. Look up the target triple in an internal map, and load that configuration if it exists. If that fails, check if the target name exists as a file, and - try loading that. + try loading that. If the file does not exist, look up `.json` in + the `RUST_TARGET_PATH`, which is a colon-separated list of directories + defaulting to `/etc/rustc`. 2. If `-C linker` is specified, use that instead of the target-specified linker. 3. If `-C link-args` is given, add those to the ones specified by the target. From 61e62316d21092d794b80f60bd6089ab4faaacb7 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sun, 20 Jul 2014 07:33:47 -0700 Subject: [PATCH 4/4] Update for new features, target_foo, and remove mention of `-T` --- active/0000-target-specification.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/active/0000-target-specification.md b/active/0000-target-specification.md index 2cfe927e593..c6c6cfa6653 100644 --- a/active/0000-target-specification.md +++ b/active/0000-target-specification.md @@ -38,7 +38,7 @@ Rather than listing specific targets for special treatment, introduce a general mechanism for specifying certain characteristics of a target triple. Redesign how targets are handled around this specification, including for the built-in targets. Extend the `--target` flag to accept a file name of a target -specificatoin. A table of the target specification flags and their meaning: +specification. A table of the target specification flags and their meaning: * `data-layout`: The [LLVM data layout](http://llvm.org/docs/LangRef.html#data-layout) to use. Mostly included @@ -50,9 +50,13 @@ for completeness; changing this is unlikely to be used. * `dynamic-linking-available`: Whether the `dylib` crate type is allowed. * `split-stacks-supported`: Whether there is runtime support that will allow LLVM's split stack prologue to function as intended. -* `target-name`: What name to use for `targ_os` for use in `cfg` and for - passing to LLVM. +* `llvm-target`: What target to pass to LLVM. * `relocation-model`: What relocation model to use by default. +* `target_endian`, `target_word_size`: Specify the strings used for the + corresponding `cfg` variables. +* `code-model`: Code model to pass to LLVM, overridable with `-C code-model`. +* `no-redzone`: Disable use of any stack redzone, overridable with `-C + no-redzone` Rather than hardcoding a specific set of behaviors per-target, with no recourse for escaping them, the compiler would also use this mechanism when @@ -71,13 +75,14 @@ deciding how to build for a given target. The process would look like: target. 6. If `-C relocation-model` is specified, replace the target `relocation-model` with it. +7. If `-C code-model` is specified, replace the target `code-model` with it. +8. If `-C no-redzone` is specified, replace the target `no-redzone` with true. Then during compilation, this information is used at the proper places rather -than matching against an enum listing the OSes we recognize. - -The complete set of target configuration flags would be mixed into the SVH -for that crate, but would not include modifications given with `-C`. +than matching against an enum listing the OSes we recognize. The `target_os`, +`target_family`, and `target_arch` `cfg` variables would be extracted from the +`--target` passed to rustc. # Drawbacks @@ -90,5 +95,4 @@ compiler. rustc is the only compiler I know of that would allow that. A less holistic approach would be to just allow disabling split stacks on a per-crate basis. Another solution could be adding a family of targets, `-unknown-unknown`, which omits all of the above complexity but does not -allow extending to new targets easily. `-T` can easily be extended for the -future needs of other targets. +allow extending to new targets easily.