summaryrefslogtreecommitdiffstats
path: root/third_party/rust/cranelift-codegen-shared
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/cranelift-codegen-shared
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/cranelift-codegen-shared')
-rw-r--r--third_party/rust/cranelift-codegen-shared/.cargo-checksum.json1
-rw-r--r--third_party/rust/cranelift-codegen-shared/Cargo.toml11
-rw-r--r--third_party/rust/cranelift-codegen-shared/LICENSE220
-rw-r--r--third_party/rust/cranelift-codegen-shared/README.md2
-rw-r--r--third_party/rust/cranelift-codegen-shared/src/condcodes.rs405
-rw-r--r--third_party/rust/cranelift-codegen-shared/src/constant_hash.rs81
-rw-r--r--third_party/rust/cranelift-codegen-shared/src/constants.rs30
-rw-r--r--third_party/rust/cranelift-codegen-shared/src/isa/mod.rs3
-rw-r--r--third_party/rust/cranelift-codegen-shared/src/isa/x86/encoding_bits.rs419
-rw-r--r--third_party/rust/cranelift-codegen-shared/src/isa/x86/mod.rs4
-rw-r--r--third_party/rust/cranelift-codegen-shared/src/lib.rs28
11 files changed, 1204 insertions, 0 deletions
diff --git a/third_party/rust/cranelift-codegen-shared/.cargo-checksum.json b/third_party/rust/cranelift-codegen-shared/.cargo-checksum.json
new file mode 100644
index 0000000000..5904608486
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"322ab8efd1588c57313b18aaa231ee30a888741828cf27283e6c62735d73d02d","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"a410bc2f5dcbde499c0cd299c2620bc8111e3c5b3fccdd9e2d85caf3c24fdab3","src/condcodes.rs":"b8d433b2217b86e172d25b6c65a3ce0cc8ca221062cad1b28b0c78d2159fbda9","src/constant_hash.rs":"ffc619f45aad62c6fdcb83553a05879691a72e9a0103375b2d6cc12d52cf72d0","src/constants.rs":"fed03a10a6316e06aa174091db6e7d1fbb5f73c82c31193012ec5ab52f1c603a","src/isa/mod.rs":"428a950eca14acbe783899ccb1aecf15027f8cbe205578308ebde203d10535f3","src/isa/x86/encoding_bits.rs":"7e013fb804b13f9f83a0d517c6f5105856938d08ad378cc44a6fe6a59adef270","src/isa/x86/mod.rs":"01ef4e4d7437f938badbe2137892183c1ac684da0f68a5bec7e06aad34f43b9b","src/lib.rs":"7a8eda4dafcf47100c41e61b5c985f089d1985c500624956dc183fcf6bc7b183"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/cranelift-codegen-shared/Cargo.toml b/third_party/rust/cranelift-codegen-shared/Cargo.toml
new file mode 100644
index 0000000000..b5e98afd50
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+authors = ["The Cranelift Project Developers"]
+name = "cranelift-codegen-shared"
+version = "0.68.0"
+description = "For code shared between cranelift-codegen-meta and cranelift-codegen"
+license = "Apache-2.0 WITH LLVM-exception"
+repository = "https://github.com/bytecodealliance/wasmtime"
+readme = "README.md"
+edition = "2018"
+
+# Since this is a shared dependency of several packages, please strive to keep this dependency-free.
diff --git a/third_party/rust/cranelift-codegen-shared/LICENSE b/third_party/rust/cranelift-codegen-shared/LICENSE
new file mode 100644
index 0000000000..f9d81955f4
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/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/cranelift-codegen-shared/README.md b/third_party/rust/cranelift-codegen-shared/README.md
new file mode 100644
index 0000000000..54f9f5d6d2
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/README.md
@@ -0,0 +1,2 @@
+This crate contains shared definitions for use in both `cranelift-codegen-meta` and `cranelift
+-codegen`.
diff --git a/third_party/rust/cranelift-codegen-shared/src/condcodes.rs b/third_party/rust/cranelift-codegen-shared/src/condcodes.rs
new file mode 100644
index 0000000000..03ae865ce4
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/src/condcodes.rs
@@ -0,0 +1,405 @@
+//! Condition codes for the Cranelift code generator.
+//!
+//! A condition code here is an enumerated type that determined how to compare two numbers. There
+//! are different rules for comparing integers and floating point numbers, so they use different
+//! condition codes.
+
+use core::fmt::{self, Display, Formatter};
+use core::str::FromStr;
+
+/// Common traits of condition codes.
+pub trait CondCode: Copy {
+ /// Get the inverse condition code of `self`.
+ ///
+ /// The inverse condition code produces the opposite result for all comparisons.
+ /// That is, `cmp CC, x, y` is true if and only if `cmp CC.inverse(), x, y` is false.
+ #[must_use]
+ fn inverse(self) -> Self;
+
+ /// Get the reversed condition code for `self`.
+ ///
+ /// The reversed condition code produces the same result as swapping `x` and `y` in the
+ /// comparison. That is, `cmp CC, x, y` is the same as `cmp CC.reverse(), y, x`.
+ #[must_use]
+ fn reverse(self) -> Self;
+}
+
+/// Condition code for comparing integers.
+///
+/// This condition code is used by the `icmp` instruction to compare integer values. There are
+/// separate codes for comparing the integers as signed or unsigned numbers where it makes a
+/// difference.
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
+pub enum IntCC {
+ /// `==`.
+ Equal,
+ /// `!=`.
+ NotEqual,
+ /// Signed `<`.
+ SignedLessThan,
+ /// Signed `>=`.
+ SignedGreaterThanOrEqual,
+ /// Signed `>`.
+ SignedGreaterThan,
+ /// Signed `<=`.
+ SignedLessThanOrEqual,
+ /// Unsigned `<`.
+ UnsignedLessThan,
+ /// Unsigned `>=`.
+ UnsignedGreaterThanOrEqual,
+ /// Unsigned `>`.
+ UnsignedGreaterThan,
+ /// Unsigned `<=`.
+ UnsignedLessThanOrEqual,
+ /// Signed Overflow.
+ Overflow,
+ /// Signed No Overflow.
+ NotOverflow,
+}
+
+impl CondCode for IntCC {
+ fn inverse(self) -> Self {
+ use self::IntCC::*;
+ match self {
+ Equal => NotEqual,
+ NotEqual => Equal,
+ SignedLessThan => SignedGreaterThanOrEqual,
+ SignedGreaterThanOrEqual => SignedLessThan,
+ SignedGreaterThan => SignedLessThanOrEqual,
+ SignedLessThanOrEqual => SignedGreaterThan,
+ UnsignedLessThan => UnsignedGreaterThanOrEqual,
+ UnsignedGreaterThanOrEqual => UnsignedLessThan,
+ UnsignedGreaterThan => UnsignedLessThanOrEqual,
+ UnsignedLessThanOrEqual => UnsignedGreaterThan,
+ Overflow => NotOverflow,
+ NotOverflow => Overflow,
+ }
+ }
+
+ fn reverse(self) -> Self {
+ use self::IntCC::*;
+ match self {
+ Equal => Equal,
+ NotEqual => NotEqual,
+ SignedGreaterThan => SignedLessThan,
+ SignedGreaterThanOrEqual => SignedLessThanOrEqual,
+ SignedLessThan => SignedGreaterThan,
+ SignedLessThanOrEqual => SignedGreaterThanOrEqual,
+ UnsignedGreaterThan => UnsignedLessThan,
+ UnsignedGreaterThanOrEqual => UnsignedLessThanOrEqual,
+ UnsignedLessThan => UnsignedGreaterThan,
+ UnsignedLessThanOrEqual => UnsignedGreaterThanOrEqual,
+ Overflow => Overflow,
+ NotOverflow => NotOverflow,
+ }
+ }
+}
+
+impl IntCC {
+ /// Get the corresponding IntCC with the equal component removed.
+ /// For conditions without a zero component, this is a no-op.
+ pub fn without_equal(self) -> Self {
+ use self::IntCC::*;
+ match self {
+ SignedGreaterThan | SignedGreaterThanOrEqual => SignedGreaterThan,
+ SignedLessThan | SignedLessThanOrEqual => SignedLessThan,
+ UnsignedGreaterThan | UnsignedGreaterThanOrEqual => UnsignedGreaterThan,
+ UnsignedLessThan | UnsignedLessThanOrEqual => UnsignedLessThan,
+ _ => self,
+ }
+ }
+
+ /// Get the corresponding IntCC with the signed component removed.
+ /// For conditions without a signed component, this is a no-op.
+ pub fn unsigned(self) -> Self {
+ use self::IntCC::*;
+ match self {
+ SignedGreaterThan | UnsignedGreaterThan => UnsignedGreaterThan,
+ SignedGreaterThanOrEqual | UnsignedGreaterThanOrEqual => UnsignedGreaterThanOrEqual,
+ SignedLessThan | UnsignedLessThan => UnsignedLessThan,
+ SignedLessThanOrEqual | UnsignedLessThanOrEqual => UnsignedLessThanOrEqual,
+ _ => self,
+ }
+ }
+
+ /// Get the corresponding string condition code for the IntCC object.
+ pub fn to_static_str(self) -> &'static str {
+ use self::IntCC::*;
+ match self {
+ Equal => "eq",
+ NotEqual => "ne",
+ SignedGreaterThan => "sgt",
+ SignedGreaterThanOrEqual => "sge",
+ SignedLessThan => "slt",
+ SignedLessThanOrEqual => "sle",
+ UnsignedGreaterThan => "ugt",
+ UnsignedGreaterThanOrEqual => "uge",
+ UnsignedLessThan => "ult",
+ UnsignedLessThanOrEqual => "ule",
+ Overflow => "of",
+ NotOverflow => "nof",
+ }
+ }
+}
+
+impl Display for IntCC {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ f.write_str(self.to_static_str())
+ }
+}
+
+impl FromStr for IntCC {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ use self::IntCC::*;
+ match s {
+ "eq" => Ok(Equal),
+ "ne" => Ok(NotEqual),
+ "sge" => Ok(SignedGreaterThanOrEqual),
+ "sgt" => Ok(SignedGreaterThan),
+ "sle" => Ok(SignedLessThanOrEqual),
+ "slt" => Ok(SignedLessThan),
+ "uge" => Ok(UnsignedGreaterThanOrEqual),
+ "ugt" => Ok(UnsignedGreaterThan),
+ "ule" => Ok(UnsignedLessThanOrEqual),
+ "ult" => Ok(UnsignedLessThan),
+ "of" => Ok(Overflow),
+ "nof" => Ok(NotOverflow),
+ _ => Err(()),
+ }
+ }
+}
+
+/// Condition code for comparing floating point numbers.
+///
+/// This condition code is used by the `fcmp` instruction to compare floating point values. Two
+/// IEEE floating point values relate in exactly one of four ways:
+///
+/// 1. `UN` - unordered when either value is NaN.
+/// 2. `EQ` - equal numerical value.
+/// 3. `LT` - `x` is less than `y`.
+/// 4. `GT` - `x` is greater than `y`.
+///
+/// Note that `0.0` and `-0.0` relate as `EQ` because they both represent the number 0.
+///
+/// The condition codes described here are used to produce a single boolean value from the
+/// comparison. The 14 condition codes here cover every possible combination of the relation above
+/// except the impossible `!UN & !EQ & !LT & !GT` and the always true `UN | EQ | LT | GT`.
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
+pub enum FloatCC {
+ /// EQ | LT | GT
+ Ordered,
+ /// UN
+ Unordered,
+
+ /// EQ
+ Equal,
+ /// The C '!=' operator is the inverse of '==': `NotEqual`.
+ /// UN | LT | GT
+ NotEqual,
+ /// LT | GT
+ OrderedNotEqual,
+ /// UN | EQ
+ UnorderedOrEqual,
+
+ /// LT
+ LessThan,
+ /// LT | EQ
+ LessThanOrEqual,
+ /// GT
+ GreaterThan,
+ /// GT | EQ
+ GreaterThanOrEqual,
+
+ /// UN | LT
+ UnorderedOrLessThan,
+ /// UN | LT | EQ
+ UnorderedOrLessThanOrEqual,
+ /// UN | GT
+ UnorderedOrGreaterThan,
+ /// UN | GT | EQ
+ UnorderedOrGreaterThanOrEqual,
+}
+
+impl CondCode for FloatCC {
+ fn inverse(self) -> Self {
+ use self::FloatCC::*;
+ match self {
+ Ordered => Unordered,
+ Unordered => Ordered,
+ Equal => NotEqual,
+ NotEqual => Equal,
+ OrderedNotEqual => UnorderedOrEqual,
+ UnorderedOrEqual => OrderedNotEqual,
+ LessThan => UnorderedOrGreaterThanOrEqual,
+ LessThanOrEqual => UnorderedOrGreaterThan,
+ GreaterThan => UnorderedOrLessThanOrEqual,
+ GreaterThanOrEqual => UnorderedOrLessThan,
+ UnorderedOrLessThan => GreaterThanOrEqual,
+ UnorderedOrLessThanOrEqual => GreaterThan,
+ UnorderedOrGreaterThan => LessThanOrEqual,
+ UnorderedOrGreaterThanOrEqual => LessThan,
+ }
+ }
+ fn reverse(self) -> Self {
+ use self::FloatCC::*;
+ match self {
+ Ordered => Ordered,
+ Unordered => Unordered,
+ Equal => Equal,
+ NotEqual => NotEqual,
+ OrderedNotEqual => OrderedNotEqual,
+ UnorderedOrEqual => UnorderedOrEqual,
+ LessThan => GreaterThan,
+ LessThanOrEqual => GreaterThanOrEqual,
+ GreaterThan => LessThan,
+ GreaterThanOrEqual => LessThanOrEqual,
+ UnorderedOrLessThan => UnorderedOrGreaterThan,
+ UnorderedOrLessThanOrEqual => UnorderedOrGreaterThanOrEqual,
+ UnorderedOrGreaterThan => UnorderedOrLessThan,
+ UnorderedOrGreaterThanOrEqual => UnorderedOrLessThanOrEqual,
+ }
+ }
+}
+
+impl Display for FloatCC {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ use self::FloatCC::*;
+ f.write_str(match *self {
+ Ordered => "ord",
+ Unordered => "uno",
+ Equal => "eq",
+ NotEqual => "ne",
+ OrderedNotEqual => "one",
+ UnorderedOrEqual => "ueq",
+ LessThan => "lt",
+ LessThanOrEqual => "le",
+ GreaterThan => "gt",
+ GreaterThanOrEqual => "ge",
+ UnorderedOrLessThan => "ult",
+ UnorderedOrLessThanOrEqual => "ule",
+ UnorderedOrGreaterThan => "ugt",
+ UnorderedOrGreaterThanOrEqual => "uge",
+ })
+ }
+}
+
+impl FromStr for FloatCC {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ use self::FloatCC::*;
+ match s {
+ "ord" => Ok(Ordered),
+ "uno" => Ok(Unordered),
+ "eq" => Ok(Equal),
+ "ne" => Ok(NotEqual),
+ "one" => Ok(OrderedNotEqual),
+ "ueq" => Ok(UnorderedOrEqual),
+ "lt" => Ok(LessThan),
+ "le" => Ok(LessThanOrEqual),
+ "gt" => Ok(GreaterThan),
+ "ge" => Ok(GreaterThanOrEqual),
+ "ult" => Ok(UnorderedOrLessThan),
+ "ule" => Ok(UnorderedOrLessThanOrEqual),
+ "ugt" => Ok(UnorderedOrGreaterThan),
+ "uge" => Ok(UnorderedOrGreaterThanOrEqual),
+ _ => Err(()),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::string::ToString;
+
+ static INT_ALL: [IntCC; 12] = [
+ IntCC::Equal,
+ IntCC::NotEqual,
+ IntCC::SignedLessThan,
+ IntCC::SignedGreaterThanOrEqual,
+ IntCC::SignedGreaterThan,
+ IntCC::SignedLessThanOrEqual,
+ IntCC::UnsignedLessThan,
+ IntCC::UnsignedGreaterThanOrEqual,
+ IntCC::UnsignedGreaterThan,
+ IntCC::UnsignedLessThanOrEqual,
+ IntCC::Overflow,
+ IntCC::NotOverflow,
+ ];
+
+ #[test]
+ fn int_inverse() {
+ for r in &INT_ALL {
+ let cc = *r;
+ let inv = cc.inverse();
+ assert!(cc != inv);
+ assert_eq!(inv.inverse(), cc);
+ }
+ }
+
+ #[test]
+ fn int_reverse() {
+ for r in &INT_ALL {
+ let cc = *r;
+ let rev = cc.reverse();
+ assert_eq!(rev.reverse(), cc);
+ }
+ }
+
+ #[test]
+ fn int_display() {
+ for r in &INT_ALL {
+ let cc = *r;
+ assert_eq!(cc.to_string().parse(), Ok(cc));
+ }
+ assert_eq!("bogus".parse::<IntCC>(), Err(()));
+ }
+
+ static FLOAT_ALL: [FloatCC; 14] = [
+ FloatCC::Ordered,
+ FloatCC::Unordered,
+ FloatCC::Equal,
+ FloatCC::NotEqual,
+ FloatCC::OrderedNotEqual,
+ FloatCC::UnorderedOrEqual,
+ FloatCC::LessThan,
+ FloatCC::LessThanOrEqual,
+ FloatCC::GreaterThan,
+ FloatCC::GreaterThanOrEqual,
+ FloatCC::UnorderedOrLessThan,
+ FloatCC::UnorderedOrLessThanOrEqual,
+ FloatCC::UnorderedOrGreaterThan,
+ FloatCC::UnorderedOrGreaterThanOrEqual,
+ ];
+
+ #[test]
+ fn float_inverse() {
+ for r in &FLOAT_ALL {
+ let cc = *r;
+ let inv = cc.inverse();
+ assert!(cc != inv);
+ assert_eq!(inv.inverse(), cc);
+ }
+ }
+
+ #[test]
+ fn float_reverse() {
+ for r in &FLOAT_ALL {
+ let cc = *r;
+ let rev = cc.reverse();
+ assert_eq!(rev.reverse(), cc);
+ }
+ }
+
+ #[test]
+ fn float_display() {
+ for r in &FLOAT_ALL {
+ let cc = *r;
+ assert_eq!(cc.to_string().parse(), Ok(cc));
+ }
+ assert_eq!("bogus".parse::<FloatCC>(), Err(()));
+ }
+}
diff --git a/third_party/rust/cranelift-codegen-shared/src/constant_hash.rs b/third_party/rust/cranelift-codegen-shared/src/constant_hash.rs
new file mode 100644
index 0000000000..ceac8e2722
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/src/constant_hash.rs
@@ -0,0 +1,81 @@
+//! Build support for precomputed constant hash tables.
+//!
+//! This module can generate constant hash tables using open addressing and quadratic probing.
+//!
+//! The hash tables are arrays that are guaranteed to:
+//!
+//! - Have a power-of-two size.
+//! - Contain at least one empty slot.
+//!
+//! This module provides build meta support for lookups in these tables, as well as the shared hash
+//! function used for probing.
+
+use std::iter;
+
+/// A primitive hash function for matching opcodes.
+pub fn simple_hash(s: &str) -> usize {
+ let mut h: u32 = 5381;
+ for c in s.chars() {
+ h = (h ^ c as u32).wrapping_add(h.rotate_right(6));
+ }
+ h as usize
+}
+
+/// Compute an open addressed, quadratically probed hash table containing
+/// `items`. The returned table is a list containing the elements of the
+/// iterable `items` and `None` in unused slots.
+#[allow(clippy::float_arithmetic)]
+pub fn generate_table<'cont, T, I: iter::Iterator<Item = &'cont T>, H: Fn(&T) -> usize>(
+ items: I,
+ num_items: usize,
+ hash_function: H,
+) -> Vec<Option<&'cont T>> {
+ let size = (1.20 * num_items as f64) as usize;
+
+ // Probing code's stop condition relies on the table having one vacant entry at least.
+ let size = if size.is_power_of_two() {
+ size * 2
+ } else {
+ size.next_power_of_two()
+ };
+
+ let mut table = vec![None; size];
+
+ for i in items {
+ let mut h = hash_function(&i) % size;
+ let mut s = 0;
+ while table[h].is_some() {
+ s += 1;
+ h = (h + s) % size;
+ }
+ table[h] = Some(i);
+ }
+
+ table
+}
+
+#[cfg(test)]
+mod tests {
+ use super::{generate_table, simple_hash};
+
+ #[test]
+ fn basic() {
+ assert_eq!(simple_hash("Hello"), 0x2fa70c01);
+ assert_eq!(simple_hash("world"), 0x5b0c31d5);
+ }
+
+ #[test]
+ fn test_generate_table() {
+ let v = vec!["Hello".to_string(), "world".to_string()];
+ let table = generate_table(v.iter(), v.len(), |s| simple_hash(&s));
+ assert_eq!(
+ table,
+ vec![
+ None,
+ Some(&"Hello".to_string()),
+ Some(&"world".to_string()),
+ None
+ ]
+ );
+ }
+}
diff --git a/third_party/rust/cranelift-codegen-shared/src/constants.rs b/third_party/rust/cranelift-codegen-shared/src/constants.rs
new file mode 100644
index 0000000000..b3f1377856
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/src/constants.rs
@@ -0,0 +1,30 @@
+//! This module contains constants that are shared between the codegen and the meta crate, so they
+//! are kept in sync.
+
+// Numbering scheme for value types:
+//
+// 0: Void
+// 0x01-0x6f: Special types
+// 0x70-0x7d: Lane types
+// 0x7e-0x7f: Reference types
+// 0x80-0xff: Vector types
+//
+// Vector types are encoded with the lane type in the low 4 bits and log2(lanes)
+// in the high 4 bits, giving a range of 2-256 lanes.
+
+/// Start of the lane types.
+pub const LANE_BASE: u8 = 0x70;
+
+/// Base for reference types.
+pub const REFERENCE_BASE: u8 = 0x7E;
+
+/// Start of the 2-lane vector types.
+pub const VECTOR_BASE: u8 = 0x80;
+
+// Some constants about register classes and types.
+
+/// Guaranteed maximum number of top-level register classes with pressure tracking in any ISA.
+pub const MAX_TRACKED_TOP_RCS: usize = 4;
+
+/// Guaranteed maximum number of register classes in any ISA.
+pub const MAX_NUM_REG_CLASSES: usize = 32;
diff --git a/third_party/rust/cranelift-codegen-shared/src/isa/mod.rs b/third_party/rust/cranelift-codegen-shared/src/isa/mod.rs
new file mode 100644
index 0000000000..4d8e485f6c
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/src/isa/mod.rs
@@ -0,0 +1,3 @@
+//! Shared ISA-specific definitions.
+
+pub mod x86;
diff --git a/third_party/rust/cranelift-codegen-shared/src/isa/x86/encoding_bits.rs b/third_party/rust/cranelift-codegen-shared/src/isa/x86/encoding_bits.rs
new file mode 100644
index 0000000000..9edb2a6e6f
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/src/isa/x86/encoding_bits.rs
@@ -0,0 +1,419 @@
+//! Provides a named interface to the `u16` Encoding bits.
+
+use std::ops::RangeInclusive;
+
+/// Named interface to the `u16` Encoding bits, representing an opcode.
+///
+/// Cranelift requires each recipe to have a single encoding size in bytes.
+/// X86 opcodes are variable length, so we use separate recipes for different
+/// styles of opcodes and prefixes. The opcode format is indicated by the
+/// recipe name prefix.
+///
+/// VEX/XOP and EVEX prefixes are not yet supported.
+/// Encodings using any of these prefixes are represented by separate recipes.
+///
+/// The encoding bits are:
+///
+/// 0-7: The opcode byte <op>.
+/// 8-9: pp, mandatory prefix:
+/// 00: none (Op*)
+/// 01: 66 (Mp*)
+/// 10: F3 (Mp*)
+/// 11: F2 (Mp*)
+/// 10-11: mm, opcode map:
+/// 00: <op> (Op1/Mp1)
+/// 01: 0F <op> (Op2/Mp2)
+/// 10: 0F 38 <op> (Op3/Mp3)
+/// 11: 0F 3A <op> (Op3/Mp3)
+/// 12-14 rrr, opcode bits for the ModR/M byte for certain opcodes.
+/// 15: REX.W bit (or VEX.W/E)
+#[derive(Copy, Clone, PartialEq)]
+pub struct EncodingBits(u16);
+const OPCODE: RangeInclusive<u16> = 0..=7;
+const OPCODE_PREFIX: RangeInclusive<u16> = 8..=11; // Includes pp and mm.
+const RRR: RangeInclusive<u16> = 12..=14;
+const REX_W: RangeInclusive<u16> = 15..=15;
+
+impl From<u16> for EncodingBits {
+ fn from(bits: u16) -> Self {
+ Self(bits)
+ }
+}
+
+impl EncodingBits {
+ /// Constructs a new EncodingBits from parts.
+ pub fn new(op_bytes: &[u8], rrr: u16, rex_w: u16) -> Self {
+ assert!(
+ !op_bytes.is_empty(),
+ "op_bytes must include at least one opcode byte"
+ );
+ let mut new = Self::from(0);
+ let last_byte = op_bytes[op_bytes.len() - 1];
+ new.write(OPCODE, last_byte as u16);
+ let prefix: u8 = OpcodePrefix::from_opcode(op_bytes).into();
+ new.write(OPCODE_PREFIX, prefix as u16);
+ new.write(RRR, rrr);
+ new.write(REX_W, rex_w);
+ new
+ }
+
+ /// Returns a copy of the EncodingBits with the RRR bits set.
+ #[inline]
+ pub fn with_rrr(mut self, rrr: u8) -> Self {
+ debug_assert_eq!(self.rrr(), 0);
+ self.write(RRR, rrr.into());
+ self
+ }
+
+ /// Returns a copy of the EncodingBits with the REX.W bit set.
+ #[inline]
+ pub fn with_rex_w(mut self) -> Self {
+ debug_assert_eq!(self.rex_w(), 0);
+ self.write(REX_W, 1);
+ self
+ }
+
+ /// Returns the raw bits.
+ #[inline]
+ pub fn bits(self) -> u16 {
+ self.0
+ }
+
+ /// Convenience method for writing bits to specific range.
+ #[inline]
+ fn write(&mut self, range: RangeInclusive<u16>, value: u16) {
+ assert!(ExactSizeIterator::len(&range) > 0);
+ let size = range.end() - range.start() + 1; // Calculate the number of bits in the range.
+ let mask = (1 << size) - 1; // Generate a bit mask.
+ debug_assert!(
+ value <= mask,
+ "The written value should have fewer than {} bits.",
+ size
+ );
+ let mask_complement = !(mask << *range.start()); // Create the bitwise complement for the clear mask.
+ self.0 &= mask_complement; // Clear the bits in `range`.
+ let value = (value & mask) << *range.start(); // Place the value in the correct location.
+ self.0 |= value; // Modify the bits in `range`.
+ }
+
+ /// Convenience method for reading bits from a specific range.
+ #[inline]
+ fn read(self, range: RangeInclusive<u16>) -> u8 {
+ assert!(ExactSizeIterator::len(&range) > 0);
+ let size = range.end() - range.start() + 1; // Calculate the number of bits in the range.
+ debug_assert!(size <= 8, "This structure expects ranges of at most 8 bits");
+ let mask = (1 << size) - 1; // Generate a bit mask.
+ ((self.0 >> *range.start()) & mask) as u8
+ }
+
+ /// Instruction opcode byte, without the prefix.
+ #[inline]
+ pub fn opcode_byte(self) -> u8 {
+ self.read(OPCODE)
+ }
+
+ /// Prefix kind for the instruction, as an enum.
+ #[inline]
+ pub fn prefix(self) -> OpcodePrefix {
+ OpcodePrefix::from(self.read(OPCODE_PREFIX))
+ }
+
+ /// Extracts the PP bits of the OpcodePrefix.
+ #[inline]
+ pub fn pp(self) -> u8 {
+ self.prefix().to_primitive() & 0x3
+ }
+
+ /// Extracts the MM bits of the OpcodePrefix.
+ #[inline]
+ pub fn mm(self) -> u8 {
+ (self.prefix().to_primitive() >> 2) & 0x3
+ }
+
+ /// Bits for the ModR/M byte for certain opcodes.
+ #[inline]
+ pub fn rrr(self) -> u8 {
+ self.read(RRR)
+ }
+
+ /// REX.W bit (or VEX.W/E).
+ #[inline]
+ pub fn rex_w(self) -> u8 {
+ self.read(REX_W)
+ }
+}
+
+/// Opcode prefix representation.
+///
+/// The prefix type occupies four of the EncodingBits.
+#[allow(non_camel_case_types)]
+#[allow(missing_docs)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum OpcodePrefix {
+ Op1,
+ Mp1_66,
+ Mp1_f3,
+ Mp1_f2,
+ Op2_0f,
+ Mp2_66_0f,
+ Mp2_f3_0f,
+ Mp2_f2_0f,
+ Op3_0f_38,
+ Mp3_66_0f_38,
+ Mp3_f3_0f_38,
+ Mp3_f2_0f_38,
+ Op3_0f_3a,
+ Mp3_66_0f_3a,
+ Mp3_f3_0f_3a,
+ Mp3_f2_0f_3a,
+}
+
+impl From<u8> for OpcodePrefix {
+ fn from(n: u8) -> Self {
+ use OpcodePrefix::*;
+ match n {
+ 0b0000 => Op1,
+ 0b0001 => Mp1_66,
+ 0b0010 => Mp1_f3,
+ 0b0011 => Mp1_f2,
+ 0b0100 => Op2_0f,
+ 0b0101 => Mp2_66_0f,
+ 0b0110 => Mp2_f3_0f,
+ 0b0111 => Mp2_f2_0f,
+ 0b1000 => Op3_0f_38,
+ 0b1001 => Mp3_66_0f_38,
+ 0b1010 => Mp3_f3_0f_38,
+ 0b1011 => Mp3_f2_0f_38,
+ 0b1100 => Op3_0f_3a,
+ 0b1101 => Mp3_66_0f_3a,
+ 0b1110 => Mp3_f3_0f_3a,
+ 0b1111 => Mp3_f2_0f_3a,
+ _ => panic!("invalid opcode prefix"),
+ }
+ }
+}
+
+impl Into<u8> for OpcodePrefix {
+ fn into(self) -> u8 {
+ use OpcodePrefix::*;
+ match self {
+ Op1 => 0b0000,
+ Mp1_66 => 0b0001,
+ Mp1_f3 => 0b0010,
+ Mp1_f2 => 0b0011,
+ Op2_0f => 0b0100,
+ Mp2_66_0f => 0b0101,
+ Mp2_f3_0f => 0b0110,
+ Mp2_f2_0f => 0b0111,
+ Op3_0f_38 => 0b1000,
+ Mp3_66_0f_38 => 0b1001,
+ Mp3_f3_0f_38 => 0b1010,
+ Mp3_f2_0f_38 => 0b1011,
+ Op3_0f_3a => 0b1100,
+ Mp3_66_0f_3a => 0b1101,
+ Mp3_f3_0f_3a => 0b1110,
+ Mp3_f2_0f_3a => 0b1111,
+ }
+ }
+}
+
+impl OpcodePrefix {
+ /// Convert an opcode prefix to a `u8`; this is a convenience proxy for `Into<u8>`.
+ fn to_primitive(self) -> u8 {
+ self.into()
+ }
+
+ /// Extracts the OpcodePrefix from the opcode.
+ pub fn from_opcode(op_bytes: &[u8]) -> Self {
+ assert!(!op_bytes.is_empty(), "at least one opcode byte");
+
+ let prefix_bytes = &op_bytes[..op_bytes.len() - 1];
+ match prefix_bytes {
+ [] => Self::Op1,
+ [0x66] => Self::Mp1_66,
+ [0xf3] => Self::Mp1_f3,
+ [0xf2] => Self::Mp1_f2,
+ [0x0f] => Self::Op2_0f,
+ [0x66, 0x0f] => Self::Mp2_66_0f,
+ [0xf3, 0x0f] => Self::Mp2_f3_0f,
+ [0xf2, 0x0f] => Self::Mp2_f2_0f,
+ [0x0f, 0x38] => Self::Op3_0f_38,
+ [0x66, 0x0f, 0x38] => Self::Mp3_66_0f_38,
+ [0xf3, 0x0f, 0x38] => Self::Mp3_f3_0f_38,
+ [0xf2, 0x0f, 0x38] => Self::Mp3_f2_0f_38,
+ [0x0f, 0x3a] => Self::Op3_0f_3a,
+ [0x66, 0x0f, 0x3a] => Self::Mp3_66_0f_3a,
+ [0xf3, 0x0f, 0x3a] => Self::Mp3_f3_0f_3a,
+ [0xf2, 0x0f, 0x3a] => Self::Mp3_f2_0f_3a,
+ _ => {
+ panic!("unexpected opcode sequence: {:?}", op_bytes);
+ }
+ }
+ }
+
+ /// Returns the recipe name prefix.
+ ///
+ /// At the moment, each similar OpcodePrefix group is given its own Recipe.
+ /// In order to distinguish them, this string is prefixed.
+ pub fn recipe_name_prefix(self) -> &'static str {
+ use OpcodePrefix::*;
+ match self {
+ Op1 => "Op1",
+ Op2_0f => "Op2",
+ Op3_0f_38 | Op3_0f_3a => "Op3",
+ Mp1_66 | Mp1_f3 | Mp1_f2 => "Mp1",
+ Mp2_66_0f | Mp2_f3_0f | Mp2_f2_0f => "Mp2",
+ Mp3_66_0f_38 | Mp3_f3_0f_38 | Mp3_f2_0f_38 => "Mp3",
+ Mp3_66_0f_3a | Mp3_f3_0f_3a | Mp3_f2_0f_3a => "Mp3",
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ /// Helper function for prefix_roundtrip() to avoid long lines.
+ fn test_roundtrip(p: OpcodePrefix) {
+ assert_eq!(p, OpcodePrefix::from(p.to_primitive()));
+ }
+
+ /// Tests that to/from each opcode matches.
+ #[test]
+ fn prefix_roundtrip() {
+ test_roundtrip(OpcodePrefix::Op1);
+ test_roundtrip(OpcodePrefix::Mp1_66);
+ test_roundtrip(OpcodePrefix::Mp1_f3);
+ test_roundtrip(OpcodePrefix::Mp1_f2);
+ test_roundtrip(OpcodePrefix::Op2_0f);
+ test_roundtrip(OpcodePrefix::Mp2_66_0f);
+ test_roundtrip(OpcodePrefix::Mp2_f3_0f);
+ test_roundtrip(OpcodePrefix::Mp2_f2_0f);
+ test_roundtrip(OpcodePrefix::Op3_0f_38);
+ test_roundtrip(OpcodePrefix::Mp3_66_0f_38);
+ test_roundtrip(OpcodePrefix::Mp3_f3_0f_38);
+ test_roundtrip(OpcodePrefix::Mp3_f2_0f_38);
+ test_roundtrip(OpcodePrefix::Op3_0f_3a);
+ test_roundtrip(OpcodePrefix::Mp3_66_0f_3a);
+ test_roundtrip(OpcodePrefix::Mp3_f3_0f_3a);
+ test_roundtrip(OpcodePrefix::Mp3_f2_0f_3a);
+ }
+
+ #[test]
+ fn prefix_to_name() {
+ assert_eq!(OpcodePrefix::Op1.recipe_name_prefix(), "Op1");
+ assert_eq!(OpcodePrefix::Op2_0f.recipe_name_prefix(), "Op2");
+ assert_eq!(OpcodePrefix::Op3_0f_38.recipe_name_prefix(), "Op3");
+ assert_eq!(OpcodePrefix::Mp1_66.recipe_name_prefix(), "Mp1");
+ assert_eq!(OpcodePrefix::Mp2_66_0f.recipe_name_prefix(), "Mp2");
+ assert_eq!(OpcodePrefix::Mp3_66_0f_3a.recipe_name_prefix(), "Mp3");
+ }
+
+ /// Tests that the opcode_byte is the lower of the EncodingBits.
+ #[test]
+ fn encodingbits_opcode_byte() {
+ let enc = EncodingBits::from(0x00ff);
+ assert_eq!(enc.opcode_byte(), 0xff);
+ assert_eq!(enc.prefix().to_primitive(), 0x0);
+ assert_eq!(enc.rrr(), 0x0);
+ assert_eq!(enc.rex_w(), 0x0);
+
+ let enc = EncodingBits::from(0x00cd);
+ assert_eq!(enc.opcode_byte(), 0xcd);
+ }
+
+ /// Tests that the OpcodePrefix is encoded correctly.
+ #[test]
+ fn encodingbits_prefix() {
+ let enc = EncodingBits::from(0x0c00);
+ assert_eq!(enc.opcode_byte(), 0x00);
+ assert_eq!(enc.prefix().to_primitive(), 0xc);
+ assert_eq!(enc.prefix(), OpcodePrefix::Op3_0f_3a);
+ assert_eq!(enc.rrr(), 0x0);
+ assert_eq!(enc.rex_w(), 0x0);
+ }
+
+ /// Tests that the PP bits are encoded correctly.
+ #[test]
+ fn encodingbits_pp() {
+ let enc = EncodingBits::from(0x0300);
+ assert_eq!(enc.opcode_byte(), 0x0);
+ assert_eq!(enc.pp(), 0x3);
+ assert_eq!(enc.mm(), 0x0);
+ assert_eq!(enc.rrr(), 0x0);
+ assert_eq!(enc.rex_w(), 0x0);
+ }
+
+ /// Tests that the MM bits are encoded correctly.
+ #[test]
+ fn encodingbits_mm() {
+ let enc = EncodingBits::from(0x0c00);
+ assert_eq!(enc.opcode_byte(), 0x0);
+ assert_eq!(enc.pp(), 0x00);
+ assert_eq!(enc.mm(), 0x3);
+ assert_eq!(enc.rrr(), 0x0);
+ assert_eq!(enc.rex_w(), 0x0);
+ }
+
+ /// Tests that the ModR/M bits are encoded correctly.
+ #[test]
+ fn encodingbits_rrr() {
+ let enc = EncodingBits::from(0x5000);
+ assert_eq!(enc.opcode_byte(), 0x0);
+ assert_eq!(enc.prefix().to_primitive(), 0x0);
+ assert_eq!(enc.rrr(), 0x5);
+ assert_eq!(enc.rex_w(), 0x0);
+ }
+
+ /// Tests that the REX.W bit is encoded correctly.
+ #[test]
+ fn encodingbits_rex_w() {
+ let enc = EncodingBits::from(0x8000);
+ assert_eq!(enc.opcode_byte(), 0x00);
+ assert_eq!(enc.prefix().to_primitive(), 0x0);
+ assert_eq!(enc.rrr(), 0x0);
+ assert_eq!(enc.rex_w(), 0x1);
+ }
+
+ /// Tests setting and unsetting a bit using EncodingBits::write.
+ #[test]
+ fn encodingbits_flip() {
+ let mut bits = EncodingBits::from(0);
+ let range = 2..=2;
+
+ bits.write(range.clone(), 1);
+ assert_eq!(bits.bits(), 0b100);
+
+ bits.write(range, 0);
+ assert_eq!(bits.bits(), 0b000);
+ }
+
+ /// Tests a round-trip of EncodingBits from/to a u16 (hardcoded endianness).
+ #[test]
+ fn encodingbits_roundtrip() {
+ let bits: u16 = 0x1234;
+ assert_eq!(EncodingBits::from(bits).bits(), bits);
+ }
+
+ #[test]
+ // I purposely want to divide the bits using the ranges defined above.
+ #[allow(clippy::inconsistent_digit_grouping)]
+ fn encodingbits_construction() {
+ assert_eq!(
+ EncodingBits::new(&[0x66, 0x40], 5, 1).bits(),
+ 0b1_101_0001_01000000 // 1 = rex_w, 101 = rrr, 0001 = prefix, 01000000 = opcode
+ );
+ }
+
+ #[test]
+ #[should_panic]
+ fn encodingbits_panics_at_write_to_invalid_range() {
+ EncodingBits::from(0).write(1..=0, 42);
+ }
+
+ #[test]
+ #[should_panic]
+ fn encodingbits_panics_at_read_to_invalid_range() {
+ EncodingBits::from(0).read(1..=0);
+ }
+}
diff --git a/third_party/rust/cranelift-codegen-shared/src/isa/x86/mod.rs b/third_party/rust/cranelift-codegen-shared/src/isa/x86/mod.rs
new file mode 100644
index 0000000000..fb45ae56c3
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/src/isa/x86/mod.rs
@@ -0,0 +1,4 @@
+//! Shared x86-specific definitions.
+
+mod encoding_bits;
+pub use encoding_bits::*;
diff --git a/third_party/rust/cranelift-codegen-shared/src/lib.rs b/third_party/rust/cranelift-codegen-shared/src/lib.rs
new file mode 100644
index 0000000000..9b4cb941ed
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/src/lib.rs
@@ -0,0 +1,28 @@
+//! This library contains code that is common to both the `cranelift-codegen` and
+//! `cranelift-codegen-meta` libraries.
+
+#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
+#![warn(unused_import_braces)]
+#![cfg_attr(feature = "std", deny(unstable_features))]
+#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
+#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))]
+#![cfg_attr(
+ feature = "cargo-clippy",
+ warn(
+ clippy::float_arithmetic,
+ clippy::mut_mut,
+ clippy::nonminimal_bool,
+ clippy::map_unwrap_or,
+ clippy::print_stdout,
+ clippy::unicode_not_nfc,
+ clippy::use_self
+ )
+)]
+
+pub mod condcodes;
+pub mod constant_hash;
+pub mod constants;
+pub mod isa;
+
+/// Version number of this crate.
+pub const VERSION: &str = env!("CARGO_PKG_VERSION");