From 0a42553b00744f30bf2453add54d6853c9110916 Mon Sep 17 00:00:00 2001 From: Remo Senekowitsch Date: Thu, 16 Mar 2023 10:40:44 +0100 Subject: [PATCH 01/14] fuzz: Add chaos mode control plane Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com> Co-authored-by: Moritz Waser --- Cargo.toml | 1 + cranelift/chaos/Cargo.toml | 19 +++ cranelift/chaos/LICENSE | 220 ++++++++++++++++++++++++++++++++ cranelift/chaos/README.md | 4 + cranelift/chaos/src/disabled.rs | 15 +++ cranelift/chaos/src/enabled.rs | 171 +++++++++++++++++++++++++ cranelift/chaos/src/lib.rs | 33 +++++ 7 files changed, 463 insertions(+) create mode 100644 cranelift/chaos/Cargo.toml create mode 100644 cranelift/chaos/LICENSE create mode 100644 cranelift/chaos/README.md create mode 100644 cranelift/chaos/src/disabled.rs create mode 100644 cranelift/chaos/src/enabled.rs create mode 100644 cranelift/chaos/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 6f081ca40a3e..805003dca5e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -161,6 +161,7 @@ cranelift-object = { path = "cranelift/object", version = "0.95.0" } cranelift-jit = { path = "cranelift/jit", version = "0.95.0" } cranelift-fuzzgen = { path = "cranelift/fuzzgen" } cranelift-bforest = { path = "cranelift/bforest", version = "0.95.0" } +cranelift-chaos = { path = "cranelift/chaos", version = "0.95.0" } cranelift = { path = "cranelift/umbrella", version = "0.95.0" } winch-codegen = { path = "winch/codegen", version = "=0.6.0" } diff --git a/cranelift/chaos/Cargo.toml b/cranelift/chaos/Cargo.toml new file mode 100644 index 000000000000..a7f9a202eae3 --- /dev/null +++ b/cranelift/chaos/Cargo.toml @@ -0,0 +1,19 @@ +[package] +authors = ["The Cranelift Project Developers"] +name = "cranelift-chaos" +version = "0.95.0" +description = "White-box fuzz testing framework" +license = "Apache-2.0 WITH LLVM-exception" +repository = "https://github.com/bytecodealliance/wasmtime" +readme = "README.md" +keywords = ["fuzz", "test"] +edition.workspace = true + +[dependencies] +arbitrary = { version = "1.1.0" } + +[features] + +# Actually turn on chaos mode. +# Without this feature, a zero-sized dummy will be compiled. +chaos = [] diff --git a/cranelift/chaos/LICENSE b/cranelift/chaos/LICENSE new file mode 100644 index 000000000000..f9d81955f4bc --- /dev/null +++ b/cranelift/chaos/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/cranelift/chaos/README.md b/cranelift/chaos/README.md new file mode 100644 index 000000000000..3eecb3d47b6b --- /dev/null +++ b/cranelift/chaos/README.md @@ -0,0 +1,4 @@ +This crate contains the control plane for "chaos mode". It can be used to +inject pseudo-random perturbations into specific sections in the code while +fuzzing. Its compilation is feature-gated to prevent any performance +impact on release builds. diff --git a/cranelift/chaos/src/disabled.rs b/cranelift/chaos/src/disabled.rs new file mode 100644 index 000000000000..450b516fd4e3 --- /dev/null +++ b/cranelift/chaos/src/disabled.rs @@ -0,0 +1,15 @@ +#[derive(Debug, Clone)] +pub struct ChaosEngine { + /// prevent direct instantiation (use `noop` or `todo` instead) + _private: (), +} + +impl ChaosEngine { + pub fn noop() -> Self { + Self { _private: () } + } + + pub fn todo() -> Self { + Self::noop() + } +} diff --git a/cranelift/chaos/src/enabled.rs b/cranelift/chaos/src/enabled.rs new file mode 100644 index 000000000000..7e983c1a80db --- /dev/null +++ b/cranelift/chaos/src/enabled.rs @@ -0,0 +1,171 @@ +use std::{ + fmt::Debug, + sync::{Arc, Mutex}, +}; + +use arbitrary::{Arbitrary, Unstructured}; + +struct ChaosEngineData { + /// # Safety + /// + /// This field must never be moved from, as it is referenced by + /// the field `unstructured` for its entire lifetime. + /// + /// This pattern is the ["self-referential" type]( + /// https://morestina.net/blog/1868/self-referential-types-for-fun-and-profit) + #[allow(dead_code)] + data: Vec, + /// We use internal mutability such that a `ChaosEngine` can be passed + /// through the call stack without having to be declared as mutable. + /// Besides the convenience, the mutation of the internal unstructured + /// data should be opaque to users anyway. + /// + /// # Safety + /// + /// The lifetime of this is actually not static, but tied to `data`. + unstructured: Mutex>, +} + +impl Debug for ChaosEngineData { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let data_len = self.data.len(); + let remaining_len = self + .unstructured + .lock() + .expect("poisoned ChaosEngineData mutex") + .len(); + let consumed_len = data_len - remaining_len; + f.debug_struct("ChaosEngineData") + .field("data", &self.data) + .field( + "unstructured", + &format!( + "(consumed {consumed_len}/{data_len} bytes, \ + {remaining_len} remaining)" + ), + ) + .finish() + } +} + +/// The control plane of chaos mode. +/// Please see the [crate-level documentation](crate). +/// +/// **Clone liberally!** The chaos engine is reference counted. +#[derive(Debug, Clone)] +pub struct ChaosEngine { + data: Arc, + is_todo: bool, +} + +impl ChaosEngine { + fn new(data: Vec, is_todo: bool) -> Self { + let unstructured = Unstructured::new(&data); + // safety: this is ok because we never move out of the vector + let unstructured = Mutex::new(unsafe { std::mem::transmute(unstructured) }); + Self { + data: Arc::new(ChaosEngineData { data, unstructured }), + is_todo, + } + } + + /// This is a zero-sized dummy for use during any builds without the + /// feature `chaos` enabled, especially release builds. It has no + /// functionality, so the programmer is prevented from using it in any + /// way in release builds, which could degrade performance. + /// + /// This should not be used on code paths that may execute while the + /// feature `chaos` is enabled. That would break the assumption that + /// [ChaosEngine] is a singleton, responsible for centrally managing + /// the pseudo-randomness injected at runtimme. + /// + /// Use [todo](ChaosEngine::todo) instead, for stubbing out code paths + /// you don't expect to be reached (yet) during chaos mode fuzzing. + /// + /// # Pancis + /// + /// Panics if it is called while the feature `chaos` is enabled. + #[track_caller] + pub fn noop() -> Self { + panic!( + "attempted to create a NOOP chaos engine \ + (while chaos mode was enabled)" + ); + } + + /// This is the same as [noop](ChaosEngine::noop) when the the feature + /// `chaos` is *disabled*. When `chaos` is enabled, it returns a + /// chaos engine that returns [Error::Todo] when + /// [get_arbitrary](ChaosEngine::get_arbitrary) is called. + /// + /// This may be used during development, in places which are (supposed + /// to be) unreachable during fuzzing. Use of this function should be + /// reduced as the chaos mode is introduced in more parts of the + /// wasmtime codebase. Eventually, it should be deleted. + pub fn todo() -> Self { + Self::new(Vec::new(), true) + } +} + +impl<'a> Arbitrary<'a> for ChaosEngine { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self::new(u.arbitrary()?, false)) + } + fn arbitrary_take_rest(u: Unstructured<'a>) -> arbitrary::Result { + Ok(Self::new(Arbitrary::arbitrary_take_rest(u)?, false)) + } +} + +/// An enumeration of chaos engine API errors, mostly propagating +/// [arbitrary::Error]. +#[derive(Debug, Clone, Copy)] +pub enum Error { + /// No choices were provided to the Unstructured::choose call. + EmptyChoose, + /// There was not enough underlying data to fulfill some request for raw + /// bytes. + NotEnoughData, + /// The input bytes were not of the right format. + IncorrectFormat, + /// The chaos engine API was accessed on a [ChaosEngine::todo]. + Todo, +} + +impl From for Error { + fn from(value: arbitrary::Error) -> Self { + // Force this match statement to be updated when arbitrary + // introduces new error variants. + #[deny(clippy::wildcard_enum_match_arm)] + match value { + arbitrary::Error::EmptyChoose => Error::EmptyChoose, + arbitrary::Error::NotEnoughData => Error::NotEnoughData, + arbitrary::Error::IncorrectFormat => Error::IncorrectFormat, + _ => unreachable!(), + } + } +} + +impl ChaosEngine { + /// Request an arbitrary value from the chaos engine. + /// + /// # Errors + /// + /// - Errors from an underlying call to [arbitrary] will be + /// propagated as-is. + /// - Calling this function on a chaos engine received from a call to + /// [todo] will return an [Error::Todo]. + /// + /// [arbitrary]: arbitrary::Arbitrary::arbitrary + /// [todo]: ChaosEngine::todo + pub fn get_arbitrary>(&self) -> Result { + if self.is_todo { + return Err(Error::Todo); + } + self.data + .unstructured + .lock() + .expect("poisoned ChaosEngineData mutex") + .arbitrary() + .map_err(Error::from) + } +} diff --git a/cranelift/chaos/src/lib.rs b/cranelift/chaos/src/lib.rs new file mode 100644 index 000000000000..2f161a80068e --- /dev/null +++ b/cranelift/chaos/src/lib.rs @@ -0,0 +1,33 @@ +//! # Cranelift Chaos Mode +//! +//! Chaos mode is a compilation feature intended to be turned on for certain +//! fuzz targets. When the feature is turned off - as is normally the case - +//! [ChaosEngine] will be a zero-sized type and optimized away. +//! +//! While the feature is turned on, the struct [ChaosEngine] +//! provides functionality to tap into pseudo-randomness at specific locations +//! in the code. It may be used for targeted fuzzing of compiler internals, +//! e.g. manipulate heuristic optimizations, clobber undefined register bits +//! etc. +//! +//! There are three ways to acquire a [ChaosEngine]: +//! - [arbitrary] for the real deal +//! - [noop] for the zero-sized type when `chaos` is disabled +//! - [todo] for stubbing out code paths during development +//! +//! The reason both [noop] and [todo] exist is so that [todo] can easily +//! be searched for and removed later. +//! +//! [arbitrary]: ChaosEngine#method.arbitrary +//! [noop]: ChaosEngine::noop +//! [todo]: ChaosEngine::todo + +#[cfg(not(any(feature = "chaos", doc)))] +mod disabled; +#[cfg(not(any(feature = "chaos", doc)))] +pub use disabled::*; + +#[cfg(any(feature = "chaos", doc))] +mod enabled; +#[cfg(any(feature = "chaos", doc))] +pub use enabled::*; From f51732ab0818d25f6c886feb1a196f87db22dbe3 Mon Sep 17 00:00:00 2001 From: Remo Senekowitsch Date: Thu, 16 Mar 2023 14:06:04 +0100 Subject: [PATCH 02/14] fuzz: Skip branch optimization with chaos mode Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com> Co-authored-by: Moritz Waser --- Cargo.lock | 17 ++++++++ cranelift/codegen/Cargo.toml | 3 ++ cranelift/codegen/src/context.rs | 12 ++++-- cranelift/codegen/src/isa/aarch64/mod.rs | 24 ++++++++++-- cranelift/codegen/src/isa/mod.rs | 39 +++++++++++++------ cranelift/codegen/src/isa/riscv64/mod.rs | 24 ++++++++++-- cranelift/codegen/src/isa/s390x/mod.rs | 23 +++++++++-- cranelift/codegen/src/isa/x64/mod.rs | 30 +++++++++++--- cranelift/codegen/src/machinst/buffer.rs | 36 ++++++++++------- cranelift/codegen/src/machinst/compile.rs | 5 ++- cranelift/codegen/src/machinst/lower.rs | 3 ++ cranelift/codegen/src/machinst/vcode.rs | 12 +++++- cranelift/filetests/Cargo.toml | 1 + cranelift/filetests/src/function_runner.rs | 5 ++- .../filetests/src/test_alias_analysis.rs | 4 +- cranelift/filetests/src/test_compile.rs | 4 +- cranelift/filetests/src/test_dce.rs | 4 +- cranelift/filetests/src/test_legalizer.rs | 4 +- cranelift/filetests/src/test_licm.rs | 4 +- cranelift/filetests/src/test_optimize.rs | 4 +- cranelift/filetests/src/test_run.rs | 6 ++- cranelift/filetests/src/test_safepoint.rs | 4 +- cranelift/filetests/src/test_simple_gvn.rs | 4 +- cranelift/filetests/src/test_simple_preopt.rs | 4 +- cranelift/filetests/src/test_unwind.rs | 4 +- cranelift/filetests/src/test_wasm.rs | 7 +++- cranelift/fuzzgen/Cargo.toml | 4 ++ cranelift/fuzzgen/src/lib.rs | 18 ++++++--- cranelift/jit/Cargo.toml | 1 + cranelift/jit/src/backend.rs | 3 +- cranelift/module/Cargo.toml | 1 + cranelift/module/src/module.rs | 3 +- cranelift/native/Cargo.toml | 2 +- cranelift/native/src/lib.rs | 10 +++-- cranelift/object/Cargo.toml | 1 + cranelift/object/tests/basic.rs | 25 ++++++++---- cranelift/reader/Cargo.toml | 1 + cranelift/reader/src/lib.rs | 20 +++++----- cranelift/reader/src/parser.rs | 5 ++- crates/cranelift/Cargo.toml | 1 + crates/cranelift/src/builder.rs | 5 ++- crates/cranelift/src/compiler.rs | 3 +- fuzz/Cargo.toml | 6 +++ fuzz/fuzz_targets/cranelift-fuzzgen.rs | 6 +-- fuzz/fuzz_targets/cranelift-icache.rs | 25 ++++++++---- 45 files changed, 322 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 36182b4548ea..5c63d9015fb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -559,6 +559,13 @@ dependencies = [ "cranelift-entity", ] +[[package]] +name = "cranelift-chaos" +version = "0.95.0" +dependencies = [ + "arbitrary", +] + [[package]] name = "cranelift-codegen" version = "0.95.0" @@ -568,6 +575,7 @@ dependencies = [ "bumpalo", "capstone", "cranelift-bforest", + "cranelift-chaos", "cranelift-codegen-meta", "cranelift-codegen-shared", "cranelift-entity", @@ -609,6 +617,7 @@ version = "0.0.0" dependencies = [ "anyhow", "cranelift", + "cranelift-chaos", "cranelift-codegen", "cranelift-frontend", "cranelift-interpreter", @@ -650,6 +659,7 @@ dependencies = [ "anyhow", "arbitrary", "cranelift", + "cranelift-chaos", "cranelift-native", "once_cell", "target-lexicon", @@ -684,6 +694,7 @@ version = "0.95.0" dependencies = [ "anyhow", "cranelift", + "cranelift-chaos", "cranelift-codegen", "cranelift-entity", "cranelift-frontend", @@ -703,6 +714,7 @@ name = "cranelift-module" version = "0.95.0" dependencies = [ "anyhow", + "cranelift-chaos", "cranelift-codegen", "hashbrown 0.13.1", ] @@ -711,6 +723,7 @@ dependencies = [ name = "cranelift-native" version = "0.95.0" dependencies = [ + "cranelift-chaos", "cranelift-codegen", "libc", "target-lexicon", @@ -721,6 +734,7 @@ name = "cranelift-object" version = "0.95.0" dependencies = [ "anyhow", + "cranelift-chaos", "cranelift-codegen", "cranelift-entity", "cranelift-frontend", @@ -735,6 +749,7 @@ name = "cranelift-reader" version = "0.95.0" dependencies = [ "anyhow", + "cranelift-chaos", "cranelift-codegen", "smallvec", "target-lexicon", @@ -3583,6 +3598,7 @@ name = "wasmtime-cranelift" version = "8.0.0" dependencies = [ "anyhow", + "cranelift-chaos", "cranelift-codegen", "cranelift-entity", "cranelift-frontend", @@ -3682,6 +3698,7 @@ dependencies = [ "arbitrary", "component-fuzz-util", "component-test-util", + "cranelift-chaos", "cranelift-codegen", "cranelift-filetests", "cranelift-fuzzgen", diff --git a/cranelift/codegen/Cargo.toml b/cranelift/codegen/Cargo.toml index 6ea37cbd480b..772aa950cc20 100644 --- a/cranelift/codegen/Cargo.toml +++ b/cranelift/codegen/Cargo.toml @@ -19,6 +19,7 @@ capstone = { workspace = true, optional = true } cranelift-codegen-shared = { path = "./shared", version = "0.95.0" } cranelift-entity = { workspace = true } cranelift-bforest = { workspace = true } +cranelift-chaos = { workspace = true } hashbrown = { workspace = true, features = ["raw"] } target-lexicon = { workspace = true } log = { workspace = true } @@ -113,6 +114,8 @@ isle-errors = ["cranelift-isle/fancy-errors"] # inspection, rather than inside of target/. isle-in-source-tree = [] +chaos = ["cranelift-chaos/chaos"] + [badges] maintenance = { status = "experimental" } diff --git a/cranelift/codegen/src/context.rs b/cranelift/codegen/src/context.rs index db0ff0434a59..569aa1497feb 100644 --- a/cranelift/codegen/src/context.rs +++ b/cranelift/codegen/src/context.rs @@ -33,6 +33,7 @@ use crate::{timing, CompileError}; #[cfg(feature = "souper-harvest")] use alloc::string::String; use alloc::vec::Vec; +use cranelift_chaos::ChaosEngine; #[cfg(feature = "souper-harvest")] use crate::souper_harvest::do_souper_harvest; @@ -56,6 +57,10 @@ pub struct Context { /// Flag: do we want a disassembly with the CompiledCode? pub want_disasm: bool, + + /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct + /// and compiled away. See [cranelift_chaos]. + chaos_eng: ChaosEngine, } impl Context { @@ -63,15 +68,15 @@ impl Context { /// /// The returned instance should be reused for compiling multiple functions in order to avoid /// needless allocator thrashing. - pub fn new() -> Self { - Self::for_function(Function::new()) + pub fn new(chaos_eng: ChaosEngine) -> Self { + Self::for_function(Function::new(), chaos_eng) } /// Allocate a new compilation context with an existing Function. /// /// The returned instance should be reused for compiling multiple functions in order to avoid /// needless allocator thrashing. - pub fn for_function(func: Function) -> Self { + pub fn for_function(func: Function, chaos_eng: ChaosEngine) -> Self { Self { func, cfg: ControlFlowGraph::new(), @@ -79,6 +84,7 @@ impl Context { loop_analysis: LoopAnalysis::new(), compiled_code: None, want_disasm: false, + chaos_eng, } } diff --git a/cranelift/codegen/src/isa/aarch64/mod.rs b/cranelift/codegen/src/isa/aarch64/mod.rs index 65c628b430f1..e414395dc14b 100644 --- a/cranelift/codegen/src/isa/aarch64/mod.rs +++ b/cranelift/codegen/src/isa/aarch64/mod.rs @@ -15,6 +15,7 @@ use crate::result::CodegenResult; use crate::settings as shared_settings; use alloc::{boxed::Box, vec::Vec}; use core::fmt; +use cranelift_chaos::ChaosEngine; use regalloc2::MachineEnv; use target_lexicon::{Aarch64Architecture, Architecture, OperatingSystem, Triple}; @@ -34,6 +35,9 @@ pub struct AArch64Backend { flags: shared_settings::Flags, isa_flags: aarch64_settings::Flags, machine_env: MachineEnv, + /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct + /// and compiled away. See [cranelift_chaos]. + chaos_eng: ChaosEngine, } impl AArch64Backend { @@ -42,6 +46,7 @@ impl AArch64Backend { triple: Triple, flags: shared_settings::Flags, isa_flags: aarch64_settings::Flags, + chaos_eng: ChaosEngine, ) -> AArch64Backend { let machine_env = create_reg_env(&flags); AArch64Backend { @@ -49,6 +54,7 @@ impl AArch64Backend { flags, isa_flags, machine_env, + chaos_eng, } } @@ -62,7 +68,15 @@ impl AArch64Backend { let emit_info = EmitInfo::new(self.flags.clone()); let sigs = SigSet::new::(func, &self.flags)?; let abi = abi::AArch64Callee::new(func, self, &self.isa_flags, &sigs)?; - compile::compile::(func, domtree, self, abi, emit_info, sigs) + compile::compile::( + func, + domtree, + self, + abi, + emit_info, + sigs, + self.chaos_eng.clone(), + ) } } @@ -231,14 +245,16 @@ impl fmt::Display for AArch64Backend { } /// Create a new `isa::Builder`. -pub fn isa_builder(triple: Triple) -> IsaBuilder { +pub fn isa_builder(triple: Triple, chaos_eng: ChaosEngine) -> IsaBuilder { assert!(triple.architecture == Architecture::Aarch64(Aarch64Architecture::Aarch64)); IsaBuilder { triple, + chaos_eng, setup: aarch64_settings::builder(), - constructor: |triple, shared_flags, builder| { + constructor: |triple, shared_flags, builder, chaos_eng| { let isa_flags = aarch64_settings::Flags::new(&shared_flags, builder); - let backend = AArch64Backend::new_with_flags(triple, shared_flags, isa_flags); + let backend = + AArch64Backend::new_with_flags(triple, shared_flags, isa_flags, chaos_eng); Ok(backend.wrapped()) }, } diff --git a/cranelift/codegen/src/isa/mod.rs b/cranelift/codegen/src/isa/mod.rs index 3baf230f7a6a..f8d9bcbb931c 100644 --- a/cranelift/codegen/src/isa/mod.rs +++ b/cranelift/codegen/src/isa/mod.rs @@ -57,6 +57,7 @@ use crate::CodegenResult; use alloc::{boxed::Box, sync::Arc, vec::Vec}; use core::fmt; use core::fmt::{Debug, Formatter}; +use cranelift_chaos::ChaosEngine; use target_lexicon::{triple, Architecture, PointerWidth, Triple}; // This module is made public here for benchmarking purposes. No guarantees are @@ -80,10 +81,10 @@ mod call_conv; /// Returns a builder that can create a corresponding `TargetIsa` /// or `Err(LookupError::SupportDisabled)` if not enabled. macro_rules! isa_builder { - ($name: ident, $cfg_terms: tt, $triple: ident) => {{ + ($name: ident, $cfg_terms: tt, $triple: ident, $chaos_eng: ident) => {{ #[cfg $cfg_terms] { - Ok($name::isa_builder($triple)) + Ok($name::isa_builder($triple, $chaos_eng)) } #[cfg(not $cfg_terms)] { @@ -94,14 +95,18 @@ macro_rules! isa_builder { /// Look for an ISA for the given `triple`. /// Return a builder that can create a corresponding `TargetIsa`. -pub fn lookup(triple: Triple) -> Result { +pub fn lookup(triple: Triple, chaos_eng: ChaosEngine) -> Result { match triple.architecture { Architecture::X86_64 => { - isa_builder!(x64, (feature = "x86"), triple) + isa_builder!(x64, (feature = "x86"), triple, chaos_eng) + } + Architecture::Aarch64 { .. } => { + isa_builder!(aarch64, (feature = "arm64"), triple, chaos_eng) + } + Architecture::S390x { .. } => isa_builder!(s390x, (feature = "s390x"), triple, chaos_eng), + Architecture::Riscv64 { .. } => { + isa_builder!(riscv64, (feature = "riscv64"), triple, chaos_eng) } - Architecture::Aarch64 { .. } => isa_builder!(aarch64, (feature = "arm64"), triple), - Architecture::S390x { .. } => isa_builder!(s390x, (feature = "s390x"), triple), - Architecture::Riscv64 { .. } => isa_builder!(riscv64, (feature = "riscv64"), triple), _ => Err(LookupError::Unsupported), } } @@ -113,9 +118,9 @@ pub const ALL_ARCHITECTURES: &[&str] = &["x86_64", "aarch64", "s390x", "riscv64" /// Look for a supported ISA with the given `name`. /// Return a builder that can create a corresponding `TargetIsa`. -pub fn lookup_by_name(name: &str) -> Result { +pub fn lookup_by_name(name: &str, chaos_eng: ChaosEngine) -> Result { use alloc::str::FromStr; - lookup(triple!(name)) + lookup(triple!(name), chaos_eng) } /// Describes reason for target lookup failure @@ -154,8 +159,11 @@ pub type Builder = IsaBuilder>; #[derive(Clone)] pub struct IsaBuilder { triple: Triple, + /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct + /// and compiled away. See [cranelift_chaos]. + chaos_eng: ChaosEngine, setup: settings::Builder, - constructor: fn(Triple, settings::Flags, &settings::Builder) -> T, + constructor: fn(Triple, settings::Flags, &settings::Builder, ChaosEngine) -> T, } impl IsaBuilder { @@ -164,11 +172,13 @@ impl IsaBuilder { /// function to generate the ISA from its components. pub fn new( triple: Triple, + chaos_eng: ChaosEngine, setup: settings::Builder, - constructor: fn(Triple, settings::Flags, &settings::Builder) -> T, + constructor: fn(Triple, settings::Flags, &settings::Builder, ChaosEngine) -> T, ) -> Self { IsaBuilder { triple, + chaos_eng, setup, constructor, } @@ -191,7 +201,12 @@ impl IsaBuilder { /// platform-independent features, like general SIMD support, may /// need certain ISA extensions to be enabled. pub fn finish(&self, shared_flags: settings::Flags) -> T { - (self.constructor)(self.triple.clone(), shared_flags, &self.setup) + (self.constructor)( + self.triple.clone(), + shared_flags, + &self.setup, + self.chaos_eng.clone(), + ) } } diff --git a/cranelift/codegen/src/isa/riscv64/mod.rs b/cranelift/codegen/src/isa/riscv64/mod.rs index 69711e0c8228..e5bd45584b68 100644 --- a/cranelift/codegen/src/isa/riscv64/mod.rs +++ b/cranelift/codegen/src/isa/riscv64/mod.rs @@ -15,6 +15,7 @@ use crate::result::CodegenResult; use crate::settings as shared_settings; use alloc::{boxed::Box, vec::Vec}; use core::fmt; +use cranelift_chaos::ChaosEngine; use regalloc2::MachineEnv; use target_lexicon::{Architecture, Triple}; mod abi; @@ -34,6 +35,9 @@ pub struct Riscv64Backend { flags: shared_settings::Flags, isa_flags: riscv_settings::Flags, mach_env: MachineEnv, + /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct + /// and compiled away. See [cranelift_chaos]. + chaos_eng: ChaosEngine, } impl Riscv64Backend { @@ -42,6 +46,7 @@ impl Riscv64Backend { triple: Triple, flags: shared_settings::Flags, isa_flags: riscv_settings::Flags, + chaos_eng: ChaosEngine, ) -> Riscv64Backend { let mach_env = crate_reg_eviroment(&flags); Riscv64Backend { @@ -49,6 +54,7 @@ impl Riscv64Backend { flags, isa_flags, mach_env, + chaos_eng, } } @@ -62,7 +68,15 @@ impl Riscv64Backend { let emit_info = EmitInfo::new(self.flags.clone(), self.isa_flags.clone()); let sigs = SigSet::new::(func, &self.flags)?; let abi = abi::Riscv64Callee::new(func, self, &self.isa_flags, &sigs)?; - compile::compile::(func, domtree, self, abi, emit_info, sigs) + compile::compile::( + func, + domtree, + self, + abi, + emit_info, + sigs, + self.chaos_eng.clone(), + ) } } @@ -203,17 +217,19 @@ impl fmt::Display for Riscv64Backend { } /// Create a new `isa::Builder`. -pub fn isa_builder(triple: Triple) -> IsaBuilder { +pub fn isa_builder(triple: Triple, chaos_eng: ChaosEngine) -> IsaBuilder { match triple.architecture { Architecture::Riscv64(..) => {} _ => unreachable!(), } IsaBuilder { triple, + chaos_eng, setup: riscv_settings::builder(), - constructor: |triple, shared_flags, builder| { + constructor: |triple, shared_flags, builder, chaos_eng| { let isa_flags = riscv_settings::Flags::new(&shared_flags, builder); - let backend = Riscv64Backend::new_with_flags(triple, shared_flags, isa_flags); + let backend = + Riscv64Backend::new_with_flags(triple, shared_flags, isa_flags, chaos_eng); Ok(backend.wrapped()) }, } diff --git a/cranelift/codegen/src/isa/s390x/mod.rs b/cranelift/codegen/src/isa/s390x/mod.rs index 9ba81d14ac39..fa4d0fb3e01d 100644 --- a/cranelift/codegen/src/isa/s390x/mod.rs +++ b/cranelift/codegen/src/isa/s390x/mod.rs @@ -15,6 +15,7 @@ use crate::result::CodegenResult; use crate::settings as shared_settings; use alloc::{boxed::Box, vec::Vec}; use core::fmt; +use cranelift_chaos::ChaosEngine; use regalloc2::MachineEnv; use target_lexicon::{Architecture, Triple}; @@ -34,6 +35,9 @@ pub struct S390xBackend { flags: shared_settings::Flags, isa_flags: s390x_settings::Flags, machine_env: MachineEnv, + /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct + /// and compiled away. See [cranelift_chaos]. + chaos_eng: ChaosEngine, } impl S390xBackend { @@ -42,6 +46,7 @@ impl S390xBackend { triple: Triple, flags: shared_settings::Flags, isa_flags: s390x_settings::Flags, + chaos_eng: ChaosEngine, ) -> S390xBackend { let machine_env = create_machine_env(&flags); S390xBackend { @@ -49,6 +54,7 @@ impl S390xBackend { flags, isa_flags, machine_env, + chaos_eng, } } @@ -62,7 +68,15 @@ impl S390xBackend { let emit_info = EmitInfo::new(self.isa_flags.clone()); let sigs = SigSet::new::(func, &self.flags)?; let abi = abi::S390xCallee::new(func, self, &self.isa_flags, &sigs)?; - compile::compile::(func, domtree, self, abi, emit_info, sigs) + compile::compile::( + func, + domtree, + self, + abi, + emit_info, + sigs, + self.chaos_eng.clone(), + ) } } @@ -203,14 +217,15 @@ impl fmt::Display for S390xBackend { } /// Create a new `isa::Builder`. -pub fn isa_builder(triple: Triple) -> IsaBuilder { +pub fn isa_builder(triple: Triple, chaos_eng: ChaosEngine) -> IsaBuilder { assert!(triple.architecture == Architecture::S390x); IsaBuilder { triple, + chaos_eng, setup: s390x_settings::builder(), - constructor: |triple, shared_flags, builder| { + constructor: |triple, shared_flags, builder, chaos_eng| { let isa_flags = s390x_settings::Flags::new(&shared_flags, builder); - let backend = S390xBackend::new_with_flags(triple, shared_flags, isa_flags); + let backend = S390xBackend::new_with_flags(triple, shared_flags, isa_flags, chaos_eng); Ok(backend.wrapped()) }, } diff --git a/cranelift/codegen/src/isa/x64/mod.rs b/cranelift/codegen/src/isa/x64/mod.rs index dd84f4395a43..7935b5db7252 100644 --- a/cranelift/codegen/src/isa/x64/mod.rs +++ b/cranelift/codegen/src/isa/x64/mod.rs @@ -17,6 +17,7 @@ use crate::result::{CodegenError, CodegenResult}; use crate::settings::{self as shared_settings, Flags}; use alloc::{boxed::Box, vec::Vec}; use core::fmt; +use cranelift_chaos::ChaosEngine; use regalloc2::MachineEnv; use target_lexicon::Triple; @@ -32,17 +33,26 @@ pub(crate) struct X64Backend { flags: Flags, x64_flags: x64_settings::Flags, reg_env: MachineEnv, + /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct + /// and compiled away. See [cranelift_chaos]. + chaos_eng: ChaosEngine, } impl X64Backend { /// Create a new X64 backend with the given (shared) flags. - fn new_with_flags(triple: Triple, flags: Flags, x64_flags: x64_settings::Flags) -> Self { + fn new_with_flags( + triple: Triple, + flags: Flags, + x64_flags: x64_settings::Flags, + chaos_eng: ChaosEngine, + ) -> Self { let reg_env = create_reg_env_systemv(&flags); Self { triple, flags, x64_flags, reg_env, + chaos_eng, } } @@ -56,7 +66,15 @@ impl X64Backend { let emit_info = EmitInfo::new(self.flags.clone(), self.x64_flags.clone()); let sigs = SigSet::new::(func, &self.flags)?; let abi = abi::X64Callee::new(func, self, &self.x64_flags, &sigs)?; - compile::compile::(func, domtree, self, abi, emit_info, sigs) + compile::compile::( + func, + domtree, + self, + abi, + emit_info, + sigs, + self.chaos_eng.clone(), + ) } } @@ -201,9 +219,10 @@ impl fmt::Display for X64Backend { } /// Create a new `isa::Builder`. -pub(crate) fn isa_builder(triple: Triple) -> IsaBuilder { +pub(crate) fn isa_builder(triple: Triple, chaos_eng: ChaosEngine) -> IsaBuilder { IsaBuilder { triple, + chaos_eng, setup: x64_settings::builder(), constructor: isa_constructor, } @@ -213,6 +232,7 @@ fn isa_constructor( triple: Triple, shared_flags: Flags, builder: &shared_settings::Builder, + chaos_eng: ChaosEngine, ) -> CodegenResult { let isa_flags = x64_settings::Flags::new(&shared_flags, builder); @@ -230,7 +250,7 @@ fn isa_constructor( } } - let backend = X64Backend::new_with_flags(triple, shared_flags, isa_flags); + let backend = X64Backend::new_with_flags(triple, shared_flags, isa_flags, chaos_eng); Ok(backend.wrapped()) } @@ -246,7 +266,7 @@ mod test { let mut shared_flags_builder = settings::builder(); shared_flags_builder.set("enable_simd", "true").unwrap(); let shared_flags = settings::Flags::new(shared_flags_builder); - let mut isa_builder = crate::isa::lookup_by_name("x86_64").unwrap(); + let mut isa_builder = crate::isa::lookup_by_name("x86_64", ChaosEngine::noop()).unwrap(); isa_builder.set("has_sse3", "false").unwrap(); isa_builder.set("has_ssse3", "false").unwrap(); isa_builder.set("has_sse41", "false").unwrap(); diff --git a/cranelift/codegen/src/machinst/buffer.rs b/cranelift/codegen/src/machinst/buffer.rs index 895f5e5ffdda..b416430982e3 100644 --- a/cranelift/codegen/src/machinst/buffer.rs +++ b/cranelift/codegen/src/machinst/buffer.rs @@ -148,6 +148,7 @@ use crate::machinst::{ }; use crate::timing; use crate::trace; +use cranelift_chaos::ChaosEngine; use cranelift_entity::{entity_impl, SecondaryMap}; use smallvec::SmallVec; use std::convert::TryFrom; @@ -263,6 +264,9 @@ pub struct MachBuffer { labels_at_tail_off: CodeOffset, /// Map used constants to their [MachLabel]. constant_labels: SecondaryMap, + /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct + /// and compiled away. See [cranelift_chaos]. + chaos_eng: ChaosEngine, } impl MachBufferFinalized { @@ -360,7 +364,7 @@ pub enum StackMapExtent { impl MachBuffer { /// Create a new section, known to start at `start_offset` and with a size limited to /// `length_limit`. - pub fn new() -> MachBuffer { + pub fn new(chaos_eng: ChaosEngine) -> MachBuffer { MachBuffer { data: SmallVec::new(), relocs: SmallVec::new(), @@ -381,6 +385,7 @@ impl MachBuffer { labels_at_tail: SmallVec::new(), labels_at_tail_off: 0, constant_labels: SecondaryMap::new(), + chaos_eng, } } @@ -774,6 +779,11 @@ impl MachBuffer { } fn optimize_branches(&mut self) { + #[cfg(feature = "chaos")] + if let Ok(true) = self.chaos_eng.get_arbitrary() { + return; + } + self.lazily_clear_labels_at_tail(); // Invariants valid at this point. @@ -1702,7 +1712,7 @@ impl MachTextSectionBuilder { /// Creates a new text section builder which will have `num_funcs` functions /// pushed into it. pub fn new(num_funcs: usize) -> MachTextSectionBuilder { - let mut buf = MachBuffer::new(); + let mut buf = MachBuffer::new(ChaosEngine::noop()); buf.reserve_labels_for_blocks(num_funcs); MachTextSectionBuilder { buf, @@ -1785,7 +1795,7 @@ mod test { #[test] fn test_elide_jump_to_next() { let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(); + let mut buf = MachBuffer::new(ChaosEngine::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(2); @@ -1800,7 +1810,7 @@ mod test { #[test] fn test_elide_trivial_jump_blocks() { let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(); + let mut buf = MachBuffer::new(ChaosEngine::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(4); @@ -1830,7 +1840,7 @@ mod test { #[test] fn test_flip_cond() { let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(); + let mut buf = MachBuffer::new(ChaosEngine::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(4); @@ -1857,7 +1867,7 @@ mod test { let buf = buf.finish(); - let mut buf2 = MachBuffer::new(); + let mut buf2 = MachBuffer::new(ChaosEngine::noop()); let mut state = Default::default(); let inst = Inst::TrapIf { kind: CondBrKind::NotZero(xreg(0)), @@ -1875,7 +1885,7 @@ mod test { #[test] fn test_island() { let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(); + let mut buf = MachBuffer::new(ChaosEngine::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(4); @@ -1909,7 +1919,7 @@ mod test { assert_eq!(2000000 + 8, buf.total_size()); - let mut buf2 = MachBuffer::new(); + let mut buf2 = MachBuffer::new(ChaosEngine::noop()); let mut state = Default::default(); let inst = Inst::CondBr { kind: CondBrKind::NotZero(xreg(0)), @@ -1942,7 +1952,7 @@ mod test { #[test] fn test_island_backward() { let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(); + let mut buf = MachBuffer::new(ChaosEngine::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(4); @@ -1973,7 +1983,7 @@ mod test { assert_eq!(2000000 + 12, buf.total_size()); - let mut buf2 = MachBuffer::new(); + let mut buf2 = MachBuffer::new(ChaosEngine::noop()); let mut state = Default::default(); let inst = Inst::CondBr { kind: CondBrKind::NotZero(xreg(0)), @@ -2027,7 +2037,7 @@ mod test { // ret let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(); + let mut buf = MachBuffer::new(ChaosEngine::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(8); @@ -2103,7 +2113,7 @@ mod test { // label0, label1, ..., label4: // b label0 let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(); + let mut buf = MachBuffer::new(ChaosEngine::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(5); @@ -2139,7 +2149,7 @@ mod test { #[test] fn metadata_records() { - let mut buf = MachBuffer::::new(); + let mut buf = MachBuffer::::new(ChaosEngine::noop()); buf.reserve_labels_for_blocks(1); diff --git a/cranelift/codegen/src/machinst/compile.rs b/cranelift/codegen/src/machinst/compile.rs index 254b4ec55750..ed62580bfad9 100644 --- a/cranelift/codegen/src/machinst/compile.rs +++ b/cranelift/codegen/src/machinst/compile.rs @@ -7,6 +7,7 @@ use crate::machinst::*; use crate::timing; use crate::trace; +use cranelift_chaos::ChaosEngine; use regalloc2::RegallocOptions; /// Compile the given function down to VCode with allocated registers, ready @@ -18,6 +19,7 @@ pub fn compile( abi: Callee<<::MInst as MachInst>::ABIMachineSpec>, emit_info: ::Info, sigs: SigSet, + chaos_eng: ChaosEngine, ) -> CodegenResult<(VCode, regalloc2::Output)> { let machine_env = b.machine_env(); @@ -25,7 +27,8 @@ pub fn compile( let block_order = BlockLoweringOrder::new(f, domtree); // Build the lowering context. - let lower = crate::machinst::Lower::new(f, machine_env, abi, emit_info, block_order, sigs)?; + let lower = + crate::machinst::Lower::new(f, machine_env, abi, emit_info, block_order, sigs, chaos_eng)?; // Lower the IR. let vcode = { diff --git a/cranelift/codegen/src/machinst/lower.rs b/cranelift/codegen/src/machinst/lower.rs index d6688c054d29..39340d5a34e0 100644 --- a/cranelift/codegen/src/machinst/lower.rs +++ b/cranelift/codegen/src/machinst/lower.rs @@ -20,6 +20,7 @@ use crate::machinst::{ }; use crate::{trace, CodegenResult}; use alloc::vec::Vec; +use cranelift_chaos::ChaosEngine; use regalloc2::{MachineEnv, PRegSet}; use smallvec::{smallvec, SmallVec}; use std::fmt::Debug; @@ -333,6 +334,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { emit_info: I::Info, block_order: BlockLoweringOrder, sigs: SigSet, + chaos_eng: ChaosEngine, ) -> CodegenResult { let constants = VCodeConstants::with_capacity(f.dfg.constants.len()); let vcode = VCodeBuilder::new( @@ -342,6 +344,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { block_order, constants, VCodeBuildDirection::Backward, + chaos_eng, ); let mut vregs = VRegAllocator::new(); diff --git a/cranelift/codegen/src/machinst/vcode.rs b/cranelift/codegen/src/machinst/vcode.rs index 81aaf54862e9..137d62be370c 100644 --- a/cranelift/codegen/src/machinst/vcode.rs +++ b/cranelift/codegen/src/machinst/vcode.rs @@ -26,6 +26,7 @@ use crate::timing; use crate::trace; use crate::CodegenError; use crate::ValueLocRange; +use cranelift_chaos::ChaosEngine; use regalloc2::{ Edit, Function as RegallocFunction, InstOrEdit, InstRange, Operand, OperandKind, PRegSet, RegClass, VReg, @@ -174,6 +175,10 @@ pub struct VCode { debug_value_labels: Vec<(VReg, InsnIndex, InsnIndex, u32)>, pub(crate) sigs: SigSet, + + /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct + /// and compiled away. See [cranelift_chaos]. + chaos_eng: ChaosEngine, } /// The result of `VCode::emit`. Contains all information computed @@ -284,8 +289,9 @@ impl VCodeBuilder { block_order: BlockLoweringOrder, constants: VCodeConstants, direction: VCodeBuildDirection, + chaos_eng: ChaosEngine, ) -> VCodeBuilder { - let vcode = VCode::new(sigs, abi, emit_info, block_order, constants); + let vcode = VCode::new(sigs, abi, emit_info, block_order, constants, chaos_eng); VCodeBuilder { vcode, @@ -642,6 +648,7 @@ impl VCode { emit_info: I::Info, block_order: BlockLoweringOrder, constants: VCodeConstants, + chaos_eng: ChaosEngine, ) -> VCode { let n_blocks = block_order.lowered_order().len(); VCode { @@ -670,6 +677,7 @@ impl VCode { constants, debug_value_labels: vec![], vreg_aliases: FxHashMap::with_capacity_and_hasher(10 * n_blocks, Default::default()), + chaos_eng, } } @@ -771,7 +779,7 @@ impl VCode { use core::fmt::Write; let _tt = timing::vcode_emit(); - let mut buffer = MachBuffer::new(); + let mut buffer = MachBuffer::new(self.chaos_eng.clone()); let mut bb_starts: Vec> = vec![]; // The first M MachLabels are reserved for block indices, the next N MachLabels for diff --git a/cranelift/filetests/Cargo.toml b/cranelift/filetests/Cargo.toml index 7ed94698ce0c..cc4073bf0007 100644 --- a/cranelift/filetests/Cargo.toml +++ b/cranelift/filetests/Cargo.toml @@ -17,6 +17,7 @@ cranelift-native = { workspace = true } cranelift-reader = { workspace = true } cranelift-jit = { workspace = true, features = ["selinux-fix"] } cranelift-module = { workspace = true } +cranelift-chaos = { workspace = true } file-per-thread-logger = "0.1.2" filecheck = "0.5.0" gimli = { workspace = true } diff --git a/cranelift/filetests/src/function_runner.rs b/cranelift/filetests/src/function_runner.rs index 1bc159451887..ba3691cae6bb 100644 --- a/cranelift/filetests/src/function_runner.rs +++ b/cranelift/filetests/src/function_runner.rs @@ -1,6 +1,7 @@ //! Provides functionality for compiling and running CLIF IR for `run` tests. use anyhow::{anyhow, Result}; use core::mem; +use cranelift_chaos::ChaosEngine; use cranelift_codegen::data_value::DataValue; use cranelift_codegen::ir::{ ExternalName, Function, InstBuilder, Signature, UserExternalName, UserFuncName, @@ -101,8 +102,8 @@ impl TestFileCompiler { /// Build a [TestFileCompiler] using the host machine's ISA and the passed flags. pub fn with_host_isa(flags: settings::Flags) -> Result { - let builder = - builder_with_options(true).expect("Unable to build a TargetIsa for the current host"); + let builder = builder_with_options(true, ChaosEngine::noop()) + .expect("Unable to build a TargetIsa for the current host"); let isa = builder.finish(flags)?; Ok(Self::new(isa)) } diff --git a/cranelift/filetests/src/test_alias_analysis.rs b/cranelift/filetests/src/test_alias_analysis.rs index 8d155811ba1c..f5491555d0ca 100644 --- a/cranelift/filetests/src/test_alias_analysis.rs +++ b/cranelift/filetests/src/test_alias_analysis.rs @@ -7,6 +7,7 @@ //! The resulting function is sent to `filecheck`. use crate::subtest::{run_filecheck, Context, SubTest}; +use cranelift_chaos::ChaosEngine; use cranelift_codegen; use cranelift_codegen::ir::Function; use cranelift_reader::TestCommand; @@ -32,7 +33,8 @@ impl SubTest for TestAliasAnalysis { } fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { - let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned()); + let mut comp_ctx = + cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); comp_ctx.flowgraph(); comp_ctx diff --git a/cranelift/filetests/src/test_compile.rs b/cranelift/filetests/src/test_compile.rs index 93421908619e..047219bbd09c 100644 --- a/cranelift/filetests/src/test_compile.rs +++ b/cranelift/filetests/src/test_compile.rs @@ -4,6 +4,7 @@ use crate::subtest::{check_precise_output, run_filecheck, Context, SubTest}; use anyhow::Result; +use cranelift_chaos::ChaosEngine; use cranelift_codegen::ir; use cranelift_reader::{TestCommand, TestOption}; use log::info; @@ -47,7 +48,8 @@ impl SubTest for TestCompile { fn run(&self, func: Cow, context: &Context) -> Result<()> { let isa = context.isa.expect("compile needs an ISA"); let params = func.params.clone(); - let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned()); + let mut comp_ctx = + cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); // With `MachBackend`s, we need to explicitly request dissassembly results. comp_ctx.set_disasm(true); diff --git a/cranelift/filetests/src/test_dce.rs b/cranelift/filetests/src/test_dce.rs index 48d28c7e72bb..3b0cb4e59cb3 100644 --- a/cranelift/filetests/src/test_dce.rs +++ b/cranelift/filetests/src/test_dce.rs @@ -6,6 +6,7 @@ //! The resulting function is sent to `filecheck`. use crate::subtest::{run_filecheck, Context, SubTest}; +use cranelift_chaos::ChaosEngine; use cranelift_codegen; use cranelift_codegen::ir::Function; use cranelift_reader::TestCommand; @@ -31,7 +32,8 @@ impl SubTest for TestDCE { } fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { - let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned()); + let mut comp_ctx = + cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); comp_ctx.flowgraph(); comp_ctx.compute_loop_analysis(); diff --git a/cranelift/filetests/src/test_legalizer.rs b/cranelift/filetests/src/test_legalizer.rs index 8af819bed234..ec92071b29e6 100644 --- a/cranelift/filetests/src/test_legalizer.rs +++ b/cranelift/filetests/src/test_legalizer.rs @@ -4,6 +4,7 @@ //! the result to filecheck. use crate::subtest::{run_filecheck, Context, SubTest}; +use cranelift_chaos::ChaosEngine; use cranelift_codegen; use cranelift_codegen::ir::Function; use cranelift_reader::TestCommand; @@ -33,7 +34,8 @@ impl SubTest for TestLegalizer { } fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { - let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned()); + let mut comp_ctx = + cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); let isa = context.isa.expect("legalizer needs an ISA"); comp_ctx.compute_cfg(); diff --git a/cranelift/filetests/src/test_licm.rs b/cranelift/filetests/src/test_licm.rs index b02bac1e74c6..a1b784a3a231 100644 --- a/cranelift/filetests/src/test_licm.rs +++ b/cranelift/filetests/src/test_licm.rs @@ -6,6 +6,7 @@ //! The resulting function is sent to `filecheck`. use crate::subtest::{run_filecheck, Context, SubTest}; +use cranelift_chaos::ChaosEngine; use cranelift_codegen; use cranelift_codegen::ir::Function; use cranelift_reader::TestCommand; @@ -36,7 +37,8 @@ impl SubTest for TestLICM { fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { let isa = context.isa.expect("LICM needs an ISA"); - let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned()); + let mut comp_ctx = + cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); comp_ctx.flowgraph(); comp_ctx.compute_loop_analysis(); diff --git a/cranelift/filetests/src/test_optimize.rs b/cranelift/filetests/src/test_optimize.rs index fd76a8fe041f..703c9c686366 100644 --- a/cranelift/filetests/src/test_optimize.rs +++ b/cranelift/filetests/src/test_optimize.rs @@ -9,6 +9,7 @@ use crate::subtest::{check_precise_output, run_filecheck, Context, SubTest}; use anyhow::Result; +use cranelift_chaos::ChaosEngine; use cranelift_codegen::ir; use cranelift_reader::{TestCommand, TestOption}; use std::borrow::Cow; @@ -50,7 +51,8 @@ impl SubTest for TestOptimize { fn run(&self, func: Cow, context: &Context) -> Result<()> { let isa = context.isa.expect("optimize needs an ISA"); - let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned()); + let mut comp_ctx = + cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); comp_ctx .optimize(isa) diff --git a/cranelift/filetests/src/test_run.rs b/cranelift/filetests/src/test_run.rs index 8b80ae99efcf..c47d1483c5c5 100644 --- a/cranelift/filetests/src/test_run.rs +++ b/cranelift/filetests/src/test_run.rs @@ -6,6 +6,7 @@ use crate::function_runner::{CompiledTestFile, TestFileCompiler}; use crate::runone::FileUpdate; use crate::subtest::{Context, SubTest}; use anyhow::Context as _; +use cranelift_chaos::ChaosEngine; use cranelift_codegen::data_value::DataValue; use cranelift_codegen::ir::Type; use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa}; @@ -35,8 +36,9 @@ fn build_host_isa( flags: settings::Flags, isa_flags: Vec, ) -> OwnedTargetIsa { - let mut builder = cranelift_native::builder_with_options(infer_native_flags) - .expect("Unable to build a TargetIsa for the current host"); + let mut builder = + cranelift_native::builder_with_options(infer_native_flags, ChaosEngine::noop()) + .expect("Unable to build a TargetIsa for the current host"); // Copy ISA Flags for value in isa_flags { diff --git a/cranelift/filetests/src/test_safepoint.rs b/cranelift/filetests/src/test_safepoint.rs index 49676e01be20..ff2702d50e93 100644 --- a/cranelift/filetests/src/test_safepoint.rs +++ b/cranelift/filetests/src/test_safepoint.rs @@ -1,4 +1,5 @@ use crate::subtest::{run_filecheck, Context, SubTest}; +use cranelift_chaos::ChaosEngine; use cranelift_codegen::ir::Function; use cranelift_reader::TestCommand; use std::borrow::Cow; @@ -19,7 +20,8 @@ impl SubTest for TestSafepoint { } fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { - let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned()); + let mut comp_ctx = + cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); let isa = context.isa.expect("register allocator needs an ISA"); comp_ctx.compute_cfg(); diff --git a/cranelift/filetests/src/test_simple_gvn.rs b/cranelift/filetests/src/test_simple_gvn.rs index bb563f4315cb..6921ebf20494 100644 --- a/cranelift/filetests/src/test_simple_gvn.rs +++ b/cranelift/filetests/src/test_simple_gvn.rs @@ -6,6 +6,7 @@ //! The resulting function is sent to `filecheck`. use crate::subtest::{run_filecheck, Context, SubTest}; +use cranelift_chaos::ChaosEngine; use cranelift_codegen; use cranelift_codegen::ir::Function; use cranelift_reader::TestCommand; @@ -31,7 +32,8 @@ impl SubTest for TestSimpleGVN { } fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { - let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned()); + let mut comp_ctx = + cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); comp_ctx.flowgraph(); comp_ctx diff --git a/cranelift/filetests/src/test_simple_preopt.rs b/cranelift/filetests/src/test_simple_preopt.rs index 9a591ef023f0..48327b612e67 100644 --- a/cranelift/filetests/src/test_simple_preopt.rs +++ b/cranelift/filetests/src/test_simple_preopt.rs @@ -3,6 +3,7 @@ //! The resulting function is sent to `filecheck`. use crate::subtest::{run_filecheck, Context, SubTest}; +use cranelift_chaos::ChaosEngine; use cranelift_codegen; use cranelift_codegen::ir::Function; use cranelift_reader::TestCommand; @@ -32,7 +33,8 @@ impl SubTest for TestSimplePreopt { } fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { - let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned()); + let mut comp_ctx = + cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); let isa = context.isa.expect("preopt needs an ISA"); comp_ctx.compute_cfg(); diff --git a/cranelift/filetests/src/test_unwind.rs b/cranelift/filetests/src/test_unwind.rs index 5174b91da0b9..f54637f20253 100644 --- a/cranelift/filetests/src/test_unwind.rs +++ b/cranelift/filetests/src/test_unwind.rs @@ -4,6 +4,7 @@ #![cfg_attr(feature = "cargo-clippy", allow(clippy::cast_ptr_alignment))] use crate::subtest::{run_filecheck, Context, SubTest}; +use cranelift_chaos::ChaosEngine; use cranelift_codegen::{self, ir, isa::unwind::UnwindInfo}; use cranelift_reader::TestCommand; use gimli::{ @@ -37,7 +38,8 @@ impl SubTest for TestUnwind { fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { let isa = context.isa.expect("unwind needs an ISA"); - let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned()); + let mut comp_ctx = + cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); let code = comp_ctx.compile(isa).expect("failed to compile function"); diff --git a/cranelift/filetests/src/test_wasm.rs b/cranelift/filetests/src/test_wasm.rs index 0ecba3510a59..216fe7f3cf98 100644 --- a/cranelift/filetests/src/test_wasm.rs +++ b/cranelift/filetests/src/test_wasm.rs @@ -5,6 +5,7 @@ mod env; use anyhow::{bail, ensure, Context, Result}; use config::TestConfig; +use cranelift_chaos::ChaosEngine; use env::ModuleEnv; use similar::TextDiff; use std::{fmt::Write, path::Path}; @@ -55,7 +56,8 @@ pub fn run(path: &Path, wat: &str) -> Result<()> { let mut actual = String::new(); for (_index, func) in env.inner.info.function_bodies.iter() { if config.compile { - let mut ctx = cranelift_codegen::Context::for_function(func.clone()); + let mut ctx = + cranelift_codegen::Context::for_function(func.clone(), ChaosEngine::noop()); ctx.set_disasm(true); let code = ctx .compile(isa) @@ -63,7 +65,8 @@ pub fn run(path: &Path, wat: &str) -> Result<()> { writeln!(&mut actual, "function {}:", func.name).unwrap(); writeln!(&mut actual, "{}", code.vcode.as_ref().unwrap()).unwrap(); } else if config.optimize { - let mut ctx = cranelift_codegen::Context::for_function(func.clone()); + let mut ctx = + cranelift_codegen::Context::for_function(func.clone(), ChaosEngine::noop()); ctx.optimize(isa) .map_err(|e| crate::pretty_anyhow_error(&ctx.func, e))?; writeln!(&mut actual, "{}", ctx.func.display()).unwrap(); diff --git a/cranelift/fuzzgen/Cargo.toml b/cranelift/fuzzgen/Cargo.toml index 014d0f076a8b..3831f4db7993 100644 --- a/cranelift/fuzzgen/Cargo.toml +++ b/cranelift/fuzzgen/Cargo.toml @@ -13,8 +13,12 @@ publish = false [dependencies] cranelift = { workspace = true } cranelift-native = { workspace = true } +cranelift-chaos = { workspace = true } anyhow = { workspace = true } arbitrary = "1.0.0" once_cell = { workspace = true } target-lexicon = { workspace = true, features = ["std"] } + +[features] +chaos = ["cranelift-chaos/chaos"] diff --git a/cranelift/fuzzgen/src/lib.rs b/cranelift/fuzzgen/src/lib.rs index e8e649314611..4c3859d9ebf3 100644 --- a/cranelift/fuzzgen/src/lib.rs +++ b/cranelift/fuzzgen/src/lib.rs @@ -11,6 +11,7 @@ use cranelift::codegen::Context; use cranelift::prelude::settings::SettingKind; use cranelift::prelude::*; use cranelift_arbitrary::CraneliftArbitrary; +use cranelift_chaos::ChaosEngine; use cranelift_native::builder_with_options; use target_lexicon::{Architecture, Triple}; @@ -39,17 +40,24 @@ where { pub u: &'r mut Unstructured<'data>, pub config: Config, + pub chaos_eng: ChaosEngine, } impl<'r, 'data> FuzzGen<'r, 'data> where 'data: 'r, { - pub fn new(u: &'r mut Unstructured<'data>) -> Self { - Self { + pub fn new(u: &'r mut Unstructured<'data>) -> anyhow::Result { + #[cfg(feature = "chaos")] + let chaos_eng = u.arbitrary()?; + #[cfg(not(feature = "chaos"))] + let chaos_eng = cranelift_chaos::ChaosEngine::noop(); + + Ok(Self { u, config: Config::default(), - } + chaos_eng, + }) } pub fn generate_signature(&mut self, architecture: Architecture) -> Result { @@ -106,7 +114,7 @@ where // This is something that we can enable via flags for the compiled version, however // the interpreter won't get that version, so call that pass manually here. - let mut ctx = Context::for_function(func); + let mut ctx = Context::for_function(func, self.chaos_eng.clone()); // Assume that we are generating this function for the current ISA. // We disable the verifier here, since if it fails it prevents a test case from // being generated and formatted by `cargo fuzz fmt`. @@ -117,7 +125,7 @@ where builder }); - let isa = builder_with_options(false) + let isa = builder_with_options(false, self.chaos_eng.clone()) .expect("Unable to build a TargetIsa for the current host") .finish(flags) .expect("Failed to build TargetISA"); diff --git a/cranelift/jit/Cargo.toml b/cranelift/jit/Cargo.toml index ec4154a93523..7b83bc565b36 100644 --- a/cranelift/jit/Cargo.toml +++ b/cranelift/jit/Cargo.toml @@ -14,6 +14,7 @@ cranelift-module = { workspace = true } cranelift-native = { workspace = true } cranelift-codegen = { workspace = true, features = ["std"] } cranelift-entity = { workspace = true } +cranelift-chaos = { workspace = true } anyhow = { workspace = true } region = "2.2.0" libc = { version = "0.2.42" } diff --git a/cranelift/jit/src/backend.rs b/cranelift/jit/src/backend.rs index e3d00a1872ff..33182c36ff5d 100644 --- a/cranelift/jit/src/backend.rs +++ b/cranelift/jit/src/backend.rs @@ -1,6 +1,7 @@ //! Defines `JITModule`. use crate::{compiled_blob::CompiledBlob, memory::BranchProtection, memory::Memory}; +use cranelift_chaos::ChaosEngine; use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa}; use cranelift_codegen::settings::Configurable; use cranelift_codegen::{self, ir, settings, MachReloc}; @@ -920,7 +921,7 @@ impl Module for JITModule { } fn make_context(&self) -> cranelift_codegen::Context { - let mut ctx = cranelift_codegen::Context::new(); + let mut ctx = cranelift_codegen::Context::new(ChaosEngine::noop()); ctx.func.signature.call_conv = self.isa().default_call_conv(); ctx } diff --git a/cranelift/module/Cargo.toml b/cranelift/module/Cargo.toml index 1352ce4a916b..c58bc07b0b3c 100644 --- a/cranelift/module/Cargo.toml +++ b/cranelift/module/Cargo.toml @@ -12,6 +12,7 @@ edition.workspace = true [dependencies] cranelift-codegen = { workspace = true } +cranelift-chaos = { workspace = true } hashbrown = { workspace = true, optional = true } anyhow = { workspace = true } diff --git a/cranelift/module/src/module.rs b/cranelift/module/src/module.rs index d6fa93b834cb..40c1c997fb1f 100644 --- a/cranelift/module/src/module.rs +++ b/cranelift/module/src/module.rs @@ -8,6 +8,7 @@ use super::HashMap; use crate::data_context::DataContext; use core::fmt::Display; +use cranelift_chaos::ChaosEngine; use cranelift_codegen::binemit::{CodeOffset, Reloc}; use cranelift_codegen::entity::{entity_impl, PrimaryMap}; use cranelift_codegen::ir::Function; @@ -550,7 +551,7 @@ pub trait Module { /// This ensures that the `Context` is initialized with the default calling /// convention for the `TargetIsa`. fn make_context(&self) -> Context { - let mut ctx = Context::new(); + let mut ctx = Context::new(ChaosEngine::noop()); ctx.func.signature.call_conv = self.isa().default_call_conv(); ctx } diff --git a/cranelift/native/Cargo.toml b/cranelift/native/Cargo.toml index 15c515609832..f2031162832f 100644 --- a/cranelift/native/Cargo.toml +++ b/cranelift/native/Cargo.toml @@ -12,6 +12,7 @@ edition.workspace = true [dependencies] cranelift-codegen = { workspace = true } +cranelift-chaos = { workspace = true } target-lexicon = { workspace = true } [target.'cfg(any(target_arch = "s390x", target_arch = "riscv64"))'.dependencies] @@ -24,4 +25,3 @@ core = ["cranelift-codegen/core"] [badges] maintenance = { status = "experimental" } - diff --git a/cranelift/native/src/lib.rs b/cranelift/native/src/lib.rs index 993fb35e09e1..5f01f7d14dad 100644 --- a/cranelift/native/src/lib.rs +++ b/cranelift/native/src/lib.rs @@ -23,6 +23,7 @@ ) )] +use cranelift_chaos::ChaosEngine; use cranelift_codegen::isa; use cranelift_codegen::settings::Configurable; use target_lexicon::Triple; @@ -31,7 +32,7 @@ use target_lexicon::Triple; /// machine, or `Err(())` if the host machine is not supported /// in the current configuration. pub fn builder() -> Result { - builder_with_options(true) + builder_with_options(true, ChaosEngine::noop()) } /// Return an `isa` builder configured for the current host @@ -41,8 +42,11 @@ pub fn builder() -> Result { /// Selects the given backend variant specifically; this is /// useful when more than oen backend exists for a given target /// (e.g., on x86-64). -pub fn builder_with_options(infer_native_flags: bool) -> Result { - let mut isa_builder = isa::lookup(Triple::host()).map_err(|err| match err { +pub fn builder_with_options( + infer_native_flags: bool, + chaos_eng: ChaosEngine, +) -> Result { + let mut isa_builder = isa::lookup(Triple::host(), chaos_eng).map_err(|err| match err { isa::LookupError::SupportDisabled => "support for architecture disabled at compile time", isa::LookupError::Unsupported => "unsupported architecture", })?; diff --git a/cranelift/object/Cargo.toml b/cranelift/object/Cargo.toml index 0811fb682458..aa598830d7bb 100644 --- a/cranelift/object/Cargo.toml +++ b/cranelift/object/Cargo.toml @@ -12,6 +12,7 @@ edition.workspace = true [dependencies] cranelift-module = { workspace = true } cranelift-codegen = { workspace = true, features = ["std"] } +cranelift-chaos = { workspace = true } object = { workspace = true, features = ["write"] } target-lexicon = { workspace = true } anyhow = { workspace = true } diff --git a/cranelift/object/tests/basic.rs b/cranelift/object/tests/basic.rs index d918f55e343d..90f91e7780b5 100644 --- a/cranelift/object/tests/basic.rs +++ b/cranelift/object/tests/basic.rs @@ -1,3 +1,4 @@ +use cranelift_chaos::ChaosEngine; use cranelift_codegen::ir::*; use cranelift_codegen::isa::CallConv; use cranelift_codegen::settings; @@ -10,7 +11,9 @@ use cranelift_object::*; #[test] fn error_on_incompatible_sig_in_declare_function() { let flag_builder = settings::builder(); - let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap(); + let isa_builder = + cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ChaosEngine::noop()) + .unwrap(); let isa = isa_builder .finish(settings::Flags::new(flag_builder)) .unwrap(); @@ -42,7 +45,7 @@ fn define_simple_function(module: &mut ObjectModule) -> FuncId { .declare_function("abc", Linkage::Local, &sig) .unwrap(); - let mut ctx = Context::new(); + let mut ctx = Context::new(ChaosEngine::noop()); ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), sig); let mut func_ctx = FunctionBuilderContext::new(); { @@ -61,7 +64,9 @@ fn define_simple_function(module: &mut ObjectModule) -> FuncId { #[should_panic(expected = "Result::unwrap()` on an `Err` value: DuplicateDefinition(\"abc\")")] fn panic_on_define_after_finalize() { let flag_builder = settings::builder(); - let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap(); + let isa_builder = + cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ChaosEngine::noop()) + .unwrap(); let isa = isa_builder .finish(settings::Flags::new(flag_builder)) .unwrap(); @@ -147,7 +152,9 @@ fn switch_error() { #[test] fn libcall_function() { let flag_builder = settings::builder(); - let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap(); + let isa_builder = + cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ChaosEngine::noop()) + .unwrap(); let isa = isa_builder .finish(settings::Flags::new(flag_builder)) .unwrap(); @@ -164,7 +171,7 @@ fn libcall_function() { .declare_function("function", Linkage::Local, &sig) .unwrap(); - let mut ctx = Context::new(); + let mut ctx = Context::new(ChaosEngine::noop()); ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), sig); let mut func_ctx = FunctionBuilderContext::new(); { @@ -201,7 +208,9 @@ fn libcall_function() { #[should_panic(expected = "has a null byte, which is disallowed")] fn reject_nul_byte_symbol_for_func() { let flag_builder = settings::builder(); - let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap(); + let isa_builder = + cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ChaosEngine::noop()) + .unwrap(); let isa = isa_builder .finish(settings::Flags::new(flag_builder)) .unwrap(); @@ -223,7 +232,9 @@ fn reject_nul_byte_symbol_for_func() { #[should_panic(expected = "has a null byte, which is disallowed")] fn reject_nul_byte_symbol_for_data() { let flag_builder = settings::builder(); - let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap(); + let isa_builder = + cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ChaosEngine::noop()) + .unwrap(); let isa = isa_builder .finish(settings::Flags::new(flag_builder)) .unwrap(); diff --git a/cranelift/reader/Cargo.toml b/cranelift/reader/Cargo.toml index 4c8e7f6b0756..13c0f0f9a28a 100644 --- a/cranelift/reader/Cargo.toml +++ b/cranelift/reader/Cargo.toml @@ -12,6 +12,7 @@ edition.workspace = true [dependencies] anyhow.workspace = true cranelift-codegen = { workspace = true } +cranelift-chaos = { workspace = true } smallvec = { workspace = true } target-lexicon = { workspace = true } diff --git a/cranelift/reader/src/lib.rs b/cranelift/reader/src/lib.rs index a691970bca21..30cb8cf8e610 100644 --- a/cranelift/reader/src/lib.rs +++ b/cranelift/reader/src/lib.rs @@ -43,6 +43,7 @@ mod testcommand; mod testfile; use anyhow::{Error, Result}; +use cranelift_chaos::ChaosEngine; use cranelift_codegen::isa::{self, OwnedTargetIsa}; use cranelift_codegen::settings::{self, FlagsOrIsa}; use std::str::FromStr; @@ -95,15 +96,16 @@ pub fn parse_sets_and_triple(flag_set: &[String], flag_triple: &str) -> Result return Err(Error::from(parse_error)), }; - let mut isa_builder = isa::lookup(triple).map_err(|err| match err { - isa::LookupError::SupportDisabled => { - anyhow::anyhow!("support for triple '{}' is disabled", triple_name) - } - isa::LookupError::Unsupported => anyhow::anyhow!( - "support for triple '{}' is not implemented yet", - triple_name - ), - })?; + let mut isa_builder = + isa::lookup(triple, ChaosEngine::noop()).map_err(|err| match err { + isa::LookupError::SupportDisabled => { + anyhow::anyhow!("support for triple '{}' is disabled", triple_name) + } + isa::LookupError::Unsupported => anyhow::anyhow!( + "support for triple '{}' is not implemented yet", + triple_name + ), + })?; // Try to parse system-wide unknown settings as target-specific settings. parse_options( diff --git a/cranelift/reader/src/parser.rs b/cranelift/reader/src/parser.rs index 1e2be48243ce..2ca01d168ddf 100644 --- a/cranelift/reader/src/parser.rs +++ b/cranelift/reader/src/parser.rs @@ -7,6 +7,7 @@ use crate::run_command::{Comparison, Invocation, RunCommand}; use crate::sourcemap::SourceMap; use crate::testcommand::TestCommand; use crate::testfile::{Comment, Details, Feature, TestFile}; +use cranelift_chaos::ChaosEngine; use cranelift_codegen::data_value::DataValue; use cranelift_codegen::entity::{EntityRef, PrimaryMap}; use cranelift_codegen::ir::entities::{AnyEntity, DynamicType}; @@ -995,7 +996,7 @@ impl<'a> Parser<'a> { Ok(triple) => triple, Err(err) => return err!(loc, err), }; - let isa_builder = match isa::lookup(triple) { + let isa_builder = match isa::lookup(triple, ChaosEngine::noop()) { Err(isa::LookupError::SupportDisabled) => { return err!(loc, "support disabled target '{}'", targ); } @@ -1084,7 +1085,7 @@ impl<'a> Parser<'a> { Ok(triple) => triple, Err(err) => return err!(loc, err), }; - let mut isa_builder = match isa::lookup(triple) { + let mut isa_builder = match isa::lookup(triple, ChaosEngine::noop()) { Err(isa::LookupError::SupportDisabled) => { continue; } diff --git a/crates/cranelift/Cargo.toml b/crates/cranelift/Cargo.toml index 7c31add30a5a..9e11bc4c8c78 100644 --- a/crates/cranelift/Cargo.toml +++ b/crates/cranelift/Cargo.toml @@ -19,6 +19,7 @@ cranelift-codegen = { workspace = true } cranelift-frontend = { workspace = true } cranelift-entity = { workspace = true } cranelift-native = { workspace = true } +cranelift-chaos = { workspace = true } wasmtime-cranelift-shared = { workspace = true } wasmparser = { workspace = true } target-lexicon = { workspace = true } diff --git a/crates/cranelift/src/builder.rs b/crates/cranelift/src/builder.rs index 1e32eed6fed6..a4e62a09101c 100644 --- a/crates/cranelift/src/builder.rs +++ b/crates/cranelift/src/builder.rs @@ -4,6 +4,7 @@ //! well as providing a function to return the default configuration to build. use anyhow::Result; +use cranelift_chaos::ChaosEngine; use cranelift_codegen::{ isa::{self, OwnedTargetIsa}, CodegenResult, @@ -34,7 +35,9 @@ pub struct LinkOptions { pub fn builder() -> Box { Box::new(Builder { - inner: IsaBuilder::new(|triple| isa::lookup(triple).map_err(|e| e.into())), + inner: IsaBuilder::new(|triple| { + isa::lookup(triple, ChaosEngine::noop()).map_err(|e| e.into()) + }), linkopts: LinkOptions::default(), cache_store: None, }) diff --git a/crates/cranelift/src/compiler.rs b/crates/cranelift/src/compiler.rs index 5733a998edb3..39264ac4a06d 100644 --- a/crates/cranelift/src/compiler.rs +++ b/crates/cranelift/src/compiler.rs @@ -5,6 +5,7 @@ use crate::{ wasmtime_call_conv, CompiledFunction, FunctionAddressMap, }; use anyhow::{Context as _, Result}; +use cranelift_chaos::ChaosEngine; use cranelift_codegen::ir::{ self, ExternalName, Function, InstBuilder, MemFlags, UserExternalName, UserFuncName, Value, }; @@ -57,7 +58,7 @@ impl Default for CompilerContext { fn default() -> Self { Self { func_translator: FuncTranslator::new(), - codegen_context: Context::new(), + codegen_context: Context::new(ChaosEngine::noop()), incremental_cache_ctx: None, validator_allocations: Default::default(), } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index f9774cac38c4..5d8cbbb26ef0 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -17,6 +17,7 @@ cranelift-filetests = { workspace = true } cranelift-interpreter = { workspace = true } cranelift-fuzzgen = { workspace = true } cranelift-native = { workspace = true } +cranelift-chaos = { workspace = true } libfuzzer-sys = { version = "0.4.0", features = ["arbitrary-derive"] } target-lexicon = { workspace = true } smallvec = { workspace = true } @@ -36,6 +37,11 @@ component-fuzz-util = { workspace = true } [features] default = ['fuzz-spec-interpreter'] fuzz-spec-interpreter = ['wasmtime-fuzzing/fuzz-spec-interpreter'] +chaos = [ + "cranelift-chaos/chaos", + "cranelift-codegen/chaos", + "cranelift-fuzzgen/chaos", +] [[bin]] name = "compile" diff --git a/fuzz/fuzz_targets/cranelift-fuzzgen.rs b/fuzz/fuzz_targets/cranelift-fuzzgen.rs index addf4f71f418..64225445fd14 100644 --- a/fuzz/fuzz_targets/cranelift-fuzzgen.rs +++ b/fuzz/fuzz_targets/cranelift-fuzzgen.rs @@ -173,14 +173,14 @@ impl<'a> Arbitrary<'a> for TestCase { impl TestCase { pub fn generate(u: &mut Unstructured) -> anyhow::Result { - let mut gen = FuzzGen::new(u); + let mut gen = FuzzGen::new(u)?; let compare_against_host = gen.u.arbitrary()?; // TestCase is meant to be consumed by a runner, so we make the assumption here that we're // generating a TargetIsa for the host. - let mut builder = - builder_with_options(true).expect("Unable to build a TargetIsa for the current host"); + let mut builder = builder_with_options(true, gen.chaos_eng.clone()) + .expect("Unable to build a TargetIsa for the current host"); let flags = gen.generate_flags(builder.triple().architecture)?; gen.set_isa_flags(&mut builder, IsaFlagGen::Host)?; let isa = builder.finish(flags)?; diff --git a/fuzz/fuzz_targets/cranelift-icache.rs b/fuzz/fuzz_targets/cranelift-icache.rs index aa4dc7c79365..497329f99349 100644 --- a/fuzz/fuzz_targets/cranelift-icache.rs +++ b/fuzz/fuzz_targets/cranelift-icache.rs @@ -1,5 +1,6 @@ #![no_main] +use cranelift_chaos::ChaosEngine; use cranelift_codegen::{ cursor::{Cursor, FuncCursor}, incremental_cache as icache, @@ -39,6 +40,8 @@ pub struct FunctionWithIsa { /// Function under test pub func: Function, + + chaos_eng: ChaosEngine, } impl FunctionWithIsa { @@ -48,11 +51,11 @@ impl FunctionWithIsa { // a supported one, so that the same fuzz input works across different build // configurations. let target = u.choose(isa::ALL_ARCHITECTURES)?; - let mut builder = - isa::lookup_by_name(target).map_err(|_| arbitrary::Error::IncorrectFormat)?; + let mut gen = FuzzGen::new(u)?; + let mut builder = isa::lookup_by_name(target, gen.chaos_eng.clone()) + .map_err(|_| arbitrary::Error::IncorrectFormat)?; let architecture = builder.triple().architecture; - let mut gen = FuzzGen::new(u); let flags = gen .generate_flags(architecture) .map_err(|_| arbitrary::Error::IncorrectFormat)?; @@ -84,7 +87,11 @@ impl FunctionWithIsa { ) .map_err(|_| arbitrary::Error::IncorrectFormat)?; - Ok(FunctionWithIsa { isa, func }) + Ok(FunctionWithIsa { + isa, + func, + chaos_eng: gen.chaos_eng, + }) } } @@ -103,11 +110,15 @@ impl<'a> Arbitrary<'a> for FunctionWithIsa { } fuzz_target!(|func: FunctionWithIsa| { - let FunctionWithIsa { mut func, isa } = func; + let FunctionWithIsa { + mut func, + isa, + chaos_eng, + } = func; let cache_key_hash = icache::compute_cache_key(&*isa, &func); - let mut context = Context::for_function(func.clone()); + let mut context = Context::for_function(func.clone(), chaos_eng.clone()); let prev_stencil = match context.compile_stencil(&*isa) { Ok(stencil) => stencil, Err(_) => return, @@ -197,7 +208,7 @@ fuzz_target!(|func: FunctionWithIsa| { assert!(cache_key_hash != new_cache_key_hash); } - context = Context::for_function(func.clone()); + context = Context::for_function(func.clone(), chaos_eng); let after_mutation_result = match context.compile(&*isa) { Ok(info) => info, From bb15b084e6f467f7e335a47d87afc2d94f427d9a Mon Sep 17 00:00:00 2001 From: Remo Senekowitsch Date: Sun, 19 Mar 2023 00:19:34 +0100 Subject: [PATCH 03/14] fuzz: Rename chaos engine -> control plane Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com> Co-authored-by: Moritz Waser --- Cargo.lock | 34 ++++++------ Cargo.toml | 2 +- cranelift/codegen/Cargo.toml | 4 +- cranelift/codegen/src/context.rs | 14 ++--- cranelift/codegen/src/isa/aarch64/mod.rs | 20 +++---- cranelift/codegen/src/isa/mod.rs | 36 +++++++------ cranelift/codegen/src/isa/riscv64/mod.rs | 20 +++---- cranelift/codegen/src/isa/s390x/mod.rs | 21 ++++---- cranelift/codegen/src/isa/x64/mod.rs | 22 ++++---- cranelift/codegen/src/machinst/buffer.rs | 36 ++++++------- cranelift/codegen/src/machinst/compile.rs | 15 ++++-- cranelift/codegen/src/machinst/lower.rs | 6 +-- cranelift/codegen/src/machinst/vcode.rs | 16 +++--- cranelift/{chaos => control}/Cargo.toml | 7 +-- cranelift/{chaos => control}/LICENSE | 0 cranelift/{chaos => control}/README.md | 0 .../src/enabled.rs => control/src/chaos.rs} | 52 +++++++++---------- cranelift/{chaos => control}/src/lib.rs | 27 +++++----- .../disabled.rs => control/src/zero_sized.rs} | 4 +- cranelift/filetests/Cargo.toml | 2 +- cranelift/filetests/src/function_runner.rs | 4 +- .../filetests/src/test_alias_analysis.rs | 4 +- cranelift/filetests/src/test_compile.rs | 4 +- cranelift/filetests/src/test_dce.rs | 4 +- cranelift/filetests/src/test_legalizer.rs | 4 +- cranelift/filetests/src/test_licm.rs | 4 +- cranelift/filetests/src/test_optimize.rs | 4 +- cranelift/filetests/src/test_run.rs | 4 +- cranelift/filetests/src/test_safepoint.rs | 4 +- cranelift/filetests/src/test_simple_gvn.rs | 4 +- cranelift/filetests/src/test_simple_preopt.rs | 4 +- cranelift/filetests/src/test_unwind.rs | 4 +- cranelift/filetests/src/test_wasm.rs | 6 +-- cranelift/fuzzgen/Cargo.toml | 4 +- cranelift/fuzzgen/src/lib.rs | 14 ++--- cranelift/jit/Cargo.toml | 2 +- cranelift/jit/src/backend.rs | 4 +- cranelift/module/Cargo.toml | 2 +- cranelift/module/src/module.rs | 4 +- cranelift/native/Cargo.toml | 3 +- cranelift/native/src/lib.rs | 8 +-- cranelift/object/Cargo.toml | 2 +- cranelift/object/tests/basic.rs | 16 +++--- cranelift/reader/Cargo.toml | 2 +- cranelift/reader/src/lib.rs | 4 +- cranelift/reader/src/parser.rs | 6 +-- crates/cranelift/Cargo.toml | 2 +- crates/cranelift/src/builder.rs | 4 +- crates/cranelift/src/compiler.rs | 4 +- fuzz/Cargo.toml | 4 +- fuzz/fuzz_targets/cranelift-fuzzgen.rs | 2 +- fuzz/fuzz_targets/cranelift-icache.rs | 14 ++--- 52 files changed, 253 insertions(+), 240 deletions(-) rename cranelift/{chaos => control}/Cargo.toml (73%) rename cranelift/{chaos => control}/LICENSE (100%) rename cranelift/{chaos => control}/README.md (100%) rename cranelift/{chaos/src/enabled.rs => control/src/chaos.rs} (77%) rename cranelift/{chaos => control}/src/lib.rs (54%) rename cranelift/{chaos/src/disabled.rs => control/src/zero_sized.rs} (83%) diff --git a/Cargo.lock b/Cargo.lock index 5c63d9015fb7..d8625d487f9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -559,13 +559,6 @@ dependencies = [ "cranelift-entity", ] -[[package]] -name = "cranelift-chaos" -version = "0.95.0" -dependencies = [ - "arbitrary", -] - [[package]] name = "cranelift-codegen" version = "0.95.0" @@ -575,9 +568,9 @@ dependencies = [ "bumpalo", "capstone", "cranelift-bforest", - "cranelift-chaos", "cranelift-codegen-meta", "cranelift-codegen-shared", + "cranelift-control", "cranelift-entity", "cranelift-isle", "criterion", @@ -604,6 +597,13 @@ dependencies = [ name = "cranelift-codegen-shared" version = "0.95.0" +[[package]] +name = "cranelift-control" +version = "0.95.0" +dependencies = [ + "arbitrary", +] + [[package]] name = "cranelift-entity" version = "0.95.0" @@ -617,8 +617,8 @@ version = "0.0.0" dependencies = [ "anyhow", "cranelift", - "cranelift-chaos", "cranelift-codegen", + "cranelift-control", "cranelift-frontend", "cranelift-interpreter", "cranelift-jit", @@ -659,7 +659,7 @@ dependencies = [ "anyhow", "arbitrary", "cranelift", - "cranelift-chaos", + "cranelift-control", "cranelift-native", "once_cell", "target-lexicon", @@ -694,8 +694,8 @@ version = "0.95.0" dependencies = [ "anyhow", "cranelift", - "cranelift-chaos", "cranelift-codegen", + "cranelift-control", "cranelift-entity", "cranelift-frontend", "cranelift-module", @@ -714,8 +714,8 @@ name = "cranelift-module" version = "0.95.0" dependencies = [ "anyhow", - "cranelift-chaos", "cranelift-codegen", + "cranelift-control", "hashbrown 0.13.1", ] @@ -723,8 +723,8 @@ dependencies = [ name = "cranelift-native" version = "0.95.0" dependencies = [ - "cranelift-chaos", "cranelift-codegen", + "cranelift-control", "libc", "target-lexicon", ] @@ -734,8 +734,8 @@ name = "cranelift-object" version = "0.95.0" dependencies = [ "anyhow", - "cranelift-chaos", "cranelift-codegen", + "cranelift-control", "cranelift-entity", "cranelift-frontend", "cranelift-module", @@ -749,8 +749,8 @@ name = "cranelift-reader" version = "0.95.0" dependencies = [ "anyhow", - "cranelift-chaos", "cranelift-codegen", + "cranelift-control", "smallvec", "target-lexicon", ] @@ -3598,8 +3598,8 @@ name = "wasmtime-cranelift" version = "8.0.0" dependencies = [ "anyhow", - "cranelift-chaos", "cranelift-codegen", + "cranelift-control", "cranelift-entity", "cranelift-frontend", "cranelift-native", @@ -3698,8 +3698,8 @@ dependencies = [ "arbitrary", "component-fuzz-util", "component-test-util", - "cranelift-chaos", "cranelift-codegen", + "cranelift-control", "cranelift-filetests", "cranelift-fuzzgen", "cranelift-interpreter", diff --git a/Cargo.toml b/Cargo.toml index 805003dca5e6..f94fbd6d1724 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -161,7 +161,7 @@ cranelift-object = { path = "cranelift/object", version = "0.95.0" } cranelift-jit = { path = "cranelift/jit", version = "0.95.0" } cranelift-fuzzgen = { path = "cranelift/fuzzgen" } cranelift-bforest = { path = "cranelift/bforest", version = "0.95.0" } -cranelift-chaos = { path = "cranelift/chaos", version = "0.95.0" } +cranelift-control = { path = "cranelift/control", version = "0.95.0" } cranelift = { path = "cranelift/umbrella", version = "0.95.0" } winch-codegen = { path = "winch/codegen", version = "=0.6.0" } diff --git a/cranelift/codegen/Cargo.toml b/cranelift/codegen/Cargo.toml index 772aa950cc20..9db523bfdf08 100644 --- a/cranelift/codegen/Cargo.toml +++ b/cranelift/codegen/Cargo.toml @@ -19,7 +19,7 @@ capstone = { workspace = true, optional = true } cranelift-codegen-shared = { path = "./shared", version = "0.95.0" } cranelift-entity = { workspace = true } cranelift-bforest = { workspace = true } -cranelift-chaos = { workspace = true } +cranelift-control = { workspace = true } hashbrown = { workspace = true, features = ["raw"] } target-lexicon = { workspace = true } log = { workspace = true } @@ -114,7 +114,7 @@ isle-errors = ["cranelift-isle/fancy-errors"] # inspection, rather than inside of target/. isle-in-source-tree = [] -chaos = ["cranelift-chaos/chaos"] +chaos = ["cranelift-control/chaos"] [badges] maintenance = { status = "experimental" } diff --git a/cranelift/codegen/src/context.rs b/cranelift/codegen/src/context.rs index 569aa1497feb..6077b3e77693 100644 --- a/cranelift/codegen/src/context.rs +++ b/cranelift/codegen/src/context.rs @@ -33,7 +33,7 @@ use crate::{timing, CompileError}; #[cfg(feature = "souper-harvest")] use alloc::string::String; use alloc::vec::Vec; -use cranelift_chaos::ChaosEngine; +use cranelift_control::ControlPlane; #[cfg(feature = "souper-harvest")] use crate::souper_harvest::do_souper_harvest; @@ -59,8 +59,8 @@ pub struct Context { pub want_disasm: bool, /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct - /// and compiled away. See [cranelift_chaos]. - chaos_eng: ChaosEngine, + /// and compiled away. See [cranelift_control]. + control_plane: ControlPlane, } impl Context { @@ -68,15 +68,15 @@ impl Context { /// /// The returned instance should be reused for compiling multiple functions in order to avoid /// needless allocator thrashing. - pub fn new(chaos_eng: ChaosEngine) -> Self { - Self::for_function(Function::new(), chaos_eng) + pub fn new(control_plane: ControlPlane) -> Self { + Self::for_function(Function::new(), control_plane) } /// Allocate a new compilation context with an existing Function. /// /// The returned instance should be reused for compiling multiple functions in order to avoid /// needless allocator thrashing. - pub fn for_function(func: Function, chaos_eng: ChaosEngine) -> Self { + pub fn for_function(func: Function, control_plane: ControlPlane) -> Self { Self { func, cfg: ControlFlowGraph::new(), @@ -84,7 +84,7 @@ impl Context { loop_analysis: LoopAnalysis::new(), compiled_code: None, want_disasm: false, - chaos_eng, + control_plane, } } diff --git a/cranelift/codegen/src/isa/aarch64/mod.rs b/cranelift/codegen/src/isa/aarch64/mod.rs index e414395dc14b..013c9e26240d 100644 --- a/cranelift/codegen/src/isa/aarch64/mod.rs +++ b/cranelift/codegen/src/isa/aarch64/mod.rs @@ -15,7 +15,7 @@ use crate::result::CodegenResult; use crate::settings as shared_settings; use alloc::{boxed::Box, vec::Vec}; use core::fmt; -use cranelift_chaos::ChaosEngine; +use cranelift_control::ControlPlane; use regalloc2::MachineEnv; use target_lexicon::{Aarch64Architecture, Architecture, OperatingSystem, Triple}; @@ -36,8 +36,8 @@ pub struct AArch64Backend { isa_flags: aarch64_settings::Flags, machine_env: MachineEnv, /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct - /// and compiled away. See [cranelift_chaos]. - chaos_eng: ChaosEngine, + /// and compiled away. See [cranelift_control]. + control_plane: ControlPlane, } impl AArch64Backend { @@ -46,7 +46,7 @@ impl AArch64Backend { triple: Triple, flags: shared_settings::Flags, isa_flags: aarch64_settings::Flags, - chaos_eng: ChaosEngine, + control_plane: ControlPlane, ) -> AArch64Backend { let machine_env = create_reg_env(&flags); AArch64Backend { @@ -54,7 +54,7 @@ impl AArch64Backend { flags, isa_flags, machine_env, - chaos_eng, + control_plane, } } @@ -75,7 +75,7 @@ impl AArch64Backend { abi, emit_info, sigs, - self.chaos_eng.clone(), + self.control_plane.clone(), ) } } @@ -245,16 +245,16 @@ impl fmt::Display for AArch64Backend { } /// Create a new `isa::Builder`. -pub fn isa_builder(triple: Triple, chaos_eng: ChaosEngine) -> IsaBuilder { +pub fn isa_builder(triple: Triple, control_plane: ControlPlane) -> IsaBuilder { assert!(triple.architecture == Architecture::Aarch64(Aarch64Architecture::Aarch64)); IsaBuilder { triple, - chaos_eng, + control_plane, setup: aarch64_settings::builder(), - constructor: |triple, shared_flags, builder, chaos_eng| { + constructor: |triple, shared_flags, builder, control_plane| { let isa_flags = aarch64_settings::Flags::new(&shared_flags, builder); let backend = - AArch64Backend::new_with_flags(triple, shared_flags, isa_flags, chaos_eng); + AArch64Backend::new_with_flags(triple, shared_flags, isa_flags, control_plane); Ok(backend.wrapped()) }, } diff --git a/cranelift/codegen/src/isa/mod.rs b/cranelift/codegen/src/isa/mod.rs index f8d9bcbb931c..3b47913f267a 100644 --- a/cranelift/codegen/src/isa/mod.rs +++ b/cranelift/codegen/src/isa/mod.rs @@ -57,7 +57,7 @@ use crate::CodegenResult; use alloc::{boxed::Box, sync::Arc, vec::Vec}; use core::fmt; use core::fmt::{Debug, Formatter}; -use cranelift_chaos::ChaosEngine; +use cranelift_control::ControlPlane; use target_lexicon::{triple, Architecture, PointerWidth, Triple}; // This module is made public here for benchmarking purposes. No guarantees are @@ -81,10 +81,10 @@ mod call_conv; /// Returns a builder that can create a corresponding `TargetIsa` /// or `Err(LookupError::SupportDisabled)` if not enabled. macro_rules! isa_builder { - ($name: ident, $cfg_terms: tt, $triple: ident, $chaos_eng: ident) => {{ + ($name: ident, $cfg_terms: tt, $triple: ident, $control_plane: ident) => {{ #[cfg $cfg_terms] { - Ok($name::isa_builder($triple, $chaos_eng)) + Ok($name::isa_builder($triple, $control_plane)) } #[cfg(not $cfg_terms)] { @@ -95,17 +95,19 @@ macro_rules! isa_builder { /// Look for an ISA for the given `triple`. /// Return a builder that can create a corresponding `TargetIsa`. -pub fn lookup(triple: Triple, chaos_eng: ChaosEngine) -> Result { +pub fn lookup(triple: Triple, control_plane: ControlPlane) -> Result { match triple.architecture { Architecture::X86_64 => { - isa_builder!(x64, (feature = "x86"), triple, chaos_eng) + isa_builder!(x64, (feature = "x86"), triple, control_plane) } Architecture::Aarch64 { .. } => { - isa_builder!(aarch64, (feature = "arm64"), triple, chaos_eng) + isa_builder!(aarch64, (feature = "arm64"), triple, control_plane) + } + Architecture::S390x { .. } => { + isa_builder!(s390x, (feature = "s390x"), triple, control_plane) } - Architecture::S390x { .. } => isa_builder!(s390x, (feature = "s390x"), triple, chaos_eng), Architecture::Riscv64 { .. } => { - isa_builder!(riscv64, (feature = "riscv64"), triple, chaos_eng) + isa_builder!(riscv64, (feature = "riscv64"), triple, control_plane) } _ => Err(LookupError::Unsupported), } @@ -118,9 +120,9 @@ pub const ALL_ARCHITECTURES: &[&str] = &["x86_64", "aarch64", "s390x", "riscv64" /// Look for a supported ISA with the given `name`. /// Return a builder that can create a corresponding `TargetIsa`. -pub fn lookup_by_name(name: &str, chaos_eng: ChaosEngine) -> Result { +pub fn lookup_by_name(name: &str, control_plane: ControlPlane) -> Result { use alloc::str::FromStr; - lookup(triple!(name), chaos_eng) + lookup(triple!(name), control_plane) } /// Describes reason for target lookup failure @@ -160,10 +162,10 @@ pub type Builder = IsaBuilder>; pub struct IsaBuilder { triple: Triple, /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct - /// and compiled away. See [cranelift_chaos]. - chaos_eng: ChaosEngine, + /// and compiled away. See [cranelift_control]. + control_plane: ControlPlane, setup: settings::Builder, - constructor: fn(Triple, settings::Flags, &settings::Builder, ChaosEngine) -> T, + constructor: fn(Triple, settings::Flags, &settings::Builder, ControlPlane) -> T, } impl IsaBuilder { @@ -172,13 +174,13 @@ impl IsaBuilder { /// function to generate the ISA from its components. pub fn new( triple: Triple, - chaos_eng: ChaosEngine, + control_plane: ControlPlane, setup: settings::Builder, - constructor: fn(Triple, settings::Flags, &settings::Builder, ChaosEngine) -> T, + constructor: fn(Triple, settings::Flags, &settings::Builder, ControlPlane) -> T, ) -> Self { IsaBuilder { triple, - chaos_eng, + control_plane, setup, constructor, } @@ -205,7 +207,7 @@ impl IsaBuilder { self.triple.clone(), shared_flags, &self.setup, - self.chaos_eng.clone(), + self.control_plane.clone(), ) } } diff --git a/cranelift/codegen/src/isa/riscv64/mod.rs b/cranelift/codegen/src/isa/riscv64/mod.rs index e5bd45584b68..55cbf470e299 100644 --- a/cranelift/codegen/src/isa/riscv64/mod.rs +++ b/cranelift/codegen/src/isa/riscv64/mod.rs @@ -15,7 +15,7 @@ use crate::result::CodegenResult; use crate::settings as shared_settings; use alloc::{boxed::Box, vec::Vec}; use core::fmt; -use cranelift_chaos::ChaosEngine; +use cranelift_control::ControlPlane; use regalloc2::MachineEnv; use target_lexicon::{Architecture, Triple}; mod abi; @@ -36,8 +36,8 @@ pub struct Riscv64Backend { isa_flags: riscv_settings::Flags, mach_env: MachineEnv, /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct - /// and compiled away. See [cranelift_chaos]. - chaos_eng: ChaosEngine, + /// and compiled away. See [cranelift_control]. + control_plane: ControlPlane, } impl Riscv64Backend { @@ -46,7 +46,7 @@ impl Riscv64Backend { triple: Triple, flags: shared_settings::Flags, isa_flags: riscv_settings::Flags, - chaos_eng: ChaosEngine, + control_plane: ControlPlane, ) -> Riscv64Backend { let mach_env = crate_reg_eviroment(&flags); Riscv64Backend { @@ -54,7 +54,7 @@ impl Riscv64Backend { flags, isa_flags, mach_env, - chaos_eng, + control_plane, } } @@ -75,7 +75,7 @@ impl Riscv64Backend { abi, emit_info, sigs, - self.chaos_eng.clone(), + self.control_plane.clone(), ) } } @@ -217,19 +217,19 @@ impl fmt::Display for Riscv64Backend { } /// Create a new `isa::Builder`. -pub fn isa_builder(triple: Triple, chaos_eng: ChaosEngine) -> IsaBuilder { +pub fn isa_builder(triple: Triple, control_plane: ControlPlane) -> IsaBuilder { match triple.architecture { Architecture::Riscv64(..) => {} _ => unreachable!(), } IsaBuilder { triple, - chaos_eng, + control_plane, setup: riscv_settings::builder(), - constructor: |triple, shared_flags, builder, chaos_eng| { + constructor: |triple, shared_flags, builder, control_plane| { let isa_flags = riscv_settings::Flags::new(&shared_flags, builder); let backend = - Riscv64Backend::new_with_flags(triple, shared_flags, isa_flags, chaos_eng); + Riscv64Backend::new_with_flags(triple, shared_flags, isa_flags, control_plane); Ok(backend.wrapped()) }, } diff --git a/cranelift/codegen/src/isa/s390x/mod.rs b/cranelift/codegen/src/isa/s390x/mod.rs index fa4d0fb3e01d..baec5bd8b6b5 100644 --- a/cranelift/codegen/src/isa/s390x/mod.rs +++ b/cranelift/codegen/src/isa/s390x/mod.rs @@ -15,7 +15,7 @@ use crate::result::CodegenResult; use crate::settings as shared_settings; use alloc::{boxed::Box, vec::Vec}; use core::fmt; -use cranelift_chaos::ChaosEngine; +use cranelift_control::ControlPlane; use regalloc2::MachineEnv; use target_lexicon::{Architecture, Triple}; @@ -36,8 +36,8 @@ pub struct S390xBackend { isa_flags: s390x_settings::Flags, machine_env: MachineEnv, /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct - /// and compiled away. See [cranelift_chaos]. - chaos_eng: ChaosEngine, + /// and compiled away. See [cranelift_control]. + control_plane: ControlPlane, } impl S390xBackend { @@ -46,7 +46,7 @@ impl S390xBackend { triple: Triple, flags: shared_settings::Flags, isa_flags: s390x_settings::Flags, - chaos_eng: ChaosEngine, + control_plane: ControlPlane, ) -> S390xBackend { let machine_env = create_machine_env(&flags); S390xBackend { @@ -54,7 +54,7 @@ impl S390xBackend { flags, isa_flags, machine_env, - chaos_eng, + control_plane, } } @@ -75,7 +75,7 @@ impl S390xBackend { abi, emit_info, sigs, - self.chaos_eng.clone(), + self.control_plane.clone(), ) } } @@ -217,15 +217,16 @@ impl fmt::Display for S390xBackend { } /// Create a new `isa::Builder`. -pub fn isa_builder(triple: Triple, chaos_eng: ChaosEngine) -> IsaBuilder { +pub fn isa_builder(triple: Triple, control_plane: ControlPlane) -> IsaBuilder { assert!(triple.architecture == Architecture::S390x); IsaBuilder { triple, - chaos_eng, + control_plane, setup: s390x_settings::builder(), - constructor: |triple, shared_flags, builder, chaos_eng| { + constructor: |triple, shared_flags, builder, control_plane| { let isa_flags = s390x_settings::Flags::new(&shared_flags, builder); - let backend = S390xBackend::new_with_flags(triple, shared_flags, isa_flags, chaos_eng); + let backend = + S390xBackend::new_with_flags(triple, shared_flags, isa_flags, control_plane); Ok(backend.wrapped()) }, } diff --git a/cranelift/codegen/src/isa/x64/mod.rs b/cranelift/codegen/src/isa/x64/mod.rs index 7935b5db7252..1092652f5179 100644 --- a/cranelift/codegen/src/isa/x64/mod.rs +++ b/cranelift/codegen/src/isa/x64/mod.rs @@ -17,7 +17,7 @@ use crate::result::{CodegenError, CodegenResult}; use crate::settings::{self as shared_settings, Flags}; use alloc::{boxed::Box, vec::Vec}; use core::fmt; -use cranelift_chaos::ChaosEngine; +use cranelift_control::ControlPlane; use regalloc2::MachineEnv; use target_lexicon::Triple; @@ -34,8 +34,8 @@ pub(crate) struct X64Backend { x64_flags: x64_settings::Flags, reg_env: MachineEnv, /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct - /// and compiled away. See [cranelift_chaos]. - chaos_eng: ChaosEngine, + /// and compiled away. See [cranelift_control]. + control_plane: ControlPlane, } impl X64Backend { @@ -44,7 +44,7 @@ impl X64Backend { triple: Triple, flags: Flags, x64_flags: x64_settings::Flags, - chaos_eng: ChaosEngine, + control_plane: ControlPlane, ) -> Self { let reg_env = create_reg_env_systemv(&flags); Self { @@ -52,7 +52,7 @@ impl X64Backend { flags, x64_flags, reg_env, - chaos_eng, + control_plane, } } @@ -73,7 +73,7 @@ impl X64Backend { abi, emit_info, sigs, - self.chaos_eng.clone(), + self.control_plane.clone(), ) } } @@ -219,10 +219,10 @@ impl fmt::Display for X64Backend { } /// Create a new `isa::Builder`. -pub(crate) fn isa_builder(triple: Triple, chaos_eng: ChaosEngine) -> IsaBuilder { +pub(crate) fn isa_builder(triple: Triple, control_plane: ControlPlane) -> IsaBuilder { IsaBuilder { triple, - chaos_eng, + control_plane, setup: x64_settings::builder(), constructor: isa_constructor, } @@ -232,7 +232,7 @@ fn isa_constructor( triple: Triple, shared_flags: Flags, builder: &shared_settings::Builder, - chaos_eng: ChaosEngine, + control_plane: ControlPlane, ) -> CodegenResult { let isa_flags = x64_settings::Flags::new(&shared_flags, builder); @@ -250,7 +250,7 @@ fn isa_constructor( } } - let backend = X64Backend::new_with_flags(triple, shared_flags, isa_flags, chaos_eng); + let backend = X64Backend::new_with_flags(triple, shared_flags, isa_flags, control_plane); Ok(backend.wrapped()) } @@ -266,7 +266,7 @@ mod test { let mut shared_flags_builder = settings::builder(); shared_flags_builder.set("enable_simd", "true").unwrap(); let shared_flags = settings::Flags::new(shared_flags_builder); - let mut isa_builder = crate::isa::lookup_by_name("x86_64", ChaosEngine::noop()).unwrap(); + let mut isa_builder = crate::isa::lookup_by_name("x86_64", ControlPlane::noop()).unwrap(); isa_builder.set("has_sse3", "false").unwrap(); isa_builder.set("has_ssse3", "false").unwrap(); isa_builder.set("has_sse41", "false").unwrap(); diff --git a/cranelift/codegen/src/machinst/buffer.rs b/cranelift/codegen/src/machinst/buffer.rs index b416430982e3..21e356af3a50 100644 --- a/cranelift/codegen/src/machinst/buffer.rs +++ b/cranelift/codegen/src/machinst/buffer.rs @@ -148,7 +148,7 @@ use crate::machinst::{ }; use crate::timing; use crate::trace; -use cranelift_chaos::ChaosEngine; +use cranelift_control::ControlPlane; use cranelift_entity::{entity_impl, SecondaryMap}; use smallvec::SmallVec; use std::convert::TryFrom; @@ -265,8 +265,8 @@ pub struct MachBuffer { /// Map used constants to their [MachLabel]. constant_labels: SecondaryMap, /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct - /// and compiled away. See [cranelift_chaos]. - chaos_eng: ChaosEngine, + /// and compiled away. See [cranelift_control]. + control_plane: ControlPlane, } impl MachBufferFinalized { @@ -364,7 +364,7 @@ pub enum StackMapExtent { impl MachBuffer { /// Create a new section, known to start at `start_offset` and with a size limited to /// `length_limit`. - pub fn new(chaos_eng: ChaosEngine) -> MachBuffer { + pub fn new(control_plane: ControlPlane) -> MachBuffer { MachBuffer { data: SmallVec::new(), relocs: SmallVec::new(), @@ -385,7 +385,7 @@ impl MachBuffer { labels_at_tail: SmallVec::new(), labels_at_tail_off: 0, constant_labels: SecondaryMap::new(), - chaos_eng, + control_plane, } } @@ -780,7 +780,7 @@ impl MachBuffer { fn optimize_branches(&mut self) { #[cfg(feature = "chaos")] - if let Ok(true) = self.chaos_eng.get_arbitrary() { + if let Ok(true) = self.control_plane.get_arbitrary() { return; } @@ -1712,7 +1712,7 @@ impl MachTextSectionBuilder { /// Creates a new text section builder which will have `num_funcs` functions /// pushed into it. pub fn new(num_funcs: usize) -> MachTextSectionBuilder { - let mut buf = MachBuffer::new(ChaosEngine::noop()); + let mut buf = MachBuffer::new(ControlPlane::noop()); buf.reserve_labels_for_blocks(num_funcs); MachTextSectionBuilder { buf, @@ -1795,7 +1795,7 @@ mod test { #[test] fn test_elide_jump_to_next() { let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(ChaosEngine::noop()); + let mut buf = MachBuffer::new(ControlPlane::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(2); @@ -1810,7 +1810,7 @@ mod test { #[test] fn test_elide_trivial_jump_blocks() { let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(ChaosEngine::noop()); + let mut buf = MachBuffer::new(ControlPlane::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(4); @@ -1840,7 +1840,7 @@ mod test { #[test] fn test_flip_cond() { let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(ChaosEngine::noop()); + let mut buf = MachBuffer::new(ControlPlane::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(4); @@ -1867,7 +1867,7 @@ mod test { let buf = buf.finish(); - let mut buf2 = MachBuffer::new(ChaosEngine::noop()); + let mut buf2 = MachBuffer::new(ControlPlane::noop()); let mut state = Default::default(); let inst = Inst::TrapIf { kind: CondBrKind::NotZero(xreg(0)), @@ -1885,7 +1885,7 @@ mod test { #[test] fn test_island() { let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(ChaosEngine::noop()); + let mut buf = MachBuffer::new(ControlPlane::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(4); @@ -1919,7 +1919,7 @@ mod test { assert_eq!(2000000 + 8, buf.total_size()); - let mut buf2 = MachBuffer::new(ChaosEngine::noop()); + let mut buf2 = MachBuffer::new(ControlPlane::noop()); let mut state = Default::default(); let inst = Inst::CondBr { kind: CondBrKind::NotZero(xreg(0)), @@ -1952,7 +1952,7 @@ mod test { #[test] fn test_island_backward() { let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(ChaosEngine::noop()); + let mut buf = MachBuffer::new(ControlPlane::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(4); @@ -1983,7 +1983,7 @@ mod test { assert_eq!(2000000 + 12, buf.total_size()); - let mut buf2 = MachBuffer::new(ChaosEngine::noop()); + let mut buf2 = MachBuffer::new(ControlPlane::noop()); let mut state = Default::default(); let inst = Inst::CondBr { kind: CondBrKind::NotZero(xreg(0)), @@ -2037,7 +2037,7 @@ mod test { // ret let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(ChaosEngine::noop()); + let mut buf = MachBuffer::new(ControlPlane::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(8); @@ -2113,7 +2113,7 @@ mod test { // label0, label1, ..., label4: // b label0 let info = EmitInfo::new(settings::Flags::new(settings::builder())); - let mut buf = MachBuffer::new(ChaosEngine::noop()); + let mut buf = MachBuffer::new(ControlPlane::noop()); let mut state = Default::default(); buf.reserve_labels_for_blocks(5); @@ -2149,7 +2149,7 @@ mod test { #[test] fn metadata_records() { - let mut buf = MachBuffer::::new(ChaosEngine::noop()); + let mut buf = MachBuffer::::new(ControlPlane::noop()); buf.reserve_labels_for_blocks(1); diff --git a/cranelift/codegen/src/machinst/compile.rs b/cranelift/codegen/src/machinst/compile.rs index ed62580bfad9..483de6e69d55 100644 --- a/cranelift/codegen/src/machinst/compile.rs +++ b/cranelift/codegen/src/machinst/compile.rs @@ -7,7 +7,7 @@ use crate::machinst::*; use crate::timing; use crate::trace; -use cranelift_chaos::ChaosEngine; +use cranelift_control::ControlPlane; use regalloc2::RegallocOptions; /// Compile the given function down to VCode with allocated registers, ready @@ -19,7 +19,7 @@ pub fn compile( abi: Callee<<::MInst as MachInst>::ABIMachineSpec>, emit_info: ::Info, sigs: SigSet, - chaos_eng: ChaosEngine, + control_plane: ControlPlane, ) -> CodegenResult<(VCode, regalloc2::Output)> { let machine_env = b.machine_env(); @@ -27,8 +27,15 @@ pub fn compile( let block_order = BlockLoweringOrder::new(f, domtree); // Build the lowering context. - let lower = - crate::machinst::Lower::new(f, machine_env, abi, emit_info, block_order, sigs, chaos_eng)?; + let lower = crate::machinst::Lower::new( + f, + machine_env, + abi, + emit_info, + block_order, + sigs, + control_plane, + )?; // Lower the IR. let vcode = { diff --git a/cranelift/codegen/src/machinst/lower.rs b/cranelift/codegen/src/machinst/lower.rs index 39340d5a34e0..60d9d482d2a5 100644 --- a/cranelift/codegen/src/machinst/lower.rs +++ b/cranelift/codegen/src/machinst/lower.rs @@ -20,7 +20,7 @@ use crate::machinst::{ }; use crate::{trace, CodegenResult}; use alloc::vec::Vec; -use cranelift_chaos::ChaosEngine; +use cranelift_control::ControlPlane; use regalloc2::{MachineEnv, PRegSet}; use smallvec::{smallvec, SmallVec}; use std::fmt::Debug; @@ -334,7 +334,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { emit_info: I::Info, block_order: BlockLoweringOrder, sigs: SigSet, - chaos_eng: ChaosEngine, + control_plane: ControlPlane, ) -> CodegenResult { let constants = VCodeConstants::with_capacity(f.dfg.constants.len()); let vcode = VCodeBuilder::new( @@ -344,7 +344,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { block_order, constants, VCodeBuildDirection::Backward, - chaos_eng, + control_plane, ); let mut vregs = VRegAllocator::new(); diff --git a/cranelift/codegen/src/machinst/vcode.rs b/cranelift/codegen/src/machinst/vcode.rs index 137d62be370c..181c59391720 100644 --- a/cranelift/codegen/src/machinst/vcode.rs +++ b/cranelift/codegen/src/machinst/vcode.rs @@ -26,7 +26,7 @@ use crate::timing; use crate::trace; use crate::CodegenError; use crate::ValueLocRange; -use cranelift_chaos::ChaosEngine; +use cranelift_control::ControlPlane; use regalloc2::{ Edit, Function as RegallocFunction, InstOrEdit, InstRange, Operand, OperandKind, PRegSet, RegClass, VReg, @@ -177,8 +177,8 @@ pub struct VCode { pub(crate) sigs: SigSet, /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct - /// and compiled away. See [cranelift_chaos]. - chaos_eng: ChaosEngine, + /// and compiled away. See [cranelift_control]. + control_plane: ControlPlane, } /// The result of `VCode::emit`. Contains all information computed @@ -289,9 +289,9 @@ impl VCodeBuilder { block_order: BlockLoweringOrder, constants: VCodeConstants, direction: VCodeBuildDirection, - chaos_eng: ChaosEngine, + control_plane: ControlPlane, ) -> VCodeBuilder { - let vcode = VCode::new(sigs, abi, emit_info, block_order, constants, chaos_eng); + let vcode = VCode::new(sigs, abi, emit_info, block_order, constants, control_plane); VCodeBuilder { vcode, @@ -648,7 +648,7 @@ impl VCode { emit_info: I::Info, block_order: BlockLoweringOrder, constants: VCodeConstants, - chaos_eng: ChaosEngine, + control_plane: ControlPlane, ) -> VCode { let n_blocks = block_order.lowered_order().len(); VCode { @@ -677,7 +677,7 @@ impl VCode { constants, debug_value_labels: vec![], vreg_aliases: FxHashMap::with_capacity_and_hasher(10 * n_blocks, Default::default()), - chaos_eng, + control_plane, } } @@ -779,7 +779,7 @@ impl VCode { use core::fmt::Write; let _tt = timing::vcode_emit(); - let mut buffer = MachBuffer::new(self.chaos_eng.clone()); + let mut buffer = MachBuffer::new(self.control_plane.clone()); let mut bb_starts: Vec> = vec![]; // The first M MachLabels are reserved for block indices, the next N MachLabels for diff --git a/cranelift/chaos/Cargo.toml b/cranelift/control/Cargo.toml similarity index 73% rename from cranelift/chaos/Cargo.toml rename to cranelift/control/Cargo.toml index a7f9a202eae3..3b0cc11c5756 100644 --- a/cranelift/chaos/Cargo.toml +++ b/cranelift/control/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["The Cranelift Project Developers"] -name = "cranelift-chaos" +name = "cranelift-control" version = "0.95.0" description = "White-box fuzz testing framework" license = "Apache-2.0 WITH LLVM-exception" @@ -14,6 +14,7 @@ arbitrary = { version = "1.1.0" } [features] -# Actually turn on chaos mode. -# Without this feature, a zero-sized dummy will be compiled. +# Turn on chaos mode. +# Without this feature, a zero-sized dummy will be compiled +# for the control plane. chaos = [] diff --git a/cranelift/chaos/LICENSE b/cranelift/control/LICENSE similarity index 100% rename from cranelift/chaos/LICENSE rename to cranelift/control/LICENSE diff --git a/cranelift/chaos/README.md b/cranelift/control/README.md similarity index 100% rename from cranelift/chaos/README.md rename to cranelift/control/README.md diff --git a/cranelift/chaos/src/enabled.rs b/cranelift/control/src/chaos.rs similarity index 77% rename from cranelift/chaos/src/enabled.rs rename to cranelift/control/src/chaos.rs index 7e983c1a80db..a709bc000265 100644 --- a/cranelift/chaos/src/enabled.rs +++ b/cranelift/control/src/chaos.rs @@ -5,7 +5,7 @@ use std::{ use arbitrary::{Arbitrary, Unstructured}; -struct ChaosEngineData { +struct ControlPlaneData { /// # Safety /// /// This field must never be moved from, as it is referenced by @@ -15,7 +15,7 @@ struct ChaosEngineData { /// https://morestina.net/blog/1868/self-referential-types-for-fun-and-profit) #[allow(dead_code)] data: Vec, - /// We use internal mutability such that a `ChaosEngine` can be passed + /// We use internal mutability such that a `ControlPlane` can be passed /// through the call stack without having to be declared as mutable. /// Besides the convenience, the mutation of the internal unstructured /// data should be opaque to users anyway. @@ -26,16 +26,16 @@ struct ChaosEngineData { unstructured: Mutex>, } -impl Debug for ChaosEngineData { +impl Debug for ControlPlaneData { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let data_len = self.data.len(); let remaining_len = self .unstructured .lock() - .expect("poisoned ChaosEngineData mutex") + .expect("poisoned ControlPlaneData mutex") .len(); let consumed_len = data_len - remaining_len; - f.debug_struct("ChaosEngineData") + f.debug_struct("ControlPlaneData") .field("data", &self.data) .field( "unstructured", @@ -51,20 +51,20 @@ impl Debug for ChaosEngineData { /// The control plane of chaos mode. /// Please see the [crate-level documentation](crate). /// -/// **Clone liberally!** The chaos engine is reference counted. +/// **Clone liberally!** The control plane is reference counted. #[derive(Debug, Clone)] -pub struct ChaosEngine { - data: Arc, +pub struct ControlPlane { + data: Arc, is_todo: bool, } -impl ChaosEngine { +impl ControlPlane { fn new(data: Vec, is_todo: bool) -> Self { let unstructured = Unstructured::new(&data); // safety: this is ok because we never move out of the vector let unstructured = Mutex::new(unsafe { std::mem::transmute(unstructured) }); Self { - data: Arc::new(ChaosEngineData { data, unstructured }), + data: Arc::new(ControlPlaneData { data, unstructured }), is_todo, } } @@ -76,27 +76,27 @@ impl ChaosEngine { /// /// This should not be used on code paths that may execute while the /// feature `chaos` is enabled. That would break the assumption that - /// [ChaosEngine] is a singleton, responsible for centrally managing + /// [ControlPlane] is a singleton, responsible for centrally managing /// the pseudo-randomness injected at runtimme. /// - /// Use [todo](ChaosEngine::todo) instead, for stubbing out code paths + /// Use [todo](ControlPlane::todo) instead, for stubbing out code paths /// you don't expect to be reached (yet) during chaos mode fuzzing. /// - /// # Pancis + /// # Panics /// /// Panics if it is called while the feature `chaos` is enabled. #[track_caller] pub fn noop() -> Self { panic!( - "attempted to create a NOOP chaos engine \ + "attempted to create a NOOP control plane \ (while chaos mode was enabled)" ); } - /// This is the same as [noop](ChaosEngine::noop) when the the feature + /// This is the same as [noop](ControlPlane::noop) when the the feature /// `chaos` is *disabled*. When `chaos` is enabled, it returns a - /// chaos engine that returns [Error::Todo] when - /// [get_arbitrary](ChaosEngine::get_arbitrary) is called. + /// control plane that returns [Error::Todo] when + /// [get_arbitrary](ControlPlane::get_arbitrary) is called. /// /// This may be used during development, in places which are (supposed /// to be) unreachable during fuzzing. Use of this function should be @@ -107,7 +107,7 @@ impl ChaosEngine { } } -impl<'a> Arbitrary<'a> for ChaosEngine { +impl<'a> Arbitrary<'a> for ControlPlane { fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { Ok(Self::new(u.arbitrary()?, false)) } @@ -116,7 +116,7 @@ impl<'a> Arbitrary<'a> for ChaosEngine { } } -/// An enumeration of chaos engine API errors, mostly propagating +/// An enumeration of control plane API errors, mostly propagating /// [arbitrary::Error]. #[derive(Debug, Clone, Copy)] pub enum Error { @@ -127,7 +127,7 @@ pub enum Error { NotEnoughData, /// The input bytes were not of the right format. IncorrectFormat, - /// The chaos engine API was accessed on a [ChaosEngine::todo]. + /// The control plane API was accessed on a [ControlPlane::todo]. Todo, } @@ -140,23 +140,23 @@ impl From for Error { arbitrary::Error::EmptyChoose => Error::EmptyChoose, arbitrary::Error::NotEnoughData => Error::NotEnoughData, arbitrary::Error::IncorrectFormat => Error::IncorrectFormat, - _ => unreachable!(), + _ => unreachable!("must propagate all error variants"), } } } -impl ChaosEngine { - /// Request an arbitrary value from the chaos engine. +impl ControlPlane { + /// Request an arbitrary value from the control plane. /// /// # Errors /// /// - Errors from an underlying call to [arbitrary] will be /// propagated as-is. - /// - Calling this function on a chaos engine received from a call to + /// - Calling this function on a control plane received from a call to /// [todo] will return an [Error::Todo]. /// /// [arbitrary]: arbitrary::Arbitrary::arbitrary - /// [todo]: ChaosEngine::todo + /// [todo]: ControlPlane::todo pub fn get_arbitrary>(&self) -> Result { if self.is_todo { return Err(Error::Todo); @@ -164,7 +164,7 @@ impl ChaosEngine { self.data .unstructured .lock() - .expect("poisoned ChaosEngineData mutex") + .expect("poisoned ControlPlaneData mutex") .arbitrary() .map_err(Error::from) } diff --git a/cranelift/chaos/src/lib.rs b/cranelift/control/src/lib.rs similarity index 54% rename from cranelift/chaos/src/lib.rs rename to cranelift/control/src/lib.rs index 2f161a80068e..1f7d593d4401 100644 --- a/cranelift/chaos/src/lib.rs +++ b/cranelift/control/src/lib.rs @@ -1,16 +1,17 @@ -//! # Cranelift Chaos Mode +//! # Cranelift Control //! -//! Chaos mode is a compilation feature intended to be turned on for certain -//! fuzz targets. When the feature is turned off - as is normally the case - -//! [ChaosEngine] will be a zero-sized type and optimized away. +//! This is the home of the control plane of chaos mode, a compilation feature +//! intended to be turned on for certain fuzz targets. When the feature is +//! turned off, as is normally the case, [ControlPlane] will be a zero-sized +//! type and optimized away. //! -//! While the feature is turned on, the struct [ChaosEngine] +//! While the feature is turned on, the struct [ControlPlane] //! provides functionality to tap into pseudo-randomness at specific locations //! in the code. It may be used for targeted fuzzing of compiler internals, //! e.g. manipulate heuristic optimizations, clobber undefined register bits //! etc. //! -//! There are three ways to acquire a [ChaosEngine]: +//! There are three ways to acquire a [ControlPlane]: //! - [arbitrary] for the real deal //! - [noop] for the zero-sized type when `chaos` is disabled //! - [todo] for stubbing out code paths during development @@ -18,16 +19,16 @@ //! The reason both [noop] and [todo] exist is so that [todo] can easily //! be searched for and removed later. //! -//! [arbitrary]: ChaosEngine#method.arbitrary -//! [noop]: ChaosEngine::noop -//! [todo]: ChaosEngine::todo +//! [arbitrary]: ControlPlane#method.arbitrary +//! [noop]: ControlPlane::noop +//! [todo]: ControlPlane::todo #[cfg(not(any(feature = "chaos", doc)))] -mod disabled; +mod zero_sized; #[cfg(not(any(feature = "chaos", doc)))] -pub use disabled::*; +pub use zero_sized::*; #[cfg(any(feature = "chaos", doc))] -mod enabled; +mod chaos; #[cfg(any(feature = "chaos", doc))] -pub use enabled::*; +pub use chaos::*; diff --git a/cranelift/chaos/src/disabled.rs b/cranelift/control/src/zero_sized.rs similarity index 83% rename from cranelift/chaos/src/disabled.rs rename to cranelift/control/src/zero_sized.rs index 450b516fd4e3..e443a4f0cdcb 100644 --- a/cranelift/chaos/src/disabled.rs +++ b/cranelift/control/src/zero_sized.rs @@ -1,10 +1,10 @@ #[derive(Debug, Clone)] -pub struct ChaosEngine { +pub struct ControlPlane { /// prevent direct instantiation (use `noop` or `todo` instead) _private: (), } -impl ChaosEngine { +impl ControlPlane { pub fn noop() -> Self { Self { _private: () } } diff --git a/cranelift/filetests/Cargo.toml b/cranelift/filetests/Cargo.toml index cc4073bf0007..789dfa5c66a1 100644 --- a/cranelift/filetests/Cargo.toml +++ b/cranelift/filetests/Cargo.toml @@ -17,7 +17,7 @@ cranelift-native = { workspace = true } cranelift-reader = { workspace = true } cranelift-jit = { workspace = true, features = ["selinux-fix"] } cranelift-module = { workspace = true } -cranelift-chaos = { workspace = true } +cranelift-control = { workspace = true } file-per-thread-logger = "0.1.2" filecheck = "0.5.0" gimli = { workspace = true } diff --git a/cranelift/filetests/src/function_runner.rs b/cranelift/filetests/src/function_runner.rs index ba3691cae6bb..87000f9574e3 100644 --- a/cranelift/filetests/src/function_runner.rs +++ b/cranelift/filetests/src/function_runner.rs @@ -1,13 +1,13 @@ //! Provides functionality for compiling and running CLIF IR for `run` tests. use anyhow::{anyhow, Result}; use core::mem; -use cranelift_chaos::ChaosEngine; use cranelift_codegen::data_value::DataValue; use cranelift_codegen::ir::{ ExternalName, Function, InstBuilder, Signature, UserExternalName, UserFuncName, }; use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa}; use cranelift_codegen::{ir, settings, CodegenError, Context}; +use cranelift_control::ControlPlane; use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use cranelift_jit::{JITBuilder, JITModule}; use cranelift_module::{FuncId, Linkage, Module, ModuleError}; @@ -102,7 +102,7 @@ impl TestFileCompiler { /// Build a [TestFileCompiler] using the host machine's ISA and the passed flags. pub fn with_host_isa(flags: settings::Flags) -> Result { - let builder = builder_with_options(true, ChaosEngine::noop()) + let builder = builder_with_options(true, ControlPlane::noop()) .expect("Unable to build a TargetIsa for the current host"); let isa = builder.finish(flags)?; Ok(Self::new(isa)) diff --git a/cranelift/filetests/src/test_alias_analysis.rs b/cranelift/filetests/src/test_alias_analysis.rs index f5491555d0ca..835675419b61 100644 --- a/cranelift/filetests/src/test_alias_analysis.rs +++ b/cranelift/filetests/src/test_alias_analysis.rs @@ -7,9 +7,9 @@ //! The resulting function is sent to `filecheck`. use crate::subtest::{run_filecheck, Context, SubTest}; -use cranelift_chaos::ChaosEngine; use cranelift_codegen; use cranelift_codegen::ir::Function; +use cranelift_control::ControlPlane; use cranelift_reader::TestCommand; use std::borrow::Cow; @@ -34,7 +34,7 @@ impl SubTest for TestAliasAnalysis { fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { let mut comp_ctx = - cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); + cranelift_codegen::Context::for_function(func.into_owned(), ControlPlane::noop()); comp_ctx.flowgraph(); comp_ctx diff --git a/cranelift/filetests/src/test_compile.rs b/cranelift/filetests/src/test_compile.rs index 047219bbd09c..72d309055105 100644 --- a/cranelift/filetests/src/test_compile.rs +++ b/cranelift/filetests/src/test_compile.rs @@ -4,8 +4,8 @@ use crate::subtest::{check_precise_output, run_filecheck, Context, SubTest}; use anyhow::Result; -use cranelift_chaos::ChaosEngine; use cranelift_codegen::ir; +use cranelift_control::ControlPlane; use cranelift_reader::{TestCommand, TestOption}; use log::info; use std::borrow::Cow; @@ -49,7 +49,7 @@ impl SubTest for TestCompile { let isa = context.isa.expect("compile needs an ISA"); let params = func.params.clone(); let mut comp_ctx = - cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); + cranelift_codegen::Context::for_function(func.into_owned(), ControlPlane::noop()); // With `MachBackend`s, we need to explicitly request dissassembly results. comp_ctx.set_disasm(true); diff --git a/cranelift/filetests/src/test_dce.rs b/cranelift/filetests/src/test_dce.rs index 3b0cb4e59cb3..48db483ddb3b 100644 --- a/cranelift/filetests/src/test_dce.rs +++ b/cranelift/filetests/src/test_dce.rs @@ -6,9 +6,9 @@ //! The resulting function is sent to `filecheck`. use crate::subtest::{run_filecheck, Context, SubTest}; -use cranelift_chaos::ChaosEngine; use cranelift_codegen; use cranelift_codegen::ir::Function; +use cranelift_control::ControlPlane; use cranelift_reader::TestCommand; use std::borrow::Cow; @@ -33,7 +33,7 @@ impl SubTest for TestDCE { fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { let mut comp_ctx = - cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); + cranelift_codegen::Context::for_function(func.into_owned(), ControlPlane::noop()); comp_ctx.flowgraph(); comp_ctx.compute_loop_analysis(); diff --git a/cranelift/filetests/src/test_legalizer.rs b/cranelift/filetests/src/test_legalizer.rs index ec92071b29e6..e5cb989bbc0e 100644 --- a/cranelift/filetests/src/test_legalizer.rs +++ b/cranelift/filetests/src/test_legalizer.rs @@ -4,9 +4,9 @@ //! the result to filecheck. use crate::subtest::{run_filecheck, Context, SubTest}; -use cranelift_chaos::ChaosEngine; use cranelift_codegen; use cranelift_codegen::ir::Function; +use cranelift_control::ControlPlane; use cranelift_reader::TestCommand; use std::borrow::Cow; @@ -35,7 +35,7 @@ impl SubTest for TestLegalizer { fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { let mut comp_ctx = - cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); + cranelift_codegen::Context::for_function(func.into_owned(), ControlPlane::noop()); let isa = context.isa.expect("legalizer needs an ISA"); comp_ctx.compute_cfg(); diff --git a/cranelift/filetests/src/test_licm.rs b/cranelift/filetests/src/test_licm.rs index a1b784a3a231..db5b03ccb2cc 100644 --- a/cranelift/filetests/src/test_licm.rs +++ b/cranelift/filetests/src/test_licm.rs @@ -6,9 +6,9 @@ //! The resulting function is sent to `filecheck`. use crate::subtest::{run_filecheck, Context, SubTest}; -use cranelift_chaos::ChaosEngine; use cranelift_codegen; use cranelift_codegen::ir::Function; +use cranelift_control::ControlPlane; use cranelift_reader::TestCommand; use std::borrow::Cow; @@ -38,7 +38,7 @@ impl SubTest for TestLICM { fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { let isa = context.isa.expect("LICM needs an ISA"); let mut comp_ctx = - cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); + cranelift_codegen::Context::for_function(func.into_owned(), ControlPlane::noop()); comp_ctx.flowgraph(); comp_ctx.compute_loop_analysis(); diff --git a/cranelift/filetests/src/test_optimize.rs b/cranelift/filetests/src/test_optimize.rs index 703c9c686366..02627e459453 100644 --- a/cranelift/filetests/src/test_optimize.rs +++ b/cranelift/filetests/src/test_optimize.rs @@ -9,8 +9,8 @@ use crate::subtest::{check_precise_output, run_filecheck, Context, SubTest}; use anyhow::Result; -use cranelift_chaos::ChaosEngine; use cranelift_codegen::ir; +use cranelift_control::ControlPlane; use cranelift_reader::{TestCommand, TestOption}; use std::borrow::Cow; @@ -52,7 +52,7 @@ impl SubTest for TestOptimize { fn run(&self, func: Cow, context: &Context) -> Result<()> { let isa = context.isa.expect("optimize needs an ISA"); let mut comp_ctx = - cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); + cranelift_codegen::Context::for_function(func.into_owned(), ControlPlane::noop()); comp_ctx .optimize(isa) diff --git a/cranelift/filetests/src/test_run.rs b/cranelift/filetests/src/test_run.rs index c47d1483c5c5..489d003c8992 100644 --- a/cranelift/filetests/src/test_run.rs +++ b/cranelift/filetests/src/test_run.rs @@ -6,12 +6,12 @@ use crate::function_runner::{CompiledTestFile, TestFileCompiler}; use crate::runone::FileUpdate; use crate::subtest::{Context, SubTest}; use anyhow::Context as _; -use cranelift_chaos::ChaosEngine; use cranelift_codegen::data_value::DataValue; use cranelift_codegen::ir::Type; use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa}; use cranelift_codegen::settings::{Configurable, Flags}; use cranelift_codegen::{ir, settings}; +use cranelift_control::ControlPlane; use cranelift_reader::TestCommand; use cranelift_reader::{parse_run_command, TestFile}; use log::{info, trace}; @@ -37,7 +37,7 @@ fn build_host_isa( isa_flags: Vec, ) -> OwnedTargetIsa { let mut builder = - cranelift_native::builder_with_options(infer_native_flags, ChaosEngine::noop()) + cranelift_native::builder_with_options(infer_native_flags, ControlPlane::noop()) .expect("Unable to build a TargetIsa for the current host"); // Copy ISA Flags diff --git a/cranelift/filetests/src/test_safepoint.rs b/cranelift/filetests/src/test_safepoint.rs index ff2702d50e93..54707328ac90 100644 --- a/cranelift/filetests/src/test_safepoint.rs +++ b/cranelift/filetests/src/test_safepoint.rs @@ -1,6 +1,6 @@ use crate::subtest::{run_filecheck, Context, SubTest}; -use cranelift_chaos::ChaosEngine; use cranelift_codegen::ir::Function; +use cranelift_control::ControlPlane; use cranelift_reader::TestCommand; use std::borrow::Cow; @@ -21,7 +21,7 @@ impl SubTest for TestSafepoint { fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { let mut comp_ctx = - cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); + cranelift_codegen::Context::for_function(func.into_owned(), ControlPlane::noop()); let isa = context.isa.expect("register allocator needs an ISA"); comp_ctx.compute_cfg(); diff --git a/cranelift/filetests/src/test_simple_gvn.rs b/cranelift/filetests/src/test_simple_gvn.rs index 6921ebf20494..53784a2dd244 100644 --- a/cranelift/filetests/src/test_simple_gvn.rs +++ b/cranelift/filetests/src/test_simple_gvn.rs @@ -6,9 +6,9 @@ //! The resulting function is sent to `filecheck`. use crate::subtest::{run_filecheck, Context, SubTest}; -use cranelift_chaos::ChaosEngine; use cranelift_codegen; use cranelift_codegen::ir::Function; +use cranelift_control::ControlPlane; use cranelift_reader::TestCommand; use std::borrow::Cow; @@ -33,7 +33,7 @@ impl SubTest for TestSimpleGVN { fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { let mut comp_ctx = - cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); + cranelift_codegen::Context::for_function(func.into_owned(), ControlPlane::noop()); comp_ctx.flowgraph(); comp_ctx diff --git a/cranelift/filetests/src/test_simple_preopt.rs b/cranelift/filetests/src/test_simple_preopt.rs index 48327b612e67..12089187cc3f 100644 --- a/cranelift/filetests/src/test_simple_preopt.rs +++ b/cranelift/filetests/src/test_simple_preopt.rs @@ -3,9 +3,9 @@ //! The resulting function is sent to `filecheck`. use crate::subtest::{run_filecheck, Context, SubTest}; -use cranelift_chaos::ChaosEngine; use cranelift_codegen; use cranelift_codegen::ir::Function; +use cranelift_control::ControlPlane; use cranelift_reader::TestCommand; use std::borrow::Cow; @@ -34,7 +34,7 @@ impl SubTest for TestSimplePreopt { fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { let mut comp_ctx = - cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); + cranelift_codegen::Context::for_function(func.into_owned(), ControlPlane::noop()); let isa = context.isa.expect("preopt needs an ISA"); comp_ctx.compute_cfg(); diff --git a/cranelift/filetests/src/test_unwind.rs b/cranelift/filetests/src/test_unwind.rs index f54637f20253..c75d1e0a1173 100644 --- a/cranelift/filetests/src/test_unwind.rs +++ b/cranelift/filetests/src/test_unwind.rs @@ -4,8 +4,8 @@ #![cfg_attr(feature = "cargo-clippy", allow(clippy::cast_ptr_alignment))] use crate::subtest::{run_filecheck, Context, SubTest}; -use cranelift_chaos::ChaosEngine; use cranelift_codegen::{self, ir, isa::unwind::UnwindInfo}; +use cranelift_control::ControlPlane; use cranelift_reader::TestCommand; use gimli::{ write::{Address, EhFrame, EndianVec, FrameTable}, @@ -39,7 +39,7 @@ impl SubTest for TestUnwind { fn run(&self, func: Cow, context: &Context) -> anyhow::Result<()> { let isa = context.isa.expect("unwind needs an ISA"); let mut comp_ctx = - cranelift_codegen::Context::for_function(func.into_owned(), ChaosEngine::noop()); + cranelift_codegen::Context::for_function(func.into_owned(), ControlPlane::noop()); let code = comp_ctx.compile(isa).expect("failed to compile function"); diff --git a/cranelift/filetests/src/test_wasm.rs b/cranelift/filetests/src/test_wasm.rs index 216fe7f3cf98..522bd5a8fe79 100644 --- a/cranelift/filetests/src/test_wasm.rs +++ b/cranelift/filetests/src/test_wasm.rs @@ -5,7 +5,7 @@ mod env; use anyhow::{bail, ensure, Context, Result}; use config::TestConfig; -use cranelift_chaos::ChaosEngine; +use cranelift_control::ControlPlane; use env::ModuleEnv; use similar::TextDiff; use std::{fmt::Write, path::Path}; @@ -57,7 +57,7 @@ pub fn run(path: &Path, wat: &str) -> Result<()> { for (_index, func) in env.inner.info.function_bodies.iter() { if config.compile { let mut ctx = - cranelift_codegen::Context::for_function(func.clone(), ChaosEngine::noop()); + cranelift_codegen::Context::for_function(func.clone(), ControlPlane::noop()); ctx.set_disasm(true); let code = ctx .compile(isa) @@ -66,7 +66,7 @@ pub fn run(path: &Path, wat: &str) -> Result<()> { writeln!(&mut actual, "{}", code.vcode.as_ref().unwrap()).unwrap(); } else if config.optimize { let mut ctx = - cranelift_codegen::Context::for_function(func.clone(), ChaosEngine::noop()); + cranelift_codegen::Context::for_function(func.clone(), ControlPlane::noop()); ctx.optimize(isa) .map_err(|e| crate::pretty_anyhow_error(&ctx.func, e))?; writeln!(&mut actual, "{}", ctx.func.display()).unwrap(); diff --git a/cranelift/fuzzgen/Cargo.toml b/cranelift/fuzzgen/Cargo.toml index 3831f4db7993..b5ecdac53c26 100644 --- a/cranelift/fuzzgen/Cargo.toml +++ b/cranelift/fuzzgen/Cargo.toml @@ -13,7 +13,7 @@ publish = false [dependencies] cranelift = { workspace = true } cranelift-native = { workspace = true } -cranelift-chaos = { workspace = true } +cranelift-control = { workspace = true } anyhow = { workspace = true } arbitrary = "1.0.0" @@ -21,4 +21,4 @@ once_cell = { workspace = true } target-lexicon = { workspace = true, features = ["std"] } [features] -chaos = ["cranelift-chaos/chaos"] +chaos = ["cranelift-control/chaos"] diff --git a/cranelift/fuzzgen/src/lib.rs b/cranelift/fuzzgen/src/lib.rs index 4c3859d9ebf3..cb8642562c79 100644 --- a/cranelift/fuzzgen/src/lib.rs +++ b/cranelift/fuzzgen/src/lib.rs @@ -11,7 +11,7 @@ use cranelift::codegen::Context; use cranelift::prelude::settings::SettingKind; use cranelift::prelude::*; use cranelift_arbitrary::CraneliftArbitrary; -use cranelift_chaos::ChaosEngine; +use cranelift_control::ControlPlane; use cranelift_native::builder_with_options; use target_lexicon::{Architecture, Triple}; @@ -40,7 +40,7 @@ where { pub u: &'r mut Unstructured<'data>, pub config: Config, - pub chaos_eng: ChaosEngine, + pub control_plane: ControlPlane, } impl<'r, 'data> FuzzGen<'r, 'data> @@ -49,14 +49,14 @@ where { pub fn new(u: &'r mut Unstructured<'data>) -> anyhow::Result { #[cfg(feature = "chaos")] - let chaos_eng = u.arbitrary()?; + let control_plane = u.arbitrary()?; #[cfg(not(feature = "chaos"))] - let chaos_eng = cranelift_chaos::ChaosEngine::noop(); + let control_plane = cranelift_control::ControlPlane::noop(); Ok(Self { u, config: Config::default(), - chaos_eng, + control_plane, }) } @@ -114,7 +114,7 @@ where // This is something that we can enable via flags for the compiled version, however // the interpreter won't get that version, so call that pass manually here. - let mut ctx = Context::for_function(func, self.chaos_eng.clone()); + let mut ctx = Context::for_function(func, self.control_plane.clone()); // Assume that we are generating this function for the current ISA. // We disable the verifier here, since if it fails it prevents a test case from // being generated and formatted by `cargo fuzz fmt`. @@ -125,7 +125,7 @@ where builder }); - let isa = builder_with_options(false, self.chaos_eng.clone()) + let isa = builder_with_options(false, self.control_plane.clone()) .expect("Unable to build a TargetIsa for the current host") .finish(flags) .expect("Failed to build TargetISA"); diff --git a/cranelift/jit/Cargo.toml b/cranelift/jit/Cargo.toml index 7b83bc565b36..7a23aa3a57d4 100644 --- a/cranelift/jit/Cargo.toml +++ b/cranelift/jit/Cargo.toml @@ -14,7 +14,7 @@ cranelift-module = { workspace = true } cranelift-native = { workspace = true } cranelift-codegen = { workspace = true, features = ["std"] } cranelift-entity = { workspace = true } -cranelift-chaos = { workspace = true } +cranelift-control = { workspace = true } anyhow = { workspace = true } region = "2.2.0" libc = { version = "0.2.42" } diff --git a/cranelift/jit/src/backend.rs b/cranelift/jit/src/backend.rs index 33182c36ff5d..becfa4594dc3 100644 --- a/cranelift/jit/src/backend.rs +++ b/cranelift/jit/src/backend.rs @@ -1,11 +1,11 @@ //! Defines `JITModule`. use crate::{compiled_blob::CompiledBlob, memory::BranchProtection, memory::Memory}; -use cranelift_chaos::ChaosEngine; use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa}; use cranelift_codegen::settings::Configurable; use cranelift_codegen::{self, ir, settings, MachReloc}; use cranelift_codegen::{binemit::Reloc, CodegenError}; +use cranelift_control::ControlPlane; use cranelift_entity::SecondaryMap; use cranelift_module::{ DataContext, DataDescription, DataId, FuncId, Init, Linkage, Module, ModuleCompiledFunction, @@ -921,7 +921,7 @@ impl Module for JITModule { } fn make_context(&self) -> cranelift_codegen::Context { - let mut ctx = cranelift_codegen::Context::new(ChaosEngine::noop()); + let mut ctx = cranelift_codegen::Context::new(ControlPlane::noop()); ctx.func.signature.call_conv = self.isa().default_call_conv(); ctx } diff --git a/cranelift/module/Cargo.toml b/cranelift/module/Cargo.toml index c58bc07b0b3c..cdf613de80e3 100644 --- a/cranelift/module/Cargo.toml +++ b/cranelift/module/Cargo.toml @@ -12,7 +12,7 @@ edition.workspace = true [dependencies] cranelift-codegen = { workspace = true } -cranelift-chaos = { workspace = true } +cranelift-control = { workspace = true } hashbrown = { workspace = true, optional = true } anyhow = { workspace = true } diff --git a/cranelift/module/src/module.rs b/cranelift/module/src/module.rs index 40c1c997fb1f..abb7b7887899 100644 --- a/cranelift/module/src/module.rs +++ b/cranelift/module/src/module.rs @@ -8,13 +8,13 @@ use super::HashMap; use crate::data_context::DataContext; use core::fmt::Display; -use cranelift_chaos::ChaosEngine; use cranelift_codegen::binemit::{CodeOffset, Reloc}; use cranelift_codegen::entity::{entity_impl, PrimaryMap}; use cranelift_codegen::ir::Function; use cranelift_codegen::settings::SetError; use cranelift_codegen::{binemit, MachReloc}; use cranelift_codegen::{ir, isa, CodegenError, CompileError, Context}; +use cranelift_control::ControlPlane; use std::borrow::ToOwned; use std::string::String; @@ -551,7 +551,7 @@ pub trait Module { /// This ensures that the `Context` is initialized with the default calling /// convention for the `TargetIsa`. fn make_context(&self) -> Context { - let mut ctx = Context::new(ChaosEngine::noop()); + let mut ctx = Context::new(ControlPlane::noop()); ctx.func.signature.call_conv = self.isa().default_call_conv(); ctx } diff --git a/cranelift/native/Cargo.toml b/cranelift/native/Cargo.toml index f2031162832f..58f8f7ede828 100644 --- a/cranelift/native/Cargo.toml +++ b/cranelift/native/Cargo.toml @@ -12,7 +12,7 @@ edition.workspace = true [dependencies] cranelift-codegen = { workspace = true } -cranelift-chaos = { workspace = true } +cranelift-control = { workspace = true } target-lexicon = { workspace = true } [target.'cfg(any(target_arch = "s390x", target_arch = "riscv64"))'.dependencies] @@ -25,3 +25,4 @@ core = ["cranelift-codegen/core"] [badges] maintenance = { status = "experimental" } + diff --git a/cranelift/native/src/lib.rs b/cranelift/native/src/lib.rs index 5f01f7d14dad..bbb3b8e942de 100644 --- a/cranelift/native/src/lib.rs +++ b/cranelift/native/src/lib.rs @@ -23,16 +23,16 @@ ) )] -use cranelift_chaos::ChaosEngine; use cranelift_codegen::isa; use cranelift_codegen::settings::Configurable; +use cranelift_control::ControlPlane; use target_lexicon::Triple; /// Return an `isa` builder configured for the current host /// machine, or `Err(())` if the host machine is not supported /// in the current configuration. pub fn builder() -> Result { - builder_with_options(true, ChaosEngine::noop()) + builder_with_options(true, ControlPlane::noop()) } /// Return an `isa` builder configured for the current host @@ -44,9 +44,9 @@ pub fn builder() -> Result { /// (e.g., on x86-64). pub fn builder_with_options( infer_native_flags: bool, - chaos_eng: ChaosEngine, + control_plane: ControlPlane, ) -> Result { - let mut isa_builder = isa::lookup(Triple::host(), chaos_eng).map_err(|err| match err { + let mut isa_builder = isa::lookup(Triple::host(), control_plane).map_err(|err| match err { isa::LookupError::SupportDisabled => "support for architecture disabled at compile time", isa::LookupError::Unsupported => "unsupported architecture", })?; diff --git a/cranelift/object/Cargo.toml b/cranelift/object/Cargo.toml index aa598830d7bb..84bd558ecee6 100644 --- a/cranelift/object/Cargo.toml +++ b/cranelift/object/Cargo.toml @@ -12,7 +12,7 @@ edition.workspace = true [dependencies] cranelift-module = { workspace = true } cranelift-codegen = { workspace = true, features = ["std"] } -cranelift-chaos = { workspace = true } +cranelift-control = { workspace = true } object = { workspace = true, features = ["write"] } target-lexicon = { workspace = true } anyhow = { workspace = true } diff --git a/cranelift/object/tests/basic.rs b/cranelift/object/tests/basic.rs index 90f91e7780b5..e3a2171bad6e 100644 --- a/cranelift/object/tests/basic.rs +++ b/cranelift/object/tests/basic.rs @@ -1,8 +1,8 @@ -use cranelift_chaos::ChaosEngine; use cranelift_codegen::ir::*; use cranelift_codegen::isa::CallConv; use cranelift_codegen::settings; use cranelift_codegen::{ir::types::I16, Context}; +use cranelift_control::ControlPlane; use cranelift_entity::EntityRef; use cranelift_frontend::*; use cranelift_module::*; @@ -12,7 +12,7 @@ use cranelift_object::*; fn error_on_incompatible_sig_in_declare_function() { let flag_builder = settings::builder(); let isa_builder = - cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ChaosEngine::noop()) + cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ControlPlane::noop()) .unwrap(); let isa = isa_builder .finish(settings::Flags::new(flag_builder)) @@ -45,7 +45,7 @@ fn define_simple_function(module: &mut ObjectModule) -> FuncId { .declare_function("abc", Linkage::Local, &sig) .unwrap(); - let mut ctx = Context::new(ChaosEngine::noop()); + let mut ctx = Context::new(ControlPlane::noop()); ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), sig); let mut func_ctx = FunctionBuilderContext::new(); { @@ -65,7 +65,7 @@ fn define_simple_function(module: &mut ObjectModule) -> FuncId { fn panic_on_define_after_finalize() { let flag_builder = settings::builder(); let isa_builder = - cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ChaosEngine::noop()) + cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ControlPlane::noop()) .unwrap(); let isa = isa_builder .finish(settings::Flags::new(flag_builder)) @@ -153,7 +153,7 @@ fn switch_error() { fn libcall_function() { let flag_builder = settings::builder(); let isa_builder = - cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ChaosEngine::noop()) + cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ControlPlane::noop()) .unwrap(); let isa = isa_builder .finish(settings::Flags::new(flag_builder)) @@ -171,7 +171,7 @@ fn libcall_function() { .declare_function("function", Linkage::Local, &sig) .unwrap(); - let mut ctx = Context::new(ChaosEngine::noop()); + let mut ctx = Context::new(ControlPlane::noop()); ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), sig); let mut func_ctx = FunctionBuilderContext::new(); { @@ -209,7 +209,7 @@ fn libcall_function() { fn reject_nul_byte_symbol_for_func() { let flag_builder = settings::builder(); let isa_builder = - cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ChaosEngine::noop()) + cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ControlPlane::noop()) .unwrap(); let isa = isa_builder .finish(settings::Flags::new(flag_builder)) @@ -233,7 +233,7 @@ fn reject_nul_byte_symbol_for_func() { fn reject_nul_byte_symbol_for_data() { let flag_builder = settings::builder(); let isa_builder = - cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ChaosEngine::noop()) + cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu", ControlPlane::noop()) .unwrap(); let isa = isa_builder .finish(settings::Flags::new(flag_builder)) diff --git a/cranelift/reader/Cargo.toml b/cranelift/reader/Cargo.toml index 13c0f0f9a28a..c3052e1352f9 100644 --- a/cranelift/reader/Cargo.toml +++ b/cranelift/reader/Cargo.toml @@ -12,7 +12,7 @@ edition.workspace = true [dependencies] anyhow.workspace = true cranelift-codegen = { workspace = true } -cranelift-chaos = { workspace = true } +cranelift-control = { workspace = true } smallvec = { workspace = true } target-lexicon = { workspace = true } diff --git a/cranelift/reader/src/lib.rs b/cranelift/reader/src/lib.rs index 30cb8cf8e610..a39233505692 100644 --- a/cranelift/reader/src/lib.rs +++ b/cranelift/reader/src/lib.rs @@ -43,9 +43,9 @@ mod testcommand; mod testfile; use anyhow::{Error, Result}; -use cranelift_chaos::ChaosEngine; use cranelift_codegen::isa::{self, OwnedTargetIsa}; use cranelift_codegen::settings::{self, FlagsOrIsa}; +use cranelift_control::ControlPlane; use std::str::FromStr; use target_lexicon::Triple; @@ -97,7 +97,7 @@ pub fn parse_sets_and_triple(flag_set: &[String], flag_triple: &str) -> Result { anyhow::anyhow!("support for triple '{}' is disabled", triple_name) } diff --git a/cranelift/reader/src/parser.rs b/cranelift/reader/src/parser.rs index 2ca01d168ddf..842cc0e0304c 100644 --- a/cranelift/reader/src/parser.rs +++ b/cranelift/reader/src/parser.rs @@ -7,7 +7,6 @@ use crate::run_command::{Comparison, Invocation, RunCommand}; use crate::sourcemap::SourceMap; use crate::testcommand::TestCommand; use crate::testfile::{Comment, Details, Feature, TestFile}; -use cranelift_chaos::ChaosEngine; use cranelift_codegen::data_value::DataValue; use cranelift_codegen::entity::{EntityRef, PrimaryMap}; use cranelift_codegen::ir::entities::{AnyEntity, DynamicType}; @@ -25,6 +24,7 @@ use cranelift_codegen::ir::{ use cranelift_codegen::isa::{self, CallConv}; use cranelift_codegen::packed_option::ReservedValue; use cranelift_codegen::{settings, settings::Configurable, timing}; +use cranelift_control::ControlPlane; use smallvec::SmallVec; use std::mem; use std::str::FromStr; @@ -996,7 +996,7 @@ impl<'a> Parser<'a> { Ok(triple) => triple, Err(err) => return err!(loc, err), }; - let isa_builder = match isa::lookup(triple, ChaosEngine::noop()) { + let isa_builder = match isa::lookup(triple, ControlPlane::noop()) { Err(isa::LookupError::SupportDisabled) => { return err!(loc, "support disabled target '{}'", targ); } @@ -1085,7 +1085,7 @@ impl<'a> Parser<'a> { Ok(triple) => triple, Err(err) => return err!(loc, err), }; - let mut isa_builder = match isa::lookup(triple, ChaosEngine::noop()) { + let mut isa_builder = match isa::lookup(triple, ControlPlane::noop()) { Err(isa::LookupError::SupportDisabled) => { continue; } diff --git a/crates/cranelift/Cargo.toml b/crates/cranelift/Cargo.toml index 9e11bc4c8c78..40a0a9bfc2d6 100644 --- a/crates/cranelift/Cargo.toml +++ b/crates/cranelift/Cargo.toml @@ -19,7 +19,7 @@ cranelift-codegen = { workspace = true } cranelift-frontend = { workspace = true } cranelift-entity = { workspace = true } cranelift-native = { workspace = true } -cranelift-chaos = { workspace = true } +cranelift-control = { workspace = true } wasmtime-cranelift-shared = { workspace = true } wasmparser = { workspace = true } target-lexicon = { workspace = true } diff --git a/crates/cranelift/src/builder.rs b/crates/cranelift/src/builder.rs index a4e62a09101c..1754943fa6cd 100644 --- a/crates/cranelift/src/builder.rs +++ b/crates/cranelift/src/builder.rs @@ -4,11 +4,11 @@ //! well as providing a function to return the default configuration to build. use anyhow::Result; -use cranelift_chaos::ChaosEngine; use cranelift_codegen::{ isa::{self, OwnedTargetIsa}, CodegenResult, }; +use cranelift_control::ControlPlane; use std::fmt; use std::sync::Arc; use wasmtime_cranelift_shared::isa_builder::IsaBuilder; @@ -36,7 +36,7 @@ pub struct LinkOptions { pub fn builder() -> Box { Box::new(Builder { inner: IsaBuilder::new(|triple| { - isa::lookup(triple, ChaosEngine::noop()).map_err(|e| e.into()) + isa::lookup(triple, ControlPlane::noop()).map_err(|e| e.into()) }), linkopts: LinkOptions::default(), cache_store: None, diff --git a/crates/cranelift/src/compiler.rs b/crates/cranelift/src/compiler.rs index 39264ac4a06d..2b08acd22593 100644 --- a/crates/cranelift/src/compiler.rs +++ b/crates/cranelift/src/compiler.rs @@ -5,7 +5,6 @@ use crate::{ wasmtime_call_conv, CompiledFunction, FunctionAddressMap, }; use anyhow::{Context as _, Result}; -use cranelift_chaos::ChaosEngine; use cranelift_codegen::ir::{ self, ExternalName, Function, InstBuilder, MemFlags, UserExternalName, UserFuncName, Value, }; @@ -14,6 +13,7 @@ use cranelift_codegen::print_errors::pretty_error; use cranelift_codegen::Context; use cranelift_codegen::{CompiledCode, MachSrcLoc, MachStackMap}; use cranelift_codegen::{MachReloc, MachTrap}; +use cranelift_control::ControlPlane; use cranelift_entity::{EntityRef, PrimaryMap}; use cranelift_frontend::FunctionBuilder; use cranelift_wasm::{ @@ -58,7 +58,7 @@ impl Default for CompilerContext { fn default() -> Self { Self { func_translator: FuncTranslator::new(), - codegen_context: Context::new(ChaosEngine::noop()), + codegen_context: Context::new(ControlPlane::noop()), incremental_cache_ctx: None, validator_allocations: Default::default(), } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 5d8cbbb26ef0..7909dfcdcaf7 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -17,7 +17,7 @@ cranelift-filetests = { workspace = true } cranelift-interpreter = { workspace = true } cranelift-fuzzgen = { workspace = true } cranelift-native = { workspace = true } -cranelift-chaos = { workspace = true } +cranelift-control = { workspace = true } libfuzzer-sys = { version = "0.4.0", features = ["arbitrary-derive"] } target-lexicon = { workspace = true } smallvec = { workspace = true } @@ -38,8 +38,8 @@ component-fuzz-util = { workspace = true } default = ['fuzz-spec-interpreter'] fuzz-spec-interpreter = ['wasmtime-fuzzing/fuzz-spec-interpreter'] chaos = [ - "cranelift-chaos/chaos", "cranelift-codegen/chaos", + "cranelift-control/chaos", "cranelift-fuzzgen/chaos", ] diff --git a/fuzz/fuzz_targets/cranelift-fuzzgen.rs b/fuzz/fuzz_targets/cranelift-fuzzgen.rs index 64225445fd14..ee322cb884fd 100644 --- a/fuzz/fuzz_targets/cranelift-fuzzgen.rs +++ b/fuzz/fuzz_targets/cranelift-fuzzgen.rs @@ -179,7 +179,7 @@ impl TestCase { // TestCase is meant to be consumed by a runner, so we make the assumption here that we're // generating a TargetIsa for the host. - let mut builder = builder_with_options(true, gen.chaos_eng.clone()) + let mut builder = builder_with_options(true, gen.control_plane.clone()) .expect("Unable to build a TargetIsa for the current host"); let flags = gen.generate_flags(builder.triple().architecture)?; gen.set_isa_flags(&mut builder, IsaFlagGen::Host)?; diff --git a/fuzz/fuzz_targets/cranelift-icache.rs b/fuzz/fuzz_targets/cranelift-icache.rs index 497329f99349..49eb7b06786c 100644 --- a/fuzz/fuzz_targets/cranelift-icache.rs +++ b/fuzz/fuzz_targets/cranelift-icache.rs @@ -1,6 +1,5 @@ #![no_main] -use cranelift_chaos::ChaosEngine; use cranelift_codegen::{ cursor::{Cursor, FuncCursor}, incremental_cache as icache, @@ -10,6 +9,7 @@ use cranelift_codegen::{ }, isa, Context, }; +use cranelift_control::ControlPlane; use libfuzzer_sys::{ arbitrary::{self, Arbitrary, Unstructured}, fuzz_target, @@ -41,7 +41,7 @@ pub struct FunctionWithIsa { /// Function under test pub func: Function, - chaos_eng: ChaosEngine, + control_plane: ControlPlane, } impl FunctionWithIsa { @@ -52,7 +52,7 @@ impl FunctionWithIsa { // configurations. let target = u.choose(isa::ALL_ARCHITECTURES)?; let mut gen = FuzzGen::new(u)?; - let mut builder = isa::lookup_by_name(target, gen.chaos_eng.clone()) + let mut builder = isa::lookup_by_name(target, gen.control_plane.clone()) .map_err(|_| arbitrary::Error::IncorrectFormat)?; let architecture = builder.triple().architecture; @@ -90,7 +90,7 @@ impl FunctionWithIsa { Ok(FunctionWithIsa { isa, func, - chaos_eng: gen.chaos_eng, + control_plane: gen.control_plane, }) } } @@ -113,12 +113,12 @@ fuzz_target!(|func: FunctionWithIsa| { let FunctionWithIsa { mut func, isa, - chaos_eng, + control_plane, } = func; let cache_key_hash = icache::compute_cache_key(&*isa, &func); - let mut context = Context::for_function(func.clone(), chaos_eng.clone()); + let mut context = Context::for_function(func.clone(), control_plane.clone()); let prev_stencil = match context.compile_stencil(&*isa) { Ok(stencil) => stencil, Err(_) => return, @@ -208,7 +208,7 @@ fuzz_target!(|func: FunctionWithIsa| { assert!(cache_key_hash != new_cache_key_hash); } - context = Context::for_function(func.clone(), chaos_eng); + context = Context::for_function(func.clone(), control_plane); let after_mutation_result = match context.compile(&*isa) { Ok(info) => info, From dfa059426d617946e9bc698e39e821958084f902 Mon Sep 17 00:00:00 2001 From: Moritz Waser Date: Wed, 22 Mar 2023 14:10:14 +0100 Subject: [PATCH 04/14] chaos mode: refactoring ControlPlane to be passed through the call stack by reference Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com> Co-authored-by: Remo Senekowitsch --- Cargo.lock | 1 + cranelift/codegen/src/context.rs | 38 +- .../codegen/src/isa/aarch64/inst/emit.rs | 104 ++-- .../src/isa/aarch64/inst/emit_tests.rs | 12 +- .../src/isa/aarch64/inst/unwind/systemv.rs | 9 +- cranelift/codegen/src/isa/aarch64/mod.rs | 27 +- cranelift/codegen/src/isa/mod.rs | 35 +- .../codegen/src/isa/riscv64/inst/emit.rs | 537 ++++++++++-------- .../src/isa/riscv64/inst/emit_tests.rs | 25 +- .../src/isa/riscv64/inst/unwind/systemv.rs | 9 +- cranelift/codegen/src/isa/riscv64/mod.rs | 27 +- cranelift/codegen/src/isa/s390x/inst/emit.rs | 107 +++- .../codegen/src/isa/s390x/inst/emit_tests.rs | 16 +- .../src/isa/s390x/inst/unwind/systemv.rs | 9 +- cranelift/codegen/src/isa/s390x/mod.rs | 33 +- cranelift/codegen/src/isa/x64/encoding/vex.rs | 14 +- cranelift/codegen/src/isa/x64/inst/emit.rs | 193 ++++--- .../codegen/src/isa/x64/inst/emit_tests.rs | 13 +- cranelift/codegen/src/isa/x64/inst/mod.rs | 4 +- .../src/isa/x64/inst/unwind/systemv.rs | 19 +- cranelift/codegen/src/isa/x64/mod.rs | 33 +- cranelift/codegen/src/machinst/buffer.rs | 257 +++++---- cranelift/codegen/src/machinst/compile.rs | 12 +- cranelift/codegen/src/machinst/lower.rs | 3 - cranelift/codegen/src/machinst/mod.rs | 12 +- cranelift/codegen/src/machinst/vcode.rs | 70 ++- cranelift/control/src/chaos.rs | 175 +----- cranelift/control/src/zero_sized.rs | 11 +- cranelift/filetests/src/function_runner.rs | 26 +- .../filetests/src/test_alias_analysis.rs | 4 +- cranelift/filetests/src/test_compile.rs | 4 +- cranelift/filetests/src/test_dce.rs | 4 +- cranelift/filetests/src/test_legalizer.rs | 4 +- cranelift/filetests/src/test_licm.rs | 4 +- cranelift/filetests/src/test_optimize.rs | 4 +- cranelift/filetests/src/test_run.rs | 8 +- cranelift/filetests/src/test_safepoint.rs | 4 +- cranelift/filetests/src/test_simple_gvn.rs | 4 +- cranelift/filetests/src/test_simple_preopt.rs | 4 +- cranelift/filetests/src/test_unwind.rs | 4 +- cranelift/filetests/src/test_wasm.rs | 7 +- cranelift/fuzzgen/src/lib.rs | 12 +- cranelift/jit/src/backend.rs | 3 +- cranelift/jit/tests/basic.rs | 28 +- cranelift/module/src/module.rs | 3 +- cranelift/native/src/lib.rs | 10 +- cranelift/object/tests/basic.rs | 55 +- cranelift/reader/src/lib.rs | 20 +- cranelift/reader/src/parser.rs | 5 +- crates/cranelift-shared/Cargo.toml | 1 + crates/cranelift-shared/src/obj.rs | 10 +- crates/cranelift/src/builder.rs | 5 +- crates/cranelift/src/compiler.rs | 6 +- fuzz/fuzz_targets/cranelift-fuzzgen.rs | 11 +- 54 files changed, 1070 insertions(+), 985 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d8625d487f9f..6a8d002cd639 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3620,6 +3620,7 @@ version = "8.0.0" dependencies = [ "anyhow", "cranelift-codegen", + "cranelift-control", "cranelift-native", "gimli", "object", diff --git a/cranelift/codegen/src/context.rs b/cranelift/codegen/src/context.rs index 6077b3e77693..6c686a79dc35 100644 --- a/cranelift/codegen/src/context.rs +++ b/cranelift/codegen/src/context.rs @@ -58,9 +58,8 @@ pub struct Context { /// Flag: do we want a disassembly with the CompiledCode? pub want_disasm: bool, - /// Only used during fuzz-testing. Otherwise, this is a zero-sized struct - /// and compiled away. See [cranelift_control]. - control_plane: ControlPlane, + /// TODO chaos: is this the right location to hold ownership? + pub ctrl_plane: ControlPlane, } impl Context { @@ -68,15 +67,20 @@ impl Context { /// /// The returned instance should be reused for compiling multiple functions in order to avoid /// needless allocator thrashing. - pub fn new(control_plane: ControlPlane) -> Self { - Self::for_function(Function::new(), control_plane) + pub fn new() -> Self { + Self::for_function(Function::new()) + } + + /// TODO: + pub fn new_with_ctrl_plane(ctrl_plane: ControlPlane) -> Self { + Self::for_function_with_ctrl_plane(Function::new(), ctrl_plane) } /// Allocate a new compilation context with an existing Function. /// /// The returned instance should be reused for compiling multiple functions in order to avoid /// needless allocator thrashing. - pub fn for_function(func: Function, control_plane: ControlPlane) -> Self { + pub fn for_function(func: Function) -> Self { Self { func, cfg: ControlFlowGraph::new(), @@ -84,7 +88,20 @@ impl Context { loop_analysis: LoopAnalysis::new(), compiled_code: None, want_disasm: false, - control_plane, + ctrl_plane: ControlPlane::default(), + } + } + + /// TODO: + pub fn for_function_with_ctrl_plane(func: Function, ctrl_plane: ControlPlane) -> Self { + Self { + func, + cfg: ControlFlowGraph::new(), + domtree: DominatorTree::new(), + loop_analysis: LoopAnalysis::new(), + compiled_code: None, + want_disasm: false, + ctrl_plane, } } @@ -146,7 +163,12 @@ impl Context { self.optimize(isa)?; - isa.compile_function(&self.func, &self.domtree, self.want_disasm) + isa.compile_function( + &self.func, + &self.domtree, + self.want_disasm, + &mut self.ctrl_plane, + ) } /// Optimize the function, performing all compilation steps up to diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs index 2e576fc895c9..a88ae26429cd 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -1,5 +1,6 @@ //! AArch64 ISA: binary code emission. +use cranelift_control::ControlPlane; use regalloc2::Allocation; use crate::binemit::{Reloc, StackMap}; @@ -693,6 +694,7 @@ impl MachInstEmit for Inst { sink: &mut MachBuffer, emit_info: &Self::Info, state: &mut EmitState, + ctrl_plane: &mut ControlPlane, ) { let mut allocs = AllocationConsumer::new(allocs); @@ -954,7 +956,7 @@ impl MachInstEmit for Inst { let (mem_insts, mem) = mem_finalize(Some(sink), &mem, state); for inst in mem_insts.into_iter() { - inst.emit(&[], sink, emit_info, state); + inst.emit(&[], sink, emit_info, state, ctrl_plane); } // ldst encoding helpers take Reg, not Writable. @@ -1099,7 +1101,7 @@ impl MachInstEmit for Inst { let (mem_insts, mem) = mem_finalize(Some(sink), &mem, state); for inst in mem_insts.into_iter() { - inst.emit(&[], sink, emit_info, state); + inst.emit(&[], sink, emit_info, state, ctrl_plane); } let (op, bits) = match self { @@ -1391,7 +1393,7 @@ impl MachInstEmit for Inst { assert!(rm.class() == RegClass::Int); assert!(rd.to_reg().class() == rm.class()); let size = OperandSize::Size64; - Inst::Mov { size, rd, rm }.emit(&[], sink, emit_info, state); + Inst::Mov { size, rd, rm }.emit(&[], sink, emit_info, state, ctrl_plane); } &Inst::MovToPReg { rd, rm } => { allocs.next_fixed_nonallocatable(rd); @@ -1407,7 +1409,7 @@ impl MachInstEmit for Inst { assert!(rd.to_reg().class() == RegClass::Int); assert!(rm.class() == rd.to_reg().class()); let size = OperandSize::Size64; - Inst::Mov { size, rd, rm }.emit(&[], sink, emit_info, state); + Inst::Mov { size, rd, rm }.emit(&[], sink, emit_info, state, ctrl_plane); } &Inst::MovWide { op, rd, imm, size } => { let rd = allocs.next_writable(rd); @@ -1511,7 +1513,7 @@ impl MachInstEmit for Inst { let again_label = sink.get_label(); // again: - sink.bind_label(again_label); + sink.bind_label(again_label, ctrl_plane); let srcloc = state.cur_srcloc(); if !srcloc.is_default() && !flags.notrap() { @@ -1539,7 +1541,7 @@ impl MachInstEmit for Inst { from_bits, to_bits: size.bits(), } - .emit(&[], sink, emit_info, state); + .emit(&[], sink, emit_info, state, ctrl_plane); } match op { @@ -1555,7 +1557,7 @@ impl MachInstEmit for Inst { rn: x27, rm: x26, } - .emit(&[], sink, emit_info, state); + .emit(&[], sink, emit_info, state, ctrl_plane); Inst::AluRRR { alu_op: ALUOp::OrrNot, @@ -1564,7 +1566,7 @@ impl MachInstEmit for Inst { rn: xzr, rm: x28, } - .emit(&[], sink, emit_info, state); + .emit(&[], sink, emit_info, state, ctrl_plane); } AtomicRMWLoopOp::Umin | AtomicRMWLoopOp::Umax @@ -1591,7 +1593,13 @@ impl MachInstEmit for Inst { rm: x26, extendop, } - .emit(&[], sink, emit_info, state); + .emit( + &[], + sink, + emit_info, + state, + ctrl_plane, + ); } else { Inst::AluRRR { alu_op: ALUOp::SubS, @@ -1600,7 +1608,13 @@ impl MachInstEmit for Inst { rn: x27, rm: x26, } - .emit(&[], sink, emit_info, state); + .emit( + &[], + sink, + emit_info, + state, + ctrl_plane, + ); } Inst::CSel { @@ -1609,7 +1623,7 @@ impl MachInstEmit for Inst { rn: x27, rm: x26, } - .emit(&[], sink, emit_info, state); + .emit(&[], sink, emit_info, state, ctrl_plane); } _ => { // add/sub/and/orr/eor x28, x27, x26 @@ -1634,7 +1648,7 @@ impl MachInstEmit for Inst { rn: x27, rm: x26, } - .emit(&[], sink, emit_info, state); + .emit(&[], sink, emit_info, state, ctrl_plane); } } @@ -1713,7 +1727,7 @@ impl MachInstEmit for Inst { let out_label = sink.get_label(); // again: - sink.bind_label(again_label); + sink.bind_label(again_label, ctrl_plane); let srcloc = state.cur_srcloc(); if !srcloc.is_default() && !flags.notrap() { @@ -1762,7 +1776,7 @@ impl MachInstEmit for Inst { sink.use_label_at_offset(br_again_offset, again_label, LabelUse::Branch19); // out: - sink.bind_label(out_label); + sink.bind_label(out_label, ctrl_plane); } &Inst::LoadAcquire { access_ty, @@ -2968,13 +2982,13 @@ impl MachInstEmit for Inst { sink.put4(enc_jump26(0b000101, 0 /* will be fixed up later */)); // else: - sink.bind_label(else_label); + sink.bind_label(else_label, ctrl_plane); // mov rd, rn sink.put4(enc_vecmov(/* 16b = */ true, rd, rn)); // out: - sink.bind_label(out_label); + sink.bind_label(out_label, ctrl_plane); } &Inst::MovToNZCV { rn } => { let rn = allocs.next(rn); @@ -3006,7 +3020,7 @@ impl MachInstEmit for Inst { rn, imml, } - .emit(&[], sink, emit_info, state); + .emit(&[], sink, emit_info, state, ctrl_plane); } &Inst::Extend { rd, @@ -3022,7 +3036,7 @@ impl MachInstEmit for Inst { rd, rm: rn, }; - mov.emit(&[], sink, emit_info, state); + mov.emit(&[], sink, emit_info, state, ctrl_plane); } &Inst::Extend { rd, @@ -3065,7 +3079,7 @@ impl MachInstEmit for Inst { if is_hint { sink.put4(0xd50323bf | key << 6); // autiasp / autibsp - Inst::Ret { rets: vec![] }.emit(&[], sink, emit_info, state); + Inst::Ret { rets: vec![] }.emit(&[], sink, emit_info, state, ctrl_plane); } else { sink.put4(0xd65f0bff | key << 10); // retaa / retab } @@ -3200,13 +3214,13 @@ impl MachInstEmit for Inst { rn: zero_reg(), rm: ridx, }; - inst.emit(&[], sink, emit_info, state); + inst.emit(&[], sink, emit_info, state, ctrl_plane); // Prevent any data value speculation. - Inst::Csdb.emit(&[], sink, emit_info, state); + Inst::Csdb.emit(&[], sink, emit_info, state, ctrl_plane); // Load address of jump table let inst = Inst::Adr { rd: rtmp1, off: 16 }; - inst.emit(&[], sink, emit_info, state); + inst.emit(&[], sink, emit_info, state, ctrl_plane); // Load value out of jump table let inst = Inst::SLoad32 { rd: rtmp2, @@ -3218,7 +3232,7 @@ impl MachInstEmit for Inst { ), flags: MemFlags::trusted(), }; - inst.emit(&[], sink, emit_info, state); + inst.emit(&[], sink, emit_info, state, ctrl_plane); // Add base of jump table to jump-table-sourced block offset let inst = Inst::AluRRR { alu_op: ALUOp::Add, @@ -3227,14 +3241,14 @@ impl MachInstEmit for Inst { rn: rtmp1.to_reg(), rm: rtmp2.to_reg(), }; - inst.emit(&[], sink, emit_info, state); + inst.emit(&[], sink, emit_info, state, ctrl_plane); // Branch to computed address. (`targets` here is only used for successor queries // and is not needed for emission.) let inst = Inst::IndirectBr { rn: rtmp1.to_reg(), targets: vec![], }; - inst.emit(&[], sink, emit_info, state); + inst.emit(&[], sink, emit_info, state, ctrl_plane); // Emit jump table (table of 32-bit offsets). let jt_off = sink.cur_offset(); for &target in info.targets.iter() { @@ -3274,7 +3288,7 @@ impl MachInstEmit for Inst { // adrp rd, symbol sink.add_reloc(Reloc::Aarch64AdrGotPage21, name, 0); let inst = Inst::Adrp { rd, off: 0 }; - inst.emit(&[], sink, emit_info, state); + inst.emit(&[], sink, emit_info, state, ctrl_plane); // ldr rd, [rd, :got_lo12:X] sink.add_reloc(Reloc::Aarch64Ld64GotLo12Nc, name, 0); @@ -3283,7 +3297,7 @@ impl MachInstEmit for Inst { mem: AMode::reg(rd.to_reg()), flags: MemFlags::trusted(), }; - inst.emit(&[], sink, emit_info, state); + inst.emit(&[], sink, emit_info, state, ctrl_plane); } else { // With absolute offsets we set up a load from a preallocated space, and then jump // over it. @@ -3300,11 +3314,11 @@ impl MachInstEmit for Inst { }, flags: MemFlags::trusted(), }; - inst.emit(&[], sink, emit_info, state); + inst.emit(&[], sink, emit_info, state, ctrl_plane); let inst = Inst::Jump { dest: BranchTarget::ResolvedOffset(12), }; - inst.emit(&[], sink, emit_info, state); + inst.emit(&[], sink, emit_info, state, ctrl_plane); sink.add_reloc(Reloc::Abs8, name, offset); sink.put8(0); } @@ -3314,7 +3328,7 @@ impl MachInstEmit for Inst { let mem = mem.with_allocs(&mut allocs); let (mem_insts, mem) = mem_finalize(Some(sink), &mem, state); for inst in mem_insts.into_iter() { - inst.emit(&[], sink, emit_info, state); + inst.emit(&[], sink, emit_info, state, ctrl_plane); } let (reg, index_reg, offset) = match mem { @@ -3349,7 +3363,7 @@ impl MachInstEmit for Inst { extendop, }; - add.emit(&[], sink, emit_info, state); + add.emit(&[], sink, emit_info, state, ctrl_plane); } else if offset == 0 { if reg != rd.to_reg() { let mov = Inst::Mov { @@ -3358,7 +3372,7 @@ impl MachInstEmit for Inst { rm: reg, }; - mov.emit(&[], sink, emit_info, state); + mov.emit(&[], sink, emit_info, state, ctrl_plane); } } else if let Some(imm12) = Imm12::maybe_from_u64(abs_offset) { let add = Inst::AluRRImm12 { @@ -3368,7 +3382,7 @@ impl MachInstEmit for Inst { rn: reg, imm12, }; - add.emit(&[], sink, emit_info, state); + add.emit(&[], sink, emit_info, state, ctrl_plane); } else { // Use `tmp2` here: `reg` may be `spilltmp` if the `AMode` on this instruction // was initially an `SPOffset`. Assert that `tmp2` is truly free to use. Note @@ -3379,7 +3393,7 @@ impl MachInstEmit for Inst { debug_assert!(reg != tmp2_reg()); let tmp = writable_tmp2_reg(); for insn in Inst::load_constant(tmp, abs_offset, &mut |_| tmp).into_iter() { - insn.emit(&[], sink, emit_info, state); + insn.emit(&[], sink, emit_info, state, ctrl_plane); } let add = Inst::AluRRR { alu_op, @@ -3388,7 +3402,7 @@ impl MachInstEmit for Inst { rn: reg, rm: tmp.to_reg(), }; - add.emit(&[], sink, emit_info, state); + add.emit(&[], sink, emit_info, state, ctrl_plane); } } &Inst::Pacisp { key } => { @@ -3424,9 +3438,9 @@ impl MachInstEmit for Inst { let jmp = Inst::Jump { dest: BranchTarget::Label(jump_around_label), }; - jmp.emit(&[], sink, emit_info, state); - sink.emit_island(needed_space + 4); - sink.bind_label(jump_around_label); + jmp.emit(&[], sink, emit_info, state, ctrl_plane); + sink.emit_island(needed_space + 4, ctrl_plane); + sink.bind_label(jump_around_label, ctrl_plane); } } @@ -3440,7 +3454,7 @@ impl MachInstEmit for Inst { // adrp x0,