summaryrefslogtreecommitdiffstats
path: root/third_party/rust/target-lexicon
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/target-lexicon')
-rw-r--r--third_party/rust/target-lexicon/.cargo-checksum.json1
-rw-r--r--third_party/rust/target-lexicon/Cargo.lock6
-rw-r--r--third_party/rust/target-lexicon/Cargo.toml33
-rw-r--r--third_party/rust/target-lexicon/LICENSE220
-rw-r--r--third_party/rust/target-lexicon/README.md20
-rw-r--r--third_party/rust/target-lexicon/build.rs191
-rw-r--r--third_party/rust/target-lexicon/examples/host.rs12
-rw-r--r--third_party/rust/target-lexicon/examples/misc.rs14
-rwxr-xr-xthird_party/rust/target-lexicon/scripts/rust-targets.sh7
-rw-r--r--third_party/rust/target-lexicon/src/data_model.rs105
-rw-r--r--third_party/rust/target-lexicon/src/host.rs56
-rw-r--r--third_party/rust/target-lexicon/src/lib.rs57
-rw-r--r--third_party/rust/target-lexicon/src/parse_error.rs34
-rw-r--r--third_party/rust/target-lexicon/src/targets.rs1445
-rw-r--r--third_party/rust/target-lexicon/src/triple.rs372
15 files changed, 2573 insertions, 0 deletions
diff --git a/third_party/rust/target-lexicon/.cargo-checksum.json b/third_party/rust/target-lexicon/.cargo-checksum.json
new file mode 100644
index 0000000000..9f8a431d3e
--- /dev/null
+++ b/third_party/rust/target-lexicon/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"764401bfb5ba50ed42c6b00274fd4444cefa31ef40183c224b11ed38abc2e68f","Cargo.toml":"d293a3613d3af95f1a0e49a08bb2c73ca0adf0ef375ffbdd4f7866c96500f0dc","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"c3467056d91be3f59562158ee9604c729b5b5f473efbefb036032803eb76809e","build.rs":"03132c64805a8acee491ca7c40d090f20a53295967a442e08d9ab15acff9d076","examples/host.rs":"503bafddfb372123fe4dc0e7b8037808beb5bfe6df60c00d3315922bd3792c6c","examples/misc.rs":"49a579845450b7b020ed5c97dca142fc548725893cbc82f6f750ee0caab2beca","scripts/rust-targets.sh":"89564342916321c5bc35e772d374a7f0af22cc9ae6dcc0027eca48d2269f18cb","src/data_model.rs":"a33e047aadd048bc5846c97351df831d34fbd2321a6560dd71868875101ba3a8","src/host.rs":"fb543df4f362e9119a58523563e453110f4e3a426f0995911d0ca386657cf1d9","src/lib.rs":"2f4874d504386b0ace62e7089a114c8ee0426c2ff0ee293ee3af8c67b92e670b","src/parse_error.rs":"b3735eabc0fd0a9dfdd6375662f20ec96a79852a00a05a98fb2e421545285e53","src/targets.rs":"0f6b07b3e7bc19e562c85a32a786cf9f551f8ea15ceef486bbd5c8cb28d11bb8","src/triple.rs":"da5705a96c6cd4cd03696ad9612e1a8a59cd9def59f16750149edbcdd1461fb4"},"package":"fe2635952a442a01fd4cb53d98858b5e4bb461b02c0d111f22f31772e3e7a8b2"} \ No newline at end of file
diff --git a/third_party/rust/target-lexicon/Cargo.lock b/third_party/rust/target-lexicon/Cargo.lock
new file mode 100644
index 0000000000..dafdbc10d2
--- /dev/null
+++ b/third_party/rust/target-lexicon/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "target-lexicon"
+version = "0.11.0"
+
diff --git a/third_party/rust/target-lexicon/Cargo.toml b/third_party/rust/target-lexicon/Cargo.toml
new file mode 100644
index 0000000000..6ced25170a
--- /dev/null
+++ b/third_party/rust/target-lexicon/Cargo.toml
@@ -0,0 +1,33 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "target-lexicon"
+version = "0.11.0"
+authors = ["Dan Gohman <sunfish@mozilla.com>"]
+description = "Targeting utilities for compilers and related tools"
+documentation = "https://docs.rs/target-lexicon/"
+readme = "README.md"
+keywords = ["target", "host", "triple", "compiler", "jit"]
+categories = ["no-std"]
+license = "Apache-2.0 WITH LLVM-exception"
+repository = "https://github.com/CraneStation/target-lexicon"
+
+[features]
+default = []
+std = []
+[badges.maintenance]
+status = "passively-maintained"
+
+[badges.travis-ci]
+repository = "CraneStation/target-lexicon"
diff --git a/third_party/rust/target-lexicon/LICENSE b/third_party/rust/target-lexicon/LICENSE
new file mode 100644
index 0000000000..f9d81955f4
--- /dev/null
+++ b/third_party/rust/target-lexicon/LICENSE
@@ -0,0 +1,220 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+--- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
diff --git a/third_party/rust/target-lexicon/README.md b/third_party/rust/target-lexicon/README.md
new file mode 100644
index 0000000000..2e539eb716
--- /dev/null
+++ b/third_party/rust/target-lexicon/README.md
@@ -0,0 +1,20 @@
+This is a library for managing targets for compilers and related tools.
+
+Currently, the main feature is support for decoding "triples", which
+are strings that identify a particular target configuration. They're named
+"triples" because historically they contained three fields, though over time
+they've added additional fields. This library provides a `Triple` struct
+containing enums for each of fields of a triple. `Triple` implements
+`FromStr` and `fmt::Display` so it can be converted to and from the
+conventional string representation of a triple.
+
+`Triple` also has functions for querying a triple's endianness,
+pointer bit width, and binary format.
+
+And, `Triple` and the enum types have `host()` constructors, for targeting
+the host.
+
+It supports all triples currently used by rustc and rustup.
+
+It does not support reading JSON target files itself. To use it with a JSON
+target file, construct a `Triple` using the value of the "llvm-target" field.
diff --git a/third_party/rust/target-lexicon/build.rs b/third_party/rust/target-lexicon/build.rs
new file mode 100644
index 0000000000..464554e854
--- /dev/null
+++ b/third_party/rust/target-lexicon/build.rs
@@ -0,0 +1,191 @@
+//! build.rs file to obtain the host information.
+
+// Allow dead code in triple.rs and targets.rs for our purposes here.
+#![allow(dead_code)]
+
+use std::env;
+use std::fs::File;
+use std::io::{self, Write};
+use std::path::PathBuf;
+use std::str::FromStr;
+
+extern crate alloc;
+
+// Include triple.rs and targets.rs so we can parse the TARGET environment variable.
+// targets.rs depends on data_model
+mod data_model {
+ include!("src/data_model.rs");
+}
+mod triple {
+ include!("src/triple.rs");
+}
+mod targets {
+ include!("src/targets.rs");
+}
+
+// Stub out `ParseError` to minimally support triple.rs and targets.rs.
+mod parse_error {
+ #[derive(Debug)]
+ pub enum ParseError {
+ UnrecognizedArchitecture(String),
+ UnrecognizedVendor(String),
+ UnrecognizedOperatingSystem(String),
+ UnrecognizedEnvironment(String),
+ UnrecognizedBinaryFormat(String),
+ UnrecognizedField(String),
+ }
+}
+
+use self::targets::Vendor;
+use self::triple::Triple;
+
+fn main() {
+ let out_dir =
+ PathBuf::from(env::var("OUT_DIR").expect("The OUT_DIR environment variable must be set"));
+ let target = env::var("TARGET").expect("The TARGET environment variable must be set");
+ let triple =
+ Triple::from_str(&target).unwrap_or_else(|_| panic!("Invalid target name: '{}'", target));
+ let out = File::create(out_dir.join("host.rs")).expect("error creating host.rs");
+ write_host_rs(out, triple).expect("error writing host.rs");
+}
+
+fn write_host_rs(mut out: File, triple: Triple) -> io::Result<()> {
+ // The generated Debug implementation for the inner architecture variants
+ // doesn't print the enum name qualifier, so import them here. There
+ // shouldn't be any conflicts because these enums all share a namespace
+ // in the triple string format.
+ writeln!(out, "#[allow(unused_imports)]")?;
+ writeln!(out, "use crate::Aarch64Architecture::*;")?;
+ writeln!(out, "#[allow(unused_imports)]")?;
+ writeln!(out, "use crate::ArmArchitecture::*;")?;
+ writeln!(out, "#[allow(unused_imports)]")?;
+ writeln!(out, "use crate::X86_32Architecture::*;")?;
+ writeln!(out, "#[allow(unused_imports)]")?;
+ writeln!(out, "use crate::Mips32Architecture::*;")?;
+ writeln!(out, "#[allow(unused_imports)]")?;
+ writeln!(out, "use crate::Mips64Architecture::*;")?;
+ writeln!(out, "#[allow(unused_imports)]")?;
+ writeln!(out, "use crate::Riscv32Architecture::*;")?;
+ writeln!(out, "#[allow(unused_imports)]")?;
+ writeln!(out, "use crate::Riscv64Architecture::*;")?;
+ writeln!(out, "#[allow(unused_imports)]")?;
+ writeln!(out, "use crate::CustomVendor;")?;
+ writeln!(out)?;
+ writeln!(out, "/// The `Triple` of the current host.")?;
+ writeln!(out, "pub const HOST: Triple = Triple {{")?;
+ writeln!(
+ out,
+ " architecture: Architecture::{:?},",
+ triple.architecture
+ )?;
+ writeln!(
+ out,
+ " vendor: Vendor::{},",
+ vendor_display(&triple.vendor)
+ )?;
+ writeln!(
+ out,
+ " operating_system: OperatingSystem::{:?},",
+ triple.operating_system
+ )?;
+ writeln!(
+ out,
+ " environment: Environment::{:?},",
+ triple.environment
+ )?;
+ writeln!(
+ out,
+ " binary_format: BinaryFormat::{:?},",
+ triple.binary_format
+ )?;
+ writeln!(out, "}};")?;
+ writeln!(out)?;
+
+ writeln!(out, "impl Architecture {{")?;
+ writeln!(out, " /// Return the architecture for the current host.")?;
+ writeln!(out, " pub const fn host() -> Self {{")?;
+ writeln!(out, " Self::{:?}", triple.architecture)?;
+ writeln!(out, " }}")?;
+ writeln!(out, "}}")?;
+ writeln!(out)?;
+
+ writeln!(out, "impl Vendor {{")?;
+ writeln!(out, " /// Return the vendor for the current host.")?;
+ writeln!(out, " pub const fn host() -> Self {{")?;
+ writeln!(out, " Self::{}", vendor_display(&triple.vendor))?;
+ writeln!(out, " }}")?;
+ writeln!(out, "}}")?;
+ writeln!(out)?;
+
+ writeln!(out, "impl OperatingSystem {{")?;
+ writeln!(
+ out,
+ " /// Return the operating system for the current host."
+ )?;
+ writeln!(out, " pub const fn host() -> Self {{")?;
+ writeln!(out, " Self::{:?}", triple.operating_system)?;
+ writeln!(out, " }}")?;
+ writeln!(out, "}}")?;
+ writeln!(out)?;
+
+ writeln!(out, "impl Environment {{")?;
+ writeln!(out, " /// Return the environment for the current host.")?;
+ writeln!(out, " pub const fn host() -> Self {{")?;
+ writeln!(out, " Self::{:?}", triple.environment)?;
+ writeln!(out, " }}")?;
+ writeln!(out, "}}")?;
+ writeln!(out)?;
+
+ writeln!(out, "impl BinaryFormat {{")?;
+ writeln!(
+ out,
+ " /// Return the binary format for the current host."
+ )?;
+ writeln!(out, " pub const fn host() -> Self {{")?;
+ writeln!(out, " Self::{:?}", triple.binary_format)?;
+ writeln!(out, " }}")?;
+ writeln!(out, "}}")?;
+ writeln!(out)?;
+
+ writeln!(out, "impl Triple {{")?;
+ writeln!(out, " /// Return the triple for the current host.")?;
+ writeln!(out, " pub const fn host() -> Self {{")?;
+ writeln!(out, " Self {{")?;
+ writeln!(
+ out,
+ " architecture: Architecture::{:?},",
+ triple.architecture
+ )?;
+ writeln!(
+ out,
+ " vendor: Vendor::{},",
+ vendor_display(&triple.vendor)
+ )?;
+ writeln!(
+ out,
+ " operating_system: OperatingSystem::{:?},",
+ triple.operating_system
+ )?;
+ writeln!(
+ out,
+ " environment: Environment::{:?},",
+ triple.environment
+ )?;
+ writeln!(
+ out,
+ " binary_format: BinaryFormat::{:?},",
+ triple.binary_format
+ )?;
+ writeln!(out, " }}")?;
+ writeln!(out, " }}")?;
+ writeln!(out, "}}")?;
+
+ Ok(())
+}
+
+fn vendor_display(vendor: &Vendor) -> String {
+ match vendor {
+ Vendor::Custom(custom) => format!("CustomVendor::Static({:?})", custom.as_str()),
+ known => format!("{:?}", known),
+ }
+}
diff --git a/third_party/rust/target-lexicon/examples/host.rs b/third_party/rust/target-lexicon/examples/host.rs
new file mode 100644
index 0000000000..055e0bffdb
--- /dev/null
+++ b/third_party/rust/target-lexicon/examples/host.rs
@@ -0,0 +1,12 @@
+extern crate target_lexicon;
+
+use target_lexicon::HOST;
+
+fn main() {
+ println!(
+ "{}",
+ HOST.pointer_width()
+ .expect("architecture should be known")
+ .bytes()
+ );
+}
diff --git a/third_party/rust/target-lexicon/examples/misc.rs b/third_party/rust/target-lexicon/examples/misc.rs
new file mode 100644
index 0000000000..25c99e8677
--- /dev/null
+++ b/third_party/rust/target-lexicon/examples/misc.rs
@@ -0,0 +1,14 @@
+extern crate target_lexicon;
+
+use core::str::FromStr;
+use target_lexicon::{Triple, HOST};
+
+fn main() {
+ println!("The host triple is {}.", HOST);
+
+ let e = Triple::from_str("riscv32-unknown-unknown")
+ .expect("expected to recognize the RISC-V target")
+ .endianness()
+ .expect("expected to know the endianness of RISC-V");
+ println!("The endianness of RISC-V is {:?}.", e);
+}
diff --git a/third_party/rust/target-lexicon/scripts/rust-targets.sh b/third_party/rust/target-lexicon/scripts/rust-targets.sh
new file mode 100755
index 0000000000..922950d0a0
--- /dev/null
+++ b/third_party/rust/target-lexicon/scripts/rust-targets.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+set -euo pipefail
+
+rustup target list | sed 's/ (.*//' > list.txt
+rustc +nightly --print target-list >> list.txt
+cat list.txt | sort | uniq |sed 's/\(.*\)/ "\1",/' > sorted.txt
+rm list.txt
diff --git a/third_party/rust/target-lexicon/src/data_model.rs b/third_party/rust/target-lexicon/src/data_model.rs
new file mode 100644
index 0000000000..738f2f6856
--- /dev/null
+++ b/third_party/rust/target-lexicon/src/data_model.rs
@@ -0,0 +1,105 @@
+/// The size of a type.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum Size {
+ U8,
+ U16,
+ U32,
+ U64,
+}
+
+impl Size {
+ /// Return the number of bits this `Size` represents.
+ pub fn bits(self) -> u8 {
+ match self {
+ Self::U8 => 8,
+ Self::U16 => 16,
+ Self::U32 => 32,
+ Self::U64 => 64,
+ }
+ }
+
+ /// Return the number of bytes in a size.
+ ///
+ /// A byte is assumed to be 8 bits.
+ pub fn bytes(self) -> u8 {
+ match self {
+ Self::U8 => 1,
+ Self::U16 => 2,
+ Self::U32 => 4,
+ Self::U64 => 8,
+ }
+ }
+}
+
+/// The C data model used on a target.
+///
+/// See also https://en.cppreference.com/w/c/language/arithmetic_types
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[non_exhaustive]
+pub enum CDataModel {
+ /// The data model used most commonly on Win16. `long` and `pointer` are 32 bits.
+ LP32,
+ /// The data model used most commonly on Win32 and 32-bit Unix systems.
+ ///
+ /// `int`, `long`, and `pointer` are all 32 bits.
+ ILP32,
+ /// The data model used most commonly on Win64
+ ///
+ /// `long long`, and `pointer` are 64 bits.
+ LLP64,
+ /// The data model used most commonly on 64-bit Unix systems
+ ///
+ /// `long`, and `pointer` are 64 bits.
+ LP64,
+ /// A rare data model used on early 64-bit Unix systems
+ ///
+ /// `int`, `long`, and `pointer` are all 64 bits.
+ ILP64,
+}
+
+impl CDataModel {
+ /// The width of a pointer (in the default address space).
+ pub fn pointer_width(self) -> Size {
+ match self {
+ Self::LP32 | Self::ILP32 => Size::U32,
+ Self::LLP64 | Self::LP64 | Self::ILP64 => Size::U64,
+ }
+ }
+ /// The size of a C `short`. This is required to be at least 16 bits.
+ pub fn short_size(self) -> Size {
+ match self {
+ Self::LP32 | Self::ILP32 | Self::LLP64 | Self::LP64 | Self::ILP64 => Size::U16,
+ }
+ }
+ /// The size of a C `int`. This is required to be at least 16 bits.
+ pub fn int_size(self) -> Size {
+ match self {
+ Self::LP32 => Size::U16,
+ Self::ILP32 | Self::LLP64 | Self::LP64 | Self::ILP64 => Size::U32,
+ }
+ }
+ /// The size of a C `long`. This is required to be at least 32 bits.
+ pub fn long_size(self) -> Size {
+ match self {
+ Self::LP32 | Self::ILP32 | Self::LLP64 | Self::ILP64 => Size::U32,
+ Self::LP64 => Size::U64,
+ }
+ }
+ /// The size of a C `long long`. This is required (in C99+) to be at least 64 bits.
+ pub fn long_long_size(self) -> Size {
+ match self {
+ Self::LP32 | Self::ILP32 | Self::LLP64 | Self::ILP64 | Self::LP64 => Size::U64,
+ }
+ }
+ /// The size of a C `float`.
+ pub fn float_size(self) -> Size {
+ // TODO: this is probably wrong on at least one architecture
+ Size::U32
+ }
+ /// The size of a C `double`.
+ pub fn double_size(self) -> Size {
+ // TODO: this is probably wrong on at least one architecture
+ Size::U64
+ }
+}
diff --git a/third_party/rust/target-lexicon/src/host.rs b/third_party/rust/target-lexicon/src/host.rs
new file mode 100644
index 0000000000..4c6ad5ba54
--- /dev/null
+++ b/third_party/rust/target-lexicon/src/host.rs
@@ -0,0 +1,56 @@
+use crate::{Architecture, BinaryFormat, Environment, OperatingSystem, Triple, Vendor};
+
+// Include the implementations of the `HOST` object containing information
+// about the current host.
+include!(concat!(env!("OUT_DIR"), "/host.rs"));
+
+#[cfg(test)]
+mod tests {
+ #[cfg(target_os = "linux")]
+ #[test]
+ fn test_linux() {
+ use super::*;
+ assert_eq!(OperatingSystem::host(), OperatingSystem::Linux);
+ }
+
+ #[cfg(target_os = "macos")]
+ #[test]
+ fn test_macos() {
+ use super::*;
+ assert_eq!(OperatingSystem::host(), OperatingSystem::Darwin);
+ }
+
+ #[cfg(windows)]
+ #[test]
+ fn test_windows() {
+ use super::*;
+ assert_eq!(OperatingSystem::host(), OperatingSystem::Windows);
+ }
+
+ #[cfg(target_pointer_width = "16")]
+ #[test]
+ fn test_ptr16() {
+ use super::*;
+ assert_eq!(Architecture::host().pointer_width().unwrap().bits(), 16);
+ }
+
+ #[cfg(target_pointer_width = "32")]
+ #[test]
+ fn test_ptr32() {
+ use super::*;
+ assert_eq!(Architecture::host().pointer_width().unwrap().bits(), 32);
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ #[test]
+ fn test_ptr64() {
+ use super::*;
+ assert_eq!(Architecture::host().pointer_width().unwrap().bits(), 64);
+ }
+
+ #[test]
+ fn host_object() {
+ use super::*;
+ assert_eq!(HOST, Triple::host());
+ }
+}
diff --git a/third_party/rust/target-lexicon/src/lib.rs b/third_party/rust/target-lexicon/src/lib.rs
new file mode 100644
index 0000000000..5b48872301
--- /dev/null
+++ b/third_party/rust/target-lexicon/src/lib.rs
@@ -0,0 +1,57 @@
+//! Target triple support.
+
+#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
+#![warn(unused_import_braces)]
+#![cfg_attr(
+ feature = "cargo-clippy",
+ warn(
+ clippy::float_arithmetic,
+ clippy::mut_mut,
+ clippy::nonminimal_bool,
+ clippy::option_map_unwrap_or,
+ clippy::option_map_unwrap_or_else,
+ clippy::print_stdout,
+ clippy::unicode_not_nfc,
+ clippy::use_self,
+ )
+)]
+#![cfg_attr(not(feature = "std"), no_std)]
+
+extern crate alloc;
+
+mod data_model;
+mod host;
+mod parse_error;
+mod targets;
+#[macro_use]
+mod triple;
+
+pub use self::data_model::{CDataModel, Size};
+pub use self::host::HOST;
+pub use self::parse_error::ParseError;
+pub use self::targets::{
+ Aarch64Architecture, Architecture, ArmArchitecture, BinaryFormat, CustomVendor, Environment,
+ Mips32Architecture, Mips64Architecture, OperatingSystem, Riscv32Architecture,
+ Riscv64Architecture, Vendor, X86_32Architecture,
+};
+pub use self::triple::{CallingConvention, Endianness, PointerWidth, Triple};
+
+/// A simple wrapper around `Triple` that provides an implementation of
+/// `Default` which defaults to `Triple::host()`.
+pub struct DefaultToHost(pub Triple);
+
+impl Default for DefaultToHost {
+ fn default() -> Self {
+ Self(Triple::host())
+ }
+}
+
+/// A simple wrapper around `Triple` that provides an implementation of
+/// `Default` which defaults to `Triple::unknown()`.
+pub struct DefaultToUnknown(pub Triple);
+
+impl Default for DefaultToUnknown {
+ fn default() -> Self {
+ Self(Triple::unknown())
+ }
+}
diff --git a/third_party/rust/target-lexicon/src/parse_error.rs b/third_party/rust/target-lexicon/src/parse_error.rs
new file mode 100644
index 0000000000..03ca4aedb9
--- /dev/null
+++ b/third_party/rust/target-lexicon/src/parse_error.rs
@@ -0,0 +1,34 @@
+use alloc::string::String;
+
+use core::fmt;
+
+/// An error returned from parsing a triple.
+#[derive(Clone, Debug, PartialEq, Eq)]
+#[allow(missing_docs)]
+pub enum ParseError {
+ UnrecognizedArchitecture(String),
+ UnrecognizedVendor(String),
+ UnrecognizedOperatingSystem(String),
+ UnrecognizedEnvironment(String),
+ UnrecognizedBinaryFormat(String),
+ UnrecognizedField(String),
+}
+
+impl fmt::Display for ParseError {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ use ParseError::*;
+ match self {
+ UnrecognizedArchitecture(msg) => write!(fmt, "Unrecognized architecture: {}", msg),
+ UnrecognizedVendor(msg) => write!(fmt, "Unrecognized vendor: {}", msg),
+ UnrecognizedOperatingSystem(msg) => {
+ write!(fmt, "Unrecognized operating system: {}", msg)
+ }
+ UnrecognizedEnvironment(msg) => write!(fmt, "Unrecognized environment: {}", msg),
+ UnrecognizedBinaryFormat(msg) => write!(fmt, "Unrecognized binary format: {}", msg),
+ UnrecognizedField(msg) => write!(fmt, "Unrecognized field: {}", msg),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for ParseError {}
diff --git a/third_party/rust/target-lexicon/src/targets.rs b/third_party/rust/target-lexicon/src/targets.rs
new file mode 100644
index 0000000000..c3d0e68e4d
--- /dev/null
+++ b/third_party/rust/target-lexicon/src/targets.rs
@@ -0,0 +1,1445 @@
+// This file defines all the identifier enums and target-aware logic.
+
+use crate::triple::{Endianness, PointerWidth, Triple};
+use alloc::boxed::Box;
+use alloc::string::String;
+use core::fmt;
+use core::hash::{Hash, Hasher};
+use core::str::FromStr;
+
+/// The "architecture" field, which in some cases also specifies a specific
+/// subarchitecture.
+#[non_exhaustive]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum Architecture {
+ Unknown,
+ Arm(ArmArchitecture),
+ AmdGcn,
+ Aarch64(Aarch64Architecture),
+ Asmjs,
+ Hexagon,
+ X86_32(X86_32Architecture),
+ Mips32(Mips32Architecture),
+ Mips64(Mips64Architecture),
+ Msp430,
+ Nvptx64,
+ Powerpc,
+ Powerpc64,
+ Powerpc64le,
+ Riscv32(Riscv32Architecture),
+ Riscv64(Riscv64Architecture),
+ S390x,
+ Sparc,
+ Sparc64,
+ Sparcv9,
+ Wasm32,
+ Wasm64,
+ X86_64,
+}
+
+#[non_exhaustive]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum ArmArchitecture {
+ Arm, // Generic arm
+ Armeb,
+ Armv4,
+ Armv4t,
+ Armv5t,
+ Armv5te,
+ Armv5tej,
+ Armv6,
+ Armv6j,
+ Armv6k,
+ Armv6z,
+ Armv6kz,
+ Armv6t2,
+ Armv6m,
+ Armv7,
+ Armv7a,
+ Armv7ve,
+ Armv7m,
+ Armv7r,
+ Armv7s,
+ Armv8,
+ Armv8a,
+ Armv8_1a,
+ Armv8_2a,
+ Armv8_3a,
+ Armv8_4a,
+ Armv8_5a,
+ Armv8mBase,
+ Armv8mMain,
+ Armv8r,
+
+ Armebv7r,
+
+ Thumbeb,
+ Thumbv6m,
+ Thumbv7a,
+ Thumbv7em,
+ Thumbv7m,
+ Thumbv7neon,
+ Thumbv8mBase,
+ Thumbv8mMain,
+}
+
+#[non_exhaustive]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum Aarch64Architecture {
+ Aarch64,
+ Aarch64be,
+}
+
+// #[non_exhaustive]
+// #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+// #[allow(missing_docs)]
+// pub enum ArmFpu {
+// Vfp,
+// Vfpv2,
+// Vfpv3,
+// Vfpv3Fp16,
+// Vfpv3Xd,
+// Vfpv3XdFp16,
+// Neon,
+// NeonVfpv3,
+// NeonVfpv4,
+// Vfpv4,
+// Vfpv4D16,
+// Fpv4SpD16,
+// Fpv5SpD16,
+// Fpv5D16,
+// FpArmv8,
+// NeonFpArmv8,
+// CryptoNeonFpArmv8,
+// }
+
+impl ArmArchitecture {
+ /// Test if this architecture uses the Thumb instruction set.
+ pub fn is_thumb(self) -> bool {
+ match self {
+ Self::Arm
+ | Self::Armeb
+ | Self::Armv4
+ | Self::Armv4t
+ | Self::Armv5t
+ | Self::Armv5te
+ | Self::Armv5tej
+ | Self::Armv6
+ | Self::Armv6j
+ | Self::Armv6k
+ | Self::Armv6z
+ | Self::Armv6kz
+ | Self::Armv6t2
+ | Self::Armv6m
+ | Self::Armv7
+ | Self::Armv7a
+ | Self::Armv7ve
+ | Self::Armv7m
+ | Self::Armv7r
+ | Self::Armv7s
+ | Self::Armv8
+ | Self::Armv8a
+ | Self::Armv8_1a
+ | Self::Armv8_2a
+ | Self::Armv8_3a
+ | Self::Armv8_4a
+ | Self::Armv8_5a
+ | Self::Armv8mBase
+ | Self::Armv8mMain
+ | Self::Armv8r
+ | Self::Armebv7r => false,
+ Self::Thumbeb
+ | Self::Thumbv6m
+ | Self::Thumbv7a
+ | Self::Thumbv7em
+ | Self::Thumbv7m
+ | Self::Thumbv7neon
+ | Self::Thumbv8mBase
+ | Self::Thumbv8mMain => true,
+ }
+ }
+
+ // pub fn has_fpu(self) -> Result<&'static [ArmFpu], ()> {
+
+ // }
+
+ /// Return the pointer bit width of this target's architecture.
+ pub fn pointer_width(self) -> PointerWidth {
+ match self {
+ Self::Arm
+ | Self::Armeb
+ | Self::Armv4
+ | Self::Armv4t
+ | Self::Armv5t
+ | Self::Armv5te
+ | Self::Armv5tej
+ | Self::Armv6
+ | Self::Armv6j
+ | Self::Armv6k
+ | Self::Armv6z
+ | Self::Armv6kz
+ | Self::Armv6t2
+ | Self::Armv6m
+ | Self::Armv7
+ | Self::Armv7a
+ | Self::Armv7ve
+ | Self::Armv7m
+ | Self::Armv7r
+ | Self::Armv7s
+ | Self::Armv8
+ | Self::Armv8a
+ | Self::Armv8_1a
+ | Self::Armv8_2a
+ | Self::Armv8_3a
+ | Self::Armv8_4a
+ | Self::Armv8_5a
+ | Self::Armv8mBase
+ | Self::Armv8mMain
+ | Self::Armv8r
+ | Self::Armebv7r
+ | Self::Thumbeb
+ | Self::Thumbv6m
+ | Self::Thumbv7a
+ | Self::Thumbv7em
+ | Self::Thumbv7m
+ | Self::Thumbv7neon
+ | Self::Thumbv8mBase
+ | Self::Thumbv8mMain => PointerWidth::U32,
+ }
+ }
+
+ /// Return the endianness of this architecture.
+ pub fn endianness(self) -> Endianness {
+ match self {
+ Self::Arm
+ | Self::Armv4
+ | Self::Armv4t
+ | Self::Armv5t
+ | Self::Armv5te
+ | Self::Armv5tej
+ | Self::Armv6
+ | Self::Armv6j
+ | Self::Armv6k
+ | Self::Armv6z
+ | Self::Armv6kz
+ | Self::Armv6t2
+ | Self::Armv6m
+ | Self::Armv7
+ | Self::Armv7a
+ | Self::Armv7ve
+ | Self::Armv7m
+ | Self::Armv7r
+ | Self::Armv7s
+ | Self::Armv8
+ | Self::Armv8a
+ | Self::Armv8_1a
+ | Self::Armv8_2a
+ | Self::Armv8_3a
+ | Self::Armv8_4a
+ | Self::Armv8_5a
+ | Self::Armv8mBase
+ | Self::Armv8mMain
+ | Self::Armv8r
+ | Self::Thumbv6m
+ | Self::Thumbv7a
+ | Self::Thumbv7em
+ | Self::Thumbv7m
+ | Self::Thumbv7neon
+ | Self::Thumbv8mBase
+ | Self::Thumbv8mMain => Endianness::Little,
+ Self::Armeb | Self::Armebv7r | Self::Thumbeb => Endianness::Big,
+ }
+ }
+}
+
+impl Aarch64Architecture {
+ /// Test if this architecture uses the Thumb instruction set.
+ pub fn is_thumb(self) -> bool {
+ match self {
+ Self::Aarch64 | Self::Aarch64be => false,
+ }
+ }
+
+ // pub fn has_fpu(self) -> Result<&'static [ArmFpu], ()> {
+
+ // }
+
+ /// Return the pointer bit width of this target's architecture.
+ pub fn pointer_width(self) -> PointerWidth {
+ match self {
+ Self::Aarch64 | Self::Aarch64be => PointerWidth::U64,
+ }
+ }
+
+ /// Return the endianness of this architecture.
+ pub fn endianness(self) -> Endianness {
+ match self {
+ Self::Aarch64 => Endianness::Little,
+ Self::Aarch64be => Endianness::Big,
+ }
+ }
+}
+
+/// An enum for all 32-bit RISC-V architectures.
+#[non_exhaustive]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum Riscv32Architecture {
+ Riscv32,
+ Riscv32i,
+ Riscv32imac,
+ Riscv32imc,
+}
+
+/// An enum for all 64-bit RISC-V architectures.
+#[non_exhaustive]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum Riscv64Architecture {
+ Riscv64,
+ Riscv64gc,
+ Riscv64imac,
+}
+
+/// An enum for all 32-bit x86 architectures.
+#[non_exhaustive]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum X86_32Architecture {
+ I386,
+ I586,
+ I686,
+}
+
+/// An enum for all 32-bit MIPS architectures (not just "MIPS32").
+#[non_exhaustive]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum Mips32Architecture {
+ Mips,
+ Mipsel,
+ Mipsisa32r6,
+ Mipsisa32r6el,
+}
+
+/// An enum for all 64-bit MIPS architectures (not just "MIPS64").
+#[non_exhaustive]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum Mips64Architecture {
+ Mips64,
+ Mips64el,
+ Mipsisa64r6,
+ Mipsisa64r6el,
+}
+
+/// A string for a `Vendor::Custom` that can either be used in `const`
+/// contexts or hold dynamic strings.
+#[derive(Clone, Debug, Eq)]
+pub enum CustomVendor {
+ /// An owned `String`. This supports the general case.
+ Owned(Box<String>),
+ /// A static `str`, so that `CustomVendor` can be constructed in `const`
+ /// contexts.
+ Static(&'static str),
+}
+
+impl CustomVendor {
+ /// Extracts a string slice.
+ pub fn as_str(&self) -> &str {
+ match self {
+ Self::Owned(s) => s,
+ Self::Static(s) => s,
+ }
+ }
+}
+
+impl PartialEq for CustomVendor {
+ fn eq(&self, other: &Self) -> bool {
+ self.as_str() == other.as_str()
+ }
+}
+
+impl Hash for CustomVendor {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.as_str().hash(state)
+ }
+}
+
+/// The "vendor" field, which in practice is little more than an arbitrary
+/// modifier.
+#[non_exhaustive]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum Vendor {
+ Unknown,
+ Amd,
+ Apple,
+ Experimental,
+ Fortanix,
+ Nvidia,
+ Pc,
+ Rumprun,
+ Sun,
+ Uwp,
+ Wrs,
+
+ /// A custom vendor. "Custom" in this context means that the vendor is
+ /// not specifically recognized by upstream Autotools, LLVM, Rust, or other
+ /// relevant authorities on triple naming. It's useful for people building
+ /// and using locally patched toolchains.
+ ///
+ /// Outside of such patched environments, users of `target-lexicon` should
+ /// treat `Custom` the same as `Unknown` and ignore the string.
+ Custom(CustomVendor),
+}
+
+/// The "operating system" field, which sometimes implies an environment, and
+/// sometimes isn't an actual operating system.
+#[non_exhaustive]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum OperatingSystem {
+ Unknown,
+ AmdHsa,
+ Bitrig,
+ Cloudabi,
+ Cuda,
+ Darwin,
+ Dragonfly,
+ Emscripten,
+ Freebsd,
+ Fuchsia,
+ Haiku,
+ Hermit,
+ Illumos,
+ Ios,
+ L4re,
+ Linux,
+ MacOSX { major: u16, minor: u16, patch: u16 },
+ Nebulet,
+ Netbsd,
+ None_,
+ Openbsd,
+ Psp,
+ Redox,
+ Solaris,
+ Uefi,
+ VxWorks,
+ Wasi,
+ Windows,
+}
+
+/// The "environment" field, which specifies an ABI environment on top of the
+/// operating system. In many configurations, this field is omitted, and the
+/// environment is implied by the operating system.
+#[non_exhaustive]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum Environment {
+ Unknown,
+ AmdGiz,
+ Android,
+ Androideabi,
+ Eabi,
+ Eabihf,
+ Gnu,
+ Gnuabi64,
+ Gnueabi,
+ Gnueabihf,
+ Gnuspe,
+ Gnux32,
+ Macabi,
+ Musl,
+ Musleabi,
+ Musleabihf,
+ Muslabi64,
+ Msvc,
+ Kernel,
+ Uclibc,
+ Sgx,
+ Softfloat,
+ Spe,
+}
+
+/// The "binary format" field, which is usually omitted, and the binary format
+/// is implied by the other fields.
+#[non_exhaustive]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum BinaryFormat {
+ Unknown,
+ Elf,
+ Coff,
+ Macho,
+ Wasm,
+}
+
+impl Architecture {
+ /// Return the endianness of this architecture.
+ pub fn endianness(self) -> Result<Endianness, ()> {
+ match self {
+ Self::Unknown => Err(()),
+ Self::Arm(arm) => Ok(arm.endianness()),
+ Self::Aarch64(aarch) => Ok(aarch.endianness()),
+ Self::AmdGcn
+ | Self::Asmjs
+ | Self::Hexagon
+ | Self::X86_32(_)
+ | Self::Mips64(Mips64Architecture::Mips64el)
+ | Self::Mips32(Mips32Architecture::Mipsel)
+ | Self::Mips32(Mips32Architecture::Mipsisa32r6el)
+ | Self::Mips64(Mips64Architecture::Mipsisa64r6el)
+ | Self::Msp430
+ | Self::Nvptx64
+ | Self::Powerpc64le
+ | Self::Riscv32(_)
+ | Self::Riscv64(_)
+ | Self::Wasm32
+ | Self::Wasm64
+ | Self::X86_64 => Ok(Endianness::Little),
+ Self::Mips32(Mips32Architecture::Mips)
+ | Self::Mips64(Mips64Architecture::Mips64)
+ | Self::Mips32(Mips32Architecture::Mipsisa32r6)
+ | Self::Mips64(Mips64Architecture::Mipsisa64r6)
+ | Self::Powerpc
+ | Self::Powerpc64
+ | Self::S390x
+ | Self::Sparc
+ | Self::Sparc64
+ | Self::Sparcv9 => Ok(Endianness::Big),
+ }
+ }
+
+ /// Return the pointer bit width of this target's architecture.
+ pub fn pointer_width(self) -> Result<PointerWidth, ()> {
+ match self {
+ Self::Unknown => Err(()),
+ Self::Msp430 => Ok(PointerWidth::U16),
+ Self::Arm(arm) => Ok(arm.pointer_width()),
+ Self::Aarch64(aarch) => Ok(aarch.pointer_width()),
+ Self::Asmjs
+ | Self::Hexagon
+ | Self::X86_32(_)
+ | Self::Riscv32(_)
+ | Self::Sparc
+ | Self::Wasm32
+ | Self::Mips32(_)
+ | Self::Powerpc => Ok(PointerWidth::U32),
+ Self::AmdGcn
+ | Self::Powerpc64le
+ | Self::Riscv64(_)
+ | Self::X86_64
+ | Self::Mips64(_)
+ | Self::Nvptx64
+ | Self::Powerpc64
+ | Self::S390x
+ | Self::Sparc64
+ | Self::Sparcv9
+ | Self::Wasm64 => Ok(PointerWidth::U64),
+ }
+ }
+}
+
+/// Return the binary format implied by this target triple, ignoring its
+/// `binary_format` field.
+pub(crate) fn default_binary_format(triple: &Triple) -> BinaryFormat {
+ match triple.operating_system {
+ OperatingSystem::None_ => match triple.environment {
+ Environment::Eabi | Environment::Eabihf => BinaryFormat::Elf,
+ _ => BinaryFormat::Unknown,
+ },
+ OperatingSystem::Darwin | OperatingSystem::Ios | OperatingSystem::MacOSX { .. } => {
+ BinaryFormat::Macho
+ }
+ OperatingSystem::Windows => BinaryFormat::Coff,
+ OperatingSystem::Nebulet
+ | OperatingSystem::Emscripten
+ | OperatingSystem::VxWorks
+ | OperatingSystem::Wasi
+ | OperatingSystem::Unknown => match triple.architecture {
+ Architecture::Wasm32 | Architecture::Wasm64 => BinaryFormat::Wasm,
+ _ => BinaryFormat::Unknown,
+ },
+ _ => BinaryFormat::Elf,
+ }
+}
+
+impl fmt::Display for ArmArchitecture {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let s = match *self {
+ Self::Arm => "arm",
+ Self::Armeb => "armeb",
+ Self::Armv4 => "armv4",
+ Self::Armv4t => "armv4t",
+ Self::Armv5t => "armv5t",
+ Self::Armv5te => "armv5te",
+ Self::Armv5tej => "armv5tej",
+ Self::Armv6 => "armv6",
+ Self::Armv6j => "armv6j",
+ Self::Armv6k => "armv6k",
+ Self::Armv6z => "armv6z",
+ Self::Armv6kz => "armv6kz",
+ Self::Armv6t2 => "armv6t2",
+ Self::Armv6m => "armv6m",
+ Self::Armv7 => "armv7",
+ Self::Armv7a => "armv7a",
+ Self::Armv7ve => "armv7ve",
+ Self::Armv7m => "armv7m",
+ Self::Armv7r => "armv7r",
+ Self::Armv7s => "armv7s",
+ Self::Armv8 => "armv8",
+ Self::Armv8a => "armv8a",
+ Self::Armv8_1a => "armv8.1a",
+ Self::Armv8_2a => "armv8.2a",
+ Self::Armv8_3a => "armv8.3a",
+ Self::Armv8_4a => "armv8.4a",
+ Self::Armv8_5a => "armv8.5a",
+ Self::Armv8mBase => "armv8m.base",
+ Self::Armv8mMain => "armv8m.main",
+ Self::Armv8r => "armv8r",
+ Self::Thumbeb => "thumbeb",
+ Self::Thumbv6m => "thumbv6m",
+ Self::Thumbv7a => "thumbv7a",
+ Self::Thumbv7em => "thumbv7em",
+ Self::Thumbv7m => "thumbv7m",
+ Self::Thumbv7neon => "thumbv7neon",
+ Self::Thumbv8mBase => "thumbv8m.base",
+ Self::Thumbv8mMain => "thumbv8m.main",
+ Self::Armebv7r => "armebv7r",
+ };
+ f.write_str(s)
+ }
+}
+
+impl fmt::Display for Aarch64Architecture {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let s = match *self {
+ Self::Aarch64 => "aarch64",
+ Self::Aarch64be => "aarch64be",
+ };
+ f.write_str(s)
+ }
+}
+
+impl fmt::Display for Riscv32Architecture {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let s = match *self {
+ Self::Riscv32 => "riscv32",
+ Self::Riscv32i => "riscv32i",
+ Self::Riscv32imac => "riscv32imac",
+ Self::Riscv32imc => "riscv32imc",
+ };
+ f.write_str(s)
+ }
+}
+
+impl fmt::Display for Riscv64Architecture {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let s = match *self {
+ Self::Riscv64 => "riscv64",
+ Self::Riscv64gc => "riscv64gc",
+ Self::Riscv64imac => "riscv64imac",
+ };
+ f.write_str(s)
+ }
+}
+
+impl fmt::Display for X86_32Architecture {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let s = match *self {
+ Self::I386 => "i386",
+ Self::I586 => "i586",
+ Self::I686 => "i686",
+ };
+ f.write_str(s)
+ }
+}
+
+impl fmt::Display for Mips32Architecture {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let s = match *self {
+ Self::Mips => "mips",
+ Self::Mipsel => "mipsel",
+ Self::Mipsisa32r6 => "mipsisa32r6",
+ Self::Mipsisa32r6el => "mipsisa32r6el",
+ };
+ f.write_str(s)
+ }
+}
+
+impl fmt::Display for Mips64Architecture {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let s = match *self {
+ Self::Mips64 => "mips64",
+ Self::Mips64el => "mips64el",
+ Self::Mipsisa64r6 => "mipsisa64r6",
+ Self::Mipsisa64r6el => "mipsisa64r6el",
+ };
+ f.write_str(s)
+ }
+}
+
+impl fmt::Display for Architecture {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ Self::Arm(arm) => arm.fmt(f),
+ Self::Aarch64(aarch) => aarch.fmt(f),
+ Self::Unknown => f.write_str("unknown"),
+ Self::AmdGcn => f.write_str("amdgcn"),
+ Self::Asmjs => f.write_str("asmjs"),
+ Self::Hexagon => f.write_str("hexagon"),
+ Self::X86_32(x86_32) => x86_32.fmt(f),
+ Self::Mips32(mips32) => mips32.fmt(f),
+ Self::Mips64(mips64) => mips64.fmt(f),
+ Self::Msp430 => f.write_str("msp430"),
+ Self::Nvptx64 => f.write_str("nvptx64"),
+ Self::Powerpc => f.write_str("powerpc"),
+ Self::Powerpc64 => f.write_str("powerpc64"),
+ Self::Powerpc64le => f.write_str("powerpc64le"),
+ Self::Riscv32(riscv32) => riscv32.fmt(f),
+ Self::Riscv64(riscv64) => riscv64.fmt(f),
+ Self::S390x => f.write_str("s390x"),
+ Self::Sparc => f.write_str("sparc"),
+ Self::Sparc64 => f.write_str("sparc64"),
+ Self::Sparcv9 => f.write_str("sparcv9"),
+ Self::Wasm32 => f.write_str("wasm32"),
+ Self::Wasm64 => f.write_str("wasm64"),
+ Self::X86_64 => f.write_str("x86_64"),
+ }
+ }
+}
+
+impl FromStr for ArmArchitecture {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, ()> {
+ Ok(match s {
+ "arm" => Self::Arm,
+ "armeb" => Self::Armeb,
+ "armv4" => Self::Armv4,
+ "armv4t" => Self::Armv4t,
+ "armv5t" => Self::Armv5t,
+ "armv5te" => Self::Armv5te,
+ "armv5tej" => Self::Armv5tej,
+ "armv6" => Self::Armv6,
+ "armv6j" => Self::Armv6j,
+ "armv6k" => Self::Armv6k,
+ "armv6z" => Self::Armv6z,
+ "armv6kz" => Self::Armv6kz,
+ "armv6t2" => Self::Armv6t2,
+ "armv6m" => Self::Armv6m,
+ "armv7" => Self::Armv7,
+ "armv7a" => Self::Armv7a,
+ "armv7ve" => Self::Armv7ve,
+ "armv7m" => Self::Armv7m,
+ "armv7r" => Self::Armv7r,
+ "armv7s" => Self::Armv7s,
+ "armv8" => Self::Armv8,
+ "armv8a" => Self::Armv8a,
+ "armv8.1a" => Self::Armv8_1a,
+ "armv8.2a" => Self::Armv8_2a,
+ "armv8.3a" => Self::Armv8_3a,
+ "armv8.4a" => Self::Armv8_4a,
+ "armv8.5a" => Self::Armv8_5a,
+ "armv8m.base" => Self::Armv8mBase,
+ "armv8m.main" => Self::Armv8mMain,
+ "armv8r" => Self::Armv8r,
+ "thumbeb" => Self::Thumbeb,
+ "thumbv6m" => Self::Thumbv6m,
+ "thumbv7a" => Self::Thumbv7a,
+ "thumbv7em" => Self::Thumbv7em,
+ "thumbv7m" => Self::Thumbv7m,
+ "thumbv7neon" => Self::Thumbv7neon,
+ "thumbv8m.base" => Self::Thumbv8mBase,
+ "thumbv8m.main" => Self::Thumbv8mMain,
+ "armebv7r" => Self::Armebv7r,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl FromStr for Aarch64Architecture {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, ()> {
+ Ok(match s {
+ "aarch64" => Self::Aarch64,
+ "arm64" => Self::Aarch64,
+ "aarch64be" => Self::Aarch64be,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl FromStr for Riscv32Architecture {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, ()> {
+ Ok(match s {
+ "riscv32" => Self::Riscv32,
+ "riscv32i" => Self::Riscv32i,
+ "riscv32imac" => Self::Riscv32imac,
+ "riscv32imc" => Self::Riscv32imc,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl FromStr for Riscv64Architecture {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, ()> {
+ Ok(match s {
+ "riscv64" => Self::Riscv64,
+ "riscv64gc" => Self::Riscv64gc,
+ "riscv64imac" => Self::Riscv64imac,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl FromStr for X86_32Architecture {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, ()> {
+ Ok(match s {
+ "i386" => Self::I386,
+ "i586" => Self::I586,
+ "i686" => Self::I686,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl FromStr for Mips32Architecture {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, ()> {
+ Ok(match s {
+ "mips" => Self::Mips,
+ "mipsel" => Self::Mipsel,
+ "mipsisa32r6" => Self::Mipsisa32r6,
+ "mipsisa32r6el" => Self::Mipsisa32r6el,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl FromStr for Mips64Architecture {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, ()> {
+ Ok(match s {
+ "mips64" => Self::Mips64,
+ "mips64el" => Self::Mips64el,
+ "mipsisa64r6" => Self::Mipsisa64r6,
+ "mipsisa64r6el" => Self::Mipsisa64r6el,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl FromStr for Architecture {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, ()> {
+ Ok(match s {
+ "unknown" => Self::Unknown,
+ "amdgcn" => Self::AmdGcn,
+ "asmjs" => Self::Asmjs,
+ "hexagon" => Self::Hexagon,
+ "msp430" => Self::Msp430,
+ "nvptx64" => Self::Nvptx64,
+ "powerpc" => Self::Powerpc,
+ "powerpc64" => Self::Powerpc64,
+ "powerpc64le" => Self::Powerpc64le,
+ "s390x" => Self::S390x,
+ "sparc" => Self::Sparc,
+ "sparc64" => Self::Sparc64,
+ "sparcv9" => Self::Sparcv9,
+ "wasm32" => Self::Wasm32,
+ "wasm64" => Self::Wasm64,
+ "x86_64" => Self::X86_64,
+ _ => {
+ if let Ok(arm) = ArmArchitecture::from_str(s) {
+ Self::Arm(arm)
+ } else if let Ok(aarch64) = Aarch64Architecture::from_str(s) {
+ Self::Aarch64(aarch64)
+ } else if let Ok(riscv32) = Riscv32Architecture::from_str(s) {
+ Self::Riscv32(riscv32)
+ } else if let Ok(riscv64) = Riscv64Architecture::from_str(s) {
+ Self::Riscv64(riscv64)
+ } else if let Ok(x86_32) = X86_32Architecture::from_str(s) {
+ Self::X86_32(x86_32)
+ } else if let Ok(mips32) = Mips32Architecture::from_str(s) {
+ Self::Mips32(mips32)
+ } else if let Ok(mips64) = Mips64Architecture::from_str(s) {
+ Self::Mips64(mips64)
+ } else {
+ return Err(());
+ }
+ }
+ })
+ }
+}
+
+impl fmt::Display for Vendor {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let s = match *self {
+ Self::Unknown => "unknown",
+ Self::Amd => "amd",
+ Self::Apple => "apple",
+ Self::Experimental => "experimental",
+ Self::Fortanix => "fortanix",
+ Self::Nvidia => "nvidia",
+ Self::Pc => "pc",
+ Self::Rumprun => "rumprun",
+ Self::Sun => "sun",
+ Self::Uwp => "uwp",
+ Self::Wrs => "wrs",
+ Self::Custom(ref name) => name.as_str(),
+ };
+ f.write_str(s)
+ }
+}
+
+impl FromStr for Vendor {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, ()> {
+ Ok(match s {
+ "unknown" => Self::Unknown,
+ "amd" => Self::Amd,
+ "apple" => Self::Apple,
+ "experimental" => Self::Experimental,
+ "fortanix" => Self::Fortanix,
+ "nvidia" => Self::Nvidia,
+ "pc" => Self::Pc,
+ "rumprun" => Self::Rumprun,
+ "sun" => Self::Sun,
+ "uwp" => Self::Uwp,
+ "wrs" => Self::Wrs,
+ custom => {
+ use alloc::borrow::ToOwned;
+
+ // A custom vendor. Since triple syntax is so loosely defined,
+ // be as conservative as we can to avoid potential ambiguities.
+ // We err on the side of being too strict here, as we can
+ // always relax it if needed.
+
+ // Don't allow empty string names.
+ if custom.is_empty() {
+ return Err(());
+ }
+
+ // Don't allow any other recognized name as a custom vendor,
+ // since vendors can be omitted in some contexts.
+ if Architecture::from_str(custom).is_ok()
+ || OperatingSystem::from_str(custom).is_ok()
+ || Environment::from_str(custom).is_ok()
+ || BinaryFormat::from_str(custom).is_ok()
+ {
+ return Err(());
+ }
+
+ // Require the first character to be an ascii lowercase.
+ if !custom.chars().next().unwrap().is_ascii_lowercase() {
+ return Err(());
+ }
+
+ // Restrict the set of characters permitted in a custom vendor.
+ let has_restricted = custom.chars().any(|c: char| {
+ !(c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '.')
+ });
+
+ if has_restricted {
+ return Err(());
+ }
+
+ Self::Custom(CustomVendor::Owned(Box::new(custom.to_owned())))
+ }
+ })
+ }
+}
+
+impl fmt::Display for OperatingSystem {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let s = match *self {
+ Self::Unknown => "unknown",
+ Self::AmdHsa => "amdhsa",
+ Self::Bitrig => "bitrig",
+ Self::Cloudabi => "cloudabi",
+ Self::Cuda => "cuda",
+ Self::Darwin => "darwin",
+ Self::Dragonfly => "dragonfly",
+ Self::Emscripten => "emscripten",
+ Self::Freebsd => "freebsd",
+ Self::Fuchsia => "fuchsia",
+ Self::Haiku => "haiku",
+ Self::Hermit => "hermit",
+ Self::Illumos => "illumos",
+ Self::Ios => "ios",
+ Self::L4re => "l4re",
+ Self::Linux => "linux",
+ Self::MacOSX {
+ major,
+ minor,
+ patch,
+ } => {
+ return write!(f, "macosx{}.{}.{}", major, minor, patch);
+ }
+ Self::Nebulet => "nebulet",
+ Self::Netbsd => "netbsd",
+ Self::None_ => "none",
+ Self::Openbsd => "openbsd",
+ Self::Psp => "psp",
+ Self::Redox => "redox",
+ Self::Solaris => "solaris",
+ Self::Uefi => "uefi",
+ Self::VxWorks => "vxworks",
+ Self::Wasi => "wasi",
+ Self::Windows => "windows",
+ };
+ f.write_str(s)
+ }
+}
+
+impl FromStr for OperatingSystem {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, ()> {
+ // TODO also parse version number for darwin and ios OSes
+ if s.starts_with("macosx") {
+ // Parse operating system names like `macosx10.7.0`.
+ let s = &s["macosx".len()..];
+ let mut parts = s.split('.').map(|num| num.parse::<u16>());
+
+ macro_rules! get_part {
+ () => {
+ if let Some(Ok(part)) = parts.next() {
+ part
+ } else {
+ return Err(());
+ }
+ };
+ }
+
+ let major = get_part!();
+ let minor = get_part!();
+ let patch = get_part!();
+
+ if parts.next().is_some() {
+ return Err(());
+ }
+
+ return Ok(Self::MacOSX {
+ major,
+ minor,
+ patch,
+ });
+ }
+
+ Ok(match s {
+ "unknown" => Self::Unknown,
+ "amdhsa" => Self::AmdHsa,
+ "bitrig" => Self::Bitrig,
+ "cloudabi" => Self::Cloudabi,
+ "cuda" => Self::Cuda,
+ "darwin" => Self::Darwin,
+ "dragonfly" => Self::Dragonfly,
+ "emscripten" => Self::Emscripten,
+ "freebsd" => Self::Freebsd,
+ "fuchsia" => Self::Fuchsia,
+ "haiku" => Self::Haiku,
+ "hermit" => Self::Hermit,
+ "illumos" => Self::Illumos,
+ "ios" => Self::Ios,
+ "l4re" => Self::L4re,
+ "linux" => Self::Linux,
+ "nebulet" => Self::Nebulet,
+ "netbsd" => Self::Netbsd,
+ "none" => Self::None_,
+ "openbsd" => Self::Openbsd,
+ "psp" => Self::Psp,
+ "redox" => Self::Redox,
+ "solaris" => Self::Solaris,
+ "uefi" => Self::Uefi,
+ "vxworks" => Self::VxWorks,
+ "wasi" => Self::Wasi,
+ "windows" => Self::Windows,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl fmt::Display for Environment {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let s = match *self {
+ Self::Unknown => "unknown",
+ Self::AmdGiz => "amdgiz",
+ Self::Android => "android",
+ Self::Androideabi => "androideabi",
+ Self::Eabi => "eabi",
+ Self::Eabihf => "eabihf",
+ Self::Gnu => "gnu",
+ Self::Gnuabi64 => "gnuabi64",
+ Self::Gnueabi => "gnueabi",
+ Self::Gnueabihf => "gnueabihf",
+ Self::Gnuspe => "gnuspe",
+ Self::Gnux32 => "gnux32",
+ Self::Macabi => "macabi",
+ Self::Musl => "musl",
+ Self::Musleabi => "musleabi",
+ Self::Musleabihf => "musleabihf",
+ Self::Muslabi64 => "muslabi64",
+ Self::Msvc => "msvc",
+ Self::Kernel => "kernel",
+ Self::Uclibc => "uclibc",
+ Self::Sgx => "sgx",
+ Self::Softfloat => "softfloat",
+ Self::Spe => "spe",
+ };
+ f.write_str(s)
+ }
+}
+
+impl FromStr for Environment {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, ()> {
+ Ok(match s {
+ "unknown" => Self::Unknown,
+ "amdgiz" => Self::AmdGiz,
+ "android" => Self::Android,
+ "androideabi" => Self::Androideabi,
+ "eabi" => Self::Eabi,
+ "eabihf" => Self::Eabihf,
+ "gnu" => Self::Gnu,
+ "gnuabi64" => Self::Gnuabi64,
+ "gnueabi" => Self::Gnueabi,
+ "gnueabihf" => Self::Gnueabihf,
+ "gnuspe" => Self::Gnuspe,
+ "gnux32" => Self::Gnux32,
+ "macabi" => Self::Macabi,
+ "musl" => Self::Musl,
+ "musleabi" => Self::Musleabi,
+ "musleabihf" => Self::Musleabihf,
+ "muslabi64" => Self::Muslabi64,
+ "msvc" => Self::Msvc,
+ "kernel" => Self::Kernel,
+ "uclibc" => Self::Uclibc,
+ "sgx" => Self::Sgx,
+ "softfloat" => Self::Softfloat,
+ "spe" => Self::Spe,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl fmt::Display for BinaryFormat {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let s = match *self {
+ Self::Unknown => "unknown",
+ Self::Elf => "elf",
+ Self::Coff => "coff",
+ Self::Macho => "macho",
+ Self::Wasm => "wasm",
+ };
+ f.write_str(s)
+ }
+}
+
+impl FromStr for BinaryFormat {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, ()> {
+ Ok(match s {
+ "unknown" => Self::Unknown,
+ "elf" => Self::Elf,
+ "coff" => Self::Coff,
+ "macho" => Self::Macho,
+ "wasm" => Self::Wasm,
+ _ => return Err(()),
+ })
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use alloc::string::ToString;
+
+ #[test]
+ fn roundtrip_known_triples() {
+ // This list is constructed from:
+ // - targets emitted by "rustup target list"
+ // - targets emitted by "rustc +nightly --print target-list"
+ // - targets contributors have added
+ let targets = [
+ "aarch64-apple-ios",
+ "aarch64-fuchsia",
+ "aarch64-linux-android",
+ "aarch64-pc-windows-msvc",
+ "aarch64-unknown-cloudabi",
+ "aarch64-unknown-freebsd",
+ "aarch64-unknown-hermit",
+ "aarch64-unknown-linux-gnu",
+ "aarch64-unknown-linux-musl",
+ "aarch64-unknown-netbsd",
+ "aarch64-unknown-none",
+ "aarch64-unknown-none-softfloat",
+ "aarch64-unknown-openbsd",
+ "aarch64-unknown-redox",
+ "aarch64-uwp-windows-msvc",
+ "aarch64-wrs-vxworks",
+ "amdgcn-amd-amdhsa",
+ "amdgcn-amd-amdhsa-amdgiz",
+ "armebv7r-none-eabi",
+ "armebv7r-none-eabihf",
+ "arm-linux-androideabi",
+ "arm-unknown-linux-gnueabi",
+ "arm-unknown-linux-gnueabihf",
+ "arm-unknown-linux-musleabi",
+ "arm-unknown-linux-musleabihf",
+ "armv4t-unknown-linux-gnueabi",
+ "armv5te-unknown-linux-gnueabi",
+ "armv5te-unknown-linux-musleabi",
+ "armv6-unknown-freebsd",
+ "armv6-unknown-netbsd-eabihf",
+ "armv7a-none-eabi",
+ "armv7a-none-eabihf",
+ "armv7-apple-ios",
+ "armv7-linux-androideabi",
+ "armv7r-none-eabi",
+ "armv7r-none-eabihf",
+ "armv7s-apple-ios",
+ "armv7-unknown-cloudabi-eabihf",
+ "armv7-unknown-freebsd",
+ "armv7-unknown-linux-gnueabi",
+ "armv7-unknown-linux-gnueabihf",
+ "armv7-unknown-linux-musleabi",
+ "armv7-unknown-linux-musleabihf",
+ "armv7-unknown-netbsd-eabihf",
+ "armv7-wrs-vxworks-eabihf",
+ "asmjs-unknown-emscripten",
+ "hexagon-unknown-linux-musl",
+ "i386-apple-ios",
+ "i586-pc-windows-msvc",
+ "i586-unknown-linux-gnu",
+ "i586-unknown-linux-musl",
+ "i686-apple-darwin",
+ "i686-linux-android",
+ "i686-apple-macosx10.7.0",
+ "i686-pc-windows-gnu",
+ "i686-pc-windows-msvc",
+ "i686-unknown-cloudabi",
+ "i686-unknown-dragonfly",
+ "i686-unknown-freebsd",
+ "i686-unknown-haiku",
+ "i686-unknown-linux-gnu",
+ "i686-unknown-linux-musl",
+ "i686-unknown-netbsd",
+ "i686-unknown-openbsd",
+ "i686-unknown-uefi",
+ "i686-uwp-windows-gnu",
+ "i686-uwp-windows-msvc",
+ "i686-wrs-vxworks",
+ "mips64el-unknown-linux-gnuabi64",
+ "mips64el-unknown-linux-muslabi64",
+ "mips64-unknown-linux-gnuabi64",
+ "mips64-unknown-linux-muslabi64",
+ "mipsel-sony-psp",
+ "mipsel-unknown-linux-gnu",
+ "mipsel-unknown-linux-musl",
+ "mipsel-unknown-linux-uclibc",
+ "mipsisa32r6el-unknown-linux-gnu",
+ "mipsisa32r6-unknown-linux-gnu",
+ "mipsisa64r6el-unknown-linux-gnuabi64",
+ "mipsisa64r6-unknown-linux-gnuabi64",
+ "mips-unknown-linux-gnu",
+ "mips-unknown-linux-musl",
+ "mips-unknown-linux-uclibc",
+ "msp430-none-elf",
+ "nvptx64-nvidia-cuda",
+ "powerpc64le-unknown-linux-gnu",
+ "powerpc64le-unknown-linux-musl",
+ "powerpc64-unknown-freebsd",
+ "powerpc64-unknown-linux-gnu",
+ "powerpc64-unknown-linux-musl",
+ "powerpc64-wrs-vxworks",
+ "powerpc-unknown-linux-gnu",
+ "powerpc-unknown-linux-gnuspe",
+ "powerpc-unknown-linux-musl",
+ "powerpc-unknown-netbsd",
+ "powerpc-wrs-vxworks",
+ "powerpc-wrs-vxworks-spe",
+ "riscv32imac-unknown-none-elf",
+ "riscv32imc-unknown-none-elf",
+ "riscv32i-unknown-none-elf",
+ "riscv64gc-unknown-linux-gnu",
+ "riscv64gc-unknown-none-elf",
+ "riscv64imac-unknown-none-elf",
+ "s390x-unknown-linux-gnu",
+ "sparc64-unknown-linux-gnu",
+ "sparc64-unknown-netbsd",
+ "sparc64-unknown-openbsd",
+ "sparc-unknown-linux-gnu",
+ "sparcv9-sun-solaris",
+ "thumbv6m-none-eabi",
+ "thumbv7a-pc-windows-msvc",
+ "thumbv7a-uwp-windows-msvc",
+ "thumbv7em-none-eabi",
+ "thumbv7em-none-eabihf",
+ "thumbv7m-none-eabi",
+ "thumbv7neon-linux-androideabi",
+ "thumbv7neon-unknown-linux-gnueabihf",
+ "thumbv7neon-unknown-linux-musleabihf",
+ "thumbv8m.base-none-eabi",
+ "thumbv8m.main-none-eabi",
+ "thumbv8m.main-none-eabihf",
+ "wasm32-experimental-emscripten",
+ "wasm32-unknown-emscripten",
+ "wasm32-unknown-unknown",
+ "wasm64-unknown-unknown",
+ "wasm32-wasi",
+ "wasm64-wasi",
+ "x86_64-apple-darwin",
+ "x86_64-apple-ios",
+ "x86_64-fortanix-unknown-sgx",
+ "x86_64-fuchsia",
+ "x86_64-linux-android",
+ "x86_64-linux-kernel",
+ "x86_64-apple-macosx10.7.0",
+ "x86_64-pc-solaris",
+ "x86_64-pc-windows-gnu",
+ "x86_64-pc-windows-msvc",
+ "x86_64-rumprun-netbsd",
+ "x86_64-sun-solaris",
+ "x86_64-unknown-bitrig",
+ "x86_64-unknown-cloudabi",
+ "x86_64-unknown-dragonfly",
+ "x86_64-unknown-freebsd",
+ "x86_64-unknown-haiku",
+ "x86_64-unknown-hermit",
+ "x86_64-unknown-hermit-kernel",
+ "x86_64-unknown-illumos",
+ "x86_64-unknown-l4re-uclibc",
+ "x86_64-unknown-linux-gnu",
+ "x86_64-unknown-linux-gnux32",
+ "x86_64-unknown-linux-musl",
+ "x86_64-unknown-netbsd",
+ "x86_64-unknown-openbsd",
+ "x86_64-unknown-redox",
+ "x86_64-unknown-uefi",
+ "x86_64-uwp-windows-gnu",
+ "x86_64-uwp-windows-msvc",
+ "x86_64-wrs-vxworks",
+ ];
+
+ for target in targets.iter() {
+ let t = Triple::from_str(target).expect("can't parse target");
+ assert_ne!(t.architecture, Architecture::Unknown);
+ assert_eq!(t.to_string(), *target);
+ }
+ }
+
+ #[test]
+ fn thumbv7em_none_eabihf() {
+ let t = Triple::from_str("thumbv7em-none-eabihf").expect("can't parse target");
+ assert_eq!(
+ t.architecture,
+ Architecture::Arm(ArmArchitecture::Thumbv7em)
+ );
+ assert_eq!(t.vendor, Vendor::Unknown);
+ assert_eq!(t.operating_system, OperatingSystem::None_);
+ assert_eq!(t.environment, Environment::Eabihf);
+ assert_eq!(t.binary_format, BinaryFormat::Elf);
+ }
+
+ #[test]
+ fn custom_vendors() {
+ // Test various invalid cases.
+ assert!(Triple::from_str("x86_64--linux").is_err());
+ assert!(Triple::from_str("x86_64-42-linux").is_err());
+ assert!(Triple::from_str("x86_64-__customvendor__-linux").is_err());
+ assert!(Triple::from_str("x86_64-^-linux").is_err());
+ assert!(Triple::from_str("x86_64- -linux").is_err());
+ assert!(Triple::from_str("x86_64-CustomVendor-linux").is_err());
+ assert!(Triple::from_str("x86_64-linux-linux").is_err());
+ assert!(Triple::from_str("x86_64-x86_64-linux").is_err());
+ assert!(Triple::from_str("x86_64-elf-linux").is_err());
+ assert!(Triple::from_str("x86_64-gnu-linux").is_err());
+ assert!(Triple::from_str("x86_64-linux-customvendor").is_err());
+ assert!(Triple::from_str("customvendor").is_err());
+ assert!(Triple::from_str("customvendor-x86_64").is_err());
+ assert!(Triple::from_str("x86_64-").is_err());
+ assert!(Triple::from_str("x86_64--").is_err());
+
+ // Test various Unicode things.
+ assert!(
+ Triple::from_str("x86_64-𝓬𝓾𝓼𝓽𝓸𝓶𝓿𝓮𝓷𝓭𝓸𝓻-linux").is_err(),
+ "unicode font hazard"
+ );
+ assert!(
+ Triple::from_str("x86_64-ćúśtőḿvéńdőŕ-linux").is_err(),
+ "diacritical mark stripping hazard"
+ );
+ assert!(
+ Triple::from_str("x86_64-customvendοr-linux").is_err(),
+ "homoglyph hazard"
+ );
+ assert!(Triple::from_str("x86_64-customvendor-linux").is_ok());
+ assert!(
+ Triple::from_str("x86_64-ffi-linux").is_err(),
+ "normalization hazard"
+ );
+ assert!(Triple::from_str("x86_64-ffi-linux").is_ok());
+ assert!(
+ Triple::from_str("x86_64-custom‍vendor-linux").is_err(),
+ "zero-width character hazard"
+ );
+ assert!(
+ Triple::from_str("x86_64-customvendor-linux").is_err(),
+ "BOM hazard"
+ );
+
+ // Test some valid cases.
+ let t = Triple::from_str("x86_64-customvendor-linux")
+ .expect("can't parse target with custom vendor");
+ assert_eq!(t.architecture, Architecture::X86_64);
+ assert_eq!(
+ t.vendor,
+ Vendor::Custom(CustomVendor::Static("customvendor"))
+ );
+ assert_eq!(t.operating_system, OperatingSystem::Linux);
+ assert_eq!(t.environment, Environment::Unknown);
+ assert_eq!(t.binary_format, BinaryFormat::Elf);
+ assert_eq!(t.to_string(), "x86_64-customvendor-linux");
+
+ let t =
+ Triple::from_str("x86_64-customvendor").expect("can't parse target with custom vendor");
+ assert_eq!(t.architecture, Architecture::X86_64);
+ assert_eq!(
+ t.vendor,
+ Vendor::Custom(CustomVendor::Static("customvendor"))
+ );
+ assert_eq!(t.operating_system, OperatingSystem::Unknown);
+ assert_eq!(t.environment, Environment::Unknown);
+ assert_eq!(t.binary_format, BinaryFormat::Unknown);
+
+ assert_eq!(
+ Triple::from_str("unknown-foo"),
+ Ok(Triple {
+ architecture: Architecture::Unknown,
+ vendor: Vendor::Custom(CustomVendor::Static("foo")),
+ operating_system: OperatingSystem::Unknown,
+ environment: Environment::Unknown,
+ binary_format: BinaryFormat::Unknown,
+ })
+ );
+ }
+}
diff --git a/third_party/rust/target-lexicon/src/triple.rs b/third_party/rust/target-lexicon/src/triple.rs
new file mode 100644
index 0000000000..a0e2735b99
--- /dev/null
+++ b/third_party/rust/target-lexicon/src/triple.rs
@@ -0,0 +1,372 @@
+// This file defines the `Triple` type and support code shared by all targets.
+
+use crate::data_model::CDataModel;
+use crate::parse_error::ParseError;
+use crate::targets::{
+ default_binary_format, Architecture, ArmArchitecture, BinaryFormat, Environment,
+ OperatingSystem, Vendor,
+};
+use alloc::borrow::ToOwned;
+use core::fmt;
+use core::str::FromStr;
+
+/// The target memory endianness.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum Endianness {
+ Little,
+ Big,
+}
+
+/// The width of a pointer (in the default address space).
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[allow(missing_docs)]
+pub enum PointerWidth {
+ U16,
+ U32,
+ U64,
+}
+
+impl PointerWidth {
+ /// Return the number of bits in a pointer.
+ pub fn bits(self) -> u8 {
+ match self {
+ Self::U16 => 16,
+ Self::U32 => 32,
+ Self::U64 => 64,
+ }
+ }
+
+ /// Return the number of bytes in a pointer.
+ ///
+ /// For these purposes, there are 8 bits in a byte.
+ pub fn bytes(self) -> u8 {
+ match self {
+ Self::U16 => 2,
+ Self::U32 => 4,
+ Self::U64 => 8,
+ }
+ }
+}
+
+/// The calling convention, which specifies things like which registers are
+/// used for passing arguments, which registers are callee-saved, and so on.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub enum CallingConvention {
+ /// "System V", which is used on most Unix-like platfoms. Note that the
+ /// specific conventions vary between hardware architectures; for example,
+ /// x86-32's "System V" is entirely different from x86-64's "System V".
+ SystemV,
+
+ /// The WebAssembly C ABI.
+ /// https://github.com/WebAssembly/tool-conventions/blob/master/BasicCABI.md
+ WasmBasicCAbi,
+
+ /// "Windows Fastcall", which is used on Windows. Note that like "System V",
+ /// this varies between hardware architectures. On x86-32 it describes what
+ /// Windows documentation calls "fastcall", and on x86-64 it describes what
+ /// Windows documentation often just calls the Windows x64 calling convention
+ /// (though the compiler still recognizes "fastcall" as an alias for it).
+ WindowsFastcall,
+}
+
+/// A target "triple". Historically such things had three fields, though they've
+/// added additional fields over time.
+///
+/// Note that `Triple` doesn't implement `Default` itself. If you want a type
+/// which defaults to the host triple, or defaults to unknown-unknown-unknown,
+/// use `DefaultToHost` or `DefaultToUnknown`, respectively.
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct Triple {
+ /// The "architecture" (and sometimes the subarchitecture).
+ pub architecture: Architecture,
+ /// The "vendor" (whatever that means).
+ pub vendor: Vendor,
+ /// The "operating system" (sometimes also the environment).
+ pub operating_system: OperatingSystem,
+ /// The "environment" on top of the operating system (often omitted for
+ /// operating systems with a single predominant environment).
+ pub environment: Environment,
+ /// The "binary format" (rarely used).
+ pub binary_format: BinaryFormat,
+}
+
+impl Triple {
+ /// Return the endianness of this target's architecture.
+ pub fn endianness(&self) -> Result<Endianness, ()> {
+ self.architecture.endianness()
+ }
+
+ /// Return the pointer width of this target's architecture.
+ pub fn pointer_width(&self) -> Result<PointerWidth, ()> {
+ self.architecture.pointer_width()
+ }
+
+ /// Return the default calling convention for the given target triple.
+ pub fn default_calling_convention(&self) -> Result<CallingConvention, ()> {
+ Ok(match self.operating_system {
+ OperatingSystem::Bitrig
+ | OperatingSystem::Cloudabi
+ | OperatingSystem::Darwin
+ | OperatingSystem::Dragonfly
+ | OperatingSystem::Freebsd
+ | OperatingSystem::Fuchsia
+ | OperatingSystem::Haiku
+ | OperatingSystem::Hermit
+ | OperatingSystem::Ios
+ | OperatingSystem::L4re
+ | OperatingSystem::Linux
+ | OperatingSystem::MacOSX { .. }
+ | OperatingSystem::Netbsd
+ | OperatingSystem::Openbsd
+ | OperatingSystem::Redox
+ | OperatingSystem::Solaris => CallingConvention::SystemV,
+ OperatingSystem::Windows => CallingConvention::WindowsFastcall,
+ OperatingSystem::Nebulet
+ | OperatingSystem::Emscripten
+ | OperatingSystem::Wasi
+ | OperatingSystem::Unknown => match self.architecture {
+ Architecture::Wasm32 => CallingConvention::WasmBasicCAbi,
+ _ => return Err(()),
+ },
+ _ => return Err(()),
+ })
+ }
+
+ /// The C data model for a given target. If the model is not known, returns `Err(())`.
+ pub fn data_model(&self) -> Result<CDataModel, ()> {
+ match self.pointer_width()? {
+ PointerWidth::U64 => {
+ if self.operating_system == OperatingSystem::Windows {
+ Ok(CDataModel::LLP64)
+ } else if self.default_calling_convention() == Ok(CallingConvention::SystemV)
+ || self.architecture == Architecture::Wasm64
+ {
+ Ok(CDataModel::LP64)
+ } else {
+ Err(())
+ }
+ }
+ PointerWidth::U32 => {
+ if self.operating_system == OperatingSystem::Windows
+ || self.default_calling_convention() == Ok(CallingConvention::SystemV)
+ || self.architecture == Architecture::Wasm32
+ {
+ Ok(CDataModel::ILP32)
+ } else {
+ Err(())
+ }
+ }
+ // TODO: on 16-bit machines there is usually a distinction
+ // between near-pointers and far-pointers.
+ // Additionally, code pointers sometimes have a different size than data pointers.
+ // We don't handle this case.
+ PointerWidth::U16 => Err(()),
+ }
+ }
+
+ /// Return a `Triple` with all unknown fields.
+ pub fn unknown() -> Self {
+ Self {
+ architecture: Architecture::Unknown,
+ vendor: Vendor::Unknown,
+ operating_system: OperatingSystem::Unknown,
+ environment: Environment::Unknown,
+ binary_format: BinaryFormat::Unknown,
+ }
+ }
+}
+
+impl fmt::Display for Triple {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let implied_binary_format = default_binary_format(&self);
+
+ write!(f, "{}", self.architecture)?;
+ if self.vendor == Vendor::Unknown
+ && ((self.operating_system == OperatingSystem::Linux
+ && (self.environment == Environment::Android
+ || self.environment == Environment::Androideabi
+ || self.environment == Environment::Kernel))
+ || self.operating_system == OperatingSystem::Fuchsia
+ || self.operating_system == OperatingSystem::Wasi
+ || (self.operating_system == OperatingSystem::None_
+ && (self.architecture == Architecture::Arm(ArmArchitecture::Armebv7r)
+ || self.architecture == Architecture::Arm(ArmArchitecture::Armv7a)
+ || self.architecture == Architecture::Arm(ArmArchitecture::Armv7r)
+ || self.architecture == Architecture::Arm(ArmArchitecture::Thumbv6m)
+ || self.architecture == Architecture::Arm(ArmArchitecture::Thumbv7em)
+ || self.architecture == Architecture::Arm(ArmArchitecture::Thumbv7m)
+ || self.architecture == Architecture::Arm(ArmArchitecture::Thumbv8mBase)
+ || self.architecture == Architecture::Arm(ArmArchitecture::Thumbv8mMain)
+ || self.architecture == Architecture::Msp430
+ || self.architecture == Architecture::X86_64)))
+ {
+ // As a special case, omit the vendor for Android, Fuchsia, Wasi, and sometimes
+ // None_, depending on the hardware architecture. This logic is entirely
+ // ad-hoc, and is just sufficient to handle the current set of recognized
+ // triples.
+ write!(f, "-{}", self.operating_system)?;
+ } else {
+ write!(f, "-{}-{}", self.vendor, self.operating_system)?;
+ }
+ if self.environment != Environment::Unknown {
+ write!(f, "-{}", self.environment)?;
+ }
+
+ if self.binary_format != implied_binary_format {
+ write!(f, "-{}", self.binary_format)?;
+ }
+ Ok(())
+ }
+}
+
+impl FromStr for Triple {
+ type Err = ParseError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let mut parts = s.split('-');
+ let mut result = Self::unknown();
+ let mut current_part;
+
+ current_part = parts.next();
+ if let Some(s) = current_part {
+ if let Ok(architecture) = Architecture::from_str(s) {
+ result.architecture = architecture;
+ current_part = parts.next();
+ } else {
+ // Insist that the triple start with a valid architecture.
+ return Err(ParseError::UnrecognizedArchitecture(s.to_owned()));
+ }
+ }
+
+ let mut has_vendor = false;
+ let mut has_operating_system = false;
+ if let Some(s) = current_part {
+ if let Ok(vendor) = Vendor::from_str(s) {
+ has_vendor = true;
+ result.vendor = vendor;
+ current_part = parts.next();
+ }
+ }
+
+ if !has_operating_system {
+ if let Some(s) = current_part {
+ if let Ok(operating_system) = OperatingSystem::from_str(s) {
+ has_operating_system = true;
+ result.operating_system = operating_system;
+ current_part = parts.next();
+ }
+ }
+ }
+
+ let mut has_environment = false;
+ if let Some(s) = current_part {
+ if let Ok(environment) = Environment::from_str(s) {
+ has_environment = true;
+ result.environment = environment;
+ current_part = parts.next();
+ }
+ }
+
+ let mut has_binary_format = false;
+ if let Some(s) = current_part {
+ if let Ok(binary_format) = BinaryFormat::from_str(s) {
+ has_binary_format = true;
+ result.binary_format = binary_format;
+ current_part = parts.next();
+ }
+ }
+
+ // The binary format is frequently omitted; if that's the case here,
+ // infer it from the other fields.
+ if !has_binary_format {
+ result.binary_format = default_binary_format(&result);
+ }
+
+ if let Some(s) = current_part {
+ Err(
+ if !has_vendor && !has_operating_system && !has_environment && !has_binary_format {
+ ParseError::UnrecognizedVendor(s.to_owned())
+ } else if !has_operating_system && !has_environment && !has_binary_format {
+ ParseError::UnrecognizedOperatingSystem(s.to_owned())
+ } else if !has_environment && !has_binary_format {
+ ParseError::UnrecognizedEnvironment(s.to_owned())
+ } else if !has_binary_format {
+ ParseError::UnrecognizedBinaryFormat(s.to_owned())
+ } else {
+ ParseError::UnrecognizedField(s.to_owned())
+ },
+ )
+ } else {
+ Ok(result)
+ }
+ }
+}
+
+/// A convenient syntax for triple literals.
+///
+/// This currently expands to code that just calls `Triple::from_str` and does
+/// an `expect`, though in the future it would be cool to use procedural macros
+/// or so to report errors at compile time instead.
+#[macro_export]
+macro_rules! triple {
+ ($str:tt) => {
+ target_lexicon::Triple::from_str($str).expect("invalid triple literal")
+ };
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn parse_errors() {
+ assert_eq!(
+ Triple::from_str(""),
+ Err(ParseError::UnrecognizedArchitecture("".to_owned()))
+ );
+ assert_eq!(
+ Triple::from_str("foo"),
+ Err(ParseError::UnrecognizedArchitecture("foo".to_owned()))
+ );
+ assert_eq!(
+ Triple::from_str("unknown-unknown-foo"),
+ Err(ParseError::UnrecognizedOperatingSystem("foo".to_owned()))
+ );
+ assert_eq!(
+ Triple::from_str("unknown-unknown-unknown-foo"),
+ Err(ParseError::UnrecognizedEnvironment("foo".to_owned()))
+ );
+ assert_eq!(
+ Triple::from_str("unknown-unknown-unknown-unknown-foo"),
+ Err(ParseError::UnrecognizedBinaryFormat("foo".to_owned()))
+ );
+ assert_eq!(
+ Triple::from_str("unknown-unknown-unknown-unknown-unknown-foo"),
+ Err(ParseError::UnrecognizedField("foo".to_owned()))
+ );
+ }
+
+ #[test]
+ fn defaults() {
+ assert_eq!(
+ Triple::from_str("unknown-unknown-unknown"),
+ Ok(Triple::unknown())
+ );
+ assert_eq!(
+ Triple::from_str("unknown-unknown-unknown-unknown"),
+ Ok(Triple::unknown())
+ );
+ assert_eq!(
+ Triple::from_str("unknown-unknown-unknown-unknown-unknown"),
+ Ok(Triple::unknown())
+ );
+ }
+
+ #[test]
+ fn unknown_properties() {
+ assert_eq!(Triple::unknown().endianness(), Err(()));
+ assert_eq!(Triple::unknown().pointer_width(), Err(()));
+ assert_eq!(Triple::unknown().default_calling_convention(), Err(()));
+ }
+}