From e776d987fdae7e225892ab72026b3d31f6d5a06e Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 12 Mar 2018 16:07:13 -0700 Subject: [PATCH 01/72] Add Cargo.toml badges for published packages. This adds a basic travis badge, as well as a badge indicating "experimental" status, since the APIs are still evolving. --- lib/cretonne/Cargo.toml | 4 ++++ lib/frontend/Cargo.toml | 4 ++++ lib/native/Cargo.toml | 4 ++++ lib/reader/Cargo.toml | 4 ++++ lib/wasm/Cargo.toml | 4 ++++ 5 files changed, 20 insertions(+) diff --git a/lib/cretonne/Cargo.toml b/lib/cretonne/Cargo.toml index 597ff1efd6..adcaa28f76 100644 --- a/lib/cretonne/Cargo.toml +++ b/lib/cretonne/Cargo.toml @@ -18,3 +18,7 @@ name = "cretonne" # Please don't add any unless they are essential to the task of creating binary # machine code. Integration tests that need external dependencies can be # accomodated in `tests`. + +[badges] +maintenance = { status = "experimental" } +travis-ci = { repository = "Cretonne/cretonne" } diff --git a/lib/frontend/Cargo.toml b/lib/frontend/Cargo.toml index 0085036ed0..368b6f058e 100644 --- a/lib/frontend/Cargo.toml +++ b/lib/frontend/Cargo.toml @@ -13,3 +13,7 @@ name = "cton_frontend" [dependencies] cretonne = { path = "../cretonne", version = "0.3.4" } + +[badges] +maintenance = { status = "experimental" } +travis-ci = { repository = "Cretonne/cretonne" } diff --git a/lib/native/Cargo.toml b/lib/native/Cargo.toml index 10856d98a5..89676fc1b3 100644 --- a/lib/native/Cargo.toml +++ b/lib/native/Cargo.toml @@ -15,3 +15,7 @@ cretonne = { path = "../cretonne", version = "0.3.4" } [target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies] raw-cpuid = "3.0.0" + +[badges] +maintenance = { status = "experimental" } +travis-ci = { repository = "Cretonne/cretonne" } diff --git a/lib/reader/Cargo.toml b/lib/reader/Cargo.toml index 0d2061e361..bd26dc0f7c 100644 --- a/lib/reader/Cargo.toml +++ b/lib/reader/Cargo.toml @@ -13,3 +13,7 @@ name = "cton_reader" [dependencies] cretonne = { path = "../cretonne", version = "0.3.4" } + +[badges] +maintenance = { status = "experimental" } +travis-ci = { repository = "Cretonne/cretonne" } diff --git a/lib/wasm/Cargo.toml b/lib/wasm/Cargo.toml index 8e61d440c0..bc50b4a303 100644 --- a/lib/wasm/Cargo.toml +++ b/lib/wasm/Cargo.toml @@ -18,3 +18,7 @@ cretonne-frontend = { path = "../frontend", version = "0.3.4" } [dev-dependencies] tempdir = "0.3.5" + +[badges] +maintenance = { status = "experimental" } +travis-ci = { repository = "Cretonne/cretonne" } From 44ca27beecc596a5eec2225ffa3cbcbd7e8d11c8 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 12 Mar 2018 16:11:14 -0700 Subject: [PATCH 02/72] Update to wasmparser 0.15.1. --- lib/wasm/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wasm/Cargo.toml b/lib/wasm/Cargo.toml index bc50b4a303..140ab69cfe 100644 --- a/lib/wasm/Cargo.toml +++ b/lib/wasm/Cargo.toml @@ -12,7 +12,7 @@ keywords = [ "webassembly", "wasm" ] name = "cton_wasm" [dependencies] -wasmparser = "0.14.1" +wasmparser = "0.15.1" cretonne = { path = "../cretonne", version = "0.3.4" } cretonne-frontend = { path = "../frontend", version = "0.3.4" } From 9128290fb4fe73104b9a48e3986b28e0d6f8f0cb Mon Sep 17 00:00:00 2001 From: Afnan Enayet Date: Wed, 14 Mar 2018 10:48:06 -0700 Subject: [PATCH 03/72] Rename `ILBuilder` to `FunctionBuilderContext` (#268) * Rename `ILBuilder` to `FunctionBuilderContext` and update corresponding code * Refactor usages of ILBuilder to become FunctionBuilderContext, update variable names to reflect this change * Reformat to ensure that lines stay under 100 char limit * Apply corrections from `rustfmt` to pass tests * Rename variables to be more consistent with refactor of ILBuilder --- lib/frontend/src/frontend.rs | 103 ++++++++++++++++---------------- lib/frontend/src/lib.rs | 14 ++--- lib/frontend/src/variable.rs | 2 +- lib/wasm/src/func_translator.rs | 10 ++-- 4 files changed, 65 insertions(+), 64 deletions(-) diff --git a/lib/frontend/src/frontend.rs b/lib/frontend/src/frontend.rs index 6802884b6a..de89698f15 100644 --- a/lib/frontend/src/frontend.rs +++ b/lib/frontend/src/frontend.rs @@ -13,13 +13,13 @@ use cretonne::packed_option::PackedOption; /// Structure used for translating a series of functions into Cretonne IL. /// /// In order to reduce memory reallocations when compiling multiple functions, -/// `ILBuilder` holds various data structures which are cleared between +/// `FunctionBuilderContext` holds various data structures which are cleared between /// functions, rather than dropped, preserving the underlying allocations. /// /// The `Variable` parameter can be any index-like type that can be made to /// implement `EntityRef`. For frontends that don't have an obvious type to /// use here, `variable::Variable` can be used. -pub struct ILBuilder +pub struct FunctionBuilderContext where Variable: EntityRef, { @@ -41,7 +41,7 @@ where /// Source location to assign to all new instructions. srcloc: ir::SourceLoc, - builder: &'a mut ILBuilder, + func_ctx: &'a mut FunctionBuilderContext, position: Position, } @@ -77,12 +77,12 @@ impl Position { } } -impl ILBuilder +impl FunctionBuilderContext where Variable: EntityRef, { - /// Creates a ILBuilder structure. The structure is automatically cleared after each - /// [`FunctionBuilder`](struct.FunctionBuilder.html) completes translating a function. + /// Creates a FunctionBuilderContext structure. The structure is automatically cleared after + /// each [`FunctionBuilder`](struct.FunctionBuilder.html) completes translating a function. pub fn new() -> Self { Self { ssa: SSABuilder::new(), @@ -172,7 +172,7 @@ impl<'short, 'long, Variable> InstBuilderBase<'short> for FuncInstBuilder<'short .entries() .map(|(_, ebb)| ebb) .filter(|dest_ebb| unique.insert(*dest_ebb)) { - self.builder.builder.ssa.declare_ebb_predecessor( + self.builder.func_ctx.ssa.declare_ebb_predecessor( dest_ebb, self.builder.position.basic_block.unwrap(), inst, @@ -213,9 +213,10 @@ impl<'short, 'long, Variable> InstBuilderBase<'short> for FuncInstBuilder<'short /// /// At creation, a `FunctionBuilder` instance borrows an already allocated `Function` which it /// modifies with the information stored in the mutable borrowed -/// [`ILBuilder`](struct.ILBuilder.html). The function passed in argument should be newly created -/// with [`Function::with_name_signature()`](../function/struct.Function.html), whereas the -/// `ILBuilder` can be kept as is between two function translations. +/// [`FunctionBuilderContext`](struct.FunctionBuilderContext.html). The function passed in +/// argument should be newly created with +/// [`Function::with_name_signature()`](../function/struct.Function.html), whereas the +/// `FunctionBuilderContext` can be kept as is between two function translations. /// /// # Errors /// @@ -228,16 +229,16 @@ where Variable: EntityRef, { /// Creates a new FunctionBuilder structure that will operate on a `Function` using a - /// `IlBuilder`. + /// `FunctionBuilderContext`. pub fn new( func: &'a mut Function, - builder: &'a mut ILBuilder, + func_ctx: &'a mut FunctionBuilderContext, ) -> FunctionBuilder<'a, Variable> { - debug_assert!(builder.is_empty()); + debug_assert!(func_ctx.is_empty()); FunctionBuilder { func: func, srcloc: Default::default(), - builder: builder, + func_ctx: func_ctx, position: Position::default(), } } @@ -250,8 +251,8 @@ where /// Creates a new `Ebb` and returns its reference. pub fn create_ebb(&mut self) -> Ebb { let ebb = self.func.dfg.make_ebb(); - self.builder.ssa.declare_ebb_header_block(ebb); - self.builder.ebbs[ebb] = EbbData { + self.func_ctx.ssa.declare_ebb_header_block(ebb); + self.func_ctx.ebbs[ebb] = EbbData { filled: false, pristine: true, user_param_count: 0, @@ -275,11 +276,11 @@ where ); // We cannot switch to a filled block debug_assert!( - !self.builder.ebbs[ebb].filled, + !self.func_ctx.ebbs[ebb].filled, "you cannot switch to a block which is already filled" ); - let basic_block = self.builder.ssa.header_block(ebb); + let basic_block = self.func_ctx.ssa.header_block(ebb); // Then we change the cursor position. self.position = Position::at(ebb, basic_block); } @@ -290,7 +291,7 @@ where /// created. Forgetting to call this method on every block will cause inconsistencies in the /// produced functions. pub fn seal_block(&mut self, ebb: Ebb) { - let side_effects = self.builder.ssa.seal_ebb_header_block(ebb, self.func); + let side_effects = self.func_ctx.ssa.seal_ebb_header_block(ebb, self.func); self.handle_ssa_side_effects(side_effects); } @@ -301,22 +302,22 @@ where /// function can be used at the end of translating all blocks to ensure /// that everything is sealed. pub fn seal_all_blocks(&mut self) { - let side_effects = self.builder.ssa.seal_all_ebb_header_blocks(self.func); + let side_effects = self.func_ctx.ssa.seal_all_ebb_header_blocks(self.func); self.handle_ssa_side_effects(side_effects); } /// In order to use a variable in a `use_var`, you need to declare its type with this method. pub fn declare_var(&mut self, var: Variable, ty: Type) { - self.builder.types[var] = ty; + self.func_ctx.types[var] = ty; } /// Returns the Cretonne IL value corresponding to the utilization at the current program /// position of a previously defined user variable. pub fn use_var(&mut self, var: Variable) -> Value { - let ty = *self.builder.types.get(var).expect( + let ty = *self.func_ctx.types.get(var).expect( "this variable is used but its type has not been declared", ); - let (val, side_effects) = self.builder.ssa.use_var( + let (val, side_effects) = self.func_ctx.ssa.use_var( self.func, var, ty, @@ -329,7 +330,7 @@ where /// Register a new definition of a user variable. Panics if the type of the value is not the /// same as the type registered for the variable. pub fn def_var(&mut self, var: Variable, val: Value) { - self.builder.ssa.def_var( + self.func_ctx.ssa.def_var( var, val, self.position.basic_block.unwrap(), @@ -382,14 +383,14 @@ where /// Make sure that the current EBB is inserted in the layout. pub fn ensure_inserted_ebb(&mut self) { let ebb = self.position.ebb.unwrap(); - if self.builder.ebbs[ebb].pristine { + if self.func_ctx.ebbs[ebb].pristine { if !self.func.layout.is_ebb_inserted(ebb) { self.func.layout.append_ebb(ebb); } - self.builder.ebbs[ebb].pristine = false; + self.func_ctx.ebbs[ebb].pristine = false; } else { debug_assert!( - !self.builder.ebbs[ebb].filled, + !self.func_ctx.ebbs[ebb].filled, "you cannot add an instruction to a block already filled" ); } @@ -412,7 +413,7 @@ where pub fn append_ebb_params_for_function_params(&mut self, ebb: Ebb) { // These parameters count as "user" parameters here because they aren't // inserted by the SSABuilder. - let user_param_count = &mut self.builder.ebbs[ebb].user_param_count; + let user_param_count = &mut self.func_ctx.ebbs[ebb].user_param_count; for argtyp in &self.func.signature.params { *user_param_count += 1; self.func.dfg.append_ebb_param(ebb, argtyp.value_type); @@ -425,7 +426,7 @@ where pub fn append_ebb_params_for_function_returns(&mut self, ebb: Ebb) { // These parameters count as "user" parameters here because they aren't // inserted by the SSABuilder. - let user_param_count = &mut self.builder.ebbs[ebb].user_param_count; + let user_param_count = &mut self.func_ctx.ebbs[ebb].user_param_count; for argtyp in &self.func.signature.returns { *user_param_count += 1; self.func.dfg.append_ebb_param(ebb, argtyp.value_type); @@ -438,21 +439,21 @@ where pub fn finalize(&mut self) { // Check that all the `Ebb`s are filled and sealed. debug_assert!( - self.builder.ebbs.keys().all(|ebb| { - self.builder.ebbs[ebb].pristine || self.builder.ssa.is_sealed(ebb) + self.func_ctx.ebbs.keys().all(|ebb| { + self.func_ctx.ebbs[ebb].pristine || self.func_ctx.ssa.is_sealed(ebb) }), "all blocks should be sealed before dropping a FunctionBuilder" ); debug_assert!( - self.builder.ebbs.keys().all(|ebb| { - self.builder.ebbs[ebb].pristine || self.builder.ebbs[ebb].filled + self.func_ctx.ebbs.keys().all(|ebb| { + self.func_ctx.ebbs[ebb].pristine || self.func_ctx.ebbs[ebb].filled }), "all blocks should be filled before dropping a FunctionBuilder" ); // Clear the state (but preserve the allocated buffers) in preparation // for translation another function. - self.builder.clear(); + self.func_ctx.clear(); // Reset srcloc and position to initial states. self.srcloc = Default::default(); @@ -486,12 +487,12 @@ where /// **Note:** this function has to be called at the creation of the `Ebb` before adding /// instructions to it, otherwise this could interfere with SSA construction. pub fn append_ebb_param(&mut self, ebb: Ebb, ty: Type) -> Value { - debug_assert!(self.builder.ebbs[ebb].pristine); + debug_assert!(self.func_ctx.ebbs[ebb].pristine); debug_assert_eq!( - self.builder.ebbs[ebb].user_param_count, + self.func_ctx.ebbs[ebb].user_param_count, self.func.dfg.num_ebb_params(ebb) ); - self.builder.ebbs[ebb].user_param_count += 1; + self.func_ctx.ebbs[ebb].user_param_count += 1; self.func.dfg.append_ebb_param(ebb, ty) } @@ -508,9 +509,9 @@ where let old_dest = self.func.dfg[inst].branch_destination_mut().expect( "you want to change the jump destination of a non-jump instruction", ); - let pred = self.builder.ssa.remove_ebb_predecessor(*old_dest, inst); + let pred = self.func_ctx.ssa.remove_ebb_predecessor(*old_dest, inst); *old_dest = new_dest; - self.builder.ssa.declare_ebb_predecessor( + self.func_ctx.ssa.declare_ebb_predecessor( new_dest, pred, inst, @@ -525,8 +526,8 @@ where None => false, Some(entry) => self.position.ebb.unwrap() == entry, }; - !is_entry && self.builder.ssa.is_sealed(self.position.ebb.unwrap()) && - self.builder + !is_entry && self.func_ctx.ssa.is_sealed(self.position.ebb.unwrap()) && + self.func_ctx .ssa .predecessors(self.position.ebb.unwrap()) .is_empty() @@ -535,13 +536,13 @@ where /// Returns `true` if and only if no instructions have been added since the last call to /// `switch_to_block`. pub fn is_pristine(&self) -> bool { - self.builder.ebbs[self.position.ebb.unwrap()].pristine + self.func_ctx.ebbs[self.position.ebb.unwrap()].pristine } /// Returns `true` if and only if a terminator instruction has been inserted since the /// last call to `switch_to_block`. pub fn is_filled(&self) -> bool { - self.builder.ebbs[self.position.ebb.unwrap()].filled + self.func_ctx.ebbs[self.position.ebb.unwrap()].filled } /// Returns a displayable object for the function as it is. @@ -558,17 +559,17 @@ where Variable: EntityRef, { fn move_to_next_basic_block(&mut self) { - self.position.basic_block = PackedOption::from(self.builder.ssa.declare_ebb_body_block( + self.position.basic_block = PackedOption::from(self.func_ctx.ssa.declare_ebb_body_block( self.position.basic_block.unwrap(), )); } fn fill_current_block(&mut self) { - self.builder.ebbs[self.position.ebb.unwrap()].filled = true; + self.func_ctx.ebbs[self.position.ebb.unwrap()].filled = true; } fn declare_successor(&mut self, dest_ebb: Ebb, jump_inst: Inst) { - self.builder.ssa.declare_ebb_predecessor( + self.func_ctx.ssa.declare_ebb_predecessor( dest_ebb, self.position.basic_block.unwrap(), jump_inst, @@ -577,10 +578,10 @@ where fn handle_ssa_side_effects(&mut self, side_effects: SideEffects) { for split_ebb in side_effects.split_ebbs_created { - self.builder.ebbs[split_ebb].filled = true + self.func_ctx.ebbs[split_ebb].filled = true } for modified_ebb in side_effects.instructions_added_to_ebbs { - self.builder.ebbs[modified_ebb].pristine = false + self.func_ctx.ebbs[modified_ebb].pristine = false } } } @@ -591,7 +592,7 @@ mod tests { use cretonne::entity::EntityRef; use cretonne::ir::{ExternalName, Function, CallConv, Signature, AbiParam, InstBuilder}; use cretonne::ir::types::*; - use frontend::{ILBuilder, FunctionBuilder}; + use frontend::{FunctionBuilderContext, FunctionBuilder}; use cretonne::verifier::verify_function; use cretonne::settings; use Variable; @@ -601,10 +602,10 @@ mod tests { sig.returns.push(AbiParam::new(I32)); sig.params.push(AbiParam::new(I32)); - let mut il_builder = ILBuilder::::new(); + let mut fn_ctx = FunctionBuilderContext::::new(); let mut func = Function::with_name_signature(ExternalName::testcase("sample"), sig); { - let mut builder = FunctionBuilder::::new(&mut func, &mut il_builder); + let mut builder = FunctionBuilder::::new(&mut func, &mut fn_ctx); let block0 = builder.create_ebb(); let block1 = builder.create_ebb(); diff --git a/lib/frontend/src/lib.rs b/lib/frontend/src/lib.rs index a95d662893..f5b4514e56 100644 --- a/lib/frontend/src/lib.rs +++ b/lib/frontend/src/lib.rs @@ -4,8 +4,8 @@ //! translated from another language. Contains an SSA construction module that lets you translate //! your non-SSA variables into SSA Cretonne IL values via `use_var` and `def_var` calls. //! -//! To get started, create an [`IlBuilder`](struct.ILBuilder.html) and pass it as an argument -//! to a [`FunctionBuilder`](struct.FunctionBuilder.html). +//! To get started, create an [`FunctionBuilderContext`](struct.FunctionBuilderContext.html) and +//! pass it as an argument to a [`FunctionBuilder`](struct.FunctionBuilder.html). //! //! # Example //! @@ -29,7 +29,7 @@ //! } //! ``` //! -//! Here is how you build the corresponding Cretonne IL function using `ILBuilder`: +//! Here is how you build the corresponding Cretonne IL function using `FunctionBuilderContext`: //! //! ```rust //! extern crate cretonne; @@ -39,17 +39,17 @@ //! use cretonne::ir::{ExternalName, CallConv, Function, Signature, AbiParam, InstBuilder}; //! use cretonne::ir::types::*; //! use cretonne::settings; -//! use cton_frontend::{ILBuilder, FunctionBuilder, Variable}; +//! use cton_frontend::{FunctionBuilderContext, FunctionBuilder, Variable}; //! use cretonne::verifier::verify_function; //! //! fn main() { //! let mut sig = Signature::new(CallConv::Native); //! sig.returns.push(AbiParam::new(I32)); //! sig.params.push(AbiParam::new(I32)); -//! let mut il_builder = ILBuilder::::new(); +//! let mut fn_builder_ctx = FunctionBuilderContext::::new(); //! let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig); //! { -//! let mut builder = FunctionBuilder::::new(&mut func, &mut il_builder); +//! let mut builder = FunctionBuilder::::new(&mut func, &mut fn_builder_ctx); //! //! let block0 = builder.create_ebb(); //! let block1 = builder.create_ebb(); @@ -133,7 +133,7 @@ extern crate cretonne; -pub use frontend::{ILBuilder, FunctionBuilder}; +pub use frontend::{FunctionBuilderContext, FunctionBuilder}; pub use variable::Variable; mod frontend; diff --git a/lib/frontend/src/variable.rs b/lib/frontend/src/variable.rs index b69a63afeb..b4e3c75da2 100644 --- a/lib/frontend/src/variable.rs +++ b/lib/frontend/src/variable.rs @@ -1,6 +1,6 @@ //! A basic `Variable` implementation. //! -//! `ILBuilder`, `FunctionBuilder`, and related types have a `Variable` +//! `FunctionBuilderContext`, `FunctionBuilder`, and related types have a `Variable` //! type parameter, to allow frontends that identify variables with //! their own index types to use them directly. Frontends which don't //! can use the `Variable` defined here. diff --git a/lib/wasm/src/func_translator.rs b/lib/wasm/src/func_translator.rs index cef629c7dc..5ac69b07b8 100644 --- a/lib/wasm/src/func_translator.rs +++ b/lib/wasm/src/func_translator.rs @@ -9,7 +9,7 @@ use cretonne::entity::EntityRef; use cretonne::ir::{self, InstBuilder, Ebb}; use cretonne::result::{CtonResult, CtonError}; use cretonne::timing; -use cton_frontend::{ILBuilder, FunctionBuilder, Variable}; +use cton_frontend::{FunctionBuilderContext, FunctionBuilder, Variable}; use environ::FuncEnvironment; use state::TranslationState; use wasmparser::{self, BinaryReader}; @@ -20,7 +20,7 @@ use wasmparser::{self, BinaryReader}; /// by a `FuncEnvironment` object. A single translator instance can be reused to translate multiple /// functions which will reduce heap allocation traffic. pub struct FuncTranslator { - il_builder: ILBuilder, + func_ctx: FunctionBuilderContext, state: TranslationState, } @@ -28,7 +28,7 @@ impl FuncTranslator { /// Create a new translator. pub fn new() -> Self { Self { - il_builder: ILBuilder::new(), + func_ctx: FunctionBuilderContext::new(), state: TranslationState::new(), } } @@ -77,8 +77,8 @@ impl FuncTranslator { debug_assert_eq!(func.dfg.num_ebbs(), 0, "Function must be empty"); debug_assert_eq!(func.dfg.num_insts(), 0, "Function must be empty"); - // This clears the `ILBuilder`. - let mut builder = FunctionBuilder::new(func, &mut self.il_builder); + // This clears the `FunctionBuilderContext`. + let mut builder = FunctionBuilder::new(func, &mut self.func_ctx); let entry_block = builder.create_ebb(); builder.append_ebb_params_for_function_params(entry_block); builder.switch_to_block(entry_block); // This also creates values for the arguments. From 3afe85ff17ca1dbd8e7bf53b83599a7a31ef1609 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 13 Mar 2018 10:06:45 -0700 Subject: [PATCH 04/72] Auto-generate `InstructionData`. The meta description has all the information to generate the `InstructionData` enum, so generate it rather than having a manually-maintained copy. --- lib/cretonne/meta/gen_instr.py | 34 +++++ lib/cretonne/src/ir/instructions.rs | 190 +--------------------------- 2 files changed, 36 insertions(+), 188 deletions(-) diff --git a/lib/cretonne/meta/gen_instr.py b/lib/cretonne/meta/gen_instr.py index 28db9e81d2..ab42b01850 100644 --- a/lib/cretonne/meta/gen_instr.py +++ b/lib/cretonne/meta/gen_instr.py @@ -103,6 +103,38 @@ def gen_arguments_method(fmt, is_mut): .format(n, capture, arg)) +def gen_instruction_data(fmt): + # type: (srcgen.Formatter) -> None + """ + Generate the InstructionData enum. + + Every variant must contain `opcode` and `ty` fields. An instruction that + doesn't produce a value should have its `ty` field set to `VOID`. The size + of `InstructionData` should be kept at 16 bytes on 64-bit architectures. If + more space is needed to represent an instruction, use a `Box` to + store the additional information out of line. + """ + + fmt.line('#[derive(Clone, Debug, Hash, PartialEq, Eq)]') + fmt.line('#[allow(missing_docs)]') + with fmt.indented('pub enum InstructionData {', '}'): + for f in InstructionFormat.all_formats: + with fmt.indented('{} {{'.format(f.name), '},'): + fmt.line('opcode: Opcode,') + if f.typevar_operand is None: + pass + elif f.has_value_list: + fmt.line('args: ValueList,') + elif f.num_value_operands == 1: + fmt.line('arg: Value,') + else: + fmt.line('args: [Value; {}],'.format(f.num_value_operands)) + for field in f.imm_fields: + fmt.line( + '{}: {},' + .format(field.member, field.kind.rust_type)) + + def gen_instruction_data_impl(fmt): # type: (srcgen.Formatter) -> None """ @@ -682,6 +714,8 @@ def generate(isas, out_dir): # opcodes.rs fmt = srcgen.Formatter() gen_formats(fmt) + gen_instruction_data(fmt) + fmt.line() gen_instruction_data_impl(fmt) fmt.line() instrs = gen_opcodes(groups, fmt) diff --git a/lib/cretonne/src/ir/instructions.rs b/lib/cretonne/src/ir/instructions.rs index 2d462064d1..358c63d942 100644 --- a/lib/cretonne/src/ir/instructions.rs +++ b/lib/cretonne/src/ir/instructions.rs @@ -11,11 +11,9 @@ use std::str::FromStr; use std::ops::{Deref, DerefMut}; use ir; -use ir::{Value, Type, Ebb, JumpTable, SigRef, FuncRef, StackSlot, MemFlags}; -use ir::immediates::{Imm64, Uimm8, Uimm32, Ieee32, Ieee64, Offset32}; -use ir::condcodes::*; +use ir::{Value, Type, Ebb, JumpTable, SigRef, FuncRef}; use ir::types; -use isa::RegUnit; +use isa; use entity; use bitset::BitSet; @@ -94,190 +92,6 @@ impl FromStr for Opcode { } } -/// Contents on an instruction. -/// -/// Every variant must contain `opcode` and `ty` fields. An instruction that doesn't produce a -/// value should have its `ty` field set to `VOID`. The size of `InstructionData` should be kept at -/// 16 bytes on 64-bit architectures. If more space is needed to represent an instruction, use a -/// `Box` to store the additional information out of line. -#[derive(Clone, Debug, Hash, PartialEq, Eq)] -#[allow(missing_docs)] -pub enum InstructionData { - Unary { opcode: Opcode, arg: Value }, - UnaryImm { opcode: Opcode, imm: Imm64 }, - UnaryIeee32 { opcode: Opcode, imm: Ieee32 }, - UnaryIeee64 { opcode: Opcode, imm: Ieee64 }, - UnaryBool { opcode: Opcode, imm: bool }, - UnaryGlobalVar { - opcode: Opcode, - global_var: ir::GlobalVar, - }, - Binary { opcode: Opcode, args: [Value; 2] }, - BinaryImm { - opcode: Opcode, - arg: Value, - imm: Imm64, - }, - Ternary { opcode: Opcode, args: [Value; 3] }, - MultiAry { opcode: Opcode, args: ValueList }, - NullAry { opcode: Opcode }, - InsertLane { - opcode: Opcode, - lane: Uimm8, - args: [Value; 2], - }, - ExtractLane { - opcode: Opcode, - lane: Uimm8, - arg: Value, - }, - IntCompare { - opcode: Opcode, - cond: IntCC, - args: [Value; 2], - }, - IntCompareImm { - opcode: Opcode, - cond: IntCC, - arg: Value, - imm: Imm64, - }, - IntCond { - opcode: Opcode, - cond: IntCC, - arg: Value, - }, - FloatCompare { - opcode: Opcode, - cond: FloatCC, - args: [Value; 2], - }, - FloatCond { - opcode: Opcode, - cond: FloatCC, - arg: Value, - }, - IntSelect { - opcode: Opcode, - cond: IntCC, - args: [Value; 3], - }, - Jump { - opcode: Opcode, - destination: Ebb, - args: ValueList, - }, - Branch { - opcode: Opcode, - destination: Ebb, - args: ValueList, - }, - BranchIcmp { - opcode: Opcode, - cond: IntCC, - destination: Ebb, - args: ValueList, - }, - BranchInt { - opcode: Opcode, - cond: IntCC, - destination: Ebb, - args: ValueList, - }, - BranchFloat { - opcode: Opcode, - cond: FloatCC, - destination: Ebb, - args: ValueList, - }, - BranchTable { - opcode: Opcode, - arg: Value, - table: JumpTable, - }, - Call { - opcode: Opcode, - func_ref: FuncRef, - args: ValueList, - }, - IndirectCall { - opcode: Opcode, - sig_ref: SigRef, - args: ValueList, - }, - FuncAddr { opcode: Opcode, func_ref: FuncRef }, - StackLoad { - opcode: Opcode, - stack_slot: StackSlot, - offset: Offset32, - }, - StackStore { - opcode: Opcode, - arg: Value, - stack_slot: StackSlot, - offset: Offset32, - }, - HeapAddr { - opcode: Opcode, - heap: ir::Heap, - arg: Value, - imm: Uimm32, - }, - Load { - opcode: Opcode, - flags: MemFlags, - arg: Value, - offset: Offset32, - }, - Store { - opcode: Opcode, - flags: MemFlags, - args: [Value; 2], - offset: Offset32, - }, - RegMove { - opcode: Opcode, - arg: Value, - src: RegUnit, - dst: RegUnit, - }, - CopySpecial { - opcode: Opcode, - src: RegUnit, - dst: RegUnit, - }, - RegSpill { - opcode: Opcode, - arg: Value, - src: RegUnit, - dst: StackSlot, - }, - RegFill { - opcode: Opcode, - arg: Value, - src: StackSlot, - dst: RegUnit, - }, - Trap { opcode: Opcode, code: ir::TrapCode }, - CondTrap { - opcode: Opcode, - arg: Value, - code: ir::TrapCode, - }, - IntCondTrap { - opcode: Opcode, - cond: IntCC, - arg: Value, - code: ir::TrapCode, - }, - FloatCondTrap { - opcode: Opcode, - cond: FloatCC, - arg: Value, - code: ir::TrapCode, - }, -} - /// A variable list of `Value` operands used for function call arguments and passing arguments to /// basic blocks. #[derive(Clone, Debug)] From cc8d6400f49f541384f51f5a848a992c58041a59 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 13 Mar 2018 17:00:23 -0700 Subject: [PATCH 05/72] Rename builder.rs to inst_builder.rs. This reflects its purpose, to define the `InstBuilder` trait. --- lib/cretonne/meta/gen_instr.py | 6 +++--- lib/cretonne/src/ir/builder.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/cretonne/meta/gen_instr.py b/lib/cretonne/meta/gen_instr.py index ab42b01850..38d120fa7e 100644 --- a/lib/cretonne/meta/gen_instr.py +++ b/lib/cretonne/meta/gen_instr.py @@ -687,7 +687,7 @@ def gen_builder(insts, fmt): fmt.doc_comment(""" Convenience methods for building instructions. - The `InstrBuilder` trait has one method per instruction opcode for + The `InstBuilder` trait has one method per instruction opcode for conveniently constructing the instruction with minimum arguments. Polymorphic instructions infer their result types from the input arguments when possible. In some cases, an explicit `ctrl_typevar` @@ -722,7 +722,7 @@ def generate(isas, out_dir): gen_type_constraints(fmt, instrs) fmt.update_file('opcodes.rs', out_dir) - # builder.rs + # inst_builder.rs fmt = srcgen.Formatter() gen_builder(instrs, fmt) - fmt.update_file('builder.rs', out_dir) + fmt.update_file('inst_builder.rs', out_dir) diff --git a/lib/cretonne/src/ir/builder.rs b/lib/cretonne/src/ir/builder.rs index a69fd4e181..7e1480186d 100644 --- a/lib/cretonne/src/ir/builder.rs +++ b/lib/cretonne/src/ir/builder.rs @@ -36,7 +36,7 @@ pub trait InstBuilderBase<'f>: Sized { // // This file defines the `InstBuilder` trait as an extension of `InstBuilderBase` with methods per // instruction format and per opcode. -include!(concat!(env!("OUT_DIR"), "/builder.rs")); +include!(concat!(env!("OUT_DIR"), "/inst_builder.rs")); /// Any type implementing `InstBuilderBase` gets all the `InstBuilder` methods for free. impl<'f, T: InstBuilderBase<'f>> InstBuilder<'f> for T {} From d9712f5d7dee23289ce944471dd167b888603c2c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 13 Mar 2018 20:56:53 -0700 Subject: [PATCH 06/72] Elaborate on some comments in generated source files. Recipe names are fairly obscure, so the more context we can give when using them the better. --- lib/cretonne/meta/gen_binemit.py | 2 +- lib/cretonne/meta/gen_encoding.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cretonne/meta/gen_binemit.py b/lib/cretonne/meta/gen_binemit.py index c3d1b18e86..5888d89e10 100644 --- a/lib/cretonne/meta/gen_binemit.py +++ b/lib/cretonne/meta/gen_binemit.py @@ -152,7 +152,7 @@ def gen_isa(isa, fmt): fmt.line('let bits = encoding.bits();') with fmt.indented('match func.encodings[inst].recipe() {', '}'): for i, recipe in enumerate(isa.all_recipes): - fmt.comment(recipe.name) + fmt.comment('Recipe {}'.format(recipe.name)) with fmt.indented('{} => {{'.format(i), '}'): gen_recipe(recipe, fmt) fmt.line('_ => {},') diff --git a/lib/cretonne/meta/gen_encoding.py b/lib/cretonne/meta/gen_encoding.py index 46fe22a913..da382a1774 100644 --- a/lib/cretonne/meta/gen_encoding.py +++ b/lib/cretonne/meta/gen_encoding.py @@ -756,7 +756,7 @@ def emit_recipe_constraints(isa, fmt): 'static RECIPE_CONSTRAINTS: [RecipeConstraints; {}] = [' .format(len(isa.all_recipes)), '];'): for r in isa.all_recipes: - fmt.comment(r.name) + fmt.comment('Constraints for recipe {}:'.format(r.name)) tied_i2o, tied_o2i = r.ties() fixed_ins, fixed_outs = r.fixed_ops() with fmt.indented('RecipeConstraints {', '},'): @@ -830,7 +830,7 @@ def emit_recipe_sizing(isa, fmt): 'static RECIPE_SIZING: [RecipeSizing; {}] = [' .format(len(isa.all_recipes)), '];'): for r in isa.all_recipes: - fmt.comment(r.name) + fmt.comment('Code size information for recipe {}:'.format(r.name)) with fmt.indented('RecipeSizing {', '},'): fmt.format('bytes: {},', r.size) if r.branch_range: From 272d03d8fc0771bb7416d81e4dc1bb2695b0deb7 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 14 Mar 2018 10:40:47 -0700 Subject: [PATCH 07/72] Add a utility for generating Rust 'match' expressions. This makes it a little simpler to generate 'match' statements, and it performs deduplication of identical arms. And it means I don't have to think about as many strings like '{} {{ {}.. }} => {}' when I'm trying to think about how instructions work :-). --- lib/cretonne/meta/gen_instr.py | 146 +++++++++++++++--------------- lib/cretonne/meta/gen_settings.py | 11 +-- lib/cretonne/meta/srcgen.py | 82 ++++++++++++++++- 3 files changed, 157 insertions(+), 82 deletions(-) diff --git a/lib/cretonne/meta/gen_instr.py b/lib/cretonne/meta/gen_instr.py index 38d120fa7e..4e0bc6cb78 100644 --- a/lib/cretonne/meta/gen_instr.py +++ b/lib/cretonne/meta/gen_instr.py @@ -49,11 +49,11 @@ def gen_formats(fmt): with fmt.indented( "fn from(inst: &'a InstructionData) -> InstructionFormat {", '}'): - with fmt.indented('match *inst {', '}'): - for f in InstructionFormat.all_formats: - fmt.line(('InstructionData::{} {{ .. }} => ' + - 'InstructionFormat::{},') - .format(f.name, f.name)) + m = srcgen.Match('*inst') + for f in InstructionFormat.all_formats: + m.arm('InstructionData::' + f.name, ['..'], + 'InstructionFormat::' + f.name) + fmt.match(m) fmt.line() @@ -74,33 +74,32 @@ def gen_arguments_method(fmt, is_mut): 'pool: &\'a {m}ir::ValueListPool) -> ' '&{m}[Value] {{' .format(f=method, m=mut), '}'): - with fmt.indented('match *self {', '}'): - for f in InstructionFormat.all_formats: - n = 'InstructionData::' + f.name + m = srcgen.Match('*self') + for f in InstructionFormat.all_formats: + n = 'InstructionData::' + f.name - # Formats with a value list put all of their arguments in the - # list. We don't split them up, just return it all as variable - # arguments. (I expect the distinction to go away). - if f.has_value_list: - arg = ''.format(mut) - fmt.line( - '{} {{ ref {}args, .. }} => args.{}(pool),' - .format(n, mut, as_slice)) - continue + # Formats with a value list put all of their arguments in the + # list. We don't split them up, just return it all as variable + # arguments. (I expect the distinction to go away). + if f.has_value_list: + m.arm(n, ['ref {}args'.format(mut), '..'], + 'args.{}(pool)'.format(as_slice)) + continue - # Fixed args. - if f.num_value_operands == 0: - arg = '&{}[]'.format(mut) - capture = '' - elif f.num_value_operands == 1: - capture = 'ref {}arg, '.format(mut) - arg = '{}(arg)'.format(rslice) - else: - capture = 'ref {}args, '.format(mut) - arg = 'args' - fmt.line( - '{} {{ {}.. }} => {},' - .format(n, capture, arg)) + # Fixed args. + fields = [] + if f.num_value_operands == 0: + arg = '&{}[]'.format(mut) + elif f.num_value_operands == 1: + fields.append('ref {}arg'.format(mut)) + arg = '{}(arg)'.format(rslice) + else: + args = 'args_arity{}'.format(f.num_value_operands) + fields.append('args: ref {}{}'.format(mut, args)) + arg = args + fields.append('..') + m.arm(n, fields, arg) + fmt.match(m) def gen_instruction_data(fmt): @@ -155,39 +154,37 @@ def gen_instruction_data_impl(fmt): with fmt.indented('impl InstructionData {', '}'): fmt.doc_comment('Get the opcode of this instruction.') with fmt.indented('pub fn opcode(&self) -> Opcode {', '}'): - with fmt.indented('match *self {', '}'): - for f in InstructionFormat.all_formats: - fmt.line( - 'InstructionData::{} {{ opcode, .. }} => opcode,' - .format(f.name)) + m = srcgen.Match('*self') + for f in InstructionFormat.all_formats: + m.arm('InstructionData::' + f.name, ['opcode', '..'], + 'opcode') + fmt.match(m) fmt.line() fmt.doc_comment('Get the controlling type variable operand.') with fmt.indented( 'pub fn typevar_operand(&self, pool: &ir::ValueListPool) -> ' 'Option {', '}'): - with fmt.indented('match *self {', '}'): - for f in InstructionFormat.all_formats: - n = 'InstructionData::' + f.name - if f.typevar_operand is None: - fmt.line(n + ' { .. } => None,') - elif f.has_value_list: - # We keep all arguments in a value list. - i = f.typevar_operand - fmt.line( - '{} {{ ref args, .. }} => ' - 'args.get({}, pool),'.format(n, i)) - elif f.num_value_operands == 1: - # We have a single value operand called 'arg'. - fmt.line(n + ' { arg, .. } => Some(arg),') - else: - # We have multiple value operands and an array `args`. - # Which `args` index to use? - i = f.typevar_operand - fmt.line( - n + - ' {{ ref args, .. }} => Some(args[{}]),' - .format(i)) + m = srcgen.Match('*self') + for f in InstructionFormat.all_formats: + n = 'InstructionData::' + f.name + if f.typevar_operand is None: + m.arm(n, ['..'], 'None') + elif f.has_value_list: + # We keep all arguments in a value list. + i = f.typevar_operand + m.arm(n, ['ref args', '..'], + 'args.get({}, pool)'.format(i)) + elif f.num_value_operands == 1: + # We have a single value operand called 'arg'. + m.arm(n, ['arg', '..'], 'Some(arg)') + else: + # We have multiple value operands and an array `args`. + # Which `args` index to use? + args = 'args_arity{}'.format(f.num_value_operands) + m.arm(n, ['args: ref {}'.format(args), '..'], + 'Some({}[{}])'.format(args, f.typevar_operand)) + fmt.match(m) fmt.line() fmt.doc_comment( @@ -216,13 +213,13 @@ def gen_instruction_data_impl(fmt): with fmt.indented( 'pub fn take_value_list(&mut self) -> Option {', '}'): - with fmt.indented('match *self {', '}'): - for f in InstructionFormat.all_formats: - n = 'InstructionData::' + f.name - if f.has_value_list: - fmt.line( - n + ' { ref mut args, .. } => Some(args.take()),') - fmt.line('_ => None,') + m = srcgen.Match('*self') + for f in InstructionFormat.all_formats: + n = 'InstructionData::' + f.name + if f.has_value_list: + m.arm(n, ['ref mut args', '..'], 'Some(args.take())') + m.arm('_', [], 'None') + fmt.match(m) fmt.line() fmt.doc_comment( @@ -307,14 +304,12 @@ def gen_opcodes(groups, fmt): fmt.doc_comment(Instruction.ATTRIBS[attr]) with fmt.indented('pub fn {}(self) -> bool {{' .format(attr), '}'): - with fmt.indented('match self {', '}'): - for i in instrs: - if getattr(i, attr): - fmt.format( - 'Opcode::{} => true,', - i.camel_name, i.name) - - fmt.line('_ => false,') + m = srcgen.Match('self') + for i in instrs: + if getattr(i, attr): + m.arm('Opcode::' + i.camel_name, [], 'true') + m.arm('_', [], 'false') + fmt.match(m) fmt.line() fmt.line() @@ -331,9 +326,10 @@ def gen_opcodes(groups, fmt): # Generate a private opcode_name function. with fmt.indented('fn opcode_name(opc: Opcode) -> &\'static str {', '}'): - with fmt.indented('match opc {', '}'): - for i in instrs: - fmt.format('Opcode::{} => "{}",', i.camel_name, i.name) + m = srcgen.Match('opc') + for i in instrs: + m.arm('Opcode::' + i.camel_name, [], '"{}"'.format(i.name)) + fmt.match(m) fmt.line() # Generate an opcode hash table for looking up opcodes by name. diff --git a/lib/cretonne/meta/gen_settings.py b/lib/cretonne/meta/gen_settings.py index 1560157915..b5f0de3488 100644 --- a/lib/cretonne/meta/gen_settings.py +++ b/lib/cretonne/meta/gen_settings.py @@ -57,12 +57,11 @@ def gen_getter(setting, sgrp, fmt): ty = camel_case(setting.name) proto = 'pub fn {}(&self) -> {}'.format(setting.name, ty) with fmt.indented(proto + ' {', '}'): - with fmt.indented( - 'match self.bytes[{}] {{' - .format(setting.byte_offset), '}'): - for i, v in enumerate(setting.values): - fmt.line('{} => {}::{},'.format(i, ty, camel_case(v))) - fmt.line('_ => panic!("Invalid enum value"),') + m = srcgen.Match('self.bytes[{}]'.format(setting.byte_offset)) + for i, v in enumerate(setting.values): + m.arm(str(i), [], '{}::{}'.format(ty, camel_case(v))) + m.arm('_', [], 'panic!("Invalid enum value")') + fmt.match(m) else: raise AssertionError("Unknown setting kind") diff --git a/lib/cretonne/meta/srcgen.py b/lib/cretonne/meta/srcgen.py index 9761160487..2201d997d5 100644 --- a/lib/cretonne/meta/srcgen.py +++ b/lib/cretonne/meta/srcgen.py @@ -8,9 +8,10 @@ source code. from __future__ import absolute_import import sys import os +import collections try: - from typing import Any, List # noqa + from typing import Any, List, Set, Tuple # noqa except ImportError: pass @@ -146,6 +147,52 @@ class Formatter(object): for l in parse_multiline(s): self.line('/// ' + l if l else '///') + def match(self, m): + # type: (Match) -> None + """ + Add a match expression. + + Example: + + >>> f = Formatter() + >>> m = Match('x') + >>> m.arm('Orange', ['a', 'b'], 'some body') + >>> m.arm('Yellow', ['a', 'b'], 'some body') + >>> m.arm('Green', ['a', 'b'], 'different body') + >>> m.arm('Blue', ['x', 'y'], 'some body') + >>> f.match(m) + >>> f.writelines() + match x { + Orange { a, b } | + Yellow { a, b } => { + some body + } + Green { a, b } => { + different body + } + Blue { x, y } => { + some body + } + } + + """ + with self.indented('match {} {{'.format(m.expr), '}'): + for (fields, body), names in m.arms.items(): + with self.indented('', '}'): + names_left = len(names) + for name in names.keys(): + fields_str = ', '.join(fields) + if len(fields) != 0: + fields_str = '{{ {} }} '.format(fields_str) + names_left -= 1 + if names_left > 0: + suffix = '|' + else: + suffix = '=> {' + self.outdented_line(name + ' ' + fields_str + suffix) + if names_left == 0: + self.multi_line(body) + def _indent(s): # type: (str) -> int @@ -195,3 +242,36 @@ def parse_multiline(s): while trimmed and not trimmed[0]: trimmed.pop(0) return trimmed + + +class Match(object): + """ + Match formatting class. + + Match objects collect all the information needed to emit a Rust `match` + expression, automatically deduplicating overlapping identical arms. + + Example: + + >>> m = Match('x') + >>> m.arm('Orange', ['a', 'b'], 'some body') + >>> m.arm('Yellow', ['a', 'b'], 'some body') + >>> m.arm('Green', ['a', 'b'], 'different body') + >>> m.arm('Blue', ['x', 'y'], 'some body') + >>> assert(len(m.arms) == 3) + + Note that this class is ignorant of Rust types, and considers two fields + with the same name to be equivalent. + """ + + def __init__(self, expr): + # type: (str) -> None + self.expr = expr + self.arms = collections.OrderedDict() # type: collections.OrderedDict[Tuple[Tuple[str, ...], str], collections.OrderedDict[str, None]] # noqa + + def arm(self, name, fields, body): + # type: (str, List[str], str) -> None + key = (tuple(fields), body) + if key not in self.arms: + self.arms[key] = collections.OrderedDict() + self.arms[key][name] = None From 48fc161b8bc437b68e95667a3fdf6e3e49f6bfac Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 14 Mar 2018 11:26:02 -0700 Subject: [PATCH 08/72] Add a badge for a Gitter chat room. I don't know how much interest there will be in Gitter, but if there is some, I'm interested in trying it out. --- README.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.rst b/README.rst index 6e6ab59bb3..7f77aa62f0 100644 --- a/README.rst +++ b/README.rst @@ -16,6 +16,10 @@ machine code. :target: https://travis-ci.org/Cretonne/cretonne :alt: Build Status +.. image:: https://badges.gitter.im/gitterHQ/gitter.png + :target: https://gitter.im/Cretonne/Lobby + :alt: Gitter chat + For more information, see `the documentation `_. From bb82bac3af562aa03a00add1fed190b7440fa08c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 14 Mar 2018 12:40:20 -0700 Subject: [PATCH 09/72] Tweak the Gitter URLs. --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 7f77aa62f0..12b889f56d 100644 --- a/README.rst +++ b/README.rst @@ -16,8 +16,8 @@ machine code. :target: https://travis-ci.org/Cretonne/cretonne :alt: Build Status -.. image:: https://badges.gitter.im/gitterHQ/gitter.png - :target: https://gitter.im/Cretonne/Lobby +.. image:: https://badges.gitter.im/Cretonne/cretonne.png + :target: https://gitter.im/Cretonne/Lobby/~chat :alt: Gitter chat For more information, see `the documentation From c842b9aaa149fad6aa07e434b43e108a262efbc3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 15 Mar 2018 10:13:26 -0700 Subject: [PATCH 10/72] Code cleanup: import OrderedDict rather than collections.OrderedDict --- lib/cretonne/meta/srcgen.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cretonne/meta/srcgen.py b/lib/cretonne/meta/srcgen.py index 2201d997d5..df5794cedb 100644 --- a/lib/cretonne/meta/srcgen.py +++ b/lib/cretonne/meta/srcgen.py @@ -8,7 +8,7 @@ source code. from __future__ import absolute_import import sys import os -import collections +from collections import OrderedDict try: from typing import Any, List, Set, Tuple # noqa @@ -267,11 +267,11 @@ class Match(object): def __init__(self, expr): # type: (str) -> None self.expr = expr - self.arms = collections.OrderedDict() # type: collections.OrderedDict[Tuple[Tuple[str, ...], str], collections.OrderedDict[str, None]] # noqa + self.arms = OrderedDict() # type: OrderedDict[Tuple[Tuple[str, ...], str], OrderedDict[str, None]] # noqa def arm(self, name, fields, body): # type: (str, List[str], str) -> None key = (tuple(fields), body) if key not in self.arms: - self.arms[key] = collections.OrderedDict() + self.arms[key] = OrderedDict() self.arms[key][name] = None From b2acd457d5a99aba90f9e3dad04cb0e1313a9739 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 15 Mar 2018 10:18:51 -0700 Subject: [PATCH 11/72] Use OrderedDict rather than explicit sorting. This reduces churn in the generated files, making it easier to inspect changes. --- lib/cretonne/meta/cdsl/isa.py | 5 ++--- lib/cretonne/meta/gen_encoding.py | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/cretonne/meta/cdsl/isa.py b/lib/cretonne/meta/cdsl/isa.py index 9fcfa440a3..064a353117 100644 --- a/lib/cretonne/meta/cdsl/isa.py +++ b/lib/cretonne/meta/cdsl/isa.py @@ -172,8 +172,7 @@ class TargetISA(object): """ for cpumode in self.cpumodes: self.legalize_code(cpumode.default_legalize) - for x in sorted(cpumode.type_legalize.values(), - key=lambda x: x.name): + for x in cpumode.type_legalize.values(): self.legalize_code(x) def legalize_code(self, xgrp): @@ -232,7 +231,7 @@ class CPUMode(object): # Tables for configuring legalization actions when no valid encoding # exists for an instruction. self.default_legalize = None # type: XFormGroup - self.type_legalize = dict() # type: Dict[ValueType, XFormGroup] + self.type_legalize = OrderedDict() # type: OrderedDict[ValueType, XFormGroup] # noqa def __str__(self): # type: () -> str diff --git a/lib/cretonne/meta/gen_encoding.py b/lib/cretonne/meta/gen_encoding.py index da382a1774..61ceb8d498 100644 --- a/lib/cretonne/meta/gen_encoding.py +++ b/lib/cretonne/meta/gen_encoding.py @@ -600,8 +600,8 @@ def make_tables(cpumode): table[ty][inst].encodings.append(enc) # Ensure there are level 1 table entries for all types with a custom - # legalize action. Try to be stable relative to dict ordering. - for ty in sorted(cpumode.type_legalize.keys(), key=str): + # legalize action. + for ty in cpumode.type_legalize.keys(): table[ty] return table From 00af7a28f39bede5fdea183c118866e4d864fb88 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 29 Aug 2017 10:43:41 -0700 Subject: [PATCH 12/72] Run the filetests as part of "cargo test". Refactor the filetests harness so that it can be run as part of `cargo test`. And begin reorganizing the test harness code in preparation for moving it out of the src directory. - Test subcommand files are now named `test_*.rs`. - cton-util subcommand files now just export their `run` and nothing else. - src/filetest/mod.rs now also just exports `run` and nothing else. - Tests are now run in release mode (with debug assertions enabled). --- cranelift/Cargo.toml | 2 +- cranelift/docs/testing.rst | 16 +++ cranelift/src/cat.rs | 36 +------ cranelift/src/filetest/mod.rs | 50 ++++----- .../filetest/{binemit.rs => test_binemit.rs} | 0 cranelift/src/filetest/test_cat.rs | 37 +++++++ .../filetest/{compile.rs => test_compile.rs} | 0 .../filetest/{domtree.rs => test_domtree.rs} | 0 .../{legalizer.rs => test_legalizer.rs} | 0 .../src/filetest/{licm.rs => test_licm.rs} | 0 .../filetest/{preopt.rs => test_preopt.rs} | 0 cranelift/src/filetest/test_print_cfg.rs | 37 +++++++ .../{regalloc.rs => test_regalloc.rs} | 0 .../{simple_gvn.rs => test_simple_gvn.rs} | 0 .../{verifier.rs => test_verifier.rs} | 0 cranelift/src/print_cfg.rs | 102 +----------------- cranelift/test-all.sh | 26 +++-- cranelift/tests/cton-util-test.rs | 34 ++++++ lib/cretonne/src/cfg_printer.rs | 76 +++++++++++++ lib/cretonne/src/lib.rs | 1 + 20 files changed, 242 insertions(+), 175 deletions(-) rename cranelift/src/filetest/{binemit.rs => test_binemit.rs} (100%) create mode 100644 cranelift/src/filetest/test_cat.rs rename cranelift/src/filetest/{compile.rs => test_compile.rs} (100%) rename cranelift/src/filetest/{domtree.rs => test_domtree.rs} (100%) rename cranelift/src/filetest/{legalizer.rs => test_legalizer.rs} (100%) rename cranelift/src/filetest/{licm.rs => test_licm.rs} (100%) rename cranelift/src/filetest/{preopt.rs => test_preopt.rs} (100%) create mode 100644 cranelift/src/filetest/test_print_cfg.rs rename cranelift/src/filetest/{regalloc.rs => test_regalloc.rs} (100%) rename cranelift/src/filetest/{simple_gvn.rs => test_simple_gvn.rs} (100%) rename cranelift/src/filetest/{verifier.rs => test_verifier.rs} (100%) create mode 100644 cranelift/tests/cton-util-test.rs create mode 100644 lib/cretonne/src/cfg_printer.rs diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index 297e8c31b3..ee904633f9 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -23,7 +23,7 @@ docopt = "0.8.0" serde = "1.0.8" serde_derive = "1.0.8" num_cpus = "1.5.1" -tempdir="0.3.5" +tempdir = "0.3.5" term = "0.5" [workspace] diff --git a/cranelift/docs/testing.rst b/cranelift/docs/testing.rst index 2b84b1c19b..07aa8f8e16 100644 --- a/cranelift/docs/testing.rst +++ b/cranelift/docs/testing.rst @@ -324,6 +324,22 @@ Test the simple GVN pass. The simple GVN pass is run on each function, and then results are run through filecheck. +`test licm` +----------------- + +Test the LICM pass. + +The LICM pass is run on each function, and then results are run +through filecheck. + +`test preopt` +----------------- + +Test the preopt pass. + +The preopt pass is run on each function, and then results are run +through filecheck. + `test compile` -------------- diff --git a/cranelift/src/cat.rs b/cranelift/src/cat.rs index 36ae818e2c..3ae9c843d8 100644 --- a/cranelift/src/cat.rs +++ b/cranelift/src/cat.rs @@ -3,12 +3,9 @@ //! Read a sequence of Cretonne IL files and print them again to stdout. This has the effect of //! normalizing formatting and removing comments. -use std::borrow::Cow; -use cretonne::ir::Function; -use cton_reader::{parse_functions, TestCommand}; +use cton_reader::parse_functions; use CommandResult; use utils::read_to_string; -use filetest::subtest::{self, SubTest, Context, Result as STResult}; pub fn run(files: Vec) -> CommandResult { for (i, f) in files.into_iter().enumerate() { @@ -37,34 +34,3 @@ fn cat_one(filename: String) -> CommandResult { Ok(()) } - -/// Object implementing the `test cat` sub-test. -/// -/// This command is used for testing the parser and function printer. It simply parses a function -/// and prints it out again. -/// -/// The result is verified by filecheck. -struct TestCat; - -pub fn subtest(parsed: &TestCommand) -> STResult> { - assert_eq!(parsed.command, "cat"); - if !parsed.options.is_empty() { - Err(format!("No options allowed on {}", parsed)) - } else { - Ok(Box::new(TestCat)) - } -} - -impl SubTest for TestCat { - fn name(&self) -> Cow { - Cow::from("cat") - } - - fn needs_verifier(&self) -> bool { - false - } - - fn run(&self, func: Cow, context: &Context) -> STResult<()> { - subtest::run_filecheck(&func.display(context.isa).to_string(), context) - } -} diff --git a/cranelift/src/filetest/mod.rs b/cranelift/src/filetest/mod.rs index 5286307811..6d7a5e39d5 100644 --- a/cranelift/src/filetest/mod.rs +++ b/cranelift/src/filetest/mod.rs @@ -7,27 +7,27 @@ use std::path::Path; use std::time; use cton_reader::TestCommand; use CommandResult; -use cat; -use print_cfg; use filetest::runner::TestRunner; -pub mod subtest; - -mod binemit; -mod compile; mod concurrent; -mod domtree; -mod legalizer; -mod licm; -mod preopt; -mod regalloc; mod runner; mod runone; -mod simple_gvn; -mod verifier; +mod subtest; + +mod test_binemit; +mod test_cat; +mod test_compile; +mod test_domtree; +mod test_legalizer; +mod test_licm; +mod test_preopt; +mod test_print_cfg; +mod test_regalloc; +mod test_simple_gvn; +mod test_verifier; /// The result of running the test in a file. -pub type TestResult = Result; +type TestResult = Result; /// Main entry point for `cton-util test`. /// @@ -59,17 +59,17 @@ pub fn run(verbose: bool, files: Vec) -> CommandResult { /// a `.cton` test file. fn new_subtest(parsed: &TestCommand) -> subtest::Result> { match parsed.command { - "binemit" => binemit::subtest(parsed), - "cat" => cat::subtest(parsed), - "compile" => compile::subtest(parsed), - "domtree" => domtree::subtest(parsed), - "legalizer" => legalizer::subtest(parsed), - "licm" => licm::subtest(parsed), - "preopt" => preopt::subtest(parsed), - "print-cfg" => print_cfg::subtest(parsed), - "regalloc" => regalloc::subtest(parsed), - "simple-gvn" => simple_gvn::subtest(parsed), - "verifier" => verifier::subtest(parsed), + "binemit" => test_binemit::subtest(parsed), + "cat" => test_cat::subtest(parsed), + "compile" => test_compile::subtest(parsed), + "domtree" => test_domtree::subtest(parsed), + "legalizer" => test_legalizer::subtest(parsed), + "licm" => test_licm::subtest(parsed), + "preopt" => test_preopt::subtest(parsed), + "print-cfg" => test_print_cfg::subtest(parsed), + "regalloc" => test_regalloc::subtest(parsed), + "simple-gvn" => test_simple_gvn::subtest(parsed), + "verifier" => test_verifier::subtest(parsed), _ => Err(format!("unknown test command '{}'", parsed.command)), } } diff --git a/cranelift/src/filetest/binemit.rs b/cranelift/src/filetest/test_binemit.rs similarity index 100% rename from cranelift/src/filetest/binemit.rs rename to cranelift/src/filetest/test_binemit.rs diff --git a/cranelift/src/filetest/test_cat.rs b/cranelift/src/filetest/test_cat.rs new file mode 100644 index 0000000000..fc4a3cac10 --- /dev/null +++ b/cranelift/src/filetest/test_cat.rs @@ -0,0 +1,37 @@ +//! The `cat` subtest. + +use std::borrow::Cow; +use cretonne::ir::Function; +use cton_reader::TestCommand; +use filetest::subtest::{self, SubTest, Context, Result as STResult}; + +/// Object implementing the `test cat` sub-test. +/// +/// This command is used for testing the parser and function printer. It simply parses a function +/// and prints it out again. +/// +/// The result is verified by filecheck. +struct TestCat; + +pub fn subtest(parsed: &TestCommand) -> STResult> { + assert_eq!(parsed.command, "cat"); + if !parsed.options.is_empty() { + Err(format!("No options allowed on {}", parsed)) + } else { + Ok(Box::new(TestCat)) + } +} + +impl SubTest for TestCat { + fn name(&self) -> Cow { + Cow::from("cat") + } + + fn needs_verifier(&self) -> bool { + false + } + + fn run(&self, func: Cow, context: &Context) -> STResult<()> { + subtest::run_filecheck(&func.display(context.isa).to_string(), context) + } +} diff --git a/cranelift/src/filetest/compile.rs b/cranelift/src/filetest/test_compile.rs similarity index 100% rename from cranelift/src/filetest/compile.rs rename to cranelift/src/filetest/test_compile.rs diff --git a/cranelift/src/filetest/domtree.rs b/cranelift/src/filetest/test_domtree.rs similarity index 100% rename from cranelift/src/filetest/domtree.rs rename to cranelift/src/filetest/test_domtree.rs diff --git a/cranelift/src/filetest/legalizer.rs b/cranelift/src/filetest/test_legalizer.rs similarity index 100% rename from cranelift/src/filetest/legalizer.rs rename to cranelift/src/filetest/test_legalizer.rs diff --git a/cranelift/src/filetest/licm.rs b/cranelift/src/filetest/test_licm.rs similarity index 100% rename from cranelift/src/filetest/licm.rs rename to cranelift/src/filetest/test_licm.rs diff --git a/cranelift/src/filetest/preopt.rs b/cranelift/src/filetest/test_preopt.rs similarity index 100% rename from cranelift/src/filetest/preopt.rs rename to cranelift/src/filetest/test_preopt.rs diff --git a/cranelift/src/filetest/test_print_cfg.rs b/cranelift/src/filetest/test_print_cfg.rs new file mode 100644 index 0000000000..1be9987087 --- /dev/null +++ b/cranelift/src/filetest/test_print_cfg.rs @@ -0,0 +1,37 @@ +//! The `print-cfg` sub-command. +//! +//! Read a series of Cretonne IL files and print their control flow graphs +//! in graphviz format. + +use std::borrow::Cow; + +use cretonne::ir::Function; +use cretonne::cfg_printer::CFGPrinter; +use cton_reader::TestCommand; +use filetest::subtest::{self, SubTest, Context, Result as STResult}; + +/// Object implementing the `test print-cfg` sub-test. +struct TestPrintCfg; + +pub fn subtest(parsed: &TestCommand) -> STResult> { + assert_eq!(parsed.command, "print-cfg"); + if !parsed.options.is_empty() { + Err(format!("No options allowed on {}", parsed)) + } else { + Ok(Box::new(TestPrintCfg)) + } +} + +impl SubTest for TestPrintCfg { + fn name(&self) -> Cow { + Cow::from("print-cfg") + } + + fn needs_verifier(&self) -> bool { + false + } + + fn run(&self, func: Cow, context: &Context) -> STResult<()> { + subtest::run_filecheck(&CFGPrinter::new(&func).to_string(), context) + } +} diff --git a/cranelift/src/filetest/regalloc.rs b/cranelift/src/filetest/test_regalloc.rs similarity index 100% rename from cranelift/src/filetest/regalloc.rs rename to cranelift/src/filetest/test_regalloc.rs diff --git a/cranelift/src/filetest/simple_gvn.rs b/cranelift/src/filetest/test_simple_gvn.rs similarity index 100% rename from cranelift/src/filetest/simple_gvn.rs rename to cranelift/src/filetest/test_simple_gvn.rs diff --git a/cranelift/src/filetest/verifier.rs b/cranelift/src/filetest/test_verifier.rs similarity index 100% rename from cranelift/src/filetest/verifier.rs rename to cranelift/src/filetest/test_verifier.rs diff --git a/cranelift/src/print_cfg.rs b/cranelift/src/print_cfg.rs index df624993ad..08ab439d05 100644 --- a/cranelift/src/print_cfg.rs +++ b/cranelift/src/print_cfg.rs @@ -3,15 +3,9 @@ //! Read a series of Cretonne IL files and print their control flow graphs //! in graphviz format. -use std::borrow::Cow; -use std::fmt::{Result, Write, Display, Formatter}; - use CommandResult; -use cretonne::flowgraph::ControlFlowGraph; -use cretonne::ir::Function; -use cretonne::ir::instructions::BranchInfo; -use cton_reader::{parse_functions, TestCommand}; -use filetest::subtest::{self, SubTest, Context, Result as STResult}; +use cretonne::cfg_printer::CFGPrinter; +use cton_reader::parse_functions; use utils::read_to_string; pub fn run(files: Vec) -> CommandResult { @@ -24,72 +18,6 @@ pub fn run(files: Vec) -> CommandResult { Ok(()) } -struct CFGPrinter<'a> { - func: &'a Function, - cfg: ControlFlowGraph, -} - -impl<'a> CFGPrinter<'a> { - pub fn new(func: &'a Function) -> CFGPrinter<'a> { - CFGPrinter { - func, - cfg: ControlFlowGraph::with_function(func), - } - } - - /// Write the CFG for this function to `w`. - pub fn write(&self, w: &mut Write) -> Result { - self.header(w)?; - self.ebb_nodes(w)?; - self.cfg_connections(w)?; - writeln!(w, "}}") - } - - fn header(&self, w: &mut Write) -> Result { - writeln!(w, "digraph \"{}\" {{", self.func.name)?; - if let Some(entry) = self.func.layout.entry_block() { - writeln!(w, " {{rank=min; {}}}", entry)?; - } - Ok(()) - } - - fn ebb_nodes(&self, w: &mut Write) -> Result { - for ebb in &self.func.layout { - write!(w, " {} [shape=record, label=\"{{{}", ebb, ebb)?; - // Add all outgoing branch instructions to the label. - for inst in self.func.layout.ebb_insts(ebb) { - let idata = &self.func.dfg[inst]; - match idata.analyze_branch(&self.func.dfg.value_lists) { - BranchInfo::SingleDest(dest, _) => { - write!(w, " | <{}>{} {}", inst, idata.opcode(), dest)? - } - BranchInfo::Table(table) => { - write!(w, " | <{}>{} {}", inst, idata.opcode(), table)? - } - BranchInfo::NotABranch => {} - } - } - writeln!(w, "}}\"]")? - } - Ok(()) - } - - fn cfg_connections(&self, w: &mut Write) -> Result { - for ebb in &self.func.layout { - for (parent, inst) in self.cfg.pred_iter(ebb) { - writeln!(w, " {}:{} -> {}", parent, inst, ebb)?; - } - } - Ok(()) - } -} - -impl<'a> Display for CFGPrinter<'a> { - fn fmt(&self, f: &mut Formatter) -> Result { - self.write(f) - } -} - fn print_cfg(filename: String) -> CommandResult { let buffer = read_to_string(&filename).map_err( |e| format!("{}: {}", filename, e), @@ -107,29 +35,3 @@ fn print_cfg(filename: String) -> CommandResult { Ok(()) } - -/// Object implementing the `test print-cfg` sub-test. -struct TestPrintCfg; - -pub fn subtest(parsed: &TestCommand) -> STResult> { - assert_eq!(parsed.command, "print-cfg"); - if !parsed.options.is_empty() { - Err(format!("No options allowed on {}", parsed)) - } else { - Ok(Box::new(TestPrintCfg)) - } -} - -impl SubTest for TestPrintCfg { - fn name(&self) -> Cow { - Cow::from("print-cfg") - } - - fn needs_verifier(&self) -> bool { - false - } - - fn run(&self, func: Cow, context: &Context) -> STResult<()> { - subtest::run_filecheck(&CFGPrinter::new(&func).to_string(), context) - } -} diff --git a/cranelift/test-all.sh b/cranelift/test-all.sh index 2402eb7a39..fec95573f4 100755 --- a/cranelift/test-all.sh +++ b/cranelift/test-all.sh @@ -43,21 +43,19 @@ if [ -n "$needcheck" ]; then fi cd "$topdir" -banner "Rust unit tests" -cargo test --all -# Build cton-util for parser testing. -cd "$topdir" -banner "Rust documentation" -echo "open $topdir/target/doc/cretonne/index.html" +# Make sure the code builds in debug mode. +banner "Rust debug build" +cargo build + +# Make sure the code builds in release mode, and run the unit tests. We run +# these in release mode for speed, but note that the top-level Cargo.toml file +# does enable debug assertions in release builds. +banner "Rust release build and unit tests" +cargo test --all --release + +# Make sure the documentation builds. +banner "Rust documentation: $topdir/target/doc/cretonne/index.html" cargo doc -banner "Rust release build" -cargo build --release - -export CTONUTIL="$topdir/target/release/cton-util" - -cd "$topdir" -banner "File tests" -"$CTONUTIL" test filetests docs banner "OK" diff --git a/cranelift/tests/cton-util-test.rs b/cranelift/tests/cton-util-test.rs new file mode 100644 index 0000000000..d9870351d1 --- /dev/null +++ b/cranelift/tests/cton-util-test.rs @@ -0,0 +1,34 @@ +//! Run `cton-util test` on all available testcases. + +use std::process::{Command, Output}; +use std::env; +use std::path::PathBuf; +use std::io::{self, Write}; + +/// Returns the target directory, where we can find build artifacts +/// and such for the current configuration. +fn get_target_dir() -> PathBuf { + let mut path = env::current_exe().unwrap(); + path.pop(); // chop off exe name + path.pop(); // chop off deps name + path +} + +#[test] +fn cton_util_test() { + let mut cmd = Command::new(&get_target_dir().join("cton-util")); + cmd.arg("test"); + + // We have testcases in the following directories: + cmd.arg("filetests"); + cmd.arg("docs"); + + let Output { + status, + stdout, + stderr, + } = cmd.output().unwrap(); + io::stdout().write(&stdout).unwrap(); + io::stderr().write(&stderr).unwrap(); + assert!(status.success(), "failed with exit status {}", status); +} diff --git a/lib/cretonne/src/cfg_printer.rs b/lib/cretonne/src/cfg_printer.rs new file mode 100644 index 0000000000..736d12f0fc --- /dev/null +++ b/lib/cretonne/src/cfg_printer.rs @@ -0,0 +1,76 @@ +//! The `CFGPrinter` utility. + +use std::fmt::{Result, Write, Display, Formatter}; + +use flowgraph::ControlFlowGraph; +use ir::Function; +use ir::instructions::BranchInfo; + +/// A utility for pretty-printing the CFG of a `Function`. +pub struct CFGPrinter<'a> { + func: &'a Function, + cfg: ControlFlowGraph, +} + +/// A utility for pretty-printing the CFG of a `Function`. +impl<'a> CFGPrinter<'a> { + /// Create a new CFGPrinter. + pub fn new(func: &'a Function) -> CFGPrinter<'a> { + CFGPrinter { + func, + cfg: ControlFlowGraph::with_function(func), + } + } + + /// Write the CFG for this function to `w`. + pub fn write(&self, w: &mut Write) -> Result { + self.header(w)?; + self.ebb_nodes(w)?; + self.cfg_connections(w)?; + writeln!(w, "}}") + } + + fn header(&self, w: &mut Write) -> Result { + writeln!(w, "digraph \"{}\" {{", self.func.name)?; + if let Some(entry) = self.func.layout.entry_block() { + writeln!(w, " {{rank=min; {}}}", entry)?; + } + Ok(()) + } + + fn ebb_nodes(&self, w: &mut Write) -> Result { + for ebb in &self.func.layout { + write!(w, " {} [shape=record, label=\"{{{}", ebb, ebb)?; + // Add all outgoing branch instructions to the label. + for inst in self.func.layout.ebb_insts(ebb) { + let idata = &self.func.dfg[inst]; + match idata.analyze_branch(&self.func.dfg.value_lists) { + BranchInfo::SingleDest(dest, _) => { + write!(w, " | <{}>{} {}", inst, idata.opcode(), dest)? + } + BranchInfo::Table(table) => { + write!(w, " | <{}>{} {}", inst, idata.opcode(), table)? + } + BranchInfo::NotABranch => {} + } + } + writeln!(w, "}}\"]")? + } + Ok(()) + } + + fn cfg_connections(&self, w: &mut Write) -> Result { + for ebb in &self.func.layout { + for (parent, inst) in self.cfg.pred_iter(ebb) { + writeln!(w, " {}:{} -> {}", parent, inst, ebb)?; + } + } + Ok(()) + } +} + +impl<'a> Display for CFGPrinter<'a> { + fn fmt(&self, f: &mut Formatter) -> Result { + self.write(f) + } +} diff --git a/lib/cretonne/src/lib.rs b/lib/cretonne/src/lib.rs index ab7bb51f03..b924f5d9e5 100644 --- a/lib/cretonne/src/lib.rs +++ b/lib/cretonne/src/lib.rs @@ -19,6 +19,7 @@ pub mod entity; pub mod bforest; pub mod binemit; +pub mod cfg_printer; pub mod cursor; pub mod dominator_tree; pub mod flowgraph; From 965b93bd2a7b754cc044c0b8cd38bf7fb9ae2076 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 15 Mar 2018 13:00:29 -0700 Subject: [PATCH 13/72] Move the filetest harness into its own crate. This allows us to run the tests via a library call rather than just as a command execution. And, it's a step toward a broader goal, which is to keep the code in the top-level src directory minimal, with important functionality exposed as crates. --- cranelift/Cargo.toml | 2 +- cranelift/docs/testing.rst | 3 + cranelift/src/compile.rs | 3 +- cranelift/src/cton-util.rs | 6 +- cranelift/src/rsfilecheck.rs | 4 ++ cranelift/src/utils.rs | 58 ------------------- cranelift/src/wasm.rs | 3 +- cranelift/test-all.sh | 9 ++- cranelift/tests/cton-util-test.rs | 34 ----------- cranelift/tests/filetests.rs | 7 +++ lib/cretonne/src/lib.rs | 1 + lib/cretonne/src/print_errors.rs | 33 +++++++++++ lib/filetests/Cargo.toml | 18 ++++++ .../filetests/src}/concurrent.rs | 2 +- .../mod.rs => lib/filetests/src/lib.rs | 16 +++-- lib/filetests/src/match_directive.rs | 27 +++++++++ .../filetest => lib/filetests/src}/runner.rs | 11 ++-- .../filetest => lib/filetests/src}/runone.rs | 16 ++++- .../filetest => lib/filetests/src}/subtest.rs | 0 .../filetests/src}/test_binemit.rs | 5 +- .../filetests/src}/test_cat.rs | 2 +- .../filetests/src}/test_compile.rs | 4 +- .../filetests/src}/test_domtree.rs | 6 +- .../filetests/src}/test_legalizer.rs | 4 +- .../filetests/src}/test_licm.rs | 4 +- .../filetests/src}/test_preopt.rs | 4 +- .../filetests/src}/test_print_cfg.rs | 2 +- .../filetests/src}/test_regalloc.rs | 4 +- .../filetests/src}/test_simple_gvn.rs | 4 +- .../filetests/src}/test_verifier.rs | 6 +- lib/wasm/tests/wasm_testsuite.rs | 26 +-------- 31 files changed, 161 insertions(+), 163 deletions(-) delete mode 100644 cranelift/tests/cton-util-test.rs create mode 100644 cranelift/tests/filetests.rs create mode 100644 lib/cretonne/src/print_errors.rs create mode 100644 lib/filetests/Cargo.toml rename {cranelift/src/filetest => lib/filetests/src}/concurrent.rs (99%) rename cranelift/src/filetest/mod.rs => lib/filetests/src/lib.rs (85%) create mode 100644 lib/filetests/src/match_directive.rs rename {cranelift/src/filetest => lib/filetests/src}/runner.rs (98%) rename {cranelift/src/filetest => lib/filetests/src}/runone.rs (91%) rename {cranelift/src/filetest => lib/filetests/src}/subtest.rs (100%) rename {cranelift/src/filetest => lib/filetests/src}/test_binemit.rs (98%) rename {cranelift/src/filetest => lib/filetests/src}/test_cat.rs (92%) rename {cranelift/src/filetest => lib/filetests/src}/test_compile.rs (96%) rename {cranelift/src/filetest => lib/filetests/src}/test_domtree.rs (97%) rename {cranelift/src/filetest => lib/filetests/src}/test_legalizer.rs (93%) rename {cranelift/src/filetest => lib/filetests/src}/test_licm.rs (93%) rename {cranelift/src/filetest => lib/filetests/src}/test_preopt.rs (92%) rename {cranelift/src/filetest => lib/filetests/src}/test_print_cfg.rs (93%) rename {cranelift/src/filetest => lib/filetests/src}/test_regalloc.rs (94%) rename {cranelift/src/filetest => lib/filetests/src}/test_simple_gvn.rs (93%) rename {cranelift/src/filetest => lib/filetests/src}/test_verifier.rs (96%) diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index ee904633f9..064a2ee5ab 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -18,11 +18,11 @@ cretonne-reader = { path = "lib/reader", version = "0.3.4" } cretonne-frontend = { path = "lib/frontend", version = "0.3.4" } cretonne-wasm = { path = "lib/wasm", version = "0.3.4" } cretonne-native = { path = "lib/native", version = "0.3.4" } +cretonne-filetests = { path = "lib/filetests", version = "0.3.4" } filecheck = { path = "lib/filecheck" } docopt = "0.8.0" serde = "1.0.8" serde_derive = "1.0.8" -num_cpus = "1.5.1" tempdir = "0.3.5" term = "0.5" diff --git a/cranelift/docs/testing.rst b/cranelift/docs/testing.rst index 07aa8f8e16..6ddc53ed84 100644 --- a/cranelift/docs/testing.rst +++ b/cranelift/docs/testing.rst @@ -136,6 +136,9 @@ This example will run the legalizer test twice. Both runs will have ``opt_level=best``, but they will have different ``is_64bit`` settings. The 32-bit run will also have the RISC-V specific flag ``supports_m`` disabled. +The filetests are run automatically as part of `cargo test`, and they can +also be run manually with the `cton-util test` command. + Filecheck --------- diff --git a/cranelift/src/compile.rs b/cranelift/src/compile.rs index 9a9644b1cf..9047f055fe 100644 --- a/cranelift/src/compile.rs +++ b/cranelift/src/compile.rs @@ -7,8 +7,9 @@ use std::path::PathBuf; use cretonne::Context; use cretonne::settings::FlagsOrIsa; use cretonne::{binemit, ir}; +use cretonne::print_errors::pretty_error; use std::path::Path; -use utils::{pretty_error, read_to_string, parse_sets_and_isa}; +use utils::{read_to_string, parse_sets_and_isa}; struct PrintRelocs { flag_print: bool, diff --git a/cranelift/src/cton-util.rs b/cranelift/src/cton-util.rs index 9f6891489e..54d7d38d4d 100644 --- a/cranelift/src/cton-util.rs +++ b/cranelift/src/cton-util.rs @@ -1,12 +1,11 @@ -#[macro_use(dbg)] extern crate cretonne; extern crate cton_reader; extern crate cton_wasm; +extern crate cton_filetests; extern crate docopt; #[macro_use] extern crate serde_derive; extern crate filecheck; -extern crate num_cpus; extern crate tempdir; extern crate term; @@ -16,7 +15,6 @@ use std::io::{self, Write}; use std::process; mod utils; -mod filetest; mod cat; mod print_cfg; mod rsfilecheck; @@ -88,7 +86,7 @@ fn cton_util() -> CommandResult { // Find the sub-command to execute. let result = if args.cmd_test { - filetest::run(args.flag_verbose, args.arg_file) + cton_filetests::run(args.flag_verbose, args.arg_file).map(|_time| ()) } else if args.cmd_cat { cat::run(args.arg_file) } else if args.cmd_filecheck { diff --git a/cranelift/src/rsfilecheck.rs b/cranelift/src/rsfilecheck.rs index 46605bb368..57b9bb9e8f 100644 --- a/cranelift/src/rsfilecheck.rs +++ b/cranelift/src/rsfilecheck.rs @@ -1,3 +1,7 @@ +//! The `filecheck` sub-command. +//! +//! This file is named to avoid a name collision with the filecheck crate. + use CommandResult; use utils::read_to_string; use filecheck::{CheckerBuilder, Checker, NO_VARIABLES}; diff --git a/cranelift/src/utils.rs b/cranelift/src/utils.rs index 25c6dbf067..7e45e99436 100644 --- a/cranelift/src/utils.rs +++ b/cranelift/src/utils.rs @@ -1,13 +1,9 @@ //! Utility functions. -use cretonne::ir::entities::AnyEntity; -use cretonne::{ir, verifier}; -use cretonne::result::CtonError; use cretonne::isa::TargetIsa; use cretonne::settings::{self, FlagsOrIsa}; use cretonne::isa; use cton_reader::{parse_options, Location}; -use std::fmt::Write; use std::fs::File; use std::io::{self, Read}; use std::path::Path; @@ -28,51 +24,6 @@ pub fn read_to_end>(path: P) -> io::Result> { Ok(buffer) } -/// Look for a directive in a comment string. -/// The directive is of the form "foo:" and should follow the leading `;` in the comment: -/// -/// ; dominates: ebb3 ebb4 -/// -/// Return the comment text following the directive. -pub fn match_directive<'a>(comment: &'a str, directive: &str) -> Option<&'a str> { - assert!( - directive.ends_with(':'), - "Directive must include trailing colon" - ); - let text = comment.trim_left_matches(';').trim_left(); - if text.starts_with(directive) { - Some(text[directive.len()..].trim()) - } else { - None - } -} - -/// Pretty-print a verifier error. -pub fn pretty_verifier_error( - func: &ir::Function, - isa: Option<&TargetIsa>, - err: verifier::Error, -) -> String { - let mut msg = err.to_string(); - match err.location { - AnyEntity::Inst(inst) => { - write!(msg, "\n{}: {}\n\n", inst, func.dfg.display_inst(inst, isa)).unwrap() - } - _ => msg.push('\n'), - } - write!(msg, "{}", func.display(isa)).unwrap(); - msg -} - -/// Pretty-print a Cretonne error. -pub fn pretty_error(func: &ir::Function, isa: Option<&TargetIsa>, err: CtonError) -> String { - if let CtonError::Verifier(e) = err { - pretty_verifier_error(func, isa, e) - } else { - err.to_string() - } -} - /// Like `FlagsOrIsa`, but holds ownership. pub enum OwnedFlagsOrIsa { Flags(settings::Flags), @@ -119,12 +70,3 @@ pub fn parse_sets_and_isa( Ok(OwnedFlagsOrIsa::Flags(settings::Flags::new(&flag_builder))) } } - -#[test] -fn test_match_directive() { - assert_eq!(match_directive("; foo: bar ", "foo:"), Some("bar")); - assert_eq!(match_directive(" foo:bar", "foo:"), Some("bar")); - assert_eq!(match_directive("foo:bar", "foo:"), Some("bar")); - assert_eq!(match_directive(";x foo: bar", "foo:"), None); - assert_eq!(match_directive(";;; foo: bar", "foo:"), Some("bar")); -} diff --git a/cranelift/src/wasm.rs b/cranelift/src/wasm.rs index ab6a245d3a..3ab877bf34 100644 --- a/cranelift/src/wasm.rs +++ b/cranelift/src/wasm.rs @@ -6,6 +6,7 @@ use cton_wasm::{translate_module, DummyEnvironment, ModuleEnvironment}; use std::path::PathBuf; use cretonne::Context; use cretonne::settings::FlagsOrIsa; +use cretonne::print_errors::{pretty_error, pretty_verifier_error}; use std::fs::File; use std::error::Error; use std::io; @@ -13,7 +14,7 @@ use std::path::Path; use std::process::Command; use tempdir::TempDir; use term; -use utils::{pretty_verifier_error, pretty_error, parse_sets_and_isa, read_to_end}; +use utils::{parse_sets_and_isa, read_to_end}; macro_rules! vprintln { ($x: expr, $($tts:tt)*) => { diff --git a/cranelift/test-all.sh b/cranelift/test-all.sh index fec95573f4..7b86495903 100755 --- a/cranelift/test-all.sh +++ b/cranelift/test-all.sh @@ -3,11 +3,10 @@ set -euo pipefail # This is the top-level test script: # -# - Build documentation for Rust code in 'src/tools/target/doc'. -# - Run unit tests for all Rust crates. -# - Make a debug build of all crates. -# - Make a release build of cton-util. -# - Run file-level tests with the release build of cton-util. +# - Make a debug build. +# - Make a release build. +# - Run unit tests for all Rust crates (including the filetests) +# - Build API documentation. # # All tests run by this script should be passing at all times. diff --git a/cranelift/tests/cton-util-test.rs b/cranelift/tests/cton-util-test.rs deleted file mode 100644 index d9870351d1..0000000000 --- a/cranelift/tests/cton-util-test.rs +++ /dev/null @@ -1,34 +0,0 @@ -//! Run `cton-util test` on all available testcases. - -use std::process::{Command, Output}; -use std::env; -use std::path::PathBuf; -use std::io::{self, Write}; - -/// Returns the target directory, where we can find build artifacts -/// and such for the current configuration. -fn get_target_dir() -> PathBuf { - let mut path = env::current_exe().unwrap(); - path.pop(); // chop off exe name - path.pop(); // chop off deps name - path -} - -#[test] -fn cton_util_test() { - let mut cmd = Command::new(&get_target_dir().join("cton-util")); - cmd.arg("test"); - - // We have testcases in the following directories: - cmd.arg("filetests"); - cmd.arg("docs"); - - let Output { - status, - stdout, - stderr, - } = cmd.output().unwrap(); - io::stdout().write(&stdout).unwrap(); - io::stderr().write(&stderr).unwrap(); - assert!(status.success(), "failed with exit status {}", status); -} diff --git a/cranelift/tests/filetests.rs b/cranelift/tests/filetests.rs new file mode 100644 index 0000000000..97fbeb296f --- /dev/null +++ b/cranelift/tests/filetests.rs @@ -0,0 +1,7 @@ +extern crate cton_filetests; + +#[test] +fn filetests() { + // Run all the filetests in the following directories. + cton_filetests::run(false, vec!["filetests".into(), "docs".into()]).expect("test harness"); +} diff --git a/lib/cretonne/src/lib.rs b/lib/cretonne/src/lib.rs index b924f5d9e5..f317ed9f85 100644 --- a/lib/cretonne/src/lib.rs +++ b/lib/cretonne/src/lib.rs @@ -27,6 +27,7 @@ pub mod ir; pub mod isa; pub mod loop_analysis; pub mod packed_option; +pub mod print_errors; pub mod result; pub mod settings; pub mod timing; diff --git a/lib/cretonne/src/print_errors.rs b/lib/cretonne/src/print_errors.rs new file mode 100644 index 0000000000..abd22f3e6b --- /dev/null +++ b/lib/cretonne/src/print_errors.rs @@ -0,0 +1,33 @@ +//! Utility routines for pretty-printing error messages. + +use ir; +use verifier; +use result::CtonError; +use isa::TargetIsa; +use std::fmt::Write; + +/// Pretty-print a verifier error. +pub fn pretty_verifier_error( + func: &ir::Function, + isa: Option<&TargetIsa>, + err: verifier::Error, +) -> String { + let mut msg = err.to_string(); + match err.location { + ir::entities::AnyEntity::Inst(inst) => { + write!(msg, "\n{}: {}\n\n", inst, func.dfg.display_inst(inst, isa)).unwrap() + } + _ => msg.push('\n'), + } + write!(msg, "{}", func.display(isa)).unwrap(); + msg +} + +/// Pretty-print a Cretonne error. +pub fn pretty_error(func: &ir::Function, isa: Option<&TargetIsa>, err: CtonError) -> String { + if let CtonError::Verifier(e) = err { + pretty_verifier_error(func, isa, e) + } else { + err.to_string() + } +} diff --git a/lib/filetests/Cargo.toml b/lib/filetests/Cargo.toml new file mode 100644 index 0000000000..215f947e74 --- /dev/null +++ b/lib/filetests/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "cretonne-filetests" +authors = ["The Cretonne Project Developers"] +version = "0.3.4" +description = "Test driver and implementations of the filetest commands" +license = "Apache-2.0" +documentation = "http://cretonne.readthedocs.io/en/latest/testing.html#file-tests" +repository = "https://github.com/Cretonne/cretonne" +publish = false + +[lib] +name = "cton_filetests" + +[dependencies] +cretonne = { path = "../cretonne", version = "0.3.4" } +cretonne-reader = { path = "../reader", version = "0.3.4" } +filecheck = { path = "../filecheck", version = "0.1.0" } +num_cpus = "1.5.1" diff --git a/cranelift/src/filetest/concurrent.rs b/lib/filetests/src/concurrent.rs similarity index 99% rename from cranelift/src/filetest/concurrent.rs rename to lib/filetests/src/concurrent.rs index a651c14071..6a18bb2390 100644 --- a/cranelift/src/filetest/concurrent.rs +++ b/lib/filetests/src/concurrent.rs @@ -11,7 +11,7 @@ use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; use num_cpus; -use filetest::{TestResult, runone}; +use {TestResult, runone}; // Request sent to worker threads contains jobid and path. struct Request(usize, PathBuf); diff --git a/cranelift/src/filetest/mod.rs b/lib/filetests/src/lib.rs similarity index 85% rename from cranelift/src/filetest/mod.rs rename to lib/filetests/src/lib.rs index 6d7a5e39d5..36d321358c 100644 --- a/cranelift/src/filetest/mod.rs +++ b/lib/filetests/src/lib.rs @@ -1,18 +1,24 @@ //! File tests. //! -//! This module contains the main driver for `cton-util test` as well as implementations of the -//! available test commands. +//! This crate contains the main test driver as well as implementations of the +//! available filetest commands. + +#[macro_use(dbg)] +extern crate cretonne; +extern crate cton_reader; +extern crate filecheck; +extern crate num_cpus; use std::path::Path; use std::time; use cton_reader::TestCommand; -use CommandResult; -use filetest::runner::TestRunner; +use runner::TestRunner; mod concurrent; mod runner; mod runone; mod subtest; +mod match_directive; mod test_binemit; mod test_cat; @@ -38,7 +44,7 @@ type TestResult = Result; /// Directories are scanned recursively for test cases ending in `.cton`. These test cases are /// executed on background threads. /// -pub fn run(verbose: bool, files: Vec) -> CommandResult { +pub fn run(verbose: bool, files: Vec) -> TestResult { let mut runner = TestRunner::new(verbose); for path in files.iter().map(Path::new) { diff --git a/lib/filetests/src/match_directive.rs b/lib/filetests/src/match_directive.rs new file mode 100644 index 0000000000..9a8d94a4df --- /dev/null +++ b/lib/filetests/src/match_directive.rs @@ -0,0 +1,27 @@ +/// Look for a directive in a comment string. +/// The directive is of the form "foo:" and should follow the leading `;` in the comment: +/// +/// ; dominates: ebb3 ebb4 +/// +/// Return the comment text following the directive. +pub fn match_directive<'a>(comment: &'a str, directive: &str) -> Option<&'a str> { + assert!( + directive.ends_with(':'), + "Directive must include trailing colon" + ); + let text = comment.trim_left_matches(';').trim_left(); + if text.starts_with(directive) { + Some(text[directive.len()..].trim()) + } else { + None + } +} + +#[test] +fn test_match_directive() { + assert_eq!(match_directive("; foo: bar ", "foo:"), Some("bar")); + assert_eq!(match_directive(" foo:bar", "foo:"), Some("bar")); + assert_eq!(match_directive("foo:bar", "foo:"), Some("bar")); + assert_eq!(match_directive(";x foo: bar", "foo:"), None); + assert_eq!(match_directive(";;; foo: bar", "foo:"), Some("bar")); +} diff --git a/cranelift/src/filetest/runner.rs b/lib/filetests/src/runner.rs similarity index 98% rename from cranelift/src/filetest/runner.rs rename to lib/filetests/src/runner.rs index 09ec3a19a9..ff40ed81e2 100644 --- a/cranelift/src/filetest/runner.rs +++ b/lib/filetests/src/runner.rs @@ -7,9 +7,9 @@ use std::error::Error; use std::fmt::{self, Display}; use std::ffi::OsStr; use std::path::{Path, PathBuf}; -use filetest::{TestResult, runone}; -use filetest::concurrent::{ConcurrentRunner, Reply}; -use CommandResult; +use std::time; +use {TestResult, runone}; +use concurrent::{ConcurrentRunner, Reply}; // Timeout in seconds when we're not making progress. const TIMEOUT_PANIC: usize = 10; @@ -323,14 +323,15 @@ impl TestRunner { } /// Scan pushed directories for tests and run them. - pub fn run(&mut self) -> CommandResult { + pub fn run(&mut self) -> TestResult { + let started = time::Instant::now(); self.scan_dirs(); self.schedule_jobs(); self.drain_threads(); self.report_slow_tests(); println!("{} tests", self.tests.len()); match self.errors { - 0 => Ok(()), + 0 => Ok(started.elapsed()), 1 => Err("1 failure".to_string()), n => Err(format!("{} failures", n)), } diff --git a/cranelift/src/filetest/runone.rs b/lib/filetests/src/runone.rs similarity index 91% rename from cranelift/src/filetest/runone.rs rename to lib/filetests/src/runone.rs index 1dc8eb9849..fcc01e4f95 100644 --- a/cranelift/src/filetest/runone.rs +++ b/lib/filetests/src/runone.rs @@ -3,16 +3,26 @@ use std::borrow::Cow; use std::path::Path; use std::time; +use std::io::{self, Read}; +use std::fs; use cretonne::ir::Function; use cretonne::isa::TargetIsa; use cretonne::settings::Flags; use cretonne::timing; use cretonne::verify_function; +use cretonne::print_errors::pretty_verifier_error; use cton_reader::parse_test; use cton_reader::IsaSpec; -use utils::{read_to_string, pretty_verifier_error}; -use filetest::{TestResult, new_subtest}; -use filetest::subtest::{SubTest, Context, Result}; +use {TestResult, new_subtest}; +use subtest::{SubTest, Context, Result}; + +/// Read an entire file into a string. +fn read_to_string>(path: P) -> io::Result { + let mut file = fs::File::open(path)?; + let mut buffer = String::new(); + file.read_to_string(&mut buffer)?; + Ok(buffer) +} /// Load `path` and run the test in it. /// diff --git a/cranelift/src/filetest/subtest.rs b/lib/filetests/src/subtest.rs similarity index 100% rename from cranelift/src/filetest/subtest.rs rename to lib/filetests/src/subtest.rs diff --git a/cranelift/src/filetest/test_binemit.rs b/lib/filetests/src/test_binemit.rs similarity index 98% rename from cranelift/src/filetest/test_binemit.rs rename to lib/filetests/src/test_binemit.rs index 3c52a63b2b..c3284c1423 100644 --- a/cranelift/src/filetest/test_binemit.rs +++ b/lib/filetests/src/test_binemit.rs @@ -11,9 +11,10 @@ use cretonne::dbg::DisplayList; use cretonne::ir; use cretonne::ir::entities::AnyEntity; use cretonne::binemit::RegDiversions; +use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use filetest::subtest::{SubTest, Context, Result}; -use utils::{match_directive, pretty_error}; +use subtest::{SubTest, Context, Result}; +use match_directive::match_directive; struct TestBinEmit; diff --git a/cranelift/src/filetest/test_cat.rs b/lib/filetests/src/test_cat.rs similarity index 92% rename from cranelift/src/filetest/test_cat.rs rename to lib/filetests/src/test_cat.rs index fc4a3cac10..fbbcbd034b 100644 --- a/cranelift/src/filetest/test_cat.rs +++ b/lib/filetests/src/test_cat.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use cretonne::ir::Function; use cton_reader::TestCommand; -use filetest::subtest::{self, SubTest, Context, Result as STResult}; +use subtest::{self, SubTest, Context, Result as STResult}; /// Object implementing the `test cat` sub-test. /// diff --git a/cranelift/src/filetest/test_compile.rs b/lib/filetests/src/test_compile.rs similarity index 96% rename from cranelift/src/filetest/test_compile.rs rename to lib/filetests/src/test_compile.rs index 8c8db46591..3772081a16 100644 --- a/cranelift/src/filetest/test_compile.rs +++ b/lib/filetests/src/test_compile.rs @@ -5,11 +5,11 @@ use cretonne::binemit; use cretonne::ir; use cretonne; +use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use filetest::subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{SubTest, Context, Result, run_filecheck}; use std::borrow::Cow; use std::fmt::Write; -use utils::pretty_error; struct TestCompile; diff --git a/cranelift/src/filetest/test_domtree.rs b/lib/filetests/src/test_domtree.rs similarity index 97% rename from cranelift/src/filetest/test_domtree.rs rename to lib/filetests/src/test_domtree.rs index 9c0fe5a841..6eae539644 100644 --- a/cranelift/src/filetest/test_domtree.rs +++ b/lib/filetests/src/test_domtree.rs @@ -2,7 +2,9 @@ //! //! The `test domtree` test command looks for annotations on instructions like this: //! +//! ```cton //! jump ebb3 ; dominates: ebb3 +//! ``` //! //! This annotation means that the jump instruction is expected to be the immediate dominator of //! `ebb3`. @@ -15,12 +17,12 @@ use cretonne::flowgraph::ControlFlowGraph; use cretonne::ir::Function; use cretonne::ir::entities::AnyEntity; use cton_reader::TestCommand; -use filetest::subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{SubTest, Context, Result, run_filecheck}; use std::borrow::{Borrow, Cow}; use std::collections::HashMap; use std::fmt::{self, Write}; use std::result; -use utils::match_directive; +use match_directive::match_directive; struct TestDomtree; diff --git a/cranelift/src/filetest/test_legalizer.rs b/lib/filetests/src/test_legalizer.rs similarity index 93% rename from cranelift/src/filetest/test_legalizer.rs rename to lib/filetests/src/test_legalizer.rs index e79aada799..c8d03e4c2a 100644 --- a/cranelift/src/filetest/test_legalizer.rs +++ b/lib/filetests/src/test_legalizer.rs @@ -6,10 +6,10 @@ use std::borrow::Cow; use cretonne; use cretonne::ir::Function; +use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use filetest::subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{SubTest, Context, Result, run_filecheck}; use std::fmt::Write; -use utils::pretty_error; struct TestLegalizer; diff --git a/cranelift/src/filetest/test_licm.rs b/lib/filetests/src/test_licm.rs similarity index 93% rename from cranelift/src/filetest/test_licm.rs rename to lib/filetests/src/test_licm.rs index 32be450476..f7d4397b5a 100644 --- a/cranelift/src/filetest/test_licm.rs +++ b/lib/filetests/src/test_licm.rs @@ -7,11 +7,11 @@ use cretonne::ir::Function; use cretonne; +use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use filetest::subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{SubTest, Context, Result, run_filecheck}; use std::borrow::Cow; use std::fmt::Write; -use utils::pretty_error; struct TestLICM; diff --git a/cranelift/src/filetest/test_preopt.rs b/lib/filetests/src/test_preopt.rs similarity index 92% rename from cranelift/src/filetest/test_preopt.rs rename to lib/filetests/src/test_preopt.rs index 60d03f8207..c141d28480 100644 --- a/cranelift/src/filetest/test_preopt.rs +++ b/lib/filetests/src/test_preopt.rs @@ -4,11 +4,11 @@ use cretonne::ir::Function; use cretonne; +use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use filetest::subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{SubTest, Context, Result, run_filecheck}; use std::borrow::Cow; use std::fmt::Write; -use utils::pretty_error; struct TestPreopt; diff --git a/cranelift/src/filetest/test_print_cfg.rs b/lib/filetests/src/test_print_cfg.rs similarity index 93% rename from cranelift/src/filetest/test_print_cfg.rs rename to lib/filetests/src/test_print_cfg.rs index 1be9987087..470d293185 100644 --- a/cranelift/src/filetest/test_print_cfg.rs +++ b/lib/filetests/src/test_print_cfg.rs @@ -8,7 +8,7 @@ use std::borrow::Cow; use cretonne::ir::Function; use cretonne::cfg_printer::CFGPrinter; use cton_reader::TestCommand; -use filetest::subtest::{self, SubTest, Context, Result as STResult}; +use subtest::{self, SubTest, Context, Result as STResult}; /// Object implementing the `test print-cfg` sub-test. struct TestPrintCfg; diff --git a/cranelift/src/filetest/test_regalloc.rs b/lib/filetests/src/test_regalloc.rs similarity index 94% rename from cranelift/src/filetest/test_regalloc.rs rename to lib/filetests/src/test_regalloc.rs index 48160796a8..7cd0788928 100644 --- a/cranelift/src/filetest/test_regalloc.rs +++ b/lib/filetests/src/test_regalloc.rs @@ -7,11 +7,11 @@ use cretonne::ir::Function; use cretonne; +use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use filetest::subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{SubTest, Context, Result, run_filecheck}; use std::borrow::Cow; use std::fmt::Write; -use utils::pretty_error; struct TestRegalloc; diff --git a/cranelift/src/filetest/test_simple_gvn.rs b/lib/filetests/src/test_simple_gvn.rs similarity index 93% rename from cranelift/src/filetest/test_simple_gvn.rs rename to lib/filetests/src/test_simple_gvn.rs index a1da0e42a4..f967c3fa91 100644 --- a/cranelift/src/filetest/test_simple_gvn.rs +++ b/lib/filetests/src/test_simple_gvn.rs @@ -7,11 +7,11 @@ use cretonne::ir::Function; use cretonne; +use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use filetest::subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{SubTest, Context, Result, run_filecheck}; use std::borrow::Cow; use std::fmt::Write; -use utils::pretty_error; struct TestSimpleGVN; diff --git a/cranelift/src/filetest/test_verifier.rs b/lib/filetests/src/test_verifier.rs similarity index 96% rename from cranelift/src/filetest/test_verifier.rs rename to lib/filetests/src/test_verifier.rs index 7834fa778d..bb4375b59e 100644 --- a/cranelift/src/filetest/test_verifier.rs +++ b/lib/filetests/src/test_verifier.rs @@ -2,7 +2,9 @@ //! //! The `test verifier` test command looks for annotations on instructions like this: //! +//! ```cton //! jump ebb3 ; error: jump to non-existent EBB +//! ``` //! //! This annotation means that the verifier is expected to given an error for the jump instruction //! containing the substring "jump to non-existent EBB". @@ -11,8 +13,8 @@ use std::borrow::{Borrow, Cow}; use cretonne::verify_function; use cretonne::ir::Function; use cton_reader::TestCommand; -use filetest::subtest::{SubTest, Context, Result}; -use utils::match_directive; +use subtest::{SubTest, Context, Result}; +use match_directive::match_directive; struct TestVerifier; diff --git a/lib/wasm/tests/wasm_testsuite.rs b/lib/wasm/tests/wasm_testsuite.rs index c551dbf783..824a7606da 100644 --- a/lib/wasm/tests/wasm_testsuite.rs +++ b/lib/wasm/tests/wasm_testsuite.rs @@ -11,11 +11,9 @@ use std::str; use std::io::prelude::*; use std::process::Command; use std::fs; -use cretonne::ir; -use cretonne::ir::entities::AnyEntity; -use cretonne::isa::TargetIsa; use cretonne::settings::{self, Configurable, Flags}; use cretonne::verifier; +use cretonne::print_errors::pretty_verifier_error; use tempdir::TempDir; #[test] @@ -109,25 +107,3 @@ fn handle_module(path: PathBuf, flags: &Flags) { .unwrap(); } } - - -/// Pretty-print a verifier error. -pub fn pretty_verifier_error( - func: &ir::Function, - isa: Option<&TargetIsa>, - err: verifier::Error, -) -> String { - let msg = err.to_string(); - let str1 = match err.location { - AnyEntity::Inst(inst) => { - format!( - "{}\n{}: {}\n\n", - msg, - inst, - func.dfg.display_inst(inst, isa) - ) - } - _ => String::from(format!("{}\n", msg)), - }; - format!("{}{}", str1, func.display(isa)) -} From e889b88d04a64bc12f89d2b4f9ecbac7783a47fb Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 15 Mar 2018 14:56:54 -0700 Subject: [PATCH 14/72] Split filecheck out into its own repo. --- cranelift/Cargo.toml | 2 +- cranelift/docs/testing.rst | 3 +- cranelift/publish-all.sh | 6 +- lib/filecheck/Cargo.toml | 14 - lib/filecheck/src/checker.rs | 456 -------------------------- lib/filecheck/src/error.rs | 69 ---- lib/filecheck/src/explain.rs | 202 ------------ lib/filecheck/src/lib.rs | 256 --------------- lib/filecheck/src/pattern.rs | 593 ---------------------------------- lib/filecheck/src/variable.rs | 62 ---- lib/filecheck/tests/basic.rs | 402 ----------------------- lib/filetests/Cargo.toml | 2 +- 12 files changed, 4 insertions(+), 2063 deletions(-) delete mode 100644 lib/filecheck/Cargo.toml delete mode 100644 lib/filecheck/src/checker.rs delete mode 100644 lib/filecheck/src/error.rs delete mode 100644 lib/filecheck/src/explain.rs delete mode 100644 lib/filecheck/src/lib.rs delete mode 100644 lib/filecheck/src/pattern.rs delete mode 100644 lib/filecheck/src/variable.rs delete mode 100644 lib/filecheck/tests/basic.rs diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index 064a2ee5ab..b9acc0606c 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -19,7 +19,7 @@ cretonne-frontend = { path = "lib/frontend", version = "0.3.4" } cretonne-wasm = { path = "lib/wasm", version = "0.3.4" } cretonne-native = { path = "lib/native", version = "0.3.4" } cretonne-filetests = { path = "lib/filetests", version = "0.3.4" } -filecheck = { path = "lib/filecheck" } +filecheck = "0.2.1" docopt = "0.8.0" serde = "1.0.8" serde_derive = "1.0.8" diff --git a/cranelift/docs/testing.rst b/cranelift/docs/testing.rst index 6ddc53ed84..320cc37389 100644 --- a/cranelift/docs/testing.rst +++ b/cranelift/docs/testing.rst @@ -144,8 +144,7 @@ Filecheck Many of the test commands described below use *filecheck* to verify their output. Filecheck is a Rust implementation of the LLVM tool of the same name. -See the :file:`lib/filecheck` `documentation `_ for -details of its syntax. +See the `documentation `_ for details of its syntax. Comments in :file:`.cton` files are associated with the entity they follow. This typically means an instruction or the whole function. Those tests that diff --git a/cranelift/publish-all.sh b/cranelift/publish-all.sh index 7d8b7f7f3c..c5cd6bfca3 100755 --- a/cranelift/publish-all.sh +++ b/cranelift/publish-all.sh @@ -4,7 +4,6 @@ cd $(dirname "$0") topdir="$(pwd)" # All the cretonne-* crates have the same version number -# The filecheck crate version is managed independently. version="0.3.4" # Update all of the Cargo.toml files. @@ -12,9 +11,6 @@ version="0.3.4" # The main Cargo.toml in the top-level directory is the cretonne-tools crate which we don't publish. echo "Updating crate versions to $version" for crate in . lib/*; do - if [ "$crate" = "lib/filecheck" ]; then - continue - fi # Update the version number of this crate to $version. sed -i.bk -e "s/^version = .*/version = \"$version\"/" "$crate/Cargo.toml" # Update the required version number of any cretonne* dependencies. @@ -31,7 +27,7 @@ cargo update echo git commit -a -m "\"Bump version to $version"\" echo git push -for crate in filecheck cretonne frontend native reader wasm; do +for crate in cretonne frontend native reader wasm; do echo cargo publish --manifest-path "lib/$crate/Cargo.toml" done echo diff --git a/lib/filecheck/Cargo.toml b/lib/filecheck/Cargo.toml deleted file mode 100644 index aec22b0f51..0000000000 --- a/lib/filecheck/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -authors = ["The Cretonne Project Developers"] -name = "filecheck" -version = "0.1.0" -description = "Library for matching test outputs against filecheck directives" -license = "Apache-2.0" -repository = "https://github.com/Cretonne/cretonne" -documentation = "https://docs.rs/filecheck" - -[lib] -name = "filecheck" - -[dependencies] -regex = "0.2.6" diff --git a/lib/filecheck/src/checker.rs b/lib/filecheck/src/checker.rs deleted file mode 100644 index b3a68fba4c..0000000000 --- a/lib/filecheck/src/checker.rs +++ /dev/null @@ -1,456 +0,0 @@ -use error::{Error, Result}; -use variable::{VariableMap, Value, varname_prefix}; -use pattern::Pattern; -use regex::{Regex, Captures}; -use std::borrow::Cow; -use std::collections::HashMap; -use std::cmp::max; -use std::fmt::{self, Display, Formatter}; -use std::mem; -use MatchRange; -use explain::{Recorder, Explainer}; - -// The different kinds of directives we support. -enum Directive { - Check(Pattern), - SameLn(Pattern), - NextLn(Pattern), - Unordered(Pattern), - Not(Pattern), - Regex(String, String), -} - -// Regular expression matching a directive. -// The match groups are: -// -// 1. Keyword. -// 2. Rest of line / pattern. -// -const DIRECTIVE_RX: &str = r"\b(check|sameln|nextln|unordered|not|regex):\s+(.*)"; - -impl Directive { - /// Create a new directive from a `DIRECTIVE_RX` match. - fn new(caps: Captures) -> Result { - let cmd = caps.get(1).map(|m| m.as_str()).expect("group 1 must match"); - let rest = caps.get(2).map(|m| m.as_str()).expect("group 2 must match"); - - if cmd == "regex" { - return Directive::regex(rest); - } - - // All other commands are followed by a pattern. - let pat = rest.parse()?; - - match cmd { - "check" => Ok(Directive::Check(pat)), - "sameln" => Ok(Directive::SameLn(pat)), - "nextln" => Ok(Directive::NextLn(pat)), - "unordered" => Ok(Directive::Unordered(pat)), - "not" => { - if !pat.defs().is_empty() { - let msg = format!( - "can't define variables '$({}=...' in not: {}", - pat.defs()[0], - rest - ); - Err(Error::DuplicateDef(msg)) - } else { - Ok(Directive::Not(pat)) - } - } - _ => panic!("unexpected command {} in regex match", cmd), - } - } - - /// Create a `regex:` directive from a `VAR=...` string. - fn regex(rest: &str) -> Result { - let varlen = varname_prefix(rest); - if varlen == 0 { - return Err(Error::Syntax( - format!("invalid variable name in regex: {}", rest), - )); - } - let var = rest[0..varlen].to_string(); - if !rest[varlen..].starts_with('=') { - return Err(Error::Syntax(format!( - "expected '=' after variable '{}' in regex: {}", - var, - rest - ))); - } - // Ignore trailing white space in the regex, including CR. - Ok(Directive::Regex( - var, - rest[varlen + 1..].trim_right().to_string(), - )) - } -} - - -/// Builder for constructing a `Checker` instance. -pub struct CheckerBuilder { - directives: Vec, - linerx: Regex, -} - -impl CheckerBuilder { - /// Create a new, blank `CheckerBuilder`. - pub fn new() -> Self { - Self { - directives: Vec::new(), - linerx: Regex::new(DIRECTIVE_RX).unwrap(), - } - } - - /// Add a potential directive line. - /// - /// Returns true if this is a directive with one of the known prefixes. - /// Returns false if no known directive was found. - /// Returns an error if there is a problem with the directive. - pub fn directive(&mut self, l: &str) -> Result { - match self.linerx.captures(l) { - Some(caps) => { - self.directives.push(Directive::new(caps)?); - Ok(true) - } - None => Ok(false), - } - } - - /// Add multiple directives. - /// - /// The text is split into lines that are added individually as potential directives. - /// This method can be used to parse a whole test file containing multiple directives. - pub fn text(&mut self, t: &str) -> Result<&mut Self> { - for caps in self.linerx.captures_iter(t) { - self.directives.push(Directive::new(caps)?); - } - Ok(self) - } - - /// Get the finished `Checker`. - pub fn finish(&mut self) -> Checker { - // Move directives into the new checker, leaving `self.directives` empty and ready for - // building a new checker. - let new_directives = mem::replace(&mut self.directives, Vec::new()); - Checker::new(new_directives) - } -} - -/// Verify a list of directives against a test input. -/// -/// Use a `CheckerBuilder` to construct a `Checker`. Then use the `test` method to verify the list -/// of directives against a test input. -pub struct Checker { - directives: Vec, -} - -impl Checker { - fn new(directives: Vec) -> Self { - Self { directives: directives } - } - - /// An empty checker contains no directives, and will match any input string. - pub fn is_empty(&self) -> bool { - self.directives.is_empty() - } - - /// Verify directives against the input text. - /// - /// This returns `true` if the text matches all the directives, `false` if it doesn't. - /// An error is only returned if there is a problem with the directives. - pub fn check(&self, text: &str, vars: &VariableMap) -> Result { - self.run(text, vars, &mut ()) - } - - /// Explain how directives are matched against the input text. - pub fn explain(&self, text: &str, vars: &VariableMap) -> Result<(bool, String)> { - let mut expl = Explainer::new(text); - let success = self.run(text, vars, &mut expl)?; - expl.finish(); - Ok((success, expl.to_string())) - } - - fn run(&self, text: &str, vars: &VariableMap, recorder: &mut Recorder) -> Result { - let mut state = State::new(text, vars, recorder); - - // For each pending `not:` check, store (begin-offset, regex). - let mut nots = Vec::new(); - - for (dct_idx, dct) in self.directives.iter().enumerate() { - let (pat, range) = match *dct { - Directive::Check(ref pat) => (pat, state.check()), - Directive::SameLn(ref pat) => (pat, state.sameln()), - Directive::NextLn(ref pat) => (pat, state.nextln()), - Directive::Unordered(ref pat) => (pat, state.unordered(pat)), - Directive::Not(ref pat) => { - // Resolve `not:` directives immediately to get the right variable values, but - // don't match it until we know the end of the range. - // - // The `not:` directives test the same range as `unordered:` directives. In - // particular, if they refer to defined variables, their range is restricted to - // the text following the match that defined the variable. - nots.push((dct_idx, state.unordered_begin(pat), pat.resolve(&state)?)); - continue; - } - Directive::Regex(ref var, ref rx) => { - state.vars.insert( - var.clone(), - VarDef { - value: Value::Regex(Cow::Borrowed(rx)), - offset: 0, - }, - ); - continue; - } - }; - // Check if `pat` matches in `range`. - state.recorder.directive(dct_idx); - if let Some((match_begin, match_end)) = state.match_positive(pat, range)? { - if let Directive::Unordered(_) = *dct { - // This was an unordered match. - // Keep track of the largest matched position, but leave `last_ordered` alone. - state.max_match = max(state.max_match, match_end); - } else { - // Ordered match. - state.last_ordered = match_end; - state.max_match = match_end; - - // Verify any pending `not:` directives now that we know their range. - for (not_idx, not_begin, rx) in nots.drain(..) { - state.recorder.directive(not_idx); - if let Some(mat) = rx.find(&text[not_begin..match_begin]) { - // Matched `not:` pattern. - state.recorder.matched_not(rx.as_str(), ( - not_begin + mat.start(), - not_begin + mat.end(), - )); - return Ok(false); - } else { - state.recorder.missed_not( - rx.as_str(), - (not_begin, match_begin), - ); - } - } - } - } else { - // No match! - return Ok(false); - } - } - - // Verify any pending `not:` directives after the last ordered directive. - for (not_idx, not_begin, rx) in nots.drain(..) { - state.recorder.directive(not_idx); - if rx.find(&text[not_begin..]).is_some() { - // Matched `not:` pattern. - // TODO: Use matched range for an error message. - return Ok(false); - } - } - - Ok(true) - } -} - -/// A local definition of a variable. -pub struct VarDef<'a> { - /// The value given to the variable. - value: Value<'a>, - /// Offset in input text from where the variable is available. - offset: usize, -} - -struct State<'a> { - text: &'a str, - env_vars: &'a VariableMap, - recorder: &'a mut Recorder, - - vars: HashMap>, - // Offset after the last ordered match. This does not include recent unordered matches. - last_ordered: usize, - // Largest offset following a positive match, including unordered matches. - max_match: usize, -} - -impl<'a> State<'a> { - fn new(text: &'a str, env_vars: &'a VariableMap, recorder: &'a mut Recorder) -> State<'a> { - State { - text, - env_vars, - recorder, - vars: HashMap::new(), - last_ordered: 0, - max_match: 0, - } - } - - // Get the offset following the match that defined `var`, or 0 if var is an environment - // variable or unknown. - fn def_offset(&self, var: &str) -> usize { - self.vars - .get(var) - .map(|&VarDef { offset, .. }| offset) - .unwrap_or(0) - } - - // Get the offset of the beginning of the next line after `pos`. - fn bol(&self, pos: usize) -> usize { - if let Some(offset) = self.text[pos..].find('\n') { - pos + offset + 1 - } else { - self.text.len() - } - } - - // Get the range in text to be matched by a `check:`. - fn check(&self) -> MatchRange { - (self.max_match, self.text.len()) - } - - // Get the range in text to be matched by a `sameln:`. - fn sameln(&self) -> MatchRange { - let b = self.max_match; - let e = self.bol(b); - (b, e) - } - - // Get the range in text to be matched by a `nextln:`. - fn nextln(&self) -> MatchRange { - let b = self.bol(self.max_match); - let e = self.bol(b); - (b, e) - } - - // Get the beginning of the range in text to be matched by a `unordered:` or `not:` directive. - // The unordered directive must match after the directives that define the variables used. - fn unordered_begin(&self, pat: &Pattern) -> usize { - pat.parts() - .iter() - .filter_map(|part| part.ref_var()) - .map(|var| self.def_offset(var)) - .fold(self.last_ordered, max) - } - - // Get the range in text to be matched by a `unordered:` directive. - fn unordered(&self, pat: &Pattern) -> MatchRange { - (self.unordered_begin(pat), self.text.len()) - } - - // Search for `pat` in `range`, return the range matched. - // After a positive match, update variable definitions, if any. - fn match_positive(&mut self, pat: &Pattern, range: MatchRange) -> Result> { - let rx = pat.resolve(self)?; - let txt = &self.text[range.0..range.1]; - let defs = pat.defs(); - let matched_range = if defs.is_empty() { - // Pattern defines no variables. Fastest search is `find`. - rx.find(txt) - } else { - // We need the captures to define variables. - rx.captures(txt).map(|caps| { - let matched_range = caps.get(0).expect("whole expression must match"); - for var in defs { - let txtval = caps.name(var).map(|mat| mat.as_str()).unwrap_or(""); - self.recorder.defined_var(var, txtval); - let vardef = VarDef { - value: Value::Text(Cow::Borrowed(txtval)), - // This offset is the end of the whole matched pattern, not just the text - // defining the variable. - offset: range.0 + matched_range.end(), - }; - self.vars.insert(var.clone(), vardef); - } - matched_range - }) - }; - Ok(if let Some(mat) = matched_range { - let r = (range.0 + mat.start(), range.0 + mat.end()); - self.recorder.matched_check(rx.as_str(), r); - Some(r) - } else { - self.recorder.missed_check(rx.as_str(), range); - None - }) - } -} - -impl<'a> VariableMap for State<'a> { - fn lookup(&self, varname: &str) -> Option { - // First look for a local define. - if let Some(&VarDef { ref value, .. }) = self.vars.get(varname) { - Some(value.clone()) - } else { - // No local, maybe an environment variable? - self.env_vars.lookup(varname) - } - } -} - -impl Display for Directive { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - use self::Directive::*; - match *self { - Check(ref pat) => writeln!(f, "check: {}", pat), - SameLn(ref pat) => writeln!(f, "sameln: {}", pat), - NextLn(ref pat) => writeln!(f, "nextln: {}", pat), - Unordered(ref pat) => writeln!(f, "unordered: {}", pat), - Not(ref pat) => writeln!(f, "not: {}", pat), - Regex(ref var, ref rx) => writeln!(f, "regex: {}={}", var, rx), - } - } -} - -impl Display for Checker { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - for (idx, dir) in self.directives.iter().enumerate() { - write!(f, "#{} {}", idx, dir)?; - } - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::CheckerBuilder; - use error::Error; - - fn e2s(e: Error) -> String { - e.to_string() - } - - #[test] - fn directive() { - let mut b = CheckerBuilder::new(); - - assert_eq!(b.directive("not here: more text").map_err(e2s), Ok(false)); - assert_eq!( - b.directive("not here: regex: X=more text").map_err(e2s), - Ok(true) - ); - assert_eq!( - b.directive("regex: X = tommy").map_err(e2s), - Err( - "expected '=' after variable 'X' in regex: X = tommy".to_string(), - ) - ); - assert_eq!( - b.directive("[arm]not: patt $x $(y) here").map_err(e2s), - Ok(true) - ); - assert_eq!( - b.directive("[x86]sameln: $x $(y=[^]]*) there").map_err(e2s), - Ok(true) - ); - // Windows line ending sneaking in. - assert_eq!(b.directive("regex: Y=foo\r").map_err(e2s), Ok(true)); - - let c = b.finish(); - assert_eq!( - c.to_string(), - "#0 regex: X=more text\n#1 not: patt $(x) $(y) here\n#2 sameln: $(x) \ - $(y=[^]]*) there\n#3 regex: Y=foo\n" - ); - } -} diff --git a/lib/filecheck/src/error.rs b/lib/filecheck/src/error.rs deleted file mode 100644 index f15cb17124..0000000000 --- a/lib/filecheck/src/error.rs +++ /dev/null @@ -1,69 +0,0 @@ -use std::result; -use std::convert::From; -use std::error::Error as StdError; -use std::fmt; -use regex; - -/// A result from the filecheck library. -pub type Result = result::Result; - -/// A filecheck error. -#[derive(Debug)] -pub enum Error { - /// A syntax error in a check line. - Syntax(String), - /// A check refers to an undefined variable. - /// - /// The pattern contains `$foo` where the `foo` variable has not yet been defined. - /// Use `$$` to match a literal dollar sign. - UndefVariable(String), - /// A pattern contains a back-reference to a variable that was defined in the same pattern. - /// - /// For example, `check: Hello $(world=.*) $world`. Backreferences are not supported. Often the - /// desired effect can be achieved with the `sameln` check: - /// - /// ```text - /// check: Hello $(world=[^ ]*) - /// sameln: $world - /// ``` - Backref(String), - /// A pattern contains multiple definitions of the same variable. - DuplicateDef(String), - /// An error in a regular expression. - /// - /// Use `cause()` to get the underlying `Regex` library error. - Regex(regex::Error), -} - -impl StdError for Error { - fn description(&self) -> &str { - use Error::*; - match *self { - Syntax(ref s) | - UndefVariable(ref s) | - Backref(ref s) | - DuplicateDef(ref s) => s, - Regex(ref err) => err.description(), - } - } - - fn cause(&self) -> Option<&StdError> { - use Error::*; - match *self { - Regex(ref err) => Some(err), - _ => None, - } - } -} - -impl fmt::Display for Error { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{}", self.description()) - } -} - -impl From for Error { - fn from(e: regex::Error) -> Error { - Error::Regex(e) - } -} diff --git a/lib/filecheck/src/explain.rs b/lib/filecheck/src/explain.rs deleted file mode 100644 index 137d360f89..0000000000 --- a/lib/filecheck/src/explain.rs +++ /dev/null @@ -1,202 +0,0 @@ -//! Explaining how *filecheck* matched or failed to match a file. - -use MatchRange; -use std::fmt::{self, Display, Formatter}; -use std::cmp::min; - -/// Record events during matching. -pub trait Recorder { - /// Set the directive we're talking about now. - fn directive(&mut self, dct: usize); - - /// Matched a positive check directive (check/sameln/nextln/unordered). - fn matched_check(&mut self, regex: &str, matched: MatchRange); - - /// Matched a `not:` directive. This means the match will fail. - fn matched_not(&mut self, regex: &str, matched: MatchRange); - - /// Missed a positive check directive. The range given is the range searched for a match. - fn missed_check(&mut self, regex: &str, searched: MatchRange); - - /// Missed `not:` directive (as intended). - fn missed_not(&mut self, regex: &str, searched: MatchRange); - - /// The directive defined a variable. - fn defined_var(&mut self, varname: &str, value: &str); -} - -/// The null recorder just doesn't listen to anything you say. -impl Recorder for () { - fn directive(&mut self, _: usize) {} - fn matched_check(&mut self, _: &str, _: MatchRange) {} - fn matched_not(&mut self, _: &str, _: MatchRange) {} - fn defined_var(&mut self, _: &str, _: &str) {} - fn missed_check(&mut self, _: &str, _: MatchRange) {} - fn missed_not(&mut self, _: &str, _: MatchRange) {} -} - -struct Match { - directive: usize, - is_match: bool, - is_not: bool, - regex: String, - range: MatchRange, -} - -struct VarDef { - directive: usize, - varname: String, - value: String, -} - -/// Record an explanation for the matching process, success or failure. -pub struct Explainer<'a> { - text: &'a str, - directive: usize, - matches: Vec, - vardefs: Vec, -} - -impl<'a> Explainer<'a> { - pub fn new(text: &'a str) -> Explainer { - Explainer { - text, - directive: 0, - matches: Vec::new(), - vardefs: Vec::new(), - } - } - - /// Finish up after recording all events in a match. - pub fn finish(&mut self) { - self.matches.sort_by_key(|m| (m.range, m.directive)); - self.vardefs.sort_by_key(|v| v.directive); - } -} - -impl<'a> Display for Explainer<'a> { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - // Offset of beginning of the last line printed. - let mut curln = 0; - // Offset of beginning of the next line to be printed. - let mut nextln = 0; - - for m in &self.matches { - // Emit lines until m.range.0 is visible. - while nextln <= m.range.0 && nextln < self.text.len() { - let newln = self.text[nextln..] - .find('\n') - .map(|d| nextln + d + 1) - .unwrap_or(self.text.len()); - assert!(newln > nextln); - writeln!(f, "> {}", &self.text[nextln..newln - 1])?; - curln = nextln; - nextln = newln; - } - - // Emit ~~~ under the part of the match in curln. - if m.is_match { - write!(f, " ")?; - let mend = min(m.range.1, nextln - 1); - for pos in curln..mend { - if pos < m.range.0 { - write!(f, " ") - } else if pos == m.range.0 { - write!(f, "^") - } else { - write!(f, "~") - }?; - } - writeln!(f, "")?; - } - - // Emit the match message itself. - writeln!( - f, - "{} #{}{}: {}", - if m.is_match { "Matched" } else { "Missed" }, - m.directive, - if m.is_not { " not" } else { "" }, - m.regex - )?; - - // Emit any variable definitions. - if let Ok(found) = self.vardefs.binary_search_by_key( - &m.directive, - |v| v.directive, - ) - { - let mut first = found; - while first > 0 && self.vardefs[first - 1].directive == m.directive { - first -= 1; - } - for d in &self.vardefs[first..] { - if d.directive != m.directive { - break; - } - writeln!(f, "Define {}={}", d.varname, d.value)?; - } - } - } - - // Emit trailing lines. - for line in self.text[nextln..].lines() { - writeln!(f, "> {}", line)?; - } - Ok(()) - } -} - -impl<'a> Recorder for Explainer<'a> { - fn directive(&mut self, dct: usize) { - self.directive = dct; - } - - fn matched_check(&mut self, regex: &str, matched: MatchRange) { - self.matches.push(Match { - directive: self.directive, - is_match: true, - is_not: false, - regex: regex.to_owned(), - range: matched, - }); - } - - fn matched_not(&mut self, regex: &str, matched: MatchRange) { - self.matches.push(Match { - directive: self.directive, - is_match: true, - is_not: true, - regex: regex.to_owned(), - range: matched, - }); - } - - fn missed_check(&mut self, regex: &str, searched: MatchRange) { - self.matches.push(Match { - directive: self.directive, - is_match: false, - is_not: false, - regex: regex.to_owned(), - range: searched, - }); - } - - fn missed_not(&mut self, regex: &str, searched: MatchRange) { - self.matches.push(Match { - directive: self.directive, - is_match: false, - is_not: true, - regex: regex.to_owned(), - range: searched, - }); - } - - fn defined_var(&mut self, varname: &str, value: &str) { - self.vardefs.push(VarDef { - directive: self.directive, - varname: varname.to_owned(), - value: value.to_owned(), - }); - } -} diff --git a/lib/filecheck/src/lib.rs b/lib/filecheck/src/lib.rs deleted file mode 100644 index 4dec7a9b65..0000000000 --- a/lib/filecheck/src/lib.rs +++ /dev/null @@ -1,256 +0,0 @@ -//! This crate provides a text pattern matching library with functionality similar to the LLVM -//! project's [FileCheck command](https://llvm.org/docs/CommandGuide/FileCheck.html). -//! -//! A list of directives is typically extracted from a file containing a test case. The test case -//! is then run through the program under test, and its output matched against the directives. -//! -//! See the [`CheckerBuilder`](struct.CheckerBuilder.html) and [`Checker`](struct.Checker.html) -//! types for the main library API. -//! -//! # Directives -//! -//! These are the directives recognized by *filecheck*: -//! -//!
-//! check: <pattern>
-//! sameln: <pattern>
-//! nextln: <pattern>
-//! unordered: <pattern>
-//! not: <pattern>
-//! regex: <variable>=<regex>
-//! 
-//! -//! Each directive is described in more detail below. -//! -//! ## Example -//! -//! The Rust program below prints the primes less than 100. It has *filecheck* directives embedded -//! in comments: -//! -//! ```rust -//! fn is_prime(x: u32) -> bool { -//! (2..x).all(|d| x % d != 0) -//! } -//! -//! // Check that we get the primes and nothing else: -//! // regex: NUM=\d+ -//! // not: $NUM -//! // check: 2 -//! // nextln: 3 -//! // check: 89 -//! // nextln: 97 -//! // not: $NUM -//! fn main() { -//! for p in (2..10).filter(|&x| is_prime(x)) { -//! println!("{}", p); -//! } -//! } -//! ``` -//! -//! A test driver compiles and runs the program, then pipes the output through *filecheck*: -//! -//! ```sh -//! $ rustc primes.rs -//! $ ./primes | cton-util filecheck -v -//! #0 regex: NUM=\d+ -//! #1 not: $NUM -//! #2 check: 2 -//! #3 nextln: 3 -//! #4 check: 89 -//! #5 nextln: 97 -//! #6 not: $NUM -//! no match #1: \d+ -//! > 2 -//! ~ -//! match #2: \b2\b -//! > 3 -//! ~ -//! match #3: \b3\b -//! > 5 -//! > 7 -//! ... -//! > 79 -//! > 83 -//! > 89 -//! ~~ -//! match #4: \b89\b -//! > 97 -//! ~~ -//! match #5: \b97\b -//! no match #6: \d+ -//! OK -//! ``` -//! -//! ## The `check:` directive -//! -//! Match patterns non-overlapping and in order: -//! -//! ```sh -//! #0 check: one -//! #1 check: two -//! ``` -//! -//! These directives will match the string `"one two"`, but not `"two one"`. The second directive -//! must match after the first one, and it can't overlap. -//! -//! ## The `sameln:` directive -//! -//! Match a pattern in the same line as the previous match. -//! -//! ```sh -//! #0 check: one -//! #1 sameln: two -//! ``` -//! -//! These directives will match the string `"one two"`, but not `"one\ntwo"`. The second match must -//! be in the same line as the first. Like the `check:` directive, the match must also follow the -//! first match, so `"two one" would not be matched. -//! -//! If there is no previous match, `sameln:` matches on the first line of the input. -//! -//! ## The `nextln:` directive -//! -//! Match a pattern in the next line after the previous match. -//! -//! ```sh -//! #0 check: one -//! #1 nextln: two -//! ``` -//! -//! These directives will match the string `"one\ntwo"`, but not `"one two"` or `"one\n\ntwo"`. -//! -//! If there is no previous match, `nextln:` matches on the second line of the input as if there -//! were a previous match on the first line. -//! -//! ## The `unordered:` directive -//! -//! Match patterns in any order, and possibly overlapping each other. -//! -//! ```sh -//! #0 unordered: one -//! #1 unordered: two -//! ``` -//! -//! These directives will match the string `"one two"` *and* the string `"two one"`. -//! -//! When a normal ordered match is inserted into a sequence of `unordered:` directives, it acts as -//! a barrier: -//! -//! ```sh -//! #0 unordered: one -//! #1 unordered: two -//! #2 check: three -//! #3 unordered: four -//! #4 unordered: five -//! ``` -//! -//! These directives will match `"two one three four five"`, but not `"two three one four five"`. -//! The `unordered:` matches are not allowed to cross the ordered `check:` directive. -//! -//! When `unordered:` matches define and use variables, a topological order is enforced. This means -//! that a match referencing a variable must follow the match where the variable was defined: -//! -//! ```sh -//! #0 regex: V=\bv\d+\b -//! #1 unordered: $(va=$V) = load -//! #2 unordered: $(vb=$V) = iadd $va -//! #3 unordered: $(vc=$V) = load -//! #4 unordered: iadd $va, $vc -//! ``` -//! -//! In the above directives, #2 must match after #1, and #4 must match after both #1 and #3, but -//! otherwise they can match in any order. -//! -//! ## The `not:` directive -//! -//! Check that a pattern *does not* appear between matches. -//! -//! ```sh -//! #0 check: one -//! #1 not: two -//! #2 check: three -//! ``` -//! -//! The directives above will match `"one five three"`, but not `"one two three"`. -//! -//! The pattern in a `not:` directive can't define any variables. Since it never matches anything, -//! the variables would not get a value. -//! -//! ## The `regex:` directive -//! -//! Define a shorthand name for a regular expression. -//! -//! ```sh -//! #0 regex: ID=\b[_a-zA-Z][_0-9a-zA-Z]*\b -//! #1 check: $ID + $ID -//! ``` -//! -//! The `regex:` directive gives a name to a regular expression which can then be used as part of a -//! pattern to match. Patterns are otherwise just plain text strings to match, so this is not -//! simple macro expansion. -//! -//! See [the Rust regex crate](../regex/index.html#syntax) for the regular expression syntax. -//! -//! # Patterns and variables -//! -//! Patterns are plain text strings to be matched in the input file. The dollar sign is used as an -//! escape character to expand variables. The following escape sequences are recognized: -//! -//!
-//! $$                Match single dollar sign.
-//! $()               Match the empty string.
-//! $(=<regex>)       Match regular expression <regex>.
-//! $<var>            Match contents of variable <var>.
-//! $(<var>)          Match contents of variable <var>.
-//! $(<var>=<regex>)  Match <regex>, then
-//!                   define <var> as the matched text.
-//! $(<var>=$<rxvar>) Match regex in <rxvar>, then
-//!                   define <var> as the matched text.
-//! 
-//! -//! Variables can contain either plain text or regular expressions. Plain text variables are -//! defined with the `$(var=...)` syntax in a previous directive. They match the same text again. -//! Backreferences within the same pattern are not allowed. When a variable is defined in a -//! pattern, it can't be referenced again in the same pattern. -//! -//! Regular expression variables are defined with the `regex:` directive. They match the regular -//! expression each time they are used, so the matches don't need to be identical. -//! -//! ## Word boundaries -//! -//! If a pattern begins or ends with a (plain text) letter or number, it will only match on a word -//! boundary. Use the `$()` empty string match to prevent this: -//! -//! ```sh -//! check: one$() -//! ``` -//! -//! This will match `"one"` and `"onetwo"`, but not `"zeroone"`. -//! -//! The empty match syntax can also be used to require leading or trailing whitespace: -//! -//! ```sh -//! check: one, $() -//! ``` -//! -//! This will match `"one, two"` , but not `"one,two"`. Without the `$()`, trailing whitespace -//! would be trimmed from the pattern. - -#![deny(missing_docs, - trivial_numeric_casts, - unused_extern_crates)] - -pub use error::{Error, Result}; -pub use variable::{VariableMap, Value, NO_VARIABLES}; -pub use checker::{Checker, CheckerBuilder}; - -extern crate regex; - -mod error; -mod variable; -mod pattern; -mod checker; -mod explain; - -/// The range of a match in the input text. -pub type MatchRange = (usize, usize); diff --git a/lib/filecheck/src/pattern.rs b/lib/filecheck/src/pattern.rs deleted file mode 100644 index 97977b191c..0000000000 --- a/lib/filecheck/src/pattern.rs +++ /dev/null @@ -1,593 +0,0 @@ -//! Pattern matching for a single directive. - -use error::{Error, Result}; -use variable::{varname_prefix, VariableMap, Value}; -use std::str::FromStr; -use std::fmt::{self, Display, Formatter, Write}; -use regex::{Regex, RegexBuilder, escape}; - -/// A pattern to match as specified in a directive. -/// -/// Each pattern is broken into a sequence of parts that must match in order. The kinds of parts -/// are: -/// -/// 1. Plain text match. -/// 2. Variable match, `$FOO` or `$(FOO)`. The variable `FOO` may expand to plain text or a regex. -/// 3. Variable definition from literal regex, `$(foo=.*)`. Match the regex and assign matching text -/// to variable `foo`. -/// 4. Variable definition from regex variable, `$(foo=$RX)`. Lookup variable `RX` which should -/// expand to a regex, match the regex, and assign matching text to variable `foo`. -/// -pub struct Pattern { - parts: Vec, - // Variables defined by this pattern. - defs: Vec, -} - -/// One atomic part of a pattern. -#[derive(Debug, PartialEq, Eq)] -pub enum Part { - /// Match a plain string. - Text(String), - /// Match a regular expression. The regex has already been wrapped in a non-capturing group if - /// necessary, so it is safe to concatenate. - Regex(String), - /// Match the contents of a variable, which can be plain text or regex. - Var(String), - /// Match literal regex, then assign match to variable. - /// The regex has already been wrapped in a named capture group. - DefLit { def: usize, regex: String }, - /// Lookup variable `var`, match resulting regex, assign matching text to variable `defs[def]`. - DefVar { def: usize, var: String }, -} - -impl Part { - /// Get the variable referenced by this part, if any. - pub fn ref_var(&self) -> Option<&str> { - match *self { - Part::Var(ref var) | - Part::DefVar { ref var, .. } => Some(var), - _ => None, - } - } -} - -impl Pattern { - /// Create a new blank pattern. Use the `FromStr` trait to generate Patterns with content. - fn new() -> Self { - Self { - parts: Vec::new(), - defs: Vec::new(), - } - } - - /// Check if the variable `v` is defined by this pattern. - pub fn defines_var(&self, v: &str) -> bool { - self.defs.iter().any(|d| d == v) - } - - /// Add a definition of a new variable. - /// Return the allocated def number. - fn add_def(&mut self, v: &str) -> Result { - if self.defines_var(v) { - Err(Error::DuplicateDef( - format!("duplicate definition of ${} in same pattern", v), - )) - } else { - let idx = self.defs.len(); - self.defs.push(v.to_string()); - Ok(idx) - } - } - - /// Parse a `Part` from a prefix of `s`. - /// Return the part and the number of bytes consumed from `s`. - /// Adds defined variables to `self.defs`. - fn parse_part(&mut self, s: &str) -> Result<(Part, usize)> { - let dollar = s.find('$'); - if dollar != Some(0) { - // String doesn't begin with a dollar sign, so match plain text up to the dollar sign. - let end = dollar.unwrap_or(s.len()); - return Ok((Part::Text(s[0..end].to_string()), end)); - } - - // String starts with a dollar sign. Look for these possibilities: - // - // 1. `$$`. - // 2. `$var`. - // 3. `$(var)`. - // 4. `$(var=regex)`. Where `regex` is a regular expression possibly containing matching - // braces. - // 5. `$(var=$VAR)`. - - // A doubled dollar sign matches a single dollar sign. - if s.starts_with("$$") { - return Ok((Part::Text("$".to_string()), 2)); - } - - // Look for `$var`. - let varname_end = 1 + varname_prefix(&s[1..]); - if varname_end != 1 { - return Ok((Part::Var(s[1..varname_end].to_string()), varname_end)); - } - - // All remaining possibilities start with `$(`. - if s.len() < 2 || !s.starts_with("$(") { - return Err(Error::Syntax( - "pattern syntax error, use $$ to match a single $" - .to_string(), - )); - } - - // Match the variable name, allowing for an empty varname in `$()`, or `$(=...)`. - let varname_end = 2 + varname_prefix(&s[2..]); - let varname = s[2..varname_end].to_string(); - - match s[varname_end..].chars().next() { - None => { - return Err(Error::Syntax(format!("unterminated $({}...", varname))); - } - Some(')') => { - let part = if varname.is_empty() { - // Match `$()`, turn it into an empty text match. - Part::Text(varname) - } else { - // Match `$(var)`. - Part::Var(varname) - }; - return Ok((part, varname_end + 1)); - } - Some('=') => { - // Variable definition. Fall through. - } - Some(ch) => { - return Err(Error::Syntax( - format!("syntax error in $({}... '{}'", varname, ch), - )); - } - } - - // This is a variable definition of the form `$(var=...`. - - // Allocate a definition index. - let def = if varname.is_empty() { - None - } else { - Some(self.add_def(&varname)?) - }; - - // Match `$(var=$PAT)`. - if s[varname_end + 1..].starts_with('$') { - let refname_begin = varname_end + 2; - let refname_end = refname_begin + varname_prefix(&s[refname_begin..]); - if refname_begin == refname_end { - return Err(Error::Syntax( - format!("expected variable name in $({}=$...", varname), - )); - } - if !s[refname_end..].starts_with(')') { - return Err(Error::Syntax(format!( - "expected ')' after $({}=${}...", - varname, - &s[refname_begin..refname_end] - ))); - } - let refname = s[refname_begin..refname_end].to_string(); - return if let Some(defidx) = def { - Ok(( - Part::DefVar { - def: defidx, - var: refname, - }, - refname_end + 1, - )) - } else { - Err(Error::Syntax( - format!("expected variable name in $(=${})", refname), - )) - }; - } - - // Last case: `$(var=...)` where `...` is a regular expression, possibly containing matched - // parentheses. - let rx_begin = varname_end + 1; - let rx_end = rx_begin + regex_prefix(&s[rx_begin..]); - if s[rx_end..].starts_with(')') { - let part = if let Some(defidx) = def { - // Wrap the regex in a named capture group. - Part::DefLit { - def: defidx, - regex: format!("(?P<{}>{})", varname, &s[rx_begin..rx_end]), - } - } else { - // When the varname is empty just match the regex, don't capture any variables. - // This is `$(=[a-z])`. - // Wrap the regex in a non-capturing group to make it concatenation-safe. - Part::Regex(format!("(?:{})", &s[rx_begin..rx_end])) - }; - Ok((part, rx_end + 1)) - } else { - Err(Error::Syntax(format!( - "missing ')' after regex in $({}={}", - varname, - &s[rx_begin..rx_end] - ))) - } - } -} - -/// Compute the length of a regular expression terminated by `)` or `}`. -/// Handle nested and escaped parentheses in the rx, but don't actually parse it. -/// Return the position of the terminating brace or the length of the string. -fn regex_prefix(s: &str) -> usize { - // The previous char was a backslash. - let mut escape = false; - // State around parsing charsets. - enum State { - Normal, // Outside any charset. - Curly, // Inside curly braces. - CSFirst, // Immediately after opening `[`. - CSNeg, // Immediately after `[^`. - CSBody, // Inside `[...`. - } - let mut state = State::Normal; - - // Current nesting level of parens. - let mut nest = 0usize; - - for (idx, ch) in s.char_indices() { - if escape { - escape = false; - continue; - } else if ch == '\\' { - escape = true; - continue; - } - match state { - State::Normal => { - match ch { - '[' => state = State::CSFirst, - '{' => state = State::Curly, - '(' => nest += 1, - ')' if nest > 0 => nest -= 1, - ')' | '}' => return idx, - _ => {} - } - } - State::Curly => { - if ch == '}' { - state = State::Normal; - } - } - State::CSFirst => { - state = match ch { - '^' => State::CSNeg, - _ => State::CSBody, - } - } - State::CSNeg => state = State::CSBody, - State::CSBody => { - if ch == ']' { - state = State::Normal; - } - } - } - } - s.len() -} - -impl FromStr for Pattern { - type Err = Error; - - fn from_str(s: &str) -> Result { - // Always remove leading and trailing whitespace. - // Use `$()` to actually include that in a match. - let s = s.trim(); - let mut pat = Pattern::new(); - let mut pos = 0; - while pos < s.len() { - let (part, len) = pat.parse_part(&s[pos..])?; - if let Some(v) = part.ref_var() { - if pat.defines_var(v) { - return Err(Error::Backref(format!( - "unsupported back-reference to '${}' \ - defined in same pattern", - v - ))); - } - } - pat.parts.push(part); - pos += len; - } - Ok(pat) - } -} - -impl Pattern { - /// Get a list of parts in this pattern. - pub fn parts(&self) -> &[Part] { - &self.parts - } - - /// Get a list of variable names defined when this pattern matches. - pub fn defs(&self) -> &[String] { - &self.defs - } - - /// Resolve all variable references in this pattern, turning it into a regular expression. - pub fn resolve(&self, vmap: &VariableMap) -> Result { - let mut out = String::new(); - - // Add a word boundary check `\b` to the beginning of the regex, but only if the first part - // is a plain text match that starts with a word character. - // - // This behavior can be disabled by starting the pattern with `$()`. - if let Some(&Part::Text(ref s)) = self.parts.first() { - if s.starts_with(char::is_alphanumeric) { - out.push_str(r"\b"); - } - } - - for part in &self.parts { - match *part { - Part::Text(ref s) => { - out.push_str(&escape(s)); - } - Part::Regex(ref rx) => out.push_str(rx), - Part::Var(ref var) => { - // Resolve the variable. We can handle a plain text expansion. - match vmap.lookup(var) { - None => { - return Err(Error::UndefVariable(format!("undefined variable ${}", var))) - } - Some(Value::Text(s)) => out.push_str(&escape(&s)), - // Wrap regex in non-capturing group for safe concatenation. - Some(Value::Regex(rx)) => write!(out, "(?:{})", rx).unwrap(), - } - } - Part::DefLit { ref regex, .. } => out.push_str(regex), - Part::DefVar { def, ref var } => { - // Wrap regex in a named capture group. - write!(out, "(?P<{}>", self.defs[def]).unwrap(); - match vmap.lookup(var) { - None => { - return Err(Error::UndefVariable(format!("undefined variable ${}", var))) - } - Some(Value::Text(s)) => write!(out, "{})", escape(&s[..])).unwrap(), - Some(Value::Regex(rx)) => write!(out, "{})", rx).unwrap(), - } - } - } - - } - - // Add a word boundary check `\b` to the end of the regex, but only if the final part - // is a plain text match that ends with a word character. - // - // This behavior can be disabled by ending the pattern with `$()`. - if let Some(&Part::Text(ref s)) = self.parts.last() { - if s.ends_with(char::is_alphanumeric) { - out.push_str(r"\b"); - } - } - - Ok(RegexBuilder::new(&out).multi_line(true).build()?) - } -} - -impl Display for Pattern { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - for part in &self.parts { - use self::Part::*; - match *part { - Text(ref txt) if txt == "" => write!(f, "$()"), - Text(ref txt) if txt == "$" => write!(f, "$$"), - Text(ref txt) => write!(f, "{}", txt), - Regex(ref rx) => write!(f, "$(={})", rx), - Var(ref var) => write!(f, "$({})", var), - DefLit { def, ref regex } => { - let defvar = &self.defs[def]; - // (?P...). - let litrx = ®ex[5 + defvar.len()..regex.len() - 1]; - write!(f, "$({}={})", defvar, litrx) - } - DefVar { def, ref var } => write!(f, "$({}=${})", self.defs[def], var), - }?; - } - Ok(()) - } -} - -#[cfg(test)] -mod tests { - #[test] - fn regex() { - use super::regex_prefix; - - assert_eq!(regex_prefix(""), 0); - assert_eq!(regex_prefix(")"), 0); - assert_eq!(regex_prefix(")c"), 0); - assert_eq!(regex_prefix("x"), 1); - assert_eq!(regex_prefix("x)x"), 1); - - assert_eq!(regex_prefix("x(c))x"), 4); - assert_eq!(regex_prefix("()x(c))x"), 6); - assert_eq!(regex_prefix("()x(c)"), 6); - - assert_eq!(regex_prefix("x([)]))x"), 6); - assert_eq!(regex_prefix("x[)])x"), 4); - assert_eq!(regex_prefix("x[^)])x"), 5); - assert_eq!(regex_prefix("x[^])x"), 6); - } - - #[test] - fn part() { - use super::{Pattern, Part}; - let mut pat = Pattern::new(); - - // This is dubious, should we panic instead? - assert_eq!(pat.parse_part("").unwrap(), (Part::Text("".to_string()), 0)); - - assert_eq!( - pat.parse_part("x").unwrap(), - (Part::Text("x".to_string()), 1) - ); - assert_eq!(pat.parse_part("x2").unwrap(), ( - Part::Text("x2".to_string()), - 2, - )); - assert_eq!(pat.parse_part("x$").unwrap(), ( - Part::Text("x".to_string()), - 1, - )); - assert_eq!(pat.parse_part("x$$").unwrap(), ( - Part::Text("x".to_string()), - 1, - )); - - assert_eq!( - pat.parse_part("$").unwrap_err().to_string(), - "pattern syntax error, use $$ to match a single $" - ); - - assert_eq!(pat.parse_part("$$").unwrap(), ( - Part::Text("$".to_string()), - 2, - )); - assert_eq!(pat.parse_part("$$ ").unwrap(), ( - Part::Text("$".to_string()), - 2, - )); - - assert_eq!( - pat.parse_part("$0").unwrap(), - (Part::Var("0".to_string()), 2) - ); - assert_eq!(pat.parse_part("$xx=").unwrap(), ( - Part::Var("xx".to_string()), - 3, - )); - assert_eq!(pat.parse_part("$xx$").unwrap(), ( - Part::Var("xx".to_string()), - 3, - )); - - assert_eq!(pat.parse_part("$(0)").unwrap(), ( - Part::Var("0".to_string()), - 4, - )); - assert_eq!(pat.parse_part("$()").unwrap(), ( - Part::Text("".to_string()), - 3, - )); - - assert_eq!( - pat.parse_part("$(0").unwrap_err().to_string(), - ("unterminated $(0...") - ); - assert_eq!( - pat.parse_part("$(foo:").unwrap_err().to_string(), - ("syntax error in $(foo... ':'") - ); - assert_eq!( - pat.parse_part("$(foo =").unwrap_err().to_string(), - ("syntax error in $(foo... ' '") - ); - assert_eq!( - pat.parse_part("$(eo0=$bar").unwrap_err().to_string(), - ("expected ')' after $(eo0=$bar...") - ); - assert_eq!( - pat.parse_part("$(eo1=$bar}").unwrap_err().to_string(), - ("expected ')' after $(eo1=$bar...") - ); - assert_eq!( - pat.parse_part("$(eo2=$)").unwrap_err().to_string(), - ("expected variable name in $(eo2=$...") - ); - assert_eq!( - pat.parse_part("$(eo3=$-)").unwrap_err().to_string(), - ("expected variable name in $(eo3=$...") - ); - } - - #[test] - fn partdefs() { - use super::{Pattern, Part}; - let mut pat = Pattern::new(); - - assert_eq!(pat.parse_part("$(foo=$bar)").unwrap(), ( - Part::DefVar { - def: 0, - var: "bar".to_string(), - }, - 11, - )); - assert_eq!( - pat.parse_part("$(foo=$bar)").unwrap_err().to_string(), - "duplicate definition of $foo in same pattern" - ); - - assert_eq!(pat.parse_part("$(fxo=$bar)x").unwrap(), ( - Part::DefVar { - def: 1, - var: "bar".to_string(), - }, - 11, - )); - - assert_eq!(pat.parse_part("$(fo2=[a-z])").unwrap(), ( - Part::DefLit { - def: 2, - regex: "(?P[a-z])".to_string(), - }, - 12, - )); - assert_eq!(pat.parse_part("$(fo3=[a-)])").unwrap(), ( - Part::DefLit { - def: 3, - regex: "(?P[a-)])".to_string(), - }, - 12, - )); - assert_eq!(pat.parse_part("$(fo4=)").unwrap(), ( - Part::DefLit { - def: 4, - regex: "(?P)".to_string(), - }, - 7, - )); - - assert_eq!(pat.parse_part("$(=.*)").unwrap(), ( - Part::Regex( - "(?:.*)".to_string(), - ), - 6, - )); - - assert_eq!(pat.parse_part("$(=)").unwrap(), ( - Part::Regex( - "(?:)".to_string(), - ), - 4, - )); - assert_eq!(pat.parse_part("$()").unwrap(), ( - Part::Text("".to_string()), - 3, - )); - } - - #[test] - fn pattern() { - use super::Pattern; - - let p: Pattern = " Hello world! ".parse().unwrap(); - assert_eq!(format!("{:?}", p.parts), "[Text(\"Hello world!\")]"); - - let p: Pattern = " $foo=$(bar) ".parse().unwrap(); - assert_eq!( - format!("{:?}", p.parts), - "[Var(\"foo\"), Text(\"=\"), Var(\"bar\")]" - ); - } -} diff --git a/lib/filecheck/src/variable.rs b/lib/filecheck/src/variable.rs deleted file mode 100644 index 5977f06354..0000000000 --- a/lib/filecheck/src/variable.rs +++ /dev/null @@ -1,62 +0,0 @@ -use std::borrow::Cow; - -/// A variable name is one or more ASCII alphanumerical characters, including underscore. -/// Note that numerical variable names like `$45` are allowed too. -/// -/// Try to parse a variable name from the beginning of `s`. -/// Return the index of the character following the varname. -/// This returns 0 if `s` doesn't have a prefix that is a variable name. -pub fn varname_prefix(s: &str) -> usize { - for (idx, ch) in s.char_indices() { - match ch { - 'a'...'z' | 'A'...'Z' | '0'...'9' | '_' => {} - _ => return idx, - } - } - s.len() -} - -/// A variable can contain either a regular expression or plain text. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum Value<'a> { - /// Verbatim text. - Text(Cow<'a, str>), - /// Regular expression. - Regex(Cow<'a, str>), -} - -/// Resolve variables by name. -pub trait VariableMap { - /// Get the value of the variable `varname`, or return `None` for an unknown variable name. - fn lookup(&self, varname: &str) -> Option; -} - -impl VariableMap for () { - fn lookup(&self, _: &str) -> Option { - None - } -} - -/// An empty variable map. -pub const NO_VARIABLES: &'static VariableMap = &(); - -#[cfg(test)] -mod tests { - #[test] - fn varname() { - use super::varname_prefix; - - assert_eq!(varname_prefix(""), 0); - assert_eq!(varname_prefix("\0"), 0); - assert_eq!(varname_prefix("_"), 1); - assert_eq!(varname_prefix("0"), 1); - assert_eq!(varname_prefix("01"), 2); - assert_eq!(varname_prefix("b"), 1); - assert_eq!(varname_prefix("C"), 1); - assert_eq!(varname_prefix("."), 0); - assert_eq!(varname_prefix(".s"), 0); - assert_eq!(varname_prefix("0."), 1); - assert_eq!(varname_prefix("01="), 2); - assert_eq!(varname_prefix("0a)"), 2); - } -} diff --git a/lib/filecheck/tests/basic.rs b/lib/filecheck/tests/basic.rs deleted file mode 100644 index 1ccc5991a5..0000000000 --- a/lib/filecheck/tests/basic.rs +++ /dev/null @@ -1,402 +0,0 @@ -extern crate filecheck; - -use filecheck::{CheckerBuilder, NO_VARIABLES, Error as FcError}; - -fn e2s(e: FcError) -> String { - e.to_string() -} - -#[test] -fn empty() { - let c = CheckerBuilder::new().finish(); - assert!(c.is_empty()); - - // An empty checker matches anything. - assert_eq!(c.check("", NO_VARIABLES).map_err(e2s), Ok(true)); - assert_eq!(c.check("hello", NO_VARIABLES).map_err(e2s), Ok(true)); -} - -#[test] -fn no_directives() { - let c = CheckerBuilder::new().text("nothing here").unwrap().finish(); - assert!(c.is_empty()); - - // An empty checker matches anything. - assert_eq!(c.check("", NO_VARIABLES).map_err(e2s), Ok(true)); - assert_eq!(c.check("hello", NO_VARIABLES).map_err(e2s), Ok(true)); -} - -#[test] -fn no_matches() { - let c = CheckerBuilder::new() - .text("regex: FOO=bar") - .unwrap() - .finish(); - assert!(!c.is_empty()); - - // An empty checker matches anything. - assert_eq!(c.check("", NO_VARIABLES).map_err(e2s), Ok(true)); - assert_eq!(c.check("hello", NO_VARIABLES).map_err(e2s), Ok(true)); -} - -#[test] -fn simple() { - let c = CheckerBuilder::new() - .text( - " - check: one - check: two - ", - ) - .unwrap() - .finish(); - - let t = " - zero - one - and a half - two - three - "; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true)); - - let t = " - zero - and a half - two - one - three - "; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); -} - -#[test] -fn sameln() { - let c = CheckerBuilder::new() - .text( - " - check: one - sameln: two - ", - ) - .unwrap() - .finish(); - - let t = " - zero - one - and a half - two - three - "; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); - - let t = " - zero - one - two - three - "; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); - - let t = " - zero - one two - three - "; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true)); -} - -#[test] -fn nextln() { - let c = CheckerBuilder::new() - .text( - " - check: one - nextln: two - ", - ) - .unwrap() - .finish(); - - let t = " - zero - one - and a half - two - three - "; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); - - let t = " - zero - one - two - three - "; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true)); - - let t = " - zero - one two - three - "; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); - - let t = " - zero - one - two"; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true)); -} - -#[test] -fn leading_nextln() { - // A leading nextln directive should match from line 2. - // This is somewhat arbitrary, but consistent with a preceding 'check: $()' directive. - let c = CheckerBuilder::new() - .text( - " - nextln: one - nextln: two - ", - ) - .unwrap() - .finish(); - - let t = "zero - one - two - three - "; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true)); - - let t = "one - two - three - "; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); -} - -#[test] -fn leading_sameln() { - // A leading sameln directive should match from line 1. - let c = CheckerBuilder::new() - .text( - " - sameln: one - sameln: two - ", - ) - .unwrap() - .finish(); - - let t = "zero - one two three - "; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); - - let t = "zero one two three"; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true)); - - let t = "zero one - two three"; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); -} - -#[test] -fn not() { - let c = CheckerBuilder::new() - .text( - " - check: one$() - not: $()eat$() - check: $()two - ", - ) - .unwrap() - .finish(); - - let t = "onetwo"; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true)); - - let t = "one eat two"; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); - - let t = "oneeattwo"; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); - - let t = "oneatwo"; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true)); -} - -#[test] -fn notnot() { - let c = CheckerBuilder::new() - .text( - " - check: one$() - not: $()eat$() - not: half - check: $()two - ", - ) - .unwrap() - .finish(); - - let t = "onetwo"; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true)); - - let t = "one eat two"; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); - - let t = "one half two"; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); - - let t = "oneeattwo"; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); - - // The `not: half` pattern only matches whole words, but the bracketing matches are considered - // word boundaries, so it does match in this case. - let t = "onehalftwo"; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false)); - - let t = "oneatwo"; - assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true)); -} - -#[test] -fn unordered() { - let c = CheckerBuilder::new() - .text( - " - check: one - unordered: two - unordered: three - check: four - ", - ) - .unwrap() - .finish(); - - assert_eq!( - c.check("one two three four", NO_VARIABLES).map_err(e2s), - Ok(true) - ); - assert_eq!( - c.check("one three two four", NO_VARIABLES).map_err(e2s), - Ok(true) - ); - - assert_eq!( - c.check("one two four three four", NO_VARIABLES).map_err( - e2s, - ), - Ok(true) - ); - assert_eq!( - c.check("one three four two four", NO_VARIABLES).map_err( - e2s, - ), - Ok(true) - ); - - assert_eq!( - c.check("one two four three", NO_VARIABLES).map_err(e2s), - Ok(false) - ); - assert_eq!( - c.check("one three four two", NO_VARIABLES).map_err(e2s), - Ok(false) - ); -} - -#[test] -fn leading_unordered() { - let c = CheckerBuilder::new() - .text( - " - unordered: two - unordered: three - check: four - ", - ) - .unwrap() - .finish(); - - assert_eq!( - c.check("one two three four", NO_VARIABLES).map_err(e2s), - Ok(true) - ); - assert_eq!( - c.check("one three two four", NO_VARIABLES).map_err(e2s), - Ok(true) - ); - - assert_eq!( - c.check("one two four three four", NO_VARIABLES).map_err( - e2s, - ), - Ok(true) - ); - assert_eq!( - c.check("one three four two four", NO_VARIABLES).map_err( - e2s, - ), - Ok(true) - ); - - assert_eq!( - c.check("one two four three", NO_VARIABLES).map_err(e2s), - Ok(false) - ); - assert_eq!( - c.check("one three four two", NO_VARIABLES).map_err(e2s), - Ok(false) - ); -} - -#[test] -fn trailing_unordered() { - let c = CheckerBuilder::new() - .text( - " - check: one - unordered: two - unordered: three - ", - ) - .unwrap() - .finish(); - - assert_eq!( - c.check("one two three four", NO_VARIABLES).map_err(e2s), - Ok(true) - ); - assert_eq!( - c.check("one three two four", NO_VARIABLES).map_err(e2s), - Ok(true) - ); - - assert_eq!( - c.check("one two four three four", NO_VARIABLES).map_err( - e2s, - ), - Ok(true) - ); - assert_eq!( - c.check("one three four two four", NO_VARIABLES).map_err( - e2s, - ), - Ok(true) - ); - - assert_eq!( - c.check("one two four three", NO_VARIABLES).map_err(e2s), - Ok(true) - ); - assert_eq!( - c.check("one three four two", NO_VARIABLES).map_err(e2s), - Ok(true) - ); -} diff --git a/lib/filetests/Cargo.toml b/lib/filetests/Cargo.toml index 215f947e74..4ef875ea2c 100644 --- a/lib/filetests/Cargo.toml +++ b/lib/filetests/Cargo.toml @@ -14,5 +14,5 @@ name = "cton_filetests" [dependencies] cretonne = { path = "../cretonne", version = "0.3.4" } cretonne-reader = { path = "../reader", version = "0.3.4" } -filecheck = { path = "../filecheck", version = "0.1.0" } +filecheck = "0.2.0" num_cpus = "1.5.1" From 4dbafb45c7121686059dee66125911d7c0f2af21 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 15 Mar 2018 21:09:59 -0700 Subject: [PATCH 15/72] Update to num_cpus 1.8, and other updates. --- cranelift/Cargo.toml | 2 +- lib/filetests/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index b9acc0606c..c7e9f6fef4 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -24,7 +24,7 @@ docopt = "0.8.0" serde = "1.0.8" serde_derive = "1.0.8" tempdir = "0.3.5" -term = "0.5" +term = "0.5.1" [workspace] diff --git a/lib/filetests/Cargo.toml b/lib/filetests/Cargo.toml index 4ef875ea2c..c1dd254902 100644 --- a/lib/filetests/Cargo.toml +++ b/lib/filetests/Cargo.toml @@ -14,5 +14,5 @@ name = "cton_filetests" [dependencies] cretonne = { path = "../cretonne", version = "0.3.4" } cretonne-reader = { path = "../reader", version = "0.3.4" } -filecheck = "0.2.0" -num_cpus = "1.5.1" +filecheck = "0.2.1" +num_cpus = "1.8.0" From e2f3079d8b04c59c6a85e74f080e1954fc3cba0d Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 15 Mar 2018 21:37:08 -0700 Subject: [PATCH 16/72] Tidy up redundant commands in test-all.sh. --- cranelift/test-all.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/cranelift/test-all.sh b/cranelift/test-all.sh index 7b86495903..2b4e2eba01 100755 --- a/cranelift/test-all.sh +++ b/cranelift/test-all.sh @@ -41,8 +41,6 @@ if [ -n "$needcheck" ]; then touch $tsfile || echo no target directory fi -cd "$topdir" - # Make sure the code builds in debug mode. banner "Rust debug build" cargo build From 5e5fcefdfd3213fddfd399b9f6c005c196bba55e Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 15 Mar 2018 21:37:31 -0700 Subject: [PATCH 17/72] Add Travis builds with Rust nightly. See [here](https://docs.travis-ci.com/user/languages/rust/) for details. --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index ce1a269955..301d7871d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,10 @@ language: rust rust: - stable - beta + - nightly +matrix: + allow_failures: + - rust: nightly dist: trusty sudo: false addons: From e6db8e278c79451355acdd604f5d7cbb20347c10 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 7 Mar 2018 21:32:47 -0800 Subject: [PATCH 18/72] Rename one more "local" to "explicit_slot". --- misc/vim/syntax/cton.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/vim/syntax/cton.vim b/misc/vim/syntax/cton.vim index 6ccacae7fc..4862c38ec8 100644 --- a/misc/vim/syntax/cton.vim +++ b/misc/vim/syntax/cton.vim @@ -14,7 +14,7 @@ endif syn spell notoplevel syn keyword ctonHeader test isa set -syn keyword ctonDecl function jump_table incoming_arg outgoing_arg spill_slot local emergency_slot +syn keyword ctonDecl function jump_table incoming_arg outgoing_arg spill_slot explicit_slot emergency_slot syn keyword ctonFilecheck check sameln nextln unordered not regex contained syn match ctonType /\<\([bif]\d\+\(x\d\+\)\?\)\|[if]flags\>/ From 99f7cb5b8d0366ab848cf002061c1df2d8fc0a1e Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 7 Mar 2018 21:32:56 -0800 Subject: [PATCH 19/72] Use debug_assert_ne rather than debug_assert with a !=. https://github.com/rust-lang-nursery/rust-clippy/wiki#should_assert_eq --- lib/cretonne/src/preopt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cretonne/src/preopt.rs b/lib/cretonne/src/preopt.rs index 8e4bef8da3..a232728efd 100644 --- a/lib/cretonne/src/preopt.rs +++ b/lib/cretonne/src/preopt.rs @@ -223,7 +223,7 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso let t3 = pos.ins().iadd(t2, q1); // I never found any case where shiftBy == 1 here. // So there's no attempt to fold out a zero shift. - debug_assert!(shiftBy != 1); + debug_assert_ne!(shiftBy, 1); qf = pos.ins().ushr_imm(t3, (shiftBy - 1) as i64); } else { debug_assert!(shiftBy >= 0 && shiftBy <= 31); @@ -295,7 +295,7 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso let t3 = pos.ins().iadd(t2, q1); // I never found any case where shiftBy == 1 here. // So there's no attempt to fold out a zero shift. - debug_assert!(shiftBy != 1); + debug_assert_ne!(shiftBy, 1); qf = pos.ins().ushr_imm(t3, (shiftBy - 1) as i64); } else { debug_assert!(shiftBy >= 0 && shiftBy <= 63); From 06fe3b654fb9adfdc8f00806e945e3fe75a3c1d3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 15 Mar 2018 22:38:46 -0700 Subject: [PATCH 20/72] Avoid match expressions with reference patterns. https://github.com/rust-lang-nursery/rust-clippy/wiki#match_ref_pats --- lib/cretonne/src/bforest/path.rs | 44 ++++++++++----------- lib/cretonne/src/bforest/pool.rs | 8 ++-- lib/cretonne/src/preopt.rs | 66 ++++++++++++++++---------------- lib/cretonne/src/settings.rs | 4 +- 4 files changed, 61 insertions(+), 61 deletions(-) diff --git a/lib/cretonne/src/bforest/path.rs b/lib/cretonne/src/bforest/path.rs index 1add8f6e63..e52c8e897e 100644 --- a/lib/cretonne/src/bforest/path.rs +++ b/lib/cretonne/src/bforest/path.rs @@ -55,8 +55,8 @@ impl Path { for level in 0.. { self.size = level + 1; self.node[level] = node; - match &pool[node] { - &NodeData::Inner { size, keys, tree } => { + match pool[node] { + NodeData::Inner { size, keys, tree } => { // Invariant: `tree[i]` contains keys smaller than // `keys[i]`, greater or equal to `keys[i-1]`. let i = match comp.search(key, &keys[0..size.into()]) { @@ -68,7 +68,7 @@ impl Path { self.entry[level] = i as u8; node = tree[i]; } - &NodeData::Leaf { size, keys, vals } => { + NodeData::Leaf { size, keys, vals } => { // For a leaf we want either the found key or an insert position. return match comp.search(key, &keys.borrow()[0..size.into()]) { Ok(i) => { @@ -81,7 +81,7 @@ impl Path { } }; } - &NodeData::Free { .. } => panic!("Free {} reached from {}", node, root), + NodeData::Free { .. } => panic!("Free {} reached from {}", node, root), } } unreachable!(); @@ -94,10 +94,10 @@ impl Path { self.size = level + 1; self.node[level] = node; self.entry[level] = 0; - match &pool[node] { - &NodeData::Inner { tree, .. } => node = tree[0], - &NodeData::Leaf { keys, vals, .. } => return (keys.borrow()[0], vals.borrow()[0]), - &NodeData::Free { .. } => panic!("Free {} reached from {}", node, root), + match pool[node] { + NodeData::Inner { tree, .. } => node = tree[0], + NodeData::Leaf { keys, vals, .. } => return (keys.borrow()[0], vals.borrow()[0]), + NodeData::Free { .. } => panic!("Free {} reached from {}", node, root), } } unreachable!(); @@ -205,17 +205,17 @@ impl Path { let mut node = root; for l in level.. { self.node[l] = node; - match &pool[node] { - &NodeData::Inner { size, ref tree, .. } => { + match pool[node] { + NodeData::Inner { size, ref tree, .. } => { self.entry[l] = size; node = tree[usize::from(size)]; } - &NodeData::Leaf { size, .. } => { + NodeData::Leaf { size, .. } => { self.entry[l] = size - 1; self.size = l + 1; break; } - &NodeData::Free { .. } => panic!("Free {} reached from {}", node, root), + NodeData::Free { .. } => panic!("Free {} reached from {}", node, root), } } node @@ -405,8 +405,8 @@ impl Path { let crit_key = pool[self.leaf_node()].leaf_crit_key(); let crit_node = self.node[crit_level]; - match &mut pool[crit_node] { - &mut NodeData::Inner { size, ref mut keys, .. } => { + match pool[crit_node] { + NodeData::Inner { size, ref mut keys, .. } => { debug_assert!(crit_kidx < size); keys[usize::from(crit_kidx)] = crit_key; } @@ -581,8 +581,8 @@ impl Path { /// /// Returns `None` if the current node is a right-most node so no right sibling exists. fn right_sibling_branch_level(&self, level: usize, pool: &NodePool) -> Option { - (0..level).rposition(|l| match &pool[self.node[l]] { - &NodeData::Inner { size, .. } => self.entry[l] < size, + (0..level).rposition(|l| match pool[self.node[l]] { + NodeData::Inner { size, .. } => self.entry[l] < size, _ => panic!("Expected inner node"), }) } @@ -622,8 +622,8 @@ impl Path { let bl = self.right_sibling_branch_level(level, pool).expect( "No right sibling exists", ); - match &mut pool[self.node[bl]] { - &mut NodeData::Inner { ref mut keys, .. } => { + match pool[self.node[bl]] { + NodeData::Inner { ref mut keys, .. } => { keys[usize::from(self.entry[bl])] = crit_key; } _ => panic!("Expected inner node"), @@ -647,8 +647,8 @@ impl Path { /// Check the internal consistency of this path. pub fn verify(&self, pool: &NodePool) { for level in 0..self.size { - match &pool[self.node[level]] { - &NodeData::Inner { size, tree, .. } => { + match pool[self.node[level]] { + NodeData::Inner { size, tree, .. } => { assert!( level < self.size - 1, "Expected leaf node at level {}", @@ -668,7 +668,7 @@ impl Path { level ); } - &NodeData::Leaf { size, .. } => { + NodeData::Leaf { size, .. } => { assert_eq!(level, self.size - 1, "Expected inner node"); assert!( self.entry[level] <= size, @@ -677,7 +677,7 @@ impl Path { size, ); } - &NodeData::Free { .. } => { + NodeData::Free { .. } => { panic!("Free {} in path", self.node[level]); } } diff --git a/lib/cretonne/src/bforest/pool.rs b/lib/cretonne/src/bforest/pool.rs index 37801ee4ab..1ce9e83279 100644 --- a/lib/cretonne/src/bforest/pool.rs +++ b/lib/cretonne/src/bforest/pool.rs @@ -104,8 +104,8 @@ impl NodePool { ); let mut lower = lkey; - match &self[node] { - &NodeData::Inner { size, keys, tree } => { + match self[node] { + NodeData::Inner { size, keys, tree } => { let size = size as usize; let capacity = tree.len(); let keys = &keys[0..size]; @@ -147,7 +147,7 @@ impl NodePool { lower = upper; } } - &NodeData::Leaf { size, keys, .. } => { + NodeData::Leaf { size, keys, .. } => { let size = size as usize; let capacity = keys.borrow().len(); let keys = &keys.borrow()[0..size]; @@ -190,7 +190,7 @@ impl NodePool { lower = upper; } } - &NodeData::Free { .. } => panic!("Free {} reached", node), + NodeData::Free { .. } => panic!("Free {} reached", node), } } } diff --git a/lib/cretonne/src/preopt.rs b/lib/cretonne/src/preopt.rs index a232728efd..f5e8b3a7fe 100644 --- a/lib/cretonne/src/preopt.rs +++ b/lib/cretonne/src/preopt.rs @@ -170,18 +170,18 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso DivRemByConstInfo::RemS64(_, _) => true, }; - match divrem_info { + match *divrem_info { // -------------------- U32 -------------------- // U32 div, rem by zero: ignore - &DivRemByConstInfo::DivU32(_n1, 0) | - &DivRemByConstInfo::RemU32(_n1, 0) => {} + DivRemByConstInfo::DivU32(_n1, 0) | + DivRemByConstInfo::RemU32(_n1, 0) => {} // U32 div by 1: identity // U32 rem by 1: zero - &DivRemByConstInfo::DivU32(n1, 1) | - &DivRemByConstInfo::RemU32(n1, 1) => { + DivRemByConstInfo::DivU32(n1, 1) | + DivRemByConstInfo::RemU32(n1, 1) => { if isRem { pos.func.dfg.replace(inst).iconst(I32, 0); } else { @@ -190,8 +190,8 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso } // U32 div, rem by a power-of-2 - &DivRemByConstInfo::DivU32(n1, d) | - &DivRemByConstInfo::RemU32(n1, d) if d.is_power_of_two() => { + DivRemByConstInfo::DivU32(n1, d) | + DivRemByConstInfo::RemU32(n1, d) if d.is_power_of_two() => { debug_assert!(d >= 2); // compute k where d == 2^k let k = d.trailing_zeros(); @@ -205,8 +205,8 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso } // U32 div, rem by non-power-of-2 - &DivRemByConstInfo::DivU32(n1, d) | - &DivRemByConstInfo::RemU32(n1, d) => { + DivRemByConstInfo::DivU32(n1, d) | + DivRemByConstInfo::RemU32(n1, d) => { debug_assert!(d >= 3); let MU32 { mulBy, @@ -247,13 +247,13 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso // -------------------- U64 -------------------- // U64 div, rem by zero: ignore - &DivRemByConstInfo::DivU64(_n1, 0) | - &DivRemByConstInfo::RemU64(_n1, 0) => {} + DivRemByConstInfo::DivU64(_n1, 0) | + DivRemByConstInfo::RemU64(_n1, 0) => {} // U64 div by 1: identity // U64 rem by 1: zero - &DivRemByConstInfo::DivU64(n1, 1) | - &DivRemByConstInfo::RemU64(n1, 1) => { + DivRemByConstInfo::DivU64(n1, 1) | + DivRemByConstInfo::RemU64(n1, 1) => { if isRem { pos.func.dfg.replace(inst).iconst(I64, 0); } else { @@ -262,8 +262,8 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso } // U64 div, rem by a power-of-2 - &DivRemByConstInfo::DivU64(n1, d) | - &DivRemByConstInfo::RemU64(n1, d) if d.is_power_of_two() => { + DivRemByConstInfo::DivU64(n1, d) | + DivRemByConstInfo::RemU64(n1, d) if d.is_power_of_two() => { debug_assert!(d >= 2); // compute k where d == 2^k let k = d.trailing_zeros(); @@ -277,8 +277,8 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso } // U64 div, rem by non-power-of-2 - &DivRemByConstInfo::DivU64(n1, d) | - &DivRemByConstInfo::RemU64(n1, d) => { + DivRemByConstInfo::DivU64(n1, d) | + DivRemByConstInfo::RemU64(n1, d) => { debug_assert!(d >= 3); let MU64 { mulBy, @@ -319,15 +319,15 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso // -------------------- S32 -------------------- // S32 div, rem by zero or -1: ignore - &DivRemByConstInfo::DivS32(_n1, -1) | - &DivRemByConstInfo::RemS32(_n1, -1) | - &DivRemByConstInfo::DivS32(_n1, 0) | - &DivRemByConstInfo::RemS32(_n1, 0) => {} + DivRemByConstInfo::DivS32(_n1, -1) | + DivRemByConstInfo::RemS32(_n1, -1) | + DivRemByConstInfo::DivS32(_n1, 0) | + DivRemByConstInfo::RemS32(_n1, 0) => {} // S32 div by 1: identity // S32 rem by 1: zero - &DivRemByConstInfo::DivS32(n1, 1) | - &DivRemByConstInfo::RemS32(n1, 1) => { + DivRemByConstInfo::DivS32(n1, 1) | + DivRemByConstInfo::RemS32(n1, 1) => { if isRem { pos.func.dfg.replace(inst).iconst(I32, 0); } else { @@ -335,8 +335,8 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso } } - &DivRemByConstInfo::DivS32(n1, d) | - &DivRemByConstInfo::RemS32(n1, d) => { + DivRemByConstInfo::DivS32(n1, d) | + DivRemByConstInfo::RemS32(n1, d) => { if let Some((isNeg, k)) = isPowerOf2_S32(d) { // k can be 31 only in the case that d is -2^31. debug_assert!(k >= 1 && k <= 31); @@ -396,15 +396,15 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso // -------------------- S64 -------------------- // S64 div, rem by zero or -1: ignore - &DivRemByConstInfo::DivS64(_n1, -1) | - &DivRemByConstInfo::RemS64(_n1, -1) | - &DivRemByConstInfo::DivS64(_n1, 0) | - &DivRemByConstInfo::RemS64(_n1, 0) => {} + DivRemByConstInfo::DivS64(_n1, -1) | + DivRemByConstInfo::RemS64(_n1, -1) | + DivRemByConstInfo::DivS64(_n1, 0) | + DivRemByConstInfo::RemS64(_n1, 0) => {} // S64 div by 1: identity // S64 rem by 1: zero - &DivRemByConstInfo::DivS64(n1, 1) | - &DivRemByConstInfo::RemS64(n1, 1) => { + DivRemByConstInfo::DivS64(n1, 1) | + DivRemByConstInfo::RemS64(n1, 1) => { if isRem { pos.func.dfg.replace(inst).iconst(I64, 0); } else { @@ -412,8 +412,8 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso } } - &DivRemByConstInfo::DivS64(n1, d) | - &DivRemByConstInfo::RemS64(n1, d) => { + DivRemByConstInfo::DivS64(n1, d) | + DivRemByConstInfo::RemS64(n1, d) => { if let Some((isNeg, k)) = isPowerOf2_S64(d) { // k can be 63 only in the case that d is -2^63. debug_assert!(k >= 1 && k <= 63); diff --git a/lib/cretonne/src/settings.rs b/lib/cretonne/src/settings.rs index a87ceda695..2cfce65957 100644 --- a/lib/cretonne/src/settings.rs +++ b/lib/cretonne/src/settings.rs @@ -302,8 +302,8 @@ pub mod detail { /// Check if a detail is a Detail::Preset. Useful because the Descriptor /// offset field has a different meaning when the detail is a preset. pub fn is_preset(&self) -> bool { - match self { - &Detail::Preset => true, + match *self { + Detail::Preset => true, _ => false, } } From a4c51d66a8f353368665498d248e842f9681124a Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 12 Mar 2018 14:06:15 -0700 Subject: [PATCH 21/72] Remove uses of `println!` in tests. In this case, it's a little nicer to just use more assertions, which will print their line number indicating how far the test got, when they fail. And this allows the tests to be run in no_std configurations. --- lib/cretonne/src/divconst_magic_numbers.rs | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/cretonne/src/divconst_magic_numbers.rs b/lib/cretonne/src/divconst_magic_numbers.rs index b046e22411..f189e23d1a 100644 --- a/lib/cretonne/src/divconst_magic_numbers.rs +++ b/lib/cretonne/src/divconst_magic_numbers.rs @@ -480,56 +480,63 @@ mod tests { // don't panic with integer wraparounds, especially at boundary // cases for their arguments. The actual results are thrown away. let mut total: u64 = 0; - println!("Testing UP magicU32"); + // Testing UP magicU32 for x in 2..(200 * 1000u32) { let m = magicU32(x); total = total ^ (m.mulBy as u64); total = total + (m.shiftBy as u64); total = total - (if m.doAdd { 123 } else { 456 }); } - println!("Testing DOWN magicU32"); + assert_eq!(total, 1747815691); + // Testing DOWN magicU32 for x in 0..(200 * 1000u32) { let m = magicU32(0xFFFF_FFFFu32 - x); total = total ^ (m.mulBy as u64); total = total + (m.shiftBy as u64); total = total - (if m.doAdd { 123 } else { 456 }); } + assert_eq!(total, 2210292772); - println!("Testing UP magicU64"); + // Testing UP magicU64 for x in 2..(200 * 1000u64) { let m = magicU64(x); total = total ^ m.mulBy; total = total + (m.shiftBy as u64); total = total - (if m.doAdd { 123 } else { 456 }); } - println!("Testing DOWN magicU64"); + assert_eq!(total, 7430004084791260605); + // Testing DOWN magicU64 for x in 0..(200 * 1000u64) { let m = magicU64(0xFFFF_FFFF_FFFF_FFFFu64 - x); total = total ^ m.mulBy; total = total + (m.shiftBy as u64); total = total - (if m.doAdd { 123 } else { 456 }); } + assert_eq!(total, 7547519887519825919); - println!("Testing UP magicS32"); + // Testing UP magicS32 for x in 0..(200 * 1000i32) { let m = magicS32(-0x8000_0000i32 + x); total = total ^ (m.mulBy as u64); total = total + (m.shiftBy as u64); } - println!("Testing DOWN magicS32"); + assert_eq!(total, 10899224186731671235); + // Testing DOWN magicS32 for x in 0..(200 * 1000i32) { let m = magicS32(0x7FFF_FFFFi32 - x); total = total ^ (m.mulBy as u64); total = total + (m.shiftBy as u64); } + assert_eq!(total, 7547519887517897369); - println!("Testing UP magicS64"); + // Testing UP magicS64 for x in 0..(200 * 1000i64) { let m = magicS64(-0x8000_0000_0000_0000i64 + x); total = total ^ (m.mulBy as u64); total = total + (m.shiftBy as u64); } - println!("Testing DOWN magicS64"); + assert_eq!(total, 8029756891368555163); + // Testing DOWN magicS64 for x in 0..(200 * 1000i64) { let m = magicS64(0x7FFF_FFFF_FFFF_FFFFi64 - x); total = total ^ (m.mulBy as u64); From 5e21ac1a307a088913fc83066cb27d0758b4ff8c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 16 Mar 2018 16:01:15 -0700 Subject: [PATCH 22/72] Use whitespace more consistently in Cargo.toml files. --- lib/cretonne/Cargo.toml | 2 +- lib/wasm/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cretonne/Cargo.toml b/lib/cretonne/Cargo.toml index adcaa28f76..96385da3e8 100644 --- a/lib/cretonne/Cargo.toml +++ b/lib/cretonne/Cargo.toml @@ -7,7 +7,7 @@ license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" repository = "https://github.com/Cretonne/cretonne" readme = "README.md" -keywords = [ "compile", "compiler", "jit" ] +keywords = ["compile", "compiler", "jit"] build = "build.rs" [lib] diff --git a/lib/wasm/Cargo.toml b/lib/wasm/Cargo.toml index 140ab69cfe..536c31daa6 100644 --- a/lib/wasm/Cargo.toml +++ b/lib/wasm/Cargo.toml @@ -6,7 +6,7 @@ description = "Translator from WebAssembly to Cretonne IL" repository = "https://github.com/Cretonne/cretonne" license = "Apache-2.0" readme = "README.md" -keywords = [ "webassembly", "wasm" ] +keywords = ["webassembly", "wasm"] [lib] name = "cton_wasm" From 921cea284532b2cf23816d1400a618f112197273 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 16 Mar 2018 16:12:56 -0700 Subject: [PATCH 23/72] Bump version to 0.4.0 --- cranelift/Cargo.toml | 14 +++++++------- cranelift/publish-all.sh | 2 +- lib/cretonne/Cargo.toml | 2 +- lib/filetests/Cargo.toml | 6 +++--- lib/frontend/Cargo.toml | 4 ++-- lib/native/Cargo.toml | 4 ++-- lib/reader/Cargo.toml | 4 ++-- lib/wasm/Cargo.toml | 6 +++--- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index c7e9f6fef4..a6d363dcdb 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cretonne-tools" authors = ["The Cretonne Project Developers"] -version = "0.3.4" +version = "0.4.0" description = "Binaries for testing the Cretonne library" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" @@ -13,12 +13,12 @@ name = "cton-util" path = "src/cton-util.rs" [dependencies] -cretonne = { path = "lib/cretonne", version = "0.3.4" } -cretonne-reader = { path = "lib/reader", version = "0.3.4" } -cretonne-frontend = { path = "lib/frontend", version = "0.3.4" } -cretonne-wasm = { path = "lib/wasm", version = "0.3.4" } -cretonne-native = { path = "lib/native", version = "0.3.4" } -cretonne-filetests = { path = "lib/filetests", version = "0.3.4" } +cretonne = { path = "lib/cretonne", version = "0.4.0" } +cretonne-reader = { path = "lib/reader", version = "0.4.0" } +cretonne-frontend = { path = "lib/frontend", version = "0.4.0" } +cretonne-wasm = { path = "lib/wasm", version = "0.4.0" } +cretonne-native = { path = "lib/native", version = "0.4.0" } +cretonne-filetests = { path = "lib/filetests", version = "0.4.0" } filecheck = "0.2.1" docopt = "0.8.0" serde = "1.0.8" diff --git a/cranelift/publish-all.sh b/cranelift/publish-all.sh index c5cd6bfca3..6b23f71064 100755 --- a/cranelift/publish-all.sh +++ b/cranelift/publish-all.sh @@ -4,7 +4,7 @@ cd $(dirname "$0") topdir="$(pwd)" # All the cretonne-* crates have the same version number -version="0.3.4" +version="0.4.0" # Update all of the Cargo.toml files. # diff --git a/lib/cretonne/Cargo.toml b/lib/cretonne/Cargo.toml index 96385da3e8..d603a9597e 100644 --- a/lib/cretonne/Cargo.toml +++ b/lib/cretonne/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cretonne Project Developers"] name = "cretonne" -version = "0.3.4" +version = "0.4.0" description = "Low-level code generator library" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" diff --git a/lib/filetests/Cargo.toml b/lib/filetests/Cargo.toml index c1dd254902..f3ecf521c0 100644 --- a/lib/filetests/Cargo.toml +++ b/lib/filetests/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cretonne-filetests" authors = ["The Cretonne Project Developers"] -version = "0.3.4" +version = "0.4.0" description = "Test driver and implementations of the filetest commands" license = "Apache-2.0" documentation = "http://cretonne.readthedocs.io/en/latest/testing.html#file-tests" @@ -12,7 +12,7 @@ publish = false name = "cton_filetests" [dependencies] -cretonne = { path = "../cretonne", version = "0.3.4" } -cretonne-reader = { path = "../reader", version = "0.3.4" } +cretonne = { path = "../cretonne", version = "0.4.0" } +cretonne-reader = { path = "../reader", version = "0.4.0" } filecheck = "0.2.1" num_cpus = "1.8.0" diff --git a/lib/frontend/Cargo.toml b/lib/frontend/Cargo.toml index 368b6f058e..bd5455d9d3 100644 --- a/lib/frontend/Cargo.toml +++ b/lib/frontend/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cretonne Project Developers"] name = "cretonne-frontend" -version = "0.3.4" +version = "0.4.0" description = "Cretonne IL builder helper" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" @@ -12,7 +12,7 @@ readme = "README.md" name = "cton_frontend" [dependencies] -cretonne = { path = "../cretonne", version = "0.3.4" } +cretonne = { path = "../cretonne", version = "0.4.0" } [badges] maintenance = { status = "experimental" } diff --git a/lib/native/Cargo.toml b/lib/native/Cargo.toml index 89676fc1b3..9a2ba0eea7 100644 --- a/lib/native/Cargo.toml +++ b/lib/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cretonne-native" -version = "0.3.4" +version = "0.4.0" authors = ["The Cretonne Project Developers"] description = "Support for targeting the host with Cretonne" repository = "https://github.com/Cretonne/cretonne" @@ -11,7 +11,7 @@ readme = "README.md" name = "cton_native" [dependencies] -cretonne = { path = "../cretonne", version = "0.3.4" } +cretonne = { path = "../cretonne", version = "0.4.0" } [target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies] raw-cpuid = "3.0.0" diff --git a/lib/reader/Cargo.toml b/lib/reader/Cargo.toml index bd26dc0f7c..1841357bc4 100644 --- a/lib/reader/Cargo.toml +++ b/lib/reader/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cretonne Project Developers"] name = "cretonne-reader" -version = "0.3.4" +version = "0.4.0" description = "Cretonne textual IL reader" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" @@ -12,7 +12,7 @@ readme = "README.md" name = "cton_reader" [dependencies] -cretonne = { path = "../cretonne", version = "0.3.4" } +cretonne = { path = "../cretonne", version = "0.4.0" } [badges] maintenance = { status = "experimental" } diff --git a/lib/wasm/Cargo.toml b/lib/wasm/Cargo.toml index 536c31daa6..df978cb4d0 100644 --- a/lib/wasm/Cargo.toml +++ b/lib/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cretonne-wasm" -version = "0.3.4" +version = "0.4.0" authors = ["The Cretonne Project Developers"] description = "Translator from WebAssembly to Cretonne IL" repository = "https://github.com/Cretonne/cretonne" @@ -13,8 +13,8 @@ name = "cton_wasm" [dependencies] wasmparser = "0.15.1" -cretonne = { path = "../cretonne", version = "0.3.4" } -cretonne-frontend = { path = "../frontend", version = "0.3.4" } +cretonne = { path = "../cretonne", version = "0.4.0" } +cretonne-frontend = { path = "../frontend", version = "0.4.0" } [dev-dependencies] tempdir = "0.3.5" From 9a49bc2ec97a2ed7b536487d42b61139322d41fb Mon Sep 17 00:00:00 2001 From: Afnan Enayet Date: Sun, 18 Mar 2018 13:50:51 -0700 Subject: [PATCH 24/72] Rename `I32` -> `X86_32` and `I64` -> `X86_64` (#271) * Rename `I32` -> `X86_32` and `I64` -> `X86_64` * Format file to pass flake8 tests * Fix comment so lines are under 80 char limit * Remove trailing whitespace from comment * Renamed `enc_i64` to `enc_x86_64` as per suggestion from PR --- lib/cretonne/meta/isa/intel/defs.py | 4 +- lib/cretonne/meta/isa/intel/encodings.py | 306 +++++++++++------------ 2 files changed, 155 insertions(+), 155 deletions(-) diff --git a/lib/cretonne/meta/isa/intel/defs.py b/lib/cretonne/meta/isa/intel/defs.py index d5bb0b5a1f..b6a4d37206 100644 --- a/lib/cretonne/meta/isa/intel/defs.py +++ b/lib/cretonne/meta/isa/intel/defs.py @@ -12,8 +12,8 @@ from base.immediates import floatcc ISA = TargetISA('intel', [base.instructions.GROUP, x86.GROUP]) # CPU modes for 32-bit and 64-bit operation. -I64 = CPUMode('I64', ISA) -I32 = CPUMode('I32', ISA) +X86_64 = CPUMode('I64', ISA) +X86_32 = CPUMode('I32', ISA) # The set of floating point condition codes that are directly supported. # Other condition codes need to be reversed or expressed as two tests. diff --git a/lib/cretonne/meta/isa/intel/encodings.py b/lib/cretonne/meta/isa/intel/encodings.py index 162caccf65..995149794a 100644 --- a/lib/cretonne/meta/isa/intel/encodings.py +++ b/lib/cretonne/meta/isa/intel/encodings.py @@ -5,7 +5,7 @@ from __future__ import absolute_import from cdsl.predicates import IsUnsignedInt, Not, And from base import instructions as base from base.formats import UnaryImm -from .defs import I32, I64 +from .defs import X86_64, X86_32 from . import recipes as r from . import settings as cfg from . import instructions as x86 @@ -22,83 +22,83 @@ except ImportError: pass -I32.legalize_monomorphic(expand_flags) -I32.legalize_type( - default=narrow, - b1=expand_flags, - i32=intel_expand, - f32=intel_expand, - f64=intel_expand) +X86_32.legalize_monomorphic(expand_flags) +X86_32.legalize_type( + default=narrow, + b1=expand_flags, + i32=intel_expand, + f32=intel_expand, + f64=intel_expand) -I64.legalize_monomorphic(expand_flags) -I64.legalize_type( - default=narrow, - b1=expand_flags, - i32=intel_expand, - i64=intel_expand, - f32=intel_expand, - f64=intel_expand) +X86_64.legalize_monomorphic(expand_flags) +X86_64.legalize_type( + default=narrow, + b1=expand_flags, + i32=intel_expand, + i64=intel_expand, + f32=intel_expand, + f64=intel_expand) # # Helper functions for generating encodings. # -def enc_i64(inst, recipe, *args, **kwargs): +def enc_x86_64(inst, recipe, *args, **kwargs): # type: (MaybeBoundInst, r.TailRecipe, *int, **int) -> None """ - Add encodings for `inst` to I64 with and without a REX prefix. + Add encodings for `inst` to X86_64 with and without a REX prefix. """ - I64.enc(inst, *recipe.rex(*args, **kwargs)) - I64.enc(inst, *recipe(*args, **kwargs)) + X86_64.enc(inst, *recipe.rex(*args, **kwargs)) + X86_64.enc(inst, *recipe(*args, **kwargs)) def enc_both(inst, recipe, *args, **kwargs): # type: (MaybeBoundInst, r.TailRecipe, *int, **Any) -> None """ - Add encodings for `inst` to both I32 and I64. + Add encodings for `inst` to both X86_32 and X86_64. """ - I32.enc(inst, *recipe(*args, **kwargs)) - enc_i64(inst, recipe, *args, **kwargs) + X86_32.enc(inst, *recipe(*args, **kwargs)) + enc_x86_64(inst, recipe, *args, **kwargs) def enc_i32_i64(inst, recipe, *args, **kwargs): # type: (MaybeBoundInst, r.TailRecipe, *int, **int) -> None """ - Add encodings for `inst.i32` to I32. - Add encodings for `inst.i32` to I64 with and without REX. - Add encodings for `inst.i64` to I64 with a REX.W prefix. + Add encodings for `inst.i32` to X86_32. + Add encodings for `inst.i32` to X86_64 with and without REX. + Add encodings for `inst.i64` to X86_64 with a REX.W prefix. """ - I32.enc(inst.i32, *recipe(*args, **kwargs)) + X86_32.enc(inst.i32, *recipe(*args, **kwargs)) # REX-less encoding must come after REX encoding so we don't use it by # default. Otherwise reg-alloc would never use r8 and up. - I64.enc(inst.i32, *recipe.rex(*args, **kwargs)) - I64.enc(inst.i32, *recipe(*args, **kwargs)) + X86_64.enc(inst.i32, *recipe.rex(*args, **kwargs)) + X86_64.enc(inst.i32, *recipe(*args, **kwargs)) - I64.enc(inst.i64, *recipe.rex(*args, w=1, **kwargs)) + X86_64.enc(inst.i64, *recipe.rex(*args, w=1, **kwargs)) def enc_i32_i64_ld_st(inst, w_bit, recipe, *args, **kwargs): # type: (MaybeBoundInst, bool, r.TailRecipe, *int, **int) -> None """ - Add encodings for `inst.i32` to I32. - Add encodings for `inst.i32` to I64 with and without REX. - Add encodings for `inst.i64` to I64 with a REX prefix, using the `w_bit` + Add encodings for `inst.i32` to X86_32. + Add encodings for `inst.i32` to X86_64 with and without REX. + Add encodings for `inst.i64` to X86_64 with a REX prefix, using the `w_bit` argument to determine whether or not to set the REX.W bit. """ - I32.enc(inst.i32.any, *recipe(*args, **kwargs)) + X86_32.enc(inst.i32.any, *recipe(*args, **kwargs)) # REX-less encoding must come after REX encoding so we don't use it by # default. Otherwise reg-alloc would never use r8 and up. - I64.enc(inst.i32.any, *recipe.rex(*args, **kwargs)) - I64.enc(inst.i32.any, *recipe(*args, **kwargs)) + X86_64.enc(inst.i32.any, *recipe.rex(*args, **kwargs)) + X86_64.enc(inst.i32.any, *recipe(*args, **kwargs)) if w_bit: - I64.enc(inst.i64.any, *recipe.rex(*args, w=1, **kwargs)) + X86_64.enc(inst.i64.any, *recipe.rex(*args, w=1, **kwargs)) else: - I64.enc(inst.i64.any, *recipe.rex(*args, **kwargs)) - I64.enc(inst.i64.any, *recipe(*args, **kwargs)) + X86_64.enc(inst.i64.any, *recipe.rex(*args, **kwargs)) + X86_64.enc(inst.i64.any, *recipe(*args, **kwargs)) for inst, opc in [ @@ -141,19 +141,19 @@ for inst, rrr in [ # band_imm.i32. Can even use the single-byte immediate for 0xffff_ffXX masks. # Immediate constants. -I32.enc(base.iconst.i32, *r.puid(0xb8)) +X86_32.enc(base.iconst.i32, *r.puid(0xb8)) -I64.enc(base.iconst.i32, *r.puid.rex(0xb8)) -I64.enc(base.iconst.i32, *r.puid(0xb8)) +X86_64.enc(base.iconst.i32, *r.puid.rex(0xb8)) +X86_64.enc(base.iconst.i32, *r.puid(0xb8)) # The 32-bit immediate movl also zero-extends to 64 bits. -I64.enc(base.iconst.i64, *r.puid.rex(0xb8), - instp=IsUnsignedInt(UnaryImm.imm, 32)) -I64.enc(base.iconst.i64, *r.puid(0xb8), - instp=IsUnsignedInt(UnaryImm.imm, 32)) +X86_64.enc(base.iconst.i64, *r.puid.rex(0xb8), + instp=IsUnsignedInt(UnaryImm.imm, 32)) +X86_64.enc(base.iconst.i64, *r.puid(0xb8), + instp=IsUnsignedInt(UnaryImm.imm, 32)) # Sign-extended 32-bit immediate. -I64.enc(base.iconst.i64, *r.uid.rex(0xc7, rrr=0, w=1)) +X86_64.enc(base.iconst.i64, *r.uid.rex(0xc7, rrr=0, w=1)) # Finally, the 0xb8 opcode takes an 8-byte immediate with a REX.W prefix. -I64.enc(base.iconst.i64, *r.puiq.rex(0xb8, w=1)) +X86_64.enc(base.iconst.i64, *r.puiq.rex(0xb8, w=1)) # Shifts and rotates. # Note that the dynamic shift amount is only masked by 5 or 6 bits; the 8-bit @@ -164,38 +164,38 @@ for inst, rrr in [ (base.ishl, 4), (base.ushr, 5), (base.sshr, 7)]: - I32.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr)) - I64.enc(inst.i64.any, *r.rc.rex(0xd3, rrr=rrr, w=1)) - I64.enc(inst.i32.any, *r.rc.rex(0xd3, rrr=rrr)) - I64.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr)) + X86_32.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr)) + X86_64.enc(inst.i64.any, *r.rc.rex(0xd3, rrr=rrr, w=1)) + X86_64.enc(inst.i32.any, *r.rc.rex(0xd3, rrr=rrr)) + X86_64.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr)) # Population count. -I32.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt) -I64.enc(base.popcnt.i64, *r.urm.rex(0xf3, 0x0f, 0xb8, w=1), - isap=cfg.use_popcnt) -I64.enc(base.popcnt.i32, *r.urm.rex(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt) -I64.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt) +X86_32.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt) +X86_64.enc(base.popcnt.i64, *r.urm.rex(0xf3, 0x0f, 0xb8, w=1), + isap=cfg.use_popcnt) +X86_64.enc(base.popcnt.i32, *r.urm.rex(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt) +X86_64.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt) # Count leading zero bits. -I32.enc(base.clz.i32, *r.urm(0xf3, 0x0f, 0xbd), isap=cfg.use_lzcnt) -I64.enc(base.clz.i64, *r.urm.rex(0xf3, 0x0f, 0xbd, w=1), - isap=cfg.use_lzcnt) -I64.enc(base.clz.i32, *r.urm.rex(0xf3, 0x0f, 0xbd), isap=cfg.use_lzcnt) -I64.enc(base.clz.i32, *r.urm(0xf3, 0x0f, 0xbd), isap=cfg.use_lzcnt) +X86_32.enc(base.clz.i32, *r.urm(0xf3, 0x0f, 0xbd), isap=cfg.use_lzcnt) +X86_64.enc(base.clz.i64, *r.urm.rex(0xf3, 0x0f, 0xbd, w=1), + isap=cfg.use_lzcnt) +X86_64.enc(base.clz.i32, *r.urm.rex(0xf3, 0x0f, 0xbd), isap=cfg.use_lzcnt) +X86_64.enc(base.clz.i32, *r.urm(0xf3, 0x0f, 0xbd), isap=cfg.use_lzcnt) # Count trailing zero bits. -I32.enc(base.ctz.i32, *r.urm(0xf3, 0x0f, 0xbc), isap=cfg.use_bmi1) -I64.enc(base.ctz.i64, *r.urm.rex(0xf3, 0x0f, 0xbc, w=1), - isap=cfg.use_bmi1) -I64.enc(base.ctz.i32, *r.urm.rex(0xf3, 0x0f, 0xbc), isap=cfg.use_bmi1) -I64.enc(base.ctz.i32, *r.urm(0xf3, 0x0f, 0xbc), isap=cfg.use_bmi1) +X86_32.enc(base.ctz.i32, *r.urm(0xf3, 0x0f, 0xbc), isap=cfg.use_bmi1) +X86_64.enc(base.ctz.i64, *r.urm.rex(0xf3, 0x0f, 0xbc, w=1), + isap=cfg.use_bmi1) +X86_64.enc(base.ctz.i32, *r.urm.rex(0xf3, 0x0f, 0xbc), isap=cfg.use_bmi1) +X86_64.enc(base.ctz.i32, *r.urm(0xf3, 0x0f, 0xbc), isap=cfg.use_bmi1) # # Loads and stores. # for recipe in [r.st, r.stDisp8, r.stDisp32]: enc_i32_i64_ld_st(base.store, True, recipe, 0x89) - enc_i64(base.istore32.i64.any, recipe, 0x89) + enc_x86_64(base.istore32.i64.any, recipe, 0x89) enc_i32_i64_ld_st(base.istore16, False, recipe, 0x66, 0x89) # Byte stores are more complicated because the registers they can address @@ -203,7 +203,7 @@ for recipe in [r.st, r.stDisp8, r.stDisp32]: # the corresponding st* recipes when a REX prefix is applied. for recipe in [r.st_abcd, r.stDisp8_abcd, r.stDisp32_abcd]: enc_both(base.istore8.i32.any, recipe, 0x88) - enc_i64(base.istore8.i64.any, recipe, 0x88) + enc_x86_64(base.istore8.i64.any, recipe, 0x88) enc_i32_i64(base.spill, r.spSib32, 0x89) enc_i32_i64(base.regspill, r.rsp32, 0x89) @@ -216,8 +216,8 @@ enc_both(base.regspill.b1, r.rsp32, 0x89) for recipe in [r.ld, r.ldDisp8, r.ldDisp32]: enc_i32_i64_ld_st(base.load, True, recipe, 0x8b) - enc_i64(base.uload32.i64, recipe, 0x8b) - I64.enc(base.sload32.i64, *recipe.rex(0x63, w=1)) + enc_x86_64(base.uload32.i64, recipe, 0x8b) + X86_64.enc(base.sload32.i64, *recipe.rex(0x63, w=1)) enc_i32_i64_ld_st(base.uload16, True, recipe, 0x0f, 0xb7) enc_i32_i64_ld_st(base.sload16, True, recipe, 0x0f, 0xbf) enc_i32_i64_ld_st(base.uload8, True, recipe, 0x0f, 0xb6) @@ -231,21 +231,21 @@ enc_both(base.fill.b1, r.fiSib32, 0x8b) enc_both(base.regfill.b1, r.rfi32, 0x8b) # Push and Pop -I32.enc(x86.push.i32, *r.pushq(0x50)) -enc_i64(x86.push.i64, r.pushq, 0x50) +X86_32.enc(x86.push.i32, *r.pushq(0x50)) +enc_x86_64(x86.push.i64, r.pushq, 0x50) -I32.enc(x86.pop.i32, *r.popq(0x58)) -enc_i64(x86.pop.i64, r.popq, 0x58) +X86_32.enc(x86.pop.i32, *r.popq(0x58)) +enc_x86_64(x86.pop.i64, r.popq, 0x58) # Copy Special -I64.enc(base.copy_special, *r.copysp.rex(0x89, w=1)) -I32.enc(base.copy_special, *r.copysp(0x89)) +X86_64.enc(base.copy_special, *r.copysp.rex(0x89, w=1)) +X86_32.enc(base.copy_special, *r.copysp(0x89)) # Adjust SP Imm -I32.enc(base.adjust_sp_imm, *r.adjustsp8(0x83)) -I32.enc(base.adjust_sp_imm, *r.adjustsp32(0x81)) -I64.enc(base.adjust_sp_imm, *r.adjustsp8.rex(0x83, w=1)) -I64.enc(base.adjust_sp_imm, *r.adjustsp32.rex(0x81, w=1)) +X86_32.enc(base.adjust_sp_imm, *r.adjustsp8(0x83)) +X86_32.enc(base.adjust_sp_imm, *r.adjustsp32(0x81)) +X86_64.enc(base.adjust_sp_imm, *r.adjustsp8.rex(0x83, w=1)) +X86_64.enc(base.adjust_sp_imm, *r.adjustsp32.rex(0x81, w=1)) # # Float loads and stores. @@ -281,43 +281,43 @@ enc_both(base.regspill.f64, r.frsp32, 0x66, 0x0f, 0xd6) # Function addresses. # -I32.enc(base.func_addr.i32, *r.fnaddr4(0xb8), - isap=Not(allones_funcaddrs)) -I64.enc(base.func_addr.i64, *r.fnaddr8.rex(0xb8, w=1), - isap=And(Not(allones_funcaddrs), Not(is_pic))) +X86_32.enc(base.func_addr.i32, *r.fnaddr4(0xb8), + isap=Not(allones_funcaddrs)) +X86_64.enc(base.func_addr.i64, *r.fnaddr8.rex(0xb8, w=1), + isap=And(Not(allones_funcaddrs), Not(is_pic))) -I32.enc(base.func_addr.i32, *r.allones_fnaddr4(0xb8), - isap=allones_funcaddrs) -I64.enc(base.func_addr.i64, *r.allones_fnaddr8.rex(0xb8, w=1), - isap=And(allones_funcaddrs, Not(is_pic))) +X86_32.enc(base.func_addr.i32, *r.allones_fnaddr4(0xb8), + isap=allones_funcaddrs) +X86_64.enc(base.func_addr.i64, *r.allones_fnaddr8.rex(0xb8, w=1), + isap=And(allones_funcaddrs, Not(is_pic))) -I64.enc(base.func_addr.i64, *r.got_fnaddr8.rex(0x8b, w=1), - isap=is_pic) +X86_64.enc(base.func_addr.i64, *r.got_fnaddr8.rex(0x8b, w=1), + isap=is_pic) # # Global addresses. # -I32.enc(base.globalsym_addr.i32, *r.gvaddr4(0xb8)) -I64.enc(base.globalsym_addr.i64, *r.gvaddr8.rex(0xb8, w=1), - isap=Not(is_pic)) +X86_32.enc(base.globalsym_addr.i32, *r.gvaddr4(0xb8)) +X86_64.enc(base.globalsym_addr.i64, *r.gvaddr8.rex(0xb8, w=1), + isap=Not(is_pic)) -I64.enc(base.globalsym_addr.i64, *r.got_gvaddr8.rex(0x8b, w=1), - isap=is_pic) +X86_64.enc(base.globalsym_addr.i64, *r.got_gvaddr8.rex(0x8b, w=1), + isap=is_pic) # # Call/return # -I32.enc(base.call, *r.call_id(0xe8)) -I64.enc(base.call, *r.call_id(0xe8), isap=Not(is_pic)) -I64.enc(base.call, *r.call_plt_id(0xe8), isap=is_pic) +X86_32.enc(base.call, *r.call_id(0xe8)) +X86_64.enc(base.call, *r.call_id(0xe8), isap=Not(is_pic)) +X86_64.enc(base.call, *r.call_plt_id(0xe8), isap=is_pic) -I32.enc(base.call_indirect.i32, *r.call_r(0xff, rrr=2)) -I64.enc(base.call_indirect.i64, *r.call_r.rex(0xff, rrr=2)) -I64.enc(base.call_indirect.i64, *r.call_r(0xff, rrr=2)) +X86_32.enc(base.call_indirect.i32, *r.call_r(0xff, rrr=2)) +X86_64.enc(base.call_indirect.i64, *r.call_r.rex(0xff, rrr=2)) +X86_64.enc(base.call_indirect.i64, *r.call_r(0xff, rrr=2)) -I32.enc(base.x_return, *r.ret(0xc3)) -I64.enc(base.x_return, *r.ret(0xc3)) +X86_32.enc(base.x_return, *r.ret(0xc3)) +X86_64.enc(base.x_return, *r.ret(0xc3)) # # Branches @@ -341,10 +341,10 @@ enc_i32_i64(base.brnz, r.tjccd, 0x85) # Branch on a b1 value in a register only looks at the low 8 bits. See also # bint encodings below. # -# Start with the worst-case encoding for I32 only. The register allocator can't -# handle a branch with an ABCD-constrained operand. -I32.enc(base.brz.b1, *r.t8jccd_long(0x84)) -I32.enc(base.brnz.b1, *r.t8jccd_long(0x85)) +# Start with the worst-case encoding for X86_32 only. The register allocator +# can't handle a branch with an ABCD-constrained operand. +X86_32.enc(base.brz.b1, *r.t8jccd_long(0x84)) +X86_32.enc(base.brnz.b1, *r.t8jccd_long(0x85)) enc_both(base.brz.b1, r.t8jccb_abcd, 0x74) enc_both(base.brz.b1, r.t8jccd_abcd, 0x84) @@ -354,14 +354,14 @@ enc_both(base.brnz.b1, r.t8jccd_abcd, 0x85) # # Trap as ud2 # -I32.enc(base.trap, *r.trap(0x0f, 0x0b)) -I64.enc(base.trap, *r.trap(0x0f, 0x0b)) +X86_32.enc(base.trap, *r.trap(0x0f, 0x0b)) +X86_64.enc(base.trap, *r.trap(0x0f, 0x0b)) # Using a standard EncRecipe, not the TailRecipe. -I32.enc(base.trapif, r.trapif, 0) -I64.enc(base.trapif, r.trapif, 0) -I32.enc(base.trapff, r.trapff, 0) -I64.enc(base.trapff, r.trapff, 0) +X86_32.enc(base.trapif, r.trapif, 0) +X86_64.enc(base.trapif, r.trapif, 0) +X86_32.enc(base.trapff, r.trapff, 0) +X86_64.enc(base.trapff, r.trapff, 0) # # Comparisons @@ -372,8 +372,8 @@ enc_i32_i64(base.ifcmp_imm, r.rcmpib, 0x83, rrr=7) enc_i32_i64(base.ifcmp_imm, r.rcmpid, 0x81, rrr=7) # TODO: We could special-case ifcmp_imm(x, 0) to TEST(x, x). -I32.enc(base.ifcmp_sp.i32, *r.rcmp_sp(0x39)) -I64.enc(base.ifcmp_sp.i64, *r.rcmp_sp.rex(0x39, w=1)) +X86_32.enc(base.ifcmp_sp.i32, *r.rcmp_sp(0x39)) +X86_64.enc(base.ifcmp_sp.i64, *r.rcmp_sp.rex(0x39, w=1)) # # Convert flags to bool. @@ -398,66 +398,66 @@ enc_i32_i64(x86.bsr, r.bsf_and_bsr, 0x0F, 0xBD) # # This assumes that b1 is represented as an 8-bit low register with the value 0 # or 1. -I32.enc(base.bint.i32.b1, *r.urm_abcd(0x0f, 0xb6)) -I64.enc(base.bint.i64.b1, *r.urm.rex(0x0f, 0xb6)) # zext to i64 implicit. -I64.enc(base.bint.i64.b1, *r.urm_abcd(0x0f, 0xb6)) # zext to i64 implicit. -I64.enc(base.bint.i32.b1, *r.urm.rex(0x0f, 0xb6)) -I64.enc(base.bint.i32.b1, *r.urm_abcd(0x0f, 0xb6)) +X86_32.enc(base.bint.i32.b1, *r.urm_abcd(0x0f, 0xb6)) +X86_64.enc(base.bint.i64.b1, *r.urm.rex(0x0f, 0xb6)) # zext to i64 implicit. +X86_64.enc(base.bint.i64.b1, *r.urm_abcd(0x0f, 0xb6)) # zext to i64 implicit. +X86_64.enc(base.bint.i32.b1, *r.urm.rex(0x0f, 0xb6)) +X86_64.enc(base.bint.i32.b1, *r.urm_abcd(0x0f, 0xb6)) # Numerical conversions. # Reducing an integer is a no-op. -I32.enc(base.ireduce.i8.i32, r.null, 0) -I32.enc(base.ireduce.i16.i32, r.null, 0) -I64.enc(base.ireduce.i8.i32, r.null, 0) -I64.enc(base.ireduce.i16.i32, r.null, 0) -I64.enc(base.ireduce.i8.i64, r.null, 0) -I64.enc(base.ireduce.i16.i64, r.null, 0) -I64.enc(base.ireduce.i32.i64, r.null, 0) +X86_32.enc(base.ireduce.i8.i32, r.null, 0) +X86_32.enc(base.ireduce.i16.i32, r.null, 0) +X86_64.enc(base.ireduce.i8.i32, r.null, 0) +X86_64.enc(base.ireduce.i16.i32, r.null, 0) +X86_64.enc(base.ireduce.i8.i64, r.null, 0) +X86_64.enc(base.ireduce.i16.i64, r.null, 0) +X86_64.enc(base.ireduce.i32.i64, r.null, 0) # TODO: Add encodings for cbw, cwde, cdqe, which are sign-extending # instructions for %al/%ax/%eax to %ax/%eax/%rax. # movsbl -I32.enc(base.sextend.i32.i8, *r.urm(0x0f, 0xbe)) -I64.enc(base.sextend.i32.i8, *r.urm.rex(0x0f, 0xbe)) -I64.enc(base.sextend.i32.i8, *r.urm(0x0f, 0xbe)) +X86_32.enc(base.sextend.i32.i8, *r.urm(0x0f, 0xbe)) +X86_64.enc(base.sextend.i32.i8, *r.urm.rex(0x0f, 0xbe)) +X86_64.enc(base.sextend.i32.i8, *r.urm(0x0f, 0xbe)) # movswl -I32.enc(base.sextend.i32.i16, *r.urm(0x0f, 0xbf)) -I64.enc(base.sextend.i32.i16, *r.urm.rex(0x0f, 0xbf)) -I64.enc(base.sextend.i32.i16, *r.urm(0x0f, 0xbf)) +X86_32.enc(base.sextend.i32.i16, *r.urm(0x0f, 0xbf)) +X86_64.enc(base.sextend.i32.i16, *r.urm.rex(0x0f, 0xbf)) +X86_64.enc(base.sextend.i32.i16, *r.urm(0x0f, 0xbf)) # movsbq -I64.enc(base.sextend.i64.i8, *r.urm.rex(0x0f, 0xbe, w=1)) +X86_64.enc(base.sextend.i64.i8, *r.urm.rex(0x0f, 0xbe, w=1)) # movswq -I64.enc(base.sextend.i64.i16, *r.urm.rex(0x0f, 0xbf, w=1)) +X86_64.enc(base.sextend.i64.i16, *r.urm.rex(0x0f, 0xbf, w=1)) # movslq -I64.enc(base.sextend.i64.i32, *r.urm.rex(0x63, w=1)) +X86_64.enc(base.sextend.i64.i32, *r.urm.rex(0x63, w=1)) # movzbl -I32.enc(base.uextend.i32.i8, *r.urm(0x0f, 0xb6)) -I64.enc(base.uextend.i32.i8, *r.urm.rex(0x0f, 0xb6)) -I64.enc(base.uextend.i32.i8, *r.urm(0x0f, 0xb6)) +X86_32.enc(base.uextend.i32.i8, *r.urm(0x0f, 0xb6)) +X86_64.enc(base.uextend.i32.i8, *r.urm.rex(0x0f, 0xb6)) +X86_64.enc(base.uextend.i32.i8, *r.urm(0x0f, 0xb6)) # movzwl -I32.enc(base.uextend.i32.i16, *r.urm(0x0f, 0xb7)) -I64.enc(base.uextend.i32.i16, *r.urm.rex(0x0f, 0xb7)) -I64.enc(base.uextend.i32.i16, *r.urm(0x0f, 0xb7)) +X86_32.enc(base.uextend.i32.i16, *r.urm(0x0f, 0xb7)) +X86_64.enc(base.uextend.i32.i16, *r.urm.rex(0x0f, 0xb7)) +X86_64.enc(base.uextend.i32.i16, *r.urm(0x0f, 0xb7)) # movzbq, encoded as movzbl because it's equivalent and shorter -I64.enc(base.uextend.i64.i8, *r.urm.rex(0x0f, 0xb6)) -I64.enc(base.uextend.i64.i8, *r.urm(0x0f, 0xb6)) +X86_64.enc(base.uextend.i64.i8, *r.urm.rex(0x0f, 0xb6)) +X86_64.enc(base.uextend.i64.i8, *r.urm(0x0f, 0xb6)) # movzwq, encoded as movzwl because it's equivalent and shorter -I64.enc(base.uextend.i64.i16, *r.urm.rex(0x0f, 0xb7)) -I64.enc(base.uextend.i64.i16, *r.urm(0x0f, 0xb7)) +X86_64.enc(base.uextend.i64.i16, *r.urm.rex(0x0f, 0xb7)) +X86_64.enc(base.uextend.i64.i16, *r.urm(0x0f, 0xb7)) # A 32-bit register copy clears the high 32 bits. -I64.enc(base.uextend.i64.i32, *r.umr.rex(0x89)) -I64.enc(base.uextend.i64.i32, *r.umr(0x89)) +X86_64.enc(base.uextend.i64.i32, *r.umr.rex(0x89)) +X86_64.enc(base.uextend.i64.i32, *r.umr(0x89)) # @@ -469,8 +469,8 @@ enc_both(base.bitcast.f32.i32, r.frurm, 0x66, 0x0f, 0x6e) enc_both(base.bitcast.i32.f32, r.rfumr, 0x66, 0x0f, 0x7e) # movq -I64.enc(base.bitcast.f64.i64, *r.frurm.rex(0x66, 0x0f, 0x6e, w=1)) -I64.enc(base.bitcast.i64.f64, *r.rfumr.rex(0x66, 0x0f, 0x7e, w=1)) +X86_64.enc(base.bitcast.f64.i64, *r.frurm.rex(0x66, 0x0f, 0x6e, w=1)) +X86_64.enc(base.bitcast.i64.f64, *r.rfumr.rex(0x66, 0x0f, 0x7e, w=1)) # movaps enc_both(base.copy.f32, r.furm, 0x0f, 0x28) @@ -492,11 +492,11 @@ enc_both(base.fdemote.f32.f64, r.furm, 0xf2, 0x0f, 0x5a) # cvttss2si enc_both(x86.cvtt2si.i32.f32, r.rfurm, 0xf3, 0x0f, 0x2c) -I64.enc(x86.cvtt2si.i64.f32, *r.rfurm.rex(0xf3, 0x0f, 0x2c, w=1)) +X86_64.enc(x86.cvtt2si.i64.f32, *r.rfurm.rex(0xf3, 0x0f, 0x2c, w=1)) # cvttsd2si enc_both(x86.cvtt2si.i32.f64, r.rfurm, 0xf2, 0x0f, 0x2c) -I64.enc(x86.cvtt2si.i64.f64, *r.rfurm.rex(0xf2, 0x0f, 0x2c, w=1)) +X86_64.enc(x86.cvtt2si.i64.f64, *r.rfurm.rex(0xf2, 0x0f, 0x2c, w=1)) # Exact square roots. enc_both(base.sqrt.f32, r.furm, 0xf3, 0x0f, 0x51) From c161b0d1030e583c96b494890c51111c86babbf2 Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Sun, 18 Mar 2018 23:53:02 +0300 Subject: [PATCH 25/72] Fix check-rustfmt.sh for macOS (#273) There are two cases: 1. It seems that grep on macOS exits as soon as it finds the first match. This makes cargo unhappy and it prints message like "failed printing to stdout: Broken pipe (os error 32)". The solution is to fully consume the output from cargo. I choose to use tee for this task. 2. When in a strict mode, bash complains that $1 is not defined (when it's actually not defined in case of omitting --install). The solution is to apply bash substitution magic: when $1 is undefined or set to null substitute it with empty string. --- check-rustfmt.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/check-rustfmt.sh b/check-rustfmt.sh index 1983493342..9a49e8bac5 100755 --- a/check-rustfmt.sh +++ b/check-rustfmt.sh @@ -22,11 +22,11 @@ set -euo pipefail # operation, however that doesn't appear to be possible through "cargo fmt"). VERS="0.9.0" -if cargo install --list | grep -q "^rustfmt v$VERS"; then +if cargo install --list | tee /dev/null | grep -q "^rustfmt v$VERS"; then exit 0 fi -if [ "$1" != "--install" ]; then +if [[ ${1:-""} != "--install" ]]; then echo "********************************************************************" echo "* Please install rustfmt v$VERS to verify formatting. *" echo "* If a newer version of rustfmt is available, update this script. *" From 832d9d9a0df56573e1ed53d73ea8c7d67aa34fb1 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sun, 18 Mar 2018 13:45:41 -0700 Subject: [PATCH 26/72] Minor code simplification. --- lib/wasm/src/code_translator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index 5535a1555e..aab015c536 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -186,8 +186,8 @@ pub fn translate_operator( } Operator::End => { let frame = state.control_stack.pop().unwrap(); - let return_count = frame.num_return_values(); if !builder.is_unreachable() || !builder.is_pristine() { + let return_count = frame.num_return_values(); builder.ins().jump( frame.following_code(), state.peekn(return_count), From 492fa1283c4d5b10901623a2810d28d507a2f046 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sun, 18 Mar 2018 13:46:07 -0700 Subject: [PATCH 27/72] Define an "interrupt" trap code. This is a trap code for interrupting the running code, to allow timeouts and safepoints to be implemented. It is resumable. --- lib/cretonne/src/ir/trapcode.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/cretonne/src/ir/trapcode.rs b/lib/cretonne/src/ir/trapcode.rs index 2374c206f3..68b836f309 100644 --- a/lib/cretonne/src/ir/trapcode.rs +++ b/lib/cretonne/src/ir/trapcode.rs @@ -38,6 +38,10 @@ pub enum TrapCode { /// Failed float-to-int conversion. BadConversionToInteger, + /// Execution has potentially run too long and may be interrupted. + /// This trap is resumable. + Interrupt, + /// A user-defined trap code. User(u16), } @@ -54,6 +58,7 @@ impl Display for TrapCode { IntegerOverflow => "int_ovf", IntegerDivisionByZero => "int_divz", BadConversionToInteger => "bad_toint", + Interrupt => "interrupt", User(x) => return write!(f, "user{}", x), }; f.write_str(identifier) @@ -74,6 +79,7 @@ impl FromStr for TrapCode { "int_ovf" => Ok(IntegerOverflow), "int_divz" => Ok(IntegerDivisionByZero), "bad_toint" => Ok(BadConversionToInteger), + "interrupt" => Ok(Interrupt), _ if s.starts_with("user") => s[4..].parse().map(User).map_err(|_| ()), _ => Err(()), } From d99b43e4b7aae1fde986c83055de99356981c363 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sun, 18 Mar 2018 13:47:17 -0700 Subject: [PATCH 28/72] Add a hook to the wasm FuncEnvironment for emitting loop headers. This will allow wasm implementations that wish to insert code into every loop, for example to insert an interrupt check or a safepoint. do so without relying on asynchronous signals. --- lib/wasm/src/code_translator.rs | 1 + lib/wasm/src/environ/spec.rs | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index aab015c536..bb675cb1c7 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -137,6 +137,7 @@ pub fn translate_operator( builder.ins().jump(loop_body, &[]); state.push_loop(loop_body, next, num_return_values(ty)); builder.switch_to_block(loop_body); + environ.translate_loop_header(builder.cursor()); } Operator::If { ty } => { let val = state.pop1(); diff --git a/lib/wasm/src/environ/spec.rs b/lib/wasm/src/environ/spec.rs index 732438a573..7f73c3fc16 100644 --- a/lib/wasm/src/environ/spec.rs +++ b/lib/wasm/src/environ/spec.rs @@ -144,6 +144,14 @@ pub trait FuncEnvironment { index: MemoryIndex, heap: ir::Heap, ) -> ir::Value; + + /// Emit code at the beginning of every wasm loop. + /// + /// This can be used to insert explicit interrupt or safepoint checking at + /// the beginnings of loops. + fn translate_loop_header(&mut self, _pos: FuncCursor) { + // By default, don't emit anything. + } } /// An object satisfying the `ModuleEnvironment` trait can be passed as argument to the From 2d1f9f874c23eab253d4048da2a2317b49df3150 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sun, 18 Mar 2018 14:56:30 -0700 Subject: [PATCH 29/72] Bump version to 0.4.1 --- cranelift/Cargo.toml | 14 +++++++------- cranelift/publish-all.sh | 2 +- lib/cretonne/Cargo.toml | 2 +- lib/filetests/Cargo.toml | 6 +++--- lib/frontend/Cargo.toml | 4 ++-- lib/native/Cargo.toml | 4 ++-- lib/reader/Cargo.toml | 4 ++-- lib/wasm/Cargo.toml | 6 +++--- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index a6d363dcdb..947b50b44a 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cretonne-tools" authors = ["The Cretonne Project Developers"] -version = "0.4.0" +version = "0.4.1" description = "Binaries for testing the Cretonne library" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" @@ -13,12 +13,12 @@ name = "cton-util" path = "src/cton-util.rs" [dependencies] -cretonne = { path = "lib/cretonne", version = "0.4.0" } -cretonne-reader = { path = "lib/reader", version = "0.4.0" } -cretonne-frontend = { path = "lib/frontend", version = "0.4.0" } -cretonne-wasm = { path = "lib/wasm", version = "0.4.0" } -cretonne-native = { path = "lib/native", version = "0.4.0" } -cretonne-filetests = { path = "lib/filetests", version = "0.4.0" } +cretonne = { path = "lib/cretonne", version = "0.4.1" } +cretonne-reader = { path = "lib/reader", version = "0.4.1" } +cretonne-frontend = { path = "lib/frontend", version = "0.4.1" } +cretonne-wasm = { path = "lib/wasm", version = "0.4.1" } +cretonne-native = { path = "lib/native", version = "0.4.1" } +cretonne-filetests = { path = "lib/filetests", version = "0.4.1" } filecheck = "0.2.1" docopt = "0.8.0" serde = "1.0.8" diff --git a/cranelift/publish-all.sh b/cranelift/publish-all.sh index 6b23f71064..a29f308929 100755 --- a/cranelift/publish-all.sh +++ b/cranelift/publish-all.sh @@ -4,7 +4,7 @@ cd $(dirname "$0") topdir="$(pwd)" # All the cretonne-* crates have the same version number -version="0.4.0" +version="0.4.1" # Update all of the Cargo.toml files. # diff --git a/lib/cretonne/Cargo.toml b/lib/cretonne/Cargo.toml index d603a9597e..66cd819715 100644 --- a/lib/cretonne/Cargo.toml +++ b/lib/cretonne/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cretonne Project Developers"] name = "cretonne" -version = "0.4.0" +version = "0.4.1" description = "Low-level code generator library" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" diff --git a/lib/filetests/Cargo.toml b/lib/filetests/Cargo.toml index f3ecf521c0..093b51b323 100644 --- a/lib/filetests/Cargo.toml +++ b/lib/filetests/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cretonne-filetests" authors = ["The Cretonne Project Developers"] -version = "0.4.0" +version = "0.4.1" description = "Test driver and implementations of the filetest commands" license = "Apache-2.0" documentation = "http://cretonne.readthedocs.io/en/latest/testing.html#file-tests" @@ -12,7 +12,7 @@ publish = false name = "cton_filetests" [dependencies] -cretonne = { path = "../cretonne", version = "0.4.0" } -cretonne-reader = { path = "../reader", version = "0.4.0" } +cretonne = { path = "../cretonne", version = "0.4.1" } +cretonne-reader = { path = "../reader", version = "0.4.1" } filecheck = "0.2.1" num_cpus = "1.8.0" diff --git a/lib/frontend/Cargo.toml b/lib/frontend/Cargo.toml index bd5455d9d3..40f1833c71 100644 --- a/lib/frontend/Cargo.toml +++ b/lib/frontend/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cretonne Project Developers"] name = "cretonne-frontend" -version = "0.4.0" +version = "0.4.1" description = "Cretonne IL builder helper" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" @@ -12,7 +12,7 @@ readme = "README.md" name = "cton_frontend" [dependencies] -cretonne = { path = "../cretonne", version = "0.4.0" } +cretonne = { path = "../cretonne", version = "0.4.1" } [badges] maintenance = { status = "experimental" } diff --git a/lib/native/Cargo.toml b/lib/native/Cargo.toml index 9a2ba0eea7..31dbdb0708 100644 --- a/lib/native/Cargo.toml +++ b/lib/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cretonne-native" -version = "0.4.0" +version = "0.4.1" authors = ["The Cretonne Project Developers"] description = "Support for targeting the host with Cretonne" repository = "https://github.com/Cretonne/cretonne" @@ -11,7 +11,7 @@ readme = "README.md" name = "cton_native" [dependencies] -cretonne = { path = "../cretonne", version = "0.4.0" } +cretonne = { path = "../cretonne", version = "0.4.1" } [target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies] raw-cpuid = "3.0.0" diff --git a/lib/reader/Cargo.toml b/lib/reader/Cargo.toml index 1841357bc4..80fab0f499 100644 --- a/lib/reader/Cargo.toml +++ b/lib/reader/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cretonne Project Developers"] name = "cretonne-reader" -version = "0.4.0" +version = "0.4.1" description = "Cretonne textual IL reader" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" @@ -12,7 +12,7 @@ readme = "README.md" name = "cton_reader" [dependencies] -cretonne = { path = "../cretonne", version = "0.4.0" } +cretonne = { path = "../cretonne", version = "0.4.1" } [badges] maintenance = { status = "experimental" } diff --git a/lib/wasm/Cargo.toml b/lib/wasm/Cargo.toml index df978cb4d0..0fcd2210f5 100644 --- a/lib/wasm/Cargo.toml +++ b/lib/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cretonne-wasm" -version = "0.4.0" +version = "0.4.1" authors = ["The Cretonne Project Developers"] description = "Translator from WebAssembly to Cretonne IL" repository = "https://github.com/Cretonne/cretonne" @@ -13,8 +13,8 @@ name = "cton_wasm" [dependencies] wasmparser = "0.15.1" -cretonne = { path = "../cretonne", version = "0.4.0" } -cretonne-frontend = { path = "../frontend", version = "0.4.0" } +cretonne = { path = "../cretonne", version = "0.4.1" } +cretonne-frontend = { path = "../frontend", version = "0.4.1" } [dev-dependencies] tempdir = "0.3.5" From c333a52e3e21dbbf1b6b87ef4991e9d8a309d561 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 13 Mar 2018 05:56:59 -0700 Subject: [PATCH 30/72] Factor out fcmp and icmp translation into helper functions. --- lib/wasm/src/code_translator.rs | 108 +++++++++++--------------------- 1 file changed, 36 insertions(+), 72 deletions(-) diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index bb675cb1c7..10c0f7fdd2 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -765,101 +765,45 @@ pub fn translate_operator( } /**************************** Comparison Operators **********************************/ Operator::I32LtS | Operator::I64LtS => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().icmp(IntCC::SignedLessThan, arg1, arg2); - state.push1(builder.ins().bint(I32, val)); + translate_icmp(IntCC::SignedLessThan, builder, state) } Operator::I32LtU | Operator::I64LtU => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().icmp(IntCC::UnsignedLessThan, arg1, arg2); - state.push1(builder.ins().bint(I32, val)); + translate_icmp(IntCC::UnsignedLessThan, builder, state) } Operator::I32LeS | Operator::I64LeS => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().icmp(IntCC::SignedLessThanOrEqual, arg1, arg2); - state.push1(builder.ins().bint(I32, val)); + translate_icmp(IntCC::SignedLessThanOrEqual, builder, state) } Operator::I32LeU | Operator::I64LeU => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().icmp( - IntCC::UnsignedLessThanOrEqual, - arg1, - arg2, - ); - state.push1(builder.ins().bint(I32, val)); + translate_icmp(IntCC::UnsignedLessThanOrEqual, builder, state) } Operator::I32GtS | Operator::I64GtS => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().icmp(IntCC::SignedGreaterThan, arg1, arg2); - state.push1(builder.ins().bint(I32, val)); + translate_icmp(IntCC::SignedGreaterThan, builder, state) } Operator::I32GtU | Operator::I64GtU => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().icmp(IntCC::UnsignedGreaterThan, arg1, arg2); - state.push1(builder.ins().bint(I32, val)); + translate_icmp(IntCC::UnsignedGreaterThan, builder, state) } Operator::I32GeS | Operator::I64GeS => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().icmp( - IntCC::SignedGreaterThanOrEqual, - arg1, - arg2, - ); - state.push1(builder.ins().bint(I32, val)); + translate_icmp(IntCC::SignedGreaterThanOrEqual, builder, state) } Operator::I32GeU | Operator::I64GeU => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().icmp( - IntCC::UnsignedGreaterThanOrEqual, - arg1, - arg2, - ); - state.push1(builder.ins().bint(I32, val)); + translate_icmp(IntCC::UnsignedGreaterThanOrEqual, builder, state) } Operator::I32Eqz | Operator::I64Eqz => { let arg = state.pop1(); let val = builder.ins().icmp_imm(IntCC::Equal, arg, 0); state.push1(builder.ins().bint(I32, val)); } - Operator::I32Eq | Operator::I64Eq => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().icmp(IntCC::Equal, arg1, arg2); - state.push1(builder.ins().bint(I32, val)); - } - Operator::F32Eq | Operator::F64Eq => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().fcmp(FloatCC::Equal, arg1, arg2); - state.push1(builder.ins().bint(I32, val)); - } - Operator::I32Ne | Operator::I64Ne => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().icmp(IntCC::NotEqual, arg1, arg2); - state.push1(builder.ins().bint(I32, val)); - } - Operator::F32Ne | Operator::F64Ne => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().fcmp(FloatCC::NotEqual, arg1, arg2); - state.push1(builder.ins().bint(I32, val)); - } - Operator::F32Gt | Operator::F64Gt => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().fcmp(FloatCC::GreaterThan, arg1, arg2); - state.push1(builder.ins().bint(I32, val)); - } + Operator::I32Eq | Operator::I64Eq => translate_icmp(IntCC::Equal, builder, state), + Operator::F32Eq | Operator::F64Eq => translate_fcmp(FloatCC::Equal, builder, state), + Operator::I32Ne | Operator::I64Ne => translate_icmp(IntCC::NotEqual, builder, state), + Operator::F32Ne | Operator::F64Ne => translate_fcmp(FloatCC::NotEqual, builder, state), + Operator::F32Gt | Operator::F64Gt => translate_fcmp(FloatCC::GreaterThan, builder, state), Operator::F32Ge | Operator::F64Ge => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().fcmp(FloatCC::GreaterThanOrEqual, arg1, arg2); - state.push1(builder.ins().bint(I32, val)); - } - Operator::F32Lt | Operator::F64Lt => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().fcmp(FloatCC::LessThan, arg1, arg2); - state.push1(builder.ins().bint(I32, val)); + translate_fcmp(FloatCC::GreaterThanOrEqual, builder, state) } + Operator::F32Lt | Operator::F64Lt => translate_fcmp(FloatCC::LessThan, builder, state), Operator::F32Le | Operator::F64Le => { - let (arg1, arg2) = state.pop2(); - let val = builder.ins().fcmp(FloatCC::LessThanOrEqual, arg1, arg2); - state.push1(builder.ins().bint(I32, val)); + translate_fcmp(FloatCC::LessThanOrEqual, builder, state) } Operator::Wake { .. } | Operator::I32Wait { .. } | @@ -1101,3 +1045,23 @@ fn translate_store( base, ); } + +fn translate_icmp( + cc: IntCC, + builder: &mut FunctionBuilder, + state: &mut TranslationState, +) { + let (arg0, arg1) = state.pop2(); + let val = builder.ins().icmp(cc, arg0, arg1); + state.push1(builder.ins().bint(I32, val)); +} + +fn translate_fcmp( + cc: FloatCC, + builder: &mut FunctionBuilder, + state: &mut TranslationState, +) { + let (arg0, arg1) = state.pop2(); + let val = builder.ins().fcmp(cc, arg0, arg1); + state.push1(builder.ins().bint(I32, val)); +} From f6b8cf86a566969544762019e96a5238f3ae89a0 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 13 Mar 2018 07:04:38 -0700 Subject: [PATCH 31/72] Factor out br_if translation into helper functions. --- lib/wasm/src/code_translator.rs | 53 ++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index 10c0f7fdd2..cccbae1368 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -247,27 +247,7 @@ pub fn translate_operator( state.popn(return_count); state.reachable = false; } - Operator::BrIf { relative_depth } => { - let val = state.pop1(); - let i = state.control_stack.len() - 1 - (relative_depth as usize); - let (return_count, br_destination) = { - let frame = &mut state.control_stack[i]; - // The values returned by the branch are still available for the reachable - // code that comes after it - frame.set_branched_to_exit(); - let return_count = if frame.is_loop() { - 0 - } else { - frame.num_return_values() - }; - (return_count, frame.br_destination()) - }; - builder.ins().brnz( - val, - br_destination, - state.peekn(return_count), - ); - } + Operator::BrIf { relative_depth } => translate_br_if(relative_depth, builder, state), Operator::BrTable { table } => { let (depths, default) = table.read_table(); let mut min_depth = default; @@ -1065,3 +1045,34 @@ fn translate_fcmp( let val = builder.ins().fcmp(cc, arg0, arg1); state.push1(builder.ins().bint(I32, val)); } + +fn translate_br_if( + relative_depth: u32, + builder: &mut FunctionBuilder, + state: &mut TranslationState, +) { + let val = state.pop1(); + let (br_destination, inputs) = translate_br_if_args(relative_depth, state); + builder.ins().brnz(val, br_destination, inputs); +} + +fn translate_br_if_args<'state>( + relative_depth: u32, + state: &'state mut TranslationState, +) -> (ir::Ebb, &'state [ir::Value]) { + let i = state.control_stack.len() - 1 - (relative_depth as usize); + let (return_count, br_destination) = { + let frame = &mut state.control_stack[i]; + // The values returned by the branch are still available for the reachable + // code that comes after it + frame.set_branched_to_exit(); + let return_count = if frame.is_loop() { + 0 + } else { + frame.num_return_values() + }; + (return_count, frame.br_destination()) + }; + let inputs = state.peekn(return_count); + (br_destination, inputs) +} From ca4582ae8231b139f6bc2bdf32fe0f1d3d0d7b99 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 19 Mar 2018 09:13:47 -0700 Subject: [PATCH 32/72] Rename the recipes for x86 spill/fill instructions. Both "sp" and "fi" have multiple meanings in this context, so use slightly longer but less ambiguous names. --- lib/cretonne/meta/isa/intel/encodings.py | 32 +++++++++---------- lib/cretonne/meta/isa/intel/recipes.py | 40 ++++++++++++++---------- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/lib/cretonne/meta/isa/intel/encodings.py b/lib/cretonne/meta/isa/intel/encodings.py index 995149794a..489e61be9f 100644 --- a/lib/cretonne/meta/isa/intel/encodings.py +++ b/lib/cretonne/meta/isa/intel/encodings.py @@ -205,14 +205,14 @@ for recipe in [r.st_abcd, r.stDisp8_abcd, r.stDisp32_abcd]: enc_both(base.istore8.i32.any, recipe, 0x88) enc_x86_64(base.istore8.i64.any, recipe, 0x88) -enc_i32_i64(base.spill, r.spSib32, 0x89) -enc_i32_i64(base.regspill, r.rsp32, 0x89) +enc_i32_i64(base.spill, r.spillSib32, 0x89) +enc_i32_i64(base.regspill, r.regspill32, 0x89) # Use a 32-bit write for spilling `b1` to avoid constraining the permitted # registers. # See MIN_SPILL_SLOT_SIZE which makes this safe. -enc_both(base.spill.b1, r.spSib32, 0x89) -enc_both(base.regspill.b1, r.rsp32, 0x89) +enc_both(base.spill.b1, r.spillSib32, 0x89) +enc_both(base.regspill.b1, r.regspill32, 0x89) for recipe in [r.ld, r.ldDisp8, r.ldDisp32]: enc_i32_i64_ld_st(base.load, True, recipe, 0x8b) @@ -223,12 +223,12 @@ for recipe in [r.ld, r.ldDisp8, r.ldDisp32]: enc_i32_i64_ld_st(base.uload8, True, recipe, 0x0f, 0xb6) enc_i32_i64_ld_st(base.sload8, True, recipe, 0x0f, 0xbe) -enc_i32_i64(base.fill, r.fiSib32, 0x8b) -enc_i32_i64(base.regfill, r.rfi32, 0x8b) +enc_i32_i64(base.fill, r.fillSib32, 0x8b) +enc_i32_i64(base.regfill, r.regfill32, 0x8b) # Load 32 bits from `b1` spill slots. See `spill.b1` above. -enc_both(base.fill.b1, r.fiSib32, 0x8b) -enc_both(base.regfill.b1, r.rfi32, 0x8b) +enc_both(base.fill.b1, r.fillSib32, 0x8b) +enc_both(base.regfill.b1, r.regfill32, 0x8b) # Push and Pop X86_32.enc(x86.push.i32, *r.pushq(0x50)) @@ -267,15 +267,15 @@ enc_both(base.store.f64.any, r.fst, 0x66, 0x0f, 0xd6) enc_both(base.store.f64.any, r.fstDisp8, 0x66, 0x0f, 0xd6) enc_both(base.store.f64.any, r.fstDisp32, 0x66, 0x0f, 0xd6) -enc_both(base.fill.f32, r.ffiSib32, 0x66, 0x0f, 0x6e) -enc_both(base.regfill.f32, r.frfi32, 0x66, 0x0f, 0x6e) -enc_both(base.fill.f64, r.ffiSib32, 0xf3, 0x0f, 0x7e) -enc_both(base.regfill.f64, r.frfi32, 0xf3, 0x0f, 0x7e) +enc_both(base.fill.f32, r.ffillSib32, 0x66, 0x0f, 0x6e) +enc_both(base.regfill.f32, r.fregfill32, 0x66, 0x0f, 0x6e) +enc_both(base.fill.f64, r.ffillSib32, 0xf3, 0x0f, 0x7e) +enc_both(base.regfill.f64, r.fregfill32, 0xf3, 0x0f, 0x7e) -enc_both(base.spill.f32, r.fspSib32, 0x66, 0x0f, 0x7e) -enc_both(base.regspill.f32, r.frsp32, 0x66, 0x0f, 0x7e) -enc_both(base.spill.f64, r.fspSib32, 0x66, 0x0f, 0xd6) -enc_both(base.regspill.f64, r.frsp32, 0x66, 0x0f, 0xd6) +enc_both(base.spill.f32, r.fspillSib32, 0x66, 0x0f, 0x7e) +enc_both(base.regspill.f32, r.fregspill32, 0x66, 0x0f, 0x7e) +enc_both(base.spill.f64, r.fspillSib32, 0x66, 0x0f, 0xd6) +enc_both(base.regspill.f64, r.fregspill32, 0x66, 0x0f, 0xd6) # # Function addresses. diff --git a/lib/cretonne/meta/isa/intel/recipes.py b/lib/cretonne/meta/isa/intel/recipes.py index 9d03d02053..9d015a25bb 100644 --- a/lib/cretonne/meta/isa/intel/recipes.py +++ b/lib/cretonne/meta/isa/intel/recipes.py @@ -756,8 +756,8 @@ fstDisp32 = TailRecipe( ''') # Unary spill with SIB and 32-bit displacement. -spSib32 = TailRecipe( - 'spSib32', Unary, size=6, ins=GPR, outs=StackGPR32, +spillSib32 = TailRecipe( + 'spillSib32', Unary, size=6, ins=GPR, outs=StackGPR32, clobbers_flags=False, emit=''' let base = stk_base(out_stk0.base); @@ -766,8 +766,10 @@ spSib32 = TailRecipe( sib_noindex(base, sink); sink.put4(out_stk0.offset as u32); ''') -fspSib32 = TailRecipe( - 'fspSib32', Unary, size=6, ins=FPR, outs=StackFPR32, + +# Like spillSib32, but targeting an FPR rather than a GPR. +fspillSib32 = TailRecipe( + 'fspillSib32', Unary, size=6, ins=FPR, outs=StackFPR32, clobbers_flags=False, emit=''' let base = stk_base(out_stk0.base); @@ -778,8 +780,8 @@ fspSib32 = TailRecipe( ''') # Regspill using RSP-relative addressing. -rsp32 = TailRecipe( - 'rsp32', RegSpill, size=6, ins=GPR, outs=(), +regspill32 = TailRecipe( + 'regspill32', RegSpill, size=6, ins=GPR, outs=(), clobbers_flags=False, emit=''' let dst = StackRef::sp(dst, &func.stack_slots); @@ -789,8 +791,10 @@ rsp32 = TailRecipe( sib_noindex(base, sink); sink.put4(dst.offset as u32); ''') -frsp32 = TailRecipe( - 'frsp32', RegSpill, size=6, ins=FPR, outs=(), + +# Like regspill32, but targeting an FPR rather than a GPR. +fregspill32 = TailRecipe( + 'fregspill32', RegSpill, size=6, ins=FPR, outs=(), clobbers_flags=False, emit=''' let dst = StackRef::sp(dst, &func.stack_slots); @@ -874,8 +878,8 @@ fldDisp32 = TailRecipe( ''') # Unary fill with SIB and 32-bit displacement. -fiSib32 = TailRecipe( - 'fiSib32', Unary, size=6, ins=StackGPR32, outs=GPR, +fillSib32 = TailRecipe( + 'fillSib32', Unary, size=6, ins=StackGPR32, outs=GPR, clobbers_flags=False, emit=''' let base = stk_base(in_stk0.base); @@ -884,8 +888,10 @@ fiSib32 = TailRecipe( sib_noindex(base, sink); sink.put4(in_stk0.offset as u32); ''') -ffiSib32 = TailRecipe( - 'ffiSib32', Unary, size=6, ins=StackFPR32, outs=FPR, + +# Like fillSib32, but targeting an FPR rather than a GPR. +ffillSib32 = TailRecipe( + 'ffillSib32', Unary, size=6, ins=StackFPR32, outs=FPR, clobbers_flags=False, emit=''' let base = stk_base(in_stk0.base); @@ -896,8 +902,8 @@ ffiSib32 = TailRecipe( ''') # Regfill with RSP-relative 32-bit displacement. -rfi32 = TailRecipe( - 'rfi32', RegFill, size=6, ins=StackGPR32, outs=(), +regfill32 = TailRecipe( + 'regfill32', RegFill, size=6, ins=StackGPR32, outs=(), clobbers_flags=False, emit=''' let src = StackRef::sp(src, &func.stack_slots); @@ -907,8 +913,10 @@ rfi32 = TailRecipe( sib_noindex(base, sink); sink.put4(src.offset as u32); ''') -frfi32 = TailRecipe( - 'frfi32', RegFill, size=6, ins=StackFPR32, outs=(), + +# Like regfill32, but targeting an FPR rather than a GPR. +fregfill32 = TailRecipe( + 'fregfill32', RegFill, size=6, ins=StackFPR32, outs=(), clobbers_flags=False, emit=''' let src = StackRef::sp(src, &func.stack_slots); From da4cf27780468b39f0983b65d074191263c8da4e Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 20 Mar 2018 12:04:17 -0700 Subject: [PATCH 33/72] Update to filecheck 0.3.0. --- lib/filetests/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/filetests/Cargo.toml b/lib/filetests/Cargo.toml index 093b51b323..0e37c1ef8d 100644 --- a/lib/filetests/Cargo.toml +++ b/lib/filetests/Cargo.toml @@ -14,5 +14,5 @@ name = "cton_filetests" [dependencies] cretonne = { path = "../cretonne", version = "0.4.1" } cretonne-reader = { path = "../reader", version = "0.4.1" } -filecheck = "0.2.1" +filecheck = "0.3.0" num_cpus = "1.8.0" From 2b3df1a506399e21dcdcc72bb835e66df7be3a74 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 20 Mar 2018 12:15:59 -0700 Subject: [PATCH 34/72] Add `use` declarations for `std` features. Merge the `use` parts of the `no_std` branch. This reduces the diffs between master and the `no_std` branch, making it easier to maintain. Most of these changes are derived from patches by @lachlansneff in https://github.com/Cretonne/cretonne/tree/no_std. --- lib/cretonne/src/abi.rs | 1 + lib/cretonne/src/bforest/map.rs | 1 + lib/cretonne/src/bforest/node.rs | 1 + lib/cretonne/src/bforest/pool.rs | 1 + lib/cretonne/src/bforest/set.rs | 1 + lib/cretonne/src/dominator_tree.rs | 2 +- lib/cretonne/src/entity/list.rs | 1 + lib/cretonne/src/entity/map.rs | 1 + lib/cretonne/src/entity/primary.rs | 1 + lib/cretonne/src/entity/set.rs | 1 + lib/cretonne/src/entity/sparse.rs | 1 + lib/cretonne/src/flowgraph.rs | 1 + lib/cretonne/src/ir/condcodes.rs | 1 + lib/cretonne/src/ir/dfg.rs | 1 + lib/cretonne/src/ir/entities.rs | 1 + lib/cretonne/src/ir/extfunc.rs | 2 ++ lib/cretonne/src/ir/extname.rs | 1 + lib/cretonne/src/ir/immediates.rs | 1 + lib/cretonne/src/ir/instructions.rs | 2 ++ lib/cretonne/src/ir/jumptable.rs | 3 +++ lib/cretonne/src/ir/layout.rs | 1 + lib/cretonne/src/ir/libcall.rs | 1 + lib/cretonne/src/ir/progpoint.rs | 1 + lib/cretonne/src/ir/sourceloc.rs | 1 + lib/cretonne/src/ir/stackslot.rs | 2 ++ lib/cretonne/src/ir/trapcode.rs | 1 + lib/cretonne/src/ir/types.rs | 1 + lib/cretonne/src/isa/arm32/mod.rs | 1 + lib/cretonne/src/isa/arm32/registers.rs | 1 + lib/cretonne/src/isa/arm64/mod.rs | 1 + lib/cretonne/src/isa/arm64/registers.rs | 1 + lib/cretonne/src/isa/intel/mod.rs | 2 +- lib/cretonne/src/isa/intel/registers.rs | 1 + lib/cretonne/src/isa/mod.rs | 1 + lib/cretonne/src/isa/riscv/mod.rs | 2 ++ lib/cretonne/src/isa/riscv/registers.rs | 1 + lib/cretonne/src/isa/riscv/settings.rs | 1 + lib/cretonne/src/iterators.rs | 2 ++ lib/cretonne/src/legalizer/boundary.rs | 1 + lib/cretonne/src/legalizer/split.rs | 1 + lib/cretonne/src/licm.rs | 1 + lib/cretonne/src/loop_analysis.rs | 2 ++ lib/cretonne/src/partition_slice.rs | 1 + lib/cretonne/src/regalloc/allocatable_set.rs | 1 + lib/cretonne/src/regalloc/coalescing.rs | 1 + lib/cretonne/src/regalloc/diversion.rs | 1 + lib/cretonne/src/regalloc/live_value_tracker.rs | 1 + lib/cretonne/src/regalloc/liveness.rs | 1 + lib/cretonne/src/regalloc/liverange.rs | 1 + lib/cretonne/src/regalloc/pressure.rs | 1 + lib/cretonne/src/regalloc/reload.rs | 1 + lib/cretonne/src/regalloc/solver.rs | 2 ++ lib/cretonne/src/regalloc/spilling.rs | 1 + lib/cretonne/src/regalloc/virtregs.rs | 1 + lib/cretonne/src/settings.rs | 2 ++ lib/cretonne/src/simple_gvn.rs | 1 + lib/cretonne/src/topo_order.rs | 1 + lib/cretonne/src/verifier/mod.rs | 2 ++ lib/cretonne/src/write.rs | 2 ++ lib/frontend/src/ssa.rs | 1 + lib/wasm/src/code_translator.rs | 1 + lib/wasm/src/environ/dummy.rs | 2 ++ lib/wasm/src/environ/spec.rs | 2 ++ lib/wasm/src/module_translator.rs | 2 ++ lib/wasm/src/sections_translator.rs | 2 ++ lib/wasm/src/state.rs | 1 + 66 files changed, 82 insertions(+), 2 deletions(-) diff --git a/lib/cretonne/src/abi.rs b/lib/cretonne/src/abi.rs index 801d4bfe9e..b69821e657 100644 --- a/lib/cretonne/src/abi.rs +++ b/lib/cretonne/src/abi.rs @@ -5,6 +5,7 @@ use ir::{ArgumentLoc, AbiParam, ArgumentExtension, Type}; use std::cmp::Ordering; +use std::vec::Vec; /// Legalization action to perform on a single argument or return value when converting a /// signature. diff --git a/lib/cretonne/src/bforest/map.rs b/lib/cretonne/src/bforest/map.rs index 5aa19bceda..edf301aa4c 100644 --- a/lib/cretonne/src/bforest/map.rs +++ b/lib/cretonne/src/bforest/map.rs @@ -423,6 +423,7 @@ where #[cfg(test)] mod test { use std::mem; + use std::vec::Vec; use super::*; use super::super::NodeData; diff --git a/lib/cretonne/src/bforest/node.rs b/lib/cretonne/src/bforest/node.rs index 3c6b8c8774..d5c46f54bd 100644 --- a/lib/cretonne/src/bforest/node.rs +++ b/lib/cretonne/src/bforest/node.rs @@ -580,6 +580,7 @@ where #[cfg(test)] mod test { use std::mem; + use std::string::ToString; use super::*; // Forest impl for a set implementation. diff --git a/lib/cretonne/src/bforest/pool.rs b/lib/cretonne/src/bforest/pool.rs index 1ce9e83279..481271c8db 100644 --- a/lib/cretonne/src/bforest/pool.rs +++ b/lib/cretonne/src/bforest/pool.rs @@ -78,6 +78,7 @@ impl NodePool { { use std::borrow::Borrow; use std::cmp::Ordering; + use std::vec::Vec; use super::Comparator; use entity::SparseSet; diff --git a/lib/cretonne/src/bforest/set.rs b/lib/cretonne/src/bforest/set.rs index 6992265773..dd7f63ca17 100644 --- a/lib/cretonne/src/bforest/set.rs +++ b/lib/cretonne/src/bforest/set.rs @@ -351,6 +351,7 @@ where #[cfg(test)] mod test { use std::mem; + use std::vec::Vec; use super::*; use super::super::NodeData; diff --git a/lib/cretonne/src/dominator_tree.rs b/lib/cretonne/src/dominator_tree.rs index e643a42592..823469d081 100644 --- a/lib/cretonne/src/dominator_tree.rs +++ b/lib/cretonne/src/dominator_tree.rs @@ -8,8 +8,8 @@ use packed_option::PackedOption; use std::cmp; use std::mem; use timing; - use std::cmp::Ordering; +use std::vec::Vec; // RPO numbers are not first assigned in a contiguous way but as multiples of STRIDE, to leave // room for modifications of the dominator tree. diff --git a/lib/cretonne/src/entity/list.rs b/lib/cretonne/src/entity/list.rs index 6c963bc377..ad03dc6c85 100644 --- a/lib/cretonne/src/entity/list.rs +++ b/lib/cretonne/src/entity/list.rs @@ -3,6 +3,7 @@ use entity::EntityRef; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::mem; +use std::vec::Vec; /// A small list of entity references allocated from a pool. /// diff --git a/lib/cretonne/src/entity/map.rs b/lib/cretonne/src/entity/map.rs index 9622f93485..f251c2f831 100644 --- a/lib/cretonne/src/entity/map.rs +++ b/lib/cretonne/src/entity/map.rs @@ -3,6 +3,7 @@ use entity::{EntityRef, Keys}; use std::marker::PhantomData; use std::ops::{Index, IndexMut}; +use std::vec::Vec; /// A mapping `K -> V` for densely indexed entity references. /// diff --git a/lib/cretonne/src/entity/primary.rs b/lib/cretonne/src/entity/primary.rs index 137320f3e5..c06b818355 100644 --- a/lib/cretonne/src/entity/primary.rs +++ b/lib/cretonne/src/entity/primary.rs @@ -2,6 +2,7 @@ use entity::{EntityRef, Keys}; use std::marker::PhantomData; use std::ops::{Index, IndexMut}; +use std::vec::Vec; /// A primary mapping `K -> V` allocating dense entity references. /// diff --git a/lib/cretonne/src/entity/set.rs b/lib/cretonne/src/entity/set.rs index 82dc1384ee..e4acf47723 100644 --- a/lib/cretonne/src/entity/set.rs +++ b/lib/cretonne/src/entity/set.rs @@ -2,6 +2,7 @@ use entity::{EntityRef, Keys}; use std::marker::PhantomData; +use std::vec::Vec; /// A set of `K` for densely indexed entity references. /// diff --git a/lib/cretonne/src/entity/sparse.rs b/lib/cretonne/src/entity/sparse.rs index 82e1b49546..488fd55393 100644 --- a/lib/cretonne/src/entity/sparse.rs +++ b/lib/cretonne/src/entity/sparse.rs @@ -11,6 +11,7 @@ use entity::{EntityRef, EntityMap}; use std::mem; use std::slice; use std::u32; +use std::vec::Vec; /// Trait for extracting keys from values stored in a `SparseMap`. /// diff --git a/lib/cretonne/src/flowgraph.rs b/lib/cretonne/src/flowgraph.rs index fbc74b79d0..dce60162a4 100644 --- a/lib/cretonne/src/flowgraph.rs +++ b/lib/cretonne/src/flowgraph.rs @@ -204,6 +204,7 @@ mod tests { use super::*; use cursor::{Cursor, FuncCursor}; use ir::{Function, InstBuilder, types}; + use std::vec::Vec; #[test] fn empty() { diff --git a/lib/cretonne/src/ir/condcodes.rs b/lib/cretonne/src/ir/condcodes.rs index 4bbf82cb6f..11c438b10a 100644 --- a/lib/cretonne/src/ir/condcodes.rs +++ b/lib/cretonne/src/ir/condcodes.rs @@ -266,6 +266,7 @@ impl FromStr for FloatCC { #[cfg(test)] mod tests { use super::*; + use std::string::ToString; static INT_ALL: [IntCC; 10] = [ IntCC::Equal, diff --git a/lib/cretonne/src/ir/dfg.rs b/lib/cretonne/src/ir/dfg.rs index ccd08f1bb5..344483a6d9 100644 --- a/lib/cretonne/src/ir/dfg.rs +++ b/lib/cretonne/src/ir/dfg.rs @@ -944,6 +944,7 @@ mod tests { use cursor::{Cursor, FuncCursor}; use ir::types; use ir::{Function, Opcode, InstructionData, TrapCode}; + use std::string::ToString; #[test] fn make_inst() { diff --git a/lib/cretonne/src/ir/entities.rs b/lib/cretonne/src/ir/entities.rs index a9e6705d98..1a4e772be4 100644 --- a/lib/cretonne/src/ir/entities.rs +++ b/lib/cretonne/src/ir/entities.rs @@ -262,6 +262,7 @@ impl From for AnyEntity { mod tests { use super::*; use std::u32; + use std::string::ToString; #[test] fn value_with_number() { diff --git a/lib/cretonne/src/ir/extfunc.rs b/lib/cretonne/src/ir/extfunc.rs index b3c3a274e7..f8fe767970 100644 --- a/lib/cretonne/src/ir/extfunc.rs +++ b/lib/cretonne/src/ir/extfunc.rs @@ -10,6 +10,7 @@ use isa::{RegInfo, RegUnit}; use std::cmp; use std::fmt; use std::str::FromStr; +use std::vec::Vec; /// Function signature. /// @@ -378,6 +379,7 @@ impl FromStr for CallConv { mod tests { use super::*; use ir::types::{I32, F32, B8}; + use std::string::ToString; #[test] fn argument_type() { diff --git a/lib/cretonne/src/ir/extname.rs b/lib/cretonne/src/ir/extname.rs index f58f8d24ec..b7bcc7d94f 100644 --- a/lib/cretonne/src/ir/extname.rs +++ b/lib/cretonne/src/ir/extname.rs @@ -122,6 +122,7 @@ impl FromStr for ExternalName { mod tests { use super::ExternalName; use ir::LibCall; + use std::string::ToString; #[test] fn display_testcase() { diff --git a/lib/cretonne/src/ir/immediates.rs b/lib/cretonne/src/ir/immediates.rs index 69c9aab51a..2e6339cc01 100644 --- a/lib/cretonne/src/ir/immediates.rs +++ b/lib/cretonne/src/ir/immediates.rs @@ -652,6 +652,7 @@ mod tests { use std::{f32, f64}; use std::str::FromStr; use std::fmt::Display; + use std::string::ToString; #[test] fn format_imm64() { diff --git a/lib/cretonne/src/ir/instructions.rs b/lib/cretonne/src/ir/instructions.rs index 358c63d942..68ee656e85 100644 --- a/lib/cretonne/src/ir/instructions.rs +++ b/lib/cretonne/src/ir/instructions.rs @@ -9,6 +9,7 @@ use std::fmt::{self, Display, Formatter}; use std::str::FromStr; use std::ops::{Deref, DerefMut}; +use std::vec::Vec; use ir; use ir::{Value, Type, Ebb, JumpTable, SigRef, FuncRef}; @@ -537,6 +538,7 @@ pub enum ResolvedConstraint { #[cfg(test)] mod tests { use super::*; + use std::string::ToString; #[test] fn opcodes() { diff --git a/lib/cretonne/src/ir/jumptable.rs b/lib/cretonne/src/ir/jumptable.rs index 2d09aab4da..1c7bf79157 100644 --- a/lib/cretonne/src/ir/jumptable.rs +++ b/lib/cretonne/src/ir/jumptable.rs @@ -8,6 +8,7 @@ use ir::entities::Ebb; use std::iter; use std::slice; use std::fmt::{self, Display, Formatter}; +use std::vec::Vec; /// Contents of a jump table. /// @@ -141,6 +142,8 @@ mod tests { use super::JumpTableData; use ir::Ebb; use entity::EntityRef; + use std::vec::Vec; + use std::string::ToString; #[test] fn empty() { diff --git a/lib/cretonne/src/ir/layout.rs b/lib/cretonne/src/ir/layout.rs index de117b3ed8..0e6e010e7c 100644 --- a/lib/cretonne/src/ir/layout.rs +++ b/lib/cretonne/src/ir/layout.rs @@ -743,6 +743,7 @@ mod tests { use entity::EntityRef; use ir::{Ebb, Inst, ProgramOrder, SourceLoc}; use std::cmp::Ordering; + use std::vec::Vec; struct LayoutCursor<'f> { /// Borrowed function layout. Public so it can be re-borrowed from this cursor. diff --git a/lib/cretonne/src/ir/libcall.rs b/lib/cretonne/src/ir/libcall.rs index e8c848f71d..85133611be 100644 --- a/lib/cretonne/src/ir/libcall.rs +++ b/lib/cretonne/src/ir/libcall.rs @@ -100,6 +100,7 @@ impl LibCall { #[cfg(test)] mod test { use super::*; + use std::string::ToString; #[test] fn display() { diff --git a/lib/cretonne/src/ir/progpoint.rs b/lib/cretonne/src/ir/progpoint.rs index b7b2994c3b..ce5b108e54 100644 --- a/lib/cretonne/src/ir/progpoint.rs +++ b/lib/cretonne/src/ir/progpoint.rs @@ -148,6 +148,7 @@ mod tests { use super::*; use entity::EntityRef; use ir::{Inst, Ebb}; + use std::string::ToString; #[test] fn convert() { diff --git a/lib/cretonne/src/ir/sourceloc.rs b/lib/cretonne/src/ir/sourceloc.rs index ffcf0db943..36e5247488 100644 --- a/lib/cretonne/src/ir/sourceloc.rs +++ b/lib/cretonne/src/ir/sourceloc.rs @@ -51,6 +51,7 @@ impl fmt::Display for SourceLoc { #[cfg(test)] mod tests { use ir::SourceLoc; + use std::string::ToString; #[test] fn display() { diff --git a/lib/cretonne/src/ir/stackslot.rs b/lib/cretonne/src/ir/stackslot.rs index ebae8e2391..5f73fb4b37 100644 --- a/lib/cretonne/src/ir/stackslot.rs +++ b/lib/cretonne/src/ir/stackslot.rs @@ -10,6 +10,7 @@ use std::cmp; use std::fmt; use std::ops::{Index, IndexMut}; use std::str::FromStr; +use std::vec::Vec; /// The size of an object on the stack, or the size of a stack frame. /// @@ -319,6 +320,7 @@ mod tests { use ir::Function; use ir::types; use super::*; + use std::string::ToString; #[test] fn stack_slot() { diff --git a/lib/cretonne/src/ir/trapcode.rs b/lib/cretonne/src/ir/trapcode.rs index 68b836f309..fe712b7ffa 100644 --- a/lib/cretonne/src/ir/trapcode.rs +++ b/lib/cretonne/src/ir/trapcode.rs @@ -89,6 +89,7 @@ impl FromStr for TrapCode { #[cfg(test)] mod tests { use super::*; + use std::string::ToString; // Everything but user-defined codes. const CODES: [TrapCode; 8] = [ diff --git a/lib/cretonne/src/ir/types.rs b/lib/cretonne/src/ir/types.rs index f8774250ec..07cf97aefa 100644 --- a/lib/cretonne/src/ir/types.rs +++ b/lib/cretonne/src/ir/types.rs @@ -324,6 +324,7 @@ impl Default for Type { #[cfg(test)] mod tests { use super::*; + use std::string::ToString; #[test] fn basic_scalars() { diff --git a/lib/cretonne/src/isa/arm32/mod.rs b/lib/cretonne/src/isa/arm32/mod.rs index c3f295d4fb..02e0d5f1af 100644 --- a/lib/cretonne/src/isa/arm32/mod.rs +++ b/lib/cretonne/src/isa/arm32/mod.rs @@ -14,6 +14,7 @@ use isa::{TargetIsa, RegInfo, RegClass, EncInfo}; use ir; use regalloc; use std::fmt; +use std::boxed::Box; #[allow(dead_code)] struct Isa { diff --git a/lib/cretonne/src/isa/arm32/registers.rs b/lib/cretonne/src/isa/arm32/registers.rs index 7c6ac406e1..e2c4813bdd 100644 --- a/lib/cretonne/src/isa/arm32/registers.rs +++ b/lib/cretonne/src/isa/arm32/registers.rs @@ -8,6 +8,7 @@ include!(concat!(env!("OUT_DIR"), "/registers-arm32.rs")); mod tests { use super::{INFO, GPR, S, D}; use isa::RegUnit; + use std::string::{String, ToString}; #[test] fn unit_encodings() { diff --git a/lib/cretonne/src/isa/arm64/mod.rs b/lib/cretonne/src/isa/arm64/mod.rs index d0644ae2f6..8239cb01e9 100644 --- a/lib/cretonne/src/isa/arm64/mod.rs +++ b/lib/cretonne/src/isa/arm64/mod.rs @@ -14,6 +14,7 @@ use isa::{TargetIsa, RegInfo, RegClass, EncInfo}; use ir; use regalloc; use std::fmt; +use std::boxed::Box; #[allow(dead_code)] struct Isa { diff --git a/lib/cretonne/src/isa/arm64/registers.rs b/lib/cretonne/src/isa/arm64/registers.rs index 62311aaebe..2c1d85e091 100644 --- a/lib/cretonne/src/isa/arm64/registers.rs +++ b/lib/cretonne/src/isa/arm64/registers.rs @@ -8,6 +8,7 @@ include!(concat!(env!("OUT_DIR"), "/registers-arm64.rs")); mod tests { use super::INFO; use isa::RegUnit; + use std::string::{String, ToString}; #[test] fn unit_encodings() { diff --git a/lib/cretonne/src/isa/intel/mod.rs b/lib/cretonne/src/isa/intel/mod.rs index 3f02890a82..578dac2d16 100644 --- a/lib/cretonne/src/isa/intel/mod.rs +++ b/lib/cretonne/src/isa/intel/mod.rs @@ -16,7 +16,7 @@ use regalloc; use result; use timing; use std::fmt; - +use std::boxed::Box; #[allow(dead_code)] struct Isa { diff --git a/lib/cretonne/src/isa/intel/registers.rs b/lib/cretonne/src/isa/intel/registers.rs index c2b96f77d3..c972c10a13 100644 --- a/lib/cretonne/src/isa/intel/registers.rs +++ b/lib/cretonne/src/isa/intel/registers.rs @@ -8,6 +8,7 @@ include!(concat!(env!("OUT_DIR"), "/registers-intel.rs")); mod tests { use super::*; use isa::RegUnit; + use std::string::{String, ToString}; #[test] fn unit_encodings() { diff --git a/lib/cretonne/src/isa/mod.rs b/lib/cretonne/src/isa/mod.rs index 28b297860c..aefe93a05d 100644 --- a/lib/cretonne/src/isa/mod.rs +++ b/lib/cretonne/src/isa/mod.rs @@ -54,6 +54,7 @@ use result; use timing; use isa::enc_tables::Encodings; use std::fmt; +use std::boxed::Box; #[cfg(build_riscv)] mod riscv; diff --git a/lib/cretonne/src/isa/riscv/mod.rs b/lib/cretonne/src/isa/riscv/mod.rs index 2fd0d5cdb9..6fc976686b 100644 --- a/lib/cretonne/src/isa/riscv/mod.rs +++ b/lib/cretonne/src/isa/riscv/mod.rs @@ -14,6 +14,7 @@ use isa::{TargetIsa, RegInfo, RegClass, EncInfo}; use ir; use regalloc; use std::fmt; +use std::boxed::Box; #[allow(dead_code)] struct Isa { @@ -116,6 +117,7 @@ mod tests { use isa; use ir::{DataFlowGraph, InstructionData, Opcode}; use ir::{types, immediates}; + use std::string::{String, ToString}; fn encstr(isa: &isa::TargetIsa, enc: Result) -> String { match enc { diff --git a/lib/cretonne/src/isa/riscv/registers.rs b/lib/cretonne/src/isa/riscv/registers.rs index 3cce8c4988..e2073899b6 100644 --- a/lib/cretonne/src/isa/riscv/registers.rs +++ b/lib/cretonne/src/isa/riscv/registers.rs @@ -8,6 +8,7 @@ include!(concat!(env!("OUT_DIR"), "/registers-riscv.rs")); mod tests { use super::{INFO, GPR, FPR}; use isa::RegUnit; + use std::string::{String, ToString}; #[test] fn unit_encodings() { diff --git a/lib/cretonne/src/isa/riscv/settings.rs b/lib/cretonne/src/isa/riscv/settings.rs index 2aa78fa853..2f0f6822a9 100644 --- a/lib/cretonne/src/isa/riscv/settings.rs +++ b/lib/cretonne/src/isa/riscv/settings.rs @@ -12,6 +12,7 @@ include!(concat!(env!("OUT_DIR"), "/settings-riscv.rs")); mod tests { use super::{builder, Flags}; use settings::{self, Configurable}; + use std::string::ToString; #[test] fn display_default() { diff --git a/lib/cretonne/src/iterators.rs b/lib/cretonne/src/iterators.rs index 08866717e8..0524343028 100644 --- a/lib/cretonne/src/iterators.rs +++ b/lib/cretonne/src/iterators.rs @@ -48,6 +48,8 @@ where #[cfg(test)] mod tests { + use std::vec::Vec; + #[test] fn adjpairs() { use super::IteratorExtras; diff --git a/lib/cretonne/src/legalizer/boundary.rs b/lib/cretonne/src/legalizer/boundary.rs index 29af50b3ad..0c5479650c 100644 --- a/lib/cretonne/src/legalizer/boundary.rs +++ b/lib/cretonne/src/legalizer/boundary.rs @@ -25,6 +25,7 @@ use ir::{Function, DataFlowGraph, Inst, InstBuilder, Ebb, Type, Value, Signature use ir::instructions::CallInfo; use isa::TargetIsa; use legalizer::split::{isplit, vsplit}; +use std::vec::Vec; /// Legalize all the function signatures in `func`. /// diff --git a/lib/cretonne/src/legalizer/split.rs b/lib/cretonne/src/legalizer/split.rs index aafc050c26..cdc60974e0 100644 --- a/lib/cretonne/src/legalizer/split.rs +++ b/lib/cretonne/src/legalizer/split.rs @@ -68,6 +68,7 @@ use cursor::{Cursor, CursorPosition, FuncCursor}; use flowgraph::ControlFlowGraph; use ir::{self, Ebb, Inst, Value, Type, Opcode, ValueDef, InstructionData, InstBuilder}; use std::iter; +use std::vec::Vec; /// Split `value` into two values using the `isplit` semantics. Do this by reusing existing values /// if possible. diff --git a/lib/cretonne/src/licm.rs b/lib/cretonne/src/licm.rs index 1eb035d9bf..e767fc838b 100644 --- a/lib/cretonne/src/licm.rs +++ b/lib/cretonne/src/licm.rs @@ -8,6 +8,7 @@ use dominator_tree::DominatorTree; use entity::{EntityList, ListPool}; use loop_analysis::{Loop, LoopAnalysis}; use timing; +use std::vec::Vec; /// Performs the LICM pass by detecting loops within the CFG and moving /// loop-invariant instructions out of them. diff --git a/lib/cretonne/src/loop_analysis.rs b/lib/cretonne/src/loop_analysis.rs index f6dee54d71..431496b6e4 100644 --- a/lib/cretonne/src/loop_analysis.rs +++ b/lib/cretonne/src/loop_analysis.rs @@ -8,6 +8,7 @@ use flowgraph::ControlFlowGraph; use ir::{Function, Ebb, Layout}; use packed_option::PackedOption; use timing; +use std::vec::Vec; /// A opaque reference to a code loop. #[derive(Copy, Clone, PartialEq, Eq, Hash)] @@ -230,6 +231,7 @@ mod test { use loop_analysis::{Loop, LoopAnalysis}; use flowgraph::ControlFlowGraph; use dominator_tree::DominatorTree; + use std::vec::Vec; #[test] fn nested_loops_detection() { diff --git a/lib/cretonne/src/partition_slice.rs b/lib/cretonne/src/partition_slice.rs index 6f106e5bfc..7a94a9fe0d 100644 --- a/lib/cretonne/src/partition_slice.rs +++ b/lib/cretonne/src/partition_slice.rs @@ -33,6 +33,7 @@ where #[cfg(test)] mod tests { use super::partition_slice; + use std::vec::Vec; fn check(x: &[u32], want: &[u32]) { assert_eq!(x.len(), want.len()); diff --git a/lib/cretonne/src/regalloc/allocatable_set.rs b/lib/cretonne/src/regalloc/allocatable_set.rs index cc72066b5d..e0abf76d37 100644 --- a/lib/cretonne/src/regalloc/allocatable_set.rs +++ b/lib/cretonne/src/regalloc/allocatable_set.rs @@ -221,6 +221,7 @@ impl fmt::Display for AllocatableSet { mod tests { use super::*; use isa::registers::{RegClass, RegClassData}; + use std::vec::Vec; // Register classes for testing. const GPR: RegClass = &RegClassData { diff --git a/lib/cretonne/src/regalloc/coalescing.rs b/lib/cretonne/src/regalloc/coalescing.rs index 3b9d6d03bb..2437fd1a03 100644 --- a/lib/cretonne/src/regalloc/coalescing.rs +++ b/lib/cretonne/src/regalloc/coalescing.rs @@ -18,6 +18,7 @@ use std::cmp; use std::iter; use std::fmt; use std::slice; +use std::vec::Vec; use isa::{TargetIsa, EncInfo}; use timing; diff --git a/lib/cretonne/src/regalloc/diversion.rs b/lib/cretonne/src/regalloc/diversion.rs index 588ad040a5..16eb0e9b50 100644 --- a/lib/cretonne/src/regalloc/diversion.rs +++ b/lib/cretonne/src/regalloc/diversion.rs @@ -11,6 +11,7 @@ use ir::{Value, ValueLoc, ValueLocations, StackSlot}; use ir::{InstructionData, Opcode}; use isa::{RegUnit, RegInfo}; use std::fmt; +use std::vec::Vec; /// A diversion of a value from its original location to a new register or stack location. /// diff --git a/lib/cretonne/src/regalloc/live_value_tracker.rs b/lib/cretonne/src/regalloc/live_value_tracker.rs index f53b5ec8bd..bedd0480e5 100644 --- a/lib/cretonne/src/regalloc/live_value_tracker.rs +++ b/lib/cretonne/src/regalloc/live_value_tracker.rs @@ -13,6 +13,7 @@ use regalloc::affinity::Affinity; use regalloc::liveness::Liveness; use regalloc::liverange::LiveRange; use std::collections::HashMap; +use std::vec::Vec; type ValueList = EntityList; diff --git a/lib/cretonne/src/regalloc/liveness.rs b/lib/cretonne/src/regalloc/liveness.rs index 11e7d8cc3d..9a76cb5899 100644 --- a/lib/cretonne/src/regalloc/liveness.rs +++ b/lib/cretonne/src/regalloc/liveness.rs @@ -184,6 +184,7 @@ use regalloc::affinity::Affinity; use regalloc::liverange::{LiveRange, LiveRangeForest, LiveRangeContext}; use std::mem; use std::ops::Index; +use std::vec::Vec; use timing; /// A set of live ranges, indexed by value number. diff --git a/lib/cretonne/src/regalloc/liverange.rs b/lib/cretonne/src/regalloc/liverange.rs index 9462d32ad0..dbde52f05d 100644 --- a/lib/cretonne/src/regalloc/liverange.rs +++ b/lib/cretonne/src/regalloc/liverange.rs @@ -463,6 +463,7 @@ mod tests { use entity::EntityRef; use ir::{ProgramOrder, ExpandedProgramPoint}; use std::cmp::Ordering; + use std::vec::Vec; // Dummy program order which simply compares indexes. // It is assumed that EBBs have indexes that are multiples of 10, and instructions have indexes diff --git a/lib/cretonne/src/regalloc/pressure.rs b/lib/cretonne/src/regalloc/pressure.rs index c71037efdd..67e0e99b70 100644 --- a/lib/cretonne/src/regalloc/pressure.rs +++ b/lib/cretonne/src/regalloc/pressure.rs @@ -273,6 +273,7 @@ mod tests { use regalloc::AllocatableSet; use std::borrow::Borrow; use super::Pressure; + use std::boxed::Box; // Make an arm32 `TargetIsa`, if possible. fn arm32() -> Option> { diff --git a/lib/cretonne/src/regalloc/reload.rs b/lib/cretonne/src/regalloc/reload.rs index 2967081807..63e7354453 100644 --- a/lib/cretonne/src/regalloc/reload.rs +++ b/lib/cretonne/src/regalloc/reload.rs @@ -21,6 +21,7 @@ use regalloc::live_value_tracker::{LiveValue, LiveValueTracker}; use regalloc::liveness::Liveness; use timing; use topo_order::TopoOrder; +use std::vec::Vec; /// Reusable data structures for the reload pass. pub struct Reload { diff --git a/lib/cretonne/src/regalloc/solver.rs b/lib/cretonne/src/regalloc/solver.rs index 0e68099a67..7824444eec 100644 --- a/lib/cretonne/src/regalloc/solver.rs +++ b/lib/cretonne/src/regalloc/solver.rs @@ -108,6 +108,7 @@ use std::fmt; use std::mem; use super::AllocatableSet; use std::u16; +use std::vec::Vec; /// A variable in the constraint problem. /// @@ -1162,6 +1163,7 @@ mod tests { use isa::{TargetIsa, RegClass, RegUnit, RegInfo}; use regalloc::AllocatableSet; use super::{Solver, Move}; + use std::boxed::Box; // Make an arm32 `TargetIsa`, if possible. fn arm32() -> Option> { diff --git a/lib/cretonne/src/regalloc/spilling.rs b/lib/cretonne/src/regalloc/spilling.rs index 15739cd260..3c3f805cbf 100644 --- a/lib/cretonne/src/regalloc/spilling.rs +++ b/lib/cretonne/src/regalloc/spilling.rs @@ -26,6 +26,7 @@ use regalloc::liveness::Liveness; use regalloc::pressure::Pressure; use regalloc::virtregs::VirtRegs; use std::fmt; +use std::vec::Vec; use timing; use topo_order::TopoOrder; diff --git a/lib/cretonne/src/regalloc/virtregs.rs b/lib/cretonne/src/regalloc/virtregs.rs index fca213a62b..097a66cccd 100644 --- a/lib/cretonne/src/regalloc/virtregs.rs +++ b/lib/cretonne/src/regalloc/virtregs.rs @@ -21,6 +21,7 @@ use packed_option::PackedOption; use ref_slice::ref_slice; use std::cmp::Ordering; use std::fmt; +use std::vec::Vec; /// A virtual register reference. #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] diff --git a/lib/cretonne/src/settings.rs b/lib/cretonne/src/settings.rs index 2cfce65957..20ba99e0d9 100644 --- a/lib/cretonne/src/settings.rs +++ b/lib/cretonne/src/settings.rs @@ -24,6 +24,7 @@ use constant_hash::{probe, simple_hash}; use isa::TargetIsa; use std::fmt; use std::result; +use std::vec::Vec; /// A string-based configurator for settings groups. /// @@ -347,6 +348,7 @@ mod tests { use super::{builder, Flags}; use super::Error::*; use super::Configurable; + use std::string::ToString; #[test] fn display_default() { diff --git a/lib/cretonne/src/simple_gvn.rs b/lib/cretonne/src/simple_gvn.rs index 8642122593..dd0fb3b1aa 100644 --- a/lib/cretonne/src/simple_gvn.rs +++ b/lib/cretonne/src/simple_gvn.rs @@ -6,6 +6,7 @@ use dominator_tree::DominatorTree; use ir::{InstructionData, Function, Inst, Opcode, Type}; use scoped_hash_map::ScopedHashMap; use timing; +use std::vec::Vec; /// Test whether the given opcode is unsafe to even consider for GVN. fn trivially_unsafe_for_gvn(opcode: Opcode) -> bool { diff --git a/lib/cretonne/src/topo_order.rs b/lib/cretonne/src/topo_order.rs index cd783c928a..373ab69e0d 100644 --- a/lib/cretonne/src/topo_order.rs +++ b/lib/cretonne/src/topo_order.rs @@ -3,6 +3,7 @@ use entity::SparseSet; use dominator_tree::DominatorTree; use ir::{Ebb, Layout}; +use std::vec::Vec; /// Present EBBs in a topological order such that all dominating EBBs are guaranteed to be visited /// before the current EBB. diff --git a/lib/cretonne/src/verifier/mod.rs b/lib/cretonne/src/verifier/mod.rs index 33fd3582cb..26eb9a53d9 100644 --- a/lib/cretonne/src/verifier/mod.rs +++ b/lib/cretonne/src/verifier/mod.rs @@ -73,6 +73,8 @@ use std::collections::BTreeSet; use std::error as std_error; use std::fmt::{self, Display, Formatter, Write}; use std::result; +use std::vec::Vec; +use std::string::String; use timing; pub use self::cssa::verify_cssa; diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index 02f0fa3ab2..50acbbf553 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -9,6 +9,7 @@ use isa::{TargetIsa, RegInfo}; use std::fmt::{self, Result, Error, Write}; use std::result; use packed_option::ReservedValue; +use std::string::String; /// Write `func` to `w` as equivalent text. /// Use `isa` to emit ISA-dependent annotations. @@ -466,6 +467,7 @@ impl<'a> fmt::Display for DisplayValues<'a> { mod tests { use ir::{Function, ExternalName, StackSlotData, StackSlotKind}; use ir::types; + use std::string::ToString; #[test] fn basic() { diff --git a/lib/frontend/src/ssa.rs b/lib/frontend/src/ssa.rs index 5b974799bf..bd4a8d89fd 100644 --- a/lib/frontend/src/ssa.rs +++ b/lib/frontend/src/ssa.rs @@ -15,6 +15,7 @@ use std::u32; use cretonne::ir::types::{F32, F64}; use cretonne::ir::immediates::{Ieee32, Ieee64}; use std::mem; +use std::vec::Vec; /// Structure containing the data relevant the construction of SSA for a given function. /// diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index cccbae1368..940725600a 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -34,6 +34,7 @@ use state::{TranslationState, ControlStackFrame}; use std::collections::{HashMap, hash_map}; use environ::{FuncEnvironment, GlobalValue}; use std::{i32, u32}; +use std::vec::Vec; /// Translates wasm operators into Cretonne IL instructions. Returns `true` if it inserted /// a return. diff --git a/lib/wasm/src/environ/dummy.rs b/lib/wasm/src/environ/dummy.rs index 5557d842f6..de941f3b9a 100644 --- a/lib/wasm/src/environ/dummy.rs +++ b/lib/wasm/src/environ/dummy.rs @@ -10,6 +10,8 @@ use cretonne::cursor::FuncCursor; use cretonne::settings; use wasmparser; use std::error::Error; +use std::vec::Vec; +use std::string::String; /// Compute a `ir::ExternalName` for a given wasm function index. fn get_func_name(func_index: FunctionIndex) -> ir::ExternalName { diff --git a/lib/wasm/src/environ/spec.rs b/lib/wasm/src/environ/spec.rs index 7f73c3fc16..41583c1185 100644 --- a/lib/wasm/src/environ/spec.rs +++ b/lib/wasm/src/environ/spec.rs @@ -5,6 +5,8 @@ use cretonne::cursor::FuncCursor; use cretonne::settings::Flags; use translation_utils::{SignatureIndex, FunctionIndex, TableIndex, GlobalIndex, MemoryIndex, Global, Table, Memory}; +use std::vec::Vec; +use std::string::String; /// The value of a WebAssembly global variable. #[derive(Clone, Copy)] diff --git a/lib/wasm/src/module_translator.rs b/lib/wasm/src/module_translator.rs index df640cbb49..bb74db4276 100644 --- a/lib/wasm/src/module_translator.rs +++ b/lib/wasm/src/module_translator.rs @@ -8,6 +8,8 @@ use sections_translator::{SectionParsingError, parse_function_signatures, parse_ parse_elements_section, parse_data_section}; use environ::ModuleEnvironment; +use std::string::String; + /// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cretonne IL /// [`Function`](../cretonne/ir/function/struct.Function.html). /// Returns the functions and also the mappings for imported functions and signature between the diff --git a/lib/wasm/src/sections_translator.rs b/lib/wasm/src/sections_translator.rs index 359510547a..1bf7c9441c 100644 --- a/lib/wasm/src/sections_translator.rs +++ b/lib/wasm/src/sections_translator.rs @@ -16,6 +16,8 @@ use wasmparser::{Parser, ParserState, FuncType, ImportSectionEntryType, External use wasmparser; use std::str::from_utf8; use environ::ModuleEnvironment; +use std::vec::Vec; +use std::string::String; pub enum SectionParsingError { WrongSectionContent(String), diff --git a/lib/wasm/src/state.rs b/lib/wasm/src/state.rs index 1943f31326..5ced6d6056 100644 --- a/lib/wasm/src/state.rs +++ b/lib/wasm/src/state.rs @@ -7,6 +7,7 @@ use cretonne::ir::{self, Ebb, Inst, Value}; use environ::{FuncEnvironment, GlobalValue}; use std::collections::HashMap; use translation_utils::{GlobalIndex, MemoryIndex, SignatureIndex, FunctionIndex}; +use std::vec::Vec; /// A control stack frame can be an `if`, a `block` or a `loop`, each one having the following /// fields: From 03ee00762467ab1adb6924e595f218d4e9a3b951 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 22 Mar 2018 13:10:41 -0700 Subject: [PATCH 35/72] Use clippy (#276) * cton-util: fix some clippy unnecessary pass-by-value warnings * clippy: ignore too many arguments / cyclomatic complexity in module since these functions are taking args coming from the command line, i dont think this is actually a valid lint, morally the arguments are all from one structure * cton-util: take care of remaining clippy warnings * cton-reader: fix all non-suspicious clippy warnings * cton-reader: disable clippy at site of suspicious lint * cton-frontend: disable clippy at the site of an invalid lint * cton-frontend: fix clippy warnings, or ignore benign ones * clippy: ignore the camelcase word WebAssembly in docs * cton-wasm: fix clippy complaints or ignore benign ones * cton-wasm tests: fix clippy complaints * cretonne: starting point turns off all clippy warnings * cretonne: clippy fixes, or lower allow() to source of problem * cretonne: more clippy fixes * cretonne: fix or disable needless_lifetimes lint this linter is buggy when the declared lifetime is used for another type constraint. * cretonne: fix clippy complaint about Pass::NoPass * rustfmt * fix prev minor api changes clippy suggested * add clippy to test-all * cton-filetests: clippy fixes * simplify clippy reporting in test-all * cretonne: document clippy allows better * cretonne: fix some more clippy lints * cretonne: fix clippy lints (mostly doc comments) * cretonne: allow all needless_lifetimes clippy warnings remove overrides at the false positives * rustfmt --- check-clippy.sh | 10 +++ clippy-all.sh | 7 ++ cranelift/clippy.toml | 1 + cranelift/src/cat.rs | 4 +- cranelift/src/compile.rs | 10 +-- cranelift/src/cton-util.rs | 19 +++-- cranelift/src/print_cfg.rs | 6 +- cranelift/src/rsfilecheck.rs | 2 +- cranelift/src/utils.rs | 5 +- cranelift/src/wasm.rs | 58 +++++++------- cranelift/test-all.sh | 8 ++ cranelift/tests/filetests.rs | 2 +- lib/cretonne/meta/gen_settings.py | 2 +- lib/cretonne/src/bforest/path.rs | 9 +-- lib/cretonne/src/bforest/pool.rs | 1 + lib/cretonne/src/binemit/relaxation.rs | 15 ++-- lib/cretonne/src/context.rs | 4 +- lib/cretonne/src/cursor.rs | 3 +- lib/cretonne/src/ir/extname.rs | 2 +- lib/cretonne/src/ir/layout.rs | 4 +- lib/cretonne/src/lib.rs | 33 +++++++- lib/cretonne/src/licm.rs | 1 + lib/cretonne/src/partition_slice.rs | 2 +- lib/cretonne/src/predicates.rs | 2 +- lib/cretonne/src/preopt.rs | 6 +- lib/cretonne/src/print_errors.rs | 4 +- lib/cretonne/src/ref_slice.rs | 2 +- lib/cretonne/src/regalloc/allocatable_set.rs | 6 +- lib/cretonne/src/regalloc/liverange.rs | 38 +++++----- lib/cretonne/src/regalloc/reload.rs | 14 ++-- lib/cretonne/src/regalloc/solver.rs | 1 + lib/cretonne/src/regalloc/virtregs.rs | 8 +- lib/cretonne/src/scoped_hash_map.rs | 2 +- lib/cretonne/src/timing.rs | 12 +-- lib/cretonne/src/verifier/liveness.rs | 34 ++++----- lib/cretonne/src/verifier/mod.rs | 79 ++++++++++---------- lib/filetests/src/concurrent.rs | 2 +- lib/filetests/src/lib.rs | 7 +- lib/filetests/src/runner.rs | 8 +- lib/filetests/src/runone.rs | 2 +- lib/filetests/src/subtest.rs | 2 +- lib/frontend/src/frontend.rs | 4 +- lib/frontend/src/lib.rs | 3 + lib/reader/src/lexer.rs | 2 +- lib/reader/src/lib.rs | 2 +- lib/reader/src/parser.rs | 32 ++++---- lib/reader/src/sourcemap.rs | 2 +- lib/wasm/src/code_translator.rs | 57 +++++++------- lib/wasm/src/environ/dummy.rs | 2 +- lib/wasm/src/lib.rs | 4 + lib/wasm/tests/wasm_testsuite.rs | 10 +-- 51 files changed, 310 insertions(+), 245 deletions(-) create mode 100755 check-clippy.sh create mode 100755 clippy-all.sh create mode 100644 cranelift/clippy.toml diff --git a/check-clippy.sh b/check-clippy.sh new file mode 100755 index 0000000000..20ac595851 --- /dev/null +++ b/check-clippy.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -euo pipefail + +# Usage: check-clippy.sh [--install] + +if cargo install --list | tee /dev/null | grep -q "^clippy v0"; then + exit 0 +else + exit 1 +fi diff --git a/clippy-all.sh b/clippy-all.sh new file mode 100755 index 0000000000..6ec2fd1411 --- /dev/null +++ b/clippy-all.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -euo pipefail + +# Check all sources with clippy. +# In the cton-util crate (root dir) clippy will only work with nightly cargo - +# there is a bug where it will reject the commands passed to it by cargo 0.25.0 +cargo +nightly clippy --all diff --git a/cranelift/clippy.toml b/cranelift/clippy.toml new file mode 100644 index 0000000000..caabf12b77 --- /dev/null +++ b/cranelift/clippy.toml @@ -0,0 +1 @@ +doc-valid-idents = [ "WebAssembly", "NaN", "SetCC" ] diff --git a/cranelift/src/cat.rs b/cranelift/src/cat.rs index 3ae9c843d8..4d3d73ac2c 100644 --- a/cranelift/src/cat.rs +++ b/cranelift/src/cat.rs @@ -7,7 +7,7 @@ use cton_reader::parse_functions; use CommandResult; use utils::read_to_string; -pub fn run(files: Vec) -> CommandResult { +pub fn run(files: &[String]) -> CommandResult { for (i, f) in files.into_iter().enumerate() { if i != 0 { println!(); @@ -17,7 +17,7 @@ pub fn run(files: Vec) -> CommandResult { Ok(()) } -fn cat_one(filename: String) -> CommandResult { +fn cat_one(filename: &str) -> CommandResult { let buffer = read_to_string(&filename).map_err( |e| format!("{}: {}", filename, e), )?; diff --git a/cranelift/src/compile.rs b/cranelift/src/compile.rs index 9047f055fe..a1cc244f5d 100644 --- a/cranelift/src/compile.rs +++ b/cranelift/src/compile.rs @@ -49,23 +49,23 @@ impl binemit::RelocSink for PrintRelocs { pub fn run( files: Vec, flag_print: bool, - flag_set: Vec, - flag_isa: String, + flag_set: &[String], + flag_isa: &str, ) -> Result<(), String> { let parsed = parse_sets_and_isa(flag_set, flag_isa)?; for filename in files { let path = Path::new(&filename); let name = String::from(path.as_os_str().to_string_lossy()); - handle_module(flag_print, path.to_path_buf(), name, parsed.as_fisa())?; + handle_module(flag_print, &path.to_path_buf(), &name, parsed.as_fisa())?; } Ok(()) } fn handle_module( flag_print: bool, - path: PathBuf, - name: String, + path: &PathBuf, + name: &str, fisa: FlagsOrIsa, ) -> Result<(), String> { let buffer = read_to_string(&path).map_err( diff --git a/cranelift/src/cton-util.rs b/cranelift/src/cton-util.rs index 54d7d38d4d..216eae458b 100644 --- a/cranelift/src/cton-util.rs +++ b/cranelift/src/cton-util.rs @@ -86,15 +86,20 @@ fn cton_util() -> CommandResult { // Find the sub-command to execute. let result = if args.cmd_test { - cton_filetests::run(args.flag_verbose, args.arg_file).map(|_time| ()) + cton_filetests::run(args.flag_verbose, &args.arg_file).map(|_time| ()) } else if args.cmd_cat { - cat::run(args.arg_file) + cat::run(&args.arg_file) } else if args.cmd_filecheck { - rsfilecheck::run(args.arg_file, args.flag_verbose) + rsfilecheck::run(&args.arg_file, args.flag_verbose) } else if args.cmd_print_cfg { - print_cfg::run(args.arg_file) + print_cfg::run(&args.arg_file) } else if args.cmd_compile { - compile::run(args.arg_file, args.flag_print, args.flag_set, args.flag_isa) + compile::run( + args.arg_file, + args.flag_print, + &args.flag_set, + &args.flag_isa, + ) } else if args.cmd_wasm { wasm::run( args.arg_file, @@ -102,8 +107,8 @@ fn cton_util() -> CommandResult { args.flag_just_decode, args.flag_check_translation, args.flag_print, - args.flag_set, - args.flag_isa, + &args.flag_set, + &args.flag_isa, args.flag_print_size, ) } else { diff --git a/cranelift/src/print_cfg.rs b/cranelift/src/print_cfg.rs index 08ab439d05..65242cc8f8 100644 --- a/cranelift/src/print_cfg.rs +++ b/cranelift/src/print_cfg.rs @@ -8,7 +8,7 @@ use cretonne::cfg_printer::CFGPrinter; use cton_reader::parse_functions; use utils::read_to_string; -pub fn run(files: Vec) -> CommandResult { +pub fn run(files: &[String]) -> CommandResult { for (i, f) in files.into_iter().enumerate() { if i != 0 { println!(); @@ -18,8 +18,8 @@ pub fn run(files: Vec) -> CommandResult { Ok(()) } -fn print_cfg(filename: String) -> CommandResult { - let buffer = read_to_string(&filename).map_err( +fn print_cfg(filename: &str) -> CommandResult { + let buffer = read_to_string(filename).map_err( |e| format!("{}: {}", filename, e), )?; let items = parse_functions(&buffer).map_err( diff --git a/cranelift/src/rsfilecheck.rs b/cranelift/src/rsfilecheck.rs index 57b9bb9e8f..58b9cb9e53 100644 --- a/cranelift/src/rsfilecheck.rs +++ b/cranelift/src/rsfilecheck.rs @@ -7,7 +7,7 @@ use utils::read_to_string; use filecheck::{CheckerBuilder, Checker, NO_VARIABLES}; use std::io::{self, Read}; -pub fn run(files: Vec, verbose: bool) -> CommandResult { +pub fn run(files: &[String], verbose: bool) -> CommandResult { if files.is_empty() { return Err("No check files".to_string()); } diff --git a/cranelift/src/utils.rs b/cranelift/src/utils.rs index 7e45e99436..dc4f501893 100644 --- a/cranelift/src/utils.rs +++ b/cranelift/src/utils.rs @@ -41,10 +41,7 @@ impl OwnedFlagsOrIsa { } /// Parse "set" and "isa" commands. -pub fn parse_sets_and_isa( - flag_set: Vec, - flag_isa: String, -) -> Result { +pub fn parse_sets_and_isa(flag_set: &[String], flag_isa: &str) -> Result { let mut flag_builder = settings::builder(); parse_options( flag_set.iter().map(|x| x.as_str()), diff --git a/cranelift/src/wasm.rs b/cranelift/src/wasm.rs index 3ab877bf34..efd93df77f 100644 --- a/cranelift/src/wasm.rs +++ b/cranelift/src/wasm.rs @@ -1,6 +1,7 @@ //! CLI tool to use the functions provided by the [cretonne-wasm](../cton_wasm/index.html) crate. //! //! Reads Wasm binary files, translates the functions' code to Cretonne IL. +#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments, cyclomatic_complexity))] use cton_wasm::{translate_module, DummyEnvironment, ModuleEnvironment}; use std::path::PathBuf; @@ -38,8 +39,8 @@ pub fn run( flag_just_decode: bool, flag_check_translation: bool, flag_print: bool, - flag_set: Vec, - flag_isa: String, + flag_set: &[String], + flag_isa: &str, flag_print_size: bool, ) -> Result<(), String> { let parsed = parse_sets_and_isa(flag_set, flag_isa)?; @@ -53,8 +54,8 @@ pub fn run( flag_check_translation, flag_print, flag_print_size, - path.to_path_buf(), - name, + &path.to_path_buf(), + &name, parsed.as_fisa(), )?; } @@ -67,8 +68,8 @@ fn handle_module( flag_check_translation: bool, flag_print: bool, flag_print_size: bool, - path: PathBuf, - name: String, + path: &PathBuf, + name: &str, fisa: FlagsOrIsa, ) -> Result<(), String> { let mut terminal = term::stdout().unwrap(); @@ -153,29 +154,27 @@ fn handle_module( context.func = func.clone(); if flag_check_translation { context.verify(fisa).map_err(|err| { - pretty_verifier_error(&context.func, fisa.isa, err) + pretty_verifier_error(&context.func, fisa.isa, &err) })?; - } else { - if let Some(isa) = fisa.isa { - let compiled_size = context.compile(isa).map_err(|err| { - pretty_error(&context.func, fisa.isa, err) - })?; - if flag_print_size { - println!( - "Function #{} code size: {} bytes", - func_index, - compiled_size - ); - total_module_code_size += compiled_size; - println!( - "Function #{} bytecode size: {} bytes", - func_index, - dummy_environ.func_bytecode_sizes[func_index] - ); - } - } else { - return Err(String::from("compilation requires a target isa")); + } else if let Some(isa) = fisa.isa { + let compiled_size = context.compile(isa).map_err(|err| { + pretty_error(&context.func, fisa.isa, err) + })?; + if flag_print_size { + println!( + "Function #{} code size: {} bytes", + func_index, + compiled_size + ); + total_module_code_size += compiled_size; + println!( + "Function #{} bytecode size: {} bytes", + func_index, + dummy_environ.func_bytecode_sizes[func_index] + ); } + } else { + return Err(String::from("compilation requires a target isa")); } if flag_print { vprintln!(flag_verbose, ""); @@ -194,10 +193,7 @@ fn handle_module( if !flag_check_translation && flag_print_size { println!("Total module code size: {} bytes", total_module_code_size); - let total_bytecode_size = dummy_environ.func_bytecode_sizes.iter().fold( - 0, - |sum, x| sum + x, - ); + let total_bytecode_size: usize = dummy_environ.func_bytecode_sizes.iter().sum(); println!("Total module bytecode size: {} bytes", total_bytecode_size); } diff --git a/cranelift/test-all.sh b/cranelift/test-all.sh index 2b4e2eba01..572bf5de7b 100755 --- a/cranelift/test-all.sh +++ b/cranelift/test-all.sh @@ -55,4 +55,12 @@ cargo test --all --release banner "Rust documentation: $topdir/target/doc/cretonne/index.html" cargo doc +# Run clippy if we have it. +banner "Rust linter" +if $topdir/check-clippy.sh; then + $topdir/clippy-all.sh --write-mode=diff +else + echo "\`cargo +nightly install clippy\` for optional rust linting" +fi + banner "OK" diff --git a/cranelift/tests/filetests.rs b/cranelift/tests/filetests.rs index 97fbeb296f..6b5e392c76 100644 --- a/cranelift/tests/filetests.rs +++ b/cranelift/tests/filetests.rs @@ -3,5 +3,5 @@ extern crate cton_filetests; #[test] fn filetests() { // Run all the filetests in the following directories. - cton_filetests::run(false, vec!["filetests".into(), "docs".into()]).expect("test harness"); + cton_filetests::run(false, &["filetests".into(), "docs".into()]).expect("test harness"); } diff --git a/lib/cretonne/meta/gen_settings.py b/lib/cretonne/meta/gen_settings.py index b5f0de3488..373c9cb1a9 100644 --- a/lib/cretonne/meta/gen_settings.py +++ b/lib/cretonne/meta/gen_settings.py @@ -28,7 +28,7 @@ def gen_enum_types(sgrp, fmt): if not isinstance(setting, EnumSetting): continue ty = camel_case(setting.name) - fmt.doc_comment('Values for {}.'.format(setting)) + fmt.doc_comment('Values for `{}`.'.format(setting)) fmt.line('#[derive(Debug, PartialEq, Eq)]') with fmt.indented('pub enum {} {{'.format(ty), '}'): for v in setting.values: diff --git a/lib/cretonne/src/bforest/path.rs b/lib/cretonne/src/bforest/path.rs index e52c8e897e..34f165d86c 100644 --- a/lib/cretonne/src/bforest/path.rs +++ b/lib/cretonne/src/bforest/path.rs @@ -437,7 +437,7 @@ impl Path { // Discard the root node if it has shrunk to a single sub-tree. let mut ns = 0; - while let &NodeData::Inner { size: 0, ref tree, .. } = &pool[self.node[ns]] { + while let NodeData::Inner { size: 0, ref tree, .. } = pool[self.node[ns]] { ns += 1; self.node[ns] = tree[0]; } @@ -529,12 +529,11 @@ impl Path { // current entry[level] was one off the end of the node, it will now point at a proper // entry. debug_assert!(usize::from(self.entry[level]) < pool[self.node[level]].entries()); - } else { + + } else if usize::from(self.entry[level]) >= pool[self.node[level]].entries() { // There's no right sibling at this level, so the node can't be rebalanced. // Check if we are in an off-the-end position. - if usize::from(self.entry[level]) >= pool[self.node[level]].entries() { - self.size = 0; - } + self.size = 0; } } diff --git a/lib/cretonne/src/bforest/pool.rs b/lib/cretonne/src/bforest/pool.rs index 481271c8db..54a1f81cef 100644 --- a/lib/cretonne/src/bforest/pool.rs +++ b/lib/cretonne/src/bforest/pool.rs @@ -57,6 +57,7 @@ impl NodePool { pub fn free_tree(&mut self, node: Node) { if let NodeData::Inner { size, tree, .. } = self[node] { // Note that we have to capture `tree` by value to avoid borrow checker trouble. + #[cfg_attr(feature = "cargo-clippy", allow(needless_range_loop))] for i in 0..usize::from(size + 1) { // Recursively free sub-trees. This recursion can never be deeper than `MAX_PATH`, // and since most trees have less than a handful of nodes, it is worthwhile to diff --git a/lib/cretonne/src/binemit/relaxation.rs b/lib/cretonne/src/binemit/relaxation.rs index b0bf6196c6..24a78ceebd 100644 --- a/lib/cretonne/src/binemit/relaxation.rs +++ b/lib/cretonne/src/binemit/relaxation.rs @@ -76,14 +76,13 @@ pub fn relax_branches(func: &mut Function, isa: &TargetIsa) -> Result(&self, isa: &TargetIsa) -> verifier::Result { + pub fn verify_locations(&self, isa: &TargetIsa) -> verifier::Result { verifier::verify_locations(isa, &self.func, None) } /// Run the locations verifier only if the `enable_verifier` setting is true. - pub fn verify_locations_if<'a>(&self, isa: &TargetIsa) -> CtonResult { + pub fn verify_locations_if(&self, isa: &TargetIsa) -> CtonResult { if isa.flags().enable_verifier() { self.verify_locations(isa).map_err(Into::into) } else { diff --git a/lib/cretonne/src/cursor.rs b/lib/cretonne/src/cursor.rs index ed2528d5be..42f5e1e741 100644 --- a/lib/cretonne/src/cursor.rs +++ b/lib/cretonne/src/cursor.rs @@ -744,8 +744,9 @@ impl<'c, 'f> ir::InstInserterBase<'c> for &'c mut EncCursor<'f> { if !self.srcloc.is_default() { self.func.srclocs[inst] = self.srcloc; } - // Assign an encoding. + // XXX Is there a way to describe this error to the user? + #[cfg_attr(feature = "cargo-clippy", allow(match_wild_err_arm))] match self.isa.encode( &self.func.dfg, &self.func.dfg[inst], diff --git a/lib/cretonne/src/ir/extname.rs b/lib/cretonne/src/ir/extname.rs index b7bcc7d94f..b37e40086c 100644 --- a/lib/cretonne/src/ir/extname.rs +++ b/lib/cretonne/src/ir/extname.rs @@ -16,7 +16,7 @@ const TESTCASE_NAME_LENGTH: usize = 16; /// to keep track of a sy mbol table. /// /// External names are primarily used as keys by code using Cretonne to map -/// from a cretonne::ir::FuncRef or similar to additional associated data. +/// from a `cretonne::ir::FuncRef` or similar to additional associated data. /// /// External names can also serve as a primitive testing and debugging tool. /// In particular, many `.cton` test files use function names to identify diff --git a/lib/cretonne/src/ir/layout.rs b/lib/cretonne/src/ir/layout.rs index 0e6e010e7c..2f4c378edd 100644 --- a/lib/cretonne/src/ir/layout.rs +++ b/lib/cretonne/src/ir/layout.rs @@ -428,7 +428,7 @@ impl Layout { } /// Return an iterator over all EBBs in layout order. - pub fn ebbs<'f>(&'f self) -> Ebbs<'f> { + pub fn ebbs(&self) -> Ebbs { Ebbs { layout: self, next: self.first_ebb, @@ -611,7 +611,7 @@ impl Layout { } /// Iterate over the instructions in `ebb` in layout order. - pub fn ebb_insts<'f>(&'f self, ebb: Ebb) -> Insts<'f> { + pub fn ebb_insts(&self, ebb: Ebb) -> Insts { Insts { layout: self, head: self.ebbs[ebb].first_inst.into(), diff --git a/lib/cretonne/src/lib.rs b/lib/cretonne/src/lib.rs index f317ed9f85..0f731b9620 100644 --- a/lib/cretonne/src/lib.rs +++ b/lib/cretonne/src/lib.rs @@ -4,13 +4,44 @@ trivial_numeric_casts, unused_extern_crates)] +#![cfg_attr(feature="clippy", + plugin(clippy(conf_file="../../clippy.toml")))] + +#![cfg_attr(feature="cargo-clippy", allow( +// Rustfmt 0.9.0 is at odds with this lint: + block_in_if_condition_stmt, +// Produces only a false positive: + while_let_loop, +// Produces many false positives, but did produce some valid lints, now fixed: + needless_lifetimes, +// Generated code makes some style transgressions, but readability doesn't suffer much: + many_single_char_names, + identity_op, + needless_borrow, + cast_lossless, + unreadable_literal, + assign_op_pattern, + empty_line_after_outer_attr, +// Hard to avoid in generated code: + cyclomatic_complexity, + too_many_arguments, +// Code generator doesn't have a way to collapse identical arms: + match_same_arms, +// These are relatively minor style issues, but would be easy to fix: + new_without_default, + new_without_default_derive, + should_implement_trait, + redundant_field_names, + useless_let_if_seq, + len_without_is_empty))] + pub use context::Context; pub use legalizer::legalize_function; pub use verifier::verify_function; pub use write::write_function; /// Version number of the cretonne crate. -pub const VERSION: &'static str = env!("CARGO_PKG_VERSION"); +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); #[macro_use] pub mod dbg; diff --git a/lib/cretonne/src/licm.rs b/lib/cretonne/src/licm.rs index e767fc838b..7887a39e4e 100644 --- a/lib/cretonne/src/licm.rs +++ b/lib/cretonne/src/licm.rs @@ -150,6 +150,7 @@ fn remove_loop_invariant_instructions( loop_values.insert(*val); } pos.goto_top(*ebb); + #[cfg_attr(feature = "cargo-clippy", allow(block_in_if_condition_stmt))] while let Some(inst) = pos.next_inst() { if pos.func.dfg.has_results(inst) && pos.func.dfg.inst_args(inst).into_iter().all(|arg| { diff --git a/lib/cretonne/src/partition_slice.rs b/lib/cretonne/src/partition_slice.rs index 7a94a9fe0d..dd0aff5da6 100644 --- a/lib/cretonne/src/partition_slice.rs +++ b/lib/cretonne/src/partition_slice.rs @@ -6,7 +6,7 @@ /// The order of elements is not preserved, unless the slice is already partitioned. /// /// Returns the number of elements where `p(t)` is true. -pub fn partition_slice<'a, T: 'a, F>(s: &'a mut [T], mut p: F) -> usize +pub fn partition_slice(s: &mut [T], mut p: F) -> usize where F: FnMut(&T) -> bool, { diff --git a/lib/cretonne/src/predicates.rs b/lib/cretonne/src/predicates.rs index 63d2e79af3..618369291d 100644 --- a/lib/cretonne/src/predicates.rs +++ b/lib/cretonne/src/predicates.rs @@ -7,7 +7,7 @@ //! bound is implemented by all the native integer types as well as `Imm64`. //! //! Some of these predicates may be unused in certain ISA configurations, so we suppress the -//! dead_code warning. +//! dead code warning. /// Check that `x` is the same as `y`. #[allow(dead_code)] diff --git a/lib/cretonne/src/preopt.rs b/lib/cretonne/src/preopt.rs index f5e8b3a7fe..698631316e 100644 --- a/lib/cretonne/src/preopt.rs +++ b/lib/cretonne/src/preopt.rs @@ -114,7 +114,7 @@ fn package_up_divrem_info( fn get_div_info(inst: Inst, dfg: &DataFlowGraph) -> Option { let idata: &InstructionData = &dfg[inst]; - if let &InstructionData::BinaryImm { opcode, arg, imm } = idata { + if let InstructionData::BinaryImm { opcode, arg, imm } = *idata { let (isSigned, isRem) = match opcode { Opcode::UdivImm => (false, false), Opcode::UremImm => (false, true), @@ -132,7 +132,7 @@ fn get_div_info(inst: Inst, dfg: &DataFlowGraph) -> Option { // that some previous constant propagation pass has pushed all such // immediates to their use points, creating BinaryImm instructions // instead? For now we take the conservative approach. - if let &InstructionData::Binary { opcode, args } = idata { + if let InstructionData::Binary { opcode, args } = *idata { let (isSigned, isRem) = match opcode { Opcode::Udiv => (false, false), Opcode::Urem => (false, true), @@ -484,7 +484,7 @@ fn get_const(value: Value, dfg: &DataFlowGraph) -> Option { match dfg.value_def(value) { ValueDef::Result(definingInst, resultNo) => { let definingIData: &InstructionData = &dfg[definingInst]; - if let &InstructionData::UnaryImm { opcode, imm } = definingIData { + if let InstructionData::UnaryImm { opcode, imm } = *definingIData { if opcode == Opcode::Iconst && resultNo == 0 { return Some(imm.into()); } diff --git a/lib/cretonne/src/print_errors.rs b/lib/cretonne/src/print_errors.rs index abd22f3e6b..1bc61cfb59 100644 --- a/lib/cretonne/src/print_errors.rs +++ b/lib/cretonne/src/print_errors.rs @@ -10,7 +10,7 @@ use std::fmt::Write; pub fn pretty_verifier_error( func: &ir::Function, isa: Option<&TargetIsa>, - err: verifier::Error, + err: &verifier::Error, ) -> String { let mut msg = err.to_string(); match err.location { @@ -26,7 +26,7 @@ pub fn pretty_verifier_error( /// Pretty-print a Cretonne error. pub fn pretty_error(func: &ir::Function, isa: Option<&TargetIsa>, err: CtonError) -> String { if let CtonError::Verifier(e) = err { - pretty_verifier_error(func, isa, e) + pretty_verifier_error(func, isa, &e) } else { err.to_string() } diff --git a/lib/cretonne/src/ref_slice.rs b/lib/cretonne/src/ref_slice.rs index b9dbd55dd1..251b601d00 100644 --- a/lib/cretonne/src/ref_slice.rs +++ b/lib/cretonne/src/ref_slice.rs @@ -1,6 +1,6 @@ //! Functions for converting a reference into a singleton slice. //! -//! See also the ref_slice crate on crates.io. +//! See also the [`ref_slice` crate](https://crates.io/crates/ref_slice). //! //! We define the functions here to avoid external dependencies, and to ensure that they are //! inlined in this crate. diff --git a/lib/cretonne/src/regalloc/allocatable_set.rs b/lib/cretonne/src/regalloc/allocatable_set.rs index e0abf76d37..8c40809310 100644 --- a/lib/cretonne/src/regalloc/allocatable_set.rs +++ b/lib/cretonne/src/regalloc/allocatable_set.rs @@ -197,9 +197,9 @@ impl<'a> fmt::Display for DisplayAllocatableSet<'a> { "{}", bank.names .get(offset as usize) - .and_then(|name| name.chars().skip(1).next()) - .unwrap_or( - char::from_digit(u32::from(offset % 10), 10).unwrap(), + .and_then(|name| name.chars().nth(1)) + .unwrap_or_else( + || char::from_digit(u32::from(offset % 10), 10).unwrap(), ) )?; } diff --git a/lib/cretonne/src/regalloc/liverange.rs b/lib/cretonne/src/regalloc/liverange.rs index dbde52f05d..2d66b010f7 100644 --- a/lib/cretonne/src/regalloc/liverange.rs +++ b/lib/cretonne/src/regalloc/liverange.rs @@ -276,33 +276,31 @@ impl GenLiveRange { } else { return first_time_livein; } - } else { + } else if let Some((_, end)) = c.prev() { // There's no interval beginning at `ebb`, but we could still be live-in at `ebb` with // a coalesced interval that begins before and ends after. - if let Some((_, end)) = c.prev() { - if order.cmp(end, ebb) == Ordering::Greater { - // Yep, the previous interval overlaps `ebb`. - first_time_livein = false; - if order.cmp(end, to) == Ordering::Less { - *c.value_mut().unwrap() = to; - } else { - return first_time_livein; - } + if order.cmp(end, ebb) == Ordering::Greater { + // Yep, the previous interval overlaps `ebb`. + first_time_livein = false; + if order.cmp(end, to) == Ordering::Less { + *c.value_mut().unwrap() = to; } else { - first_time_livein = true; - // The current interval does not overlap `ebb`, but it may still be possible to - // coalesce with it. - if order.is_ebb_gap(end, ebb) { - *c.value_mut().unwrap() = to; - } else { - c.insert(ebb, to); - } + return first_time_livein; } } else { - // There is no existing interval before `ebb`. first_time_livein = true; - c.insert(ebb, to); + // The current interval does not overlap `ebb`, but it may still be possible to + // coalesce with it. + if order.is_ebb_gap(end, ebb) { + *c.value_mut().unwrap() = to; + } else { + c.insert(ebb, to); + } } + } else { + // There is no existing interval before `ebb`. + first_time_livein = true; + c.insert(ebb, to); } // Now `c` to left pointing at an interval that ends in `to`. diff --git a/lib/cretonne/src/regalloc/reload.rs b/lib/cretonne/src/regalloc/reload.rs index 63e7354453..106830bc19 100644 --- a/lib/cretonne/src/regalloc/reload.rs +++ b/lib/cretonne/src/regalloc/reload.rs @@ -306,14 +306,12 @@ impl<'a> Context<'a> { let args = self.cur.func.dfg.inst_args(inst); for (argidx, (op, &arg)) in constraints.ins.iter().zip(args).enumerate() { - if op.kind != ConstraintKind::Stack { - if self.liveness[arg].affinity.is_stack() { - self.candidates.push(ReloadCandidate { - argidx, - value: arg, - regclass: op.regclass, - }) - } + if op.kind != ConstraintKind::Stack && self.liveness[arg].affinity.is_stack() { + self.candidates.push(ReloadCandidate { + argidx, + value: arg, + regclass: op.regclass, + }) } } diff --git a/lib/cretonne/src/regalloc/solver.rs b/lib/cretonne/src/regalloc/solver.rs index 7824444eec..3559623ae4 100644 --- a/lib/cretonne/src/regalloc/solver.rs +++ b/lib/cretonne/src/regalloc/solver.rs @@ -299,6 +299,7 @@ impl Move { } /// Get the "from" register and register class, if possible. + #[cfg_attr(feature = "cargo-clippy", allow(wrong_self_convention))] fn from_reg(&self) -> Option<(RegClass, RegUnit)> { match *self { Move::Reg { rc, from, .. } | diff --git a/lib/cretonne/src/regalloc/virtregs.rs b/lib/cretonne/src/regalloc/virtregs.rs index 097a66cccd..8069a0b69b 100644 --- a/lib/cretonne/src/regalloc/virtregs.rs +++ b/lib/cretonne/src/regalloc/virtregs.rs @@ -101,8 +101,10 @@ impl VirtRegs { where 'a: 'b, { - self.get(*value).map(|vr| self.values(vr)).unwrap_or( - ref_slice(value), + self.get(*value).map(|vr| self.values(vr)).unwrap_or_else( + || { + ref_slice(value) + }, ) } @@ -371,7 +373,7 @@ impl VirtRegs { let vreg = self.get(leader).unwrap_or_else(|| { // Allocate a vreg for `leader`, but leave it empty. let vr = self.alloc(); - if let &mut Some(ref mut vec) = &mut new_vregs { + if let Some(ref mut vec) = new_vregs { vec.push(vr); } self.value_vregs[leader] = vr.into(); diff --git a/lib/cretonne/src/scoped_hash_map.rs b/lib/cretonne/src/scoped_hash_map.rs index d5acf2ecb6..ded42672ab 100644 --- a/lib/cretonne/src/scoped_hash_map.rs +++ b/lib/cretonne/src/scoped_hash_map.rs @@ -1,4 +1,4 @@ -//! ScopedHashMap +//! `ScopedHashMap` //! //! This module defines a struct `ScopedHashMap` which defines a `HashMap`-like //! container that has a concept of scopes that can be entered and exited, such that diff --git a/lib/cretonne/src/timing.rs b/lib/cretonne/src/timing.rs index 7a7572f5c7..647e0a07aa 100644 --- a/lib/cretonne/src/timing.rs +++ b/lib/cretonne/src/timing.rs @@ -11,7 +11,7 @@ pub use self::details::{TimingToken, PassTimes, take_current, add_to_current}; // // This macro defines: // -// - A C-style enum containing all the pass names and a `NoPass` variant. +// - A C-style enum containing all the pass names and a `None` variant. // - A usize constant with the number of defined passes. // - A const array of pass descriptions. // - A public function per pass used to start the timing of that pass. @@ -21,9 +21,9 @@ macro_rules! define_passes { } => { #[allow(non_camel_case_types)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] - enum $enum { $($pass,)+ NoPass } + enum $enum { $($pass,)+ None} - const $num_passes: usize = $enum::NoPass as usize; + const $num_passes: usize = $enum::None as usize; const $descriptions: [&str; $num_passes] = [ $($desc),+ ]; @@ -164,7 +164,7 @@ mod details { /// Information about passes in a single thread. thread_local!{ - static CURRENT_PASS: Cell = Cell::new(Pass::NoPass); + static CURRENT_PASS: Cell = Cell::new(Pass::None); static PASS_TIME: RefCell = RefCell::new(Default::default()); } @@ -204,7 +204,7 @@ mod details { } /// Add `timings` to the accumulated timings for the current thread. - pub fn add_to_current(times: PassTimes) { + pub fn add_to_current(times: &PassTimes) { PASS_TIME.with(|rc| for (a, b) in rc.borrow_mut().pass.iter_mut().zip( ×.pass, ) @@ -221,7 +221,7 @@ mod test { #[test] fn display() { - assert_eq!(Pass::NoPass.to_string(), ""); + assert_eq!(Pass::None.to_string(), ""); assert_eq!(Pass::regalloc.to_string(), "Register allocation"); } } diff --git a/lib/cretonne/src/verifier/liveness.rs b/lib/cretonne/src/verifier/liveness.rs index 95691625c8..8f971e2d05 100644 --- a/lib/cretonne/src/verifier/liveness.rs +++ b/lib/cretonne/src/verifier/liveness.rs @@ -86,16 +86,14 @@ impl<'a> LivenessVerifier<'a> { self.isa.encoding_info().display(encoding) ); } - } else { + } else if !lr.affinity.is_none() { // A non-encoded instruction can only define ghost values. - if !lr.affinity.is_none() { - return err!( - inst, - "{} is a real {} value defined by a ghost instruction", - val, - lr.affinity.display(&self.isa.register_info()) - ); - } + return err!( + inst, + "{} is a real {} value defined by a ghost instruction", + val, + lr.affinity.display(&self.isa.register_info()) + ); } } @@ -109,16 +107,14 @@ impl<'a> LivenessVerifier<'a> { return err!(inst, "{} is not live at this use", val); } - if encoding.is_legal() { - // A legal instruction is not allowed to depend on ghost values. - if lr.affinity.is_none() { - return err!( - inst, - "{} is a ghost value used by a real [{}] instruction", - val, - self.isa.encoding_info().display(encoding) - ); - } + // A legal instruction is not allowed to depend on ghost values. + if encoding.is_legal() && lr.affinity.is_none() { + return err!( + inst, + "{} is a ghost value used by a real [{}] instruction", + val, + self.isa.encoding_info().display(encoding) + ); } } } diff --git a/lib/cretonne/src/verifier/mod.rs b/lib/cretonne/src/verifier/mod.rs index 26eb9a53d9..b19510a485 100644 --- a/lib/cretonne/src/verifier/mod.rs +++ b/lib/cretonne/src/verifier/mod.rs @@ -34,7 +34,7 @@ //! For polymorphic opcodes, determine the controlling type variable first. //! - Branches and jumps must pass arguments to destination EBBs that match the //! expected types exactly. The number of arguments must match. -//! - All EBBs in a jump_table must take no arguments. +//! - All EBBs in a jump table must take no arguments. //! - Function calls are type checked against their signature. //! - The entry block must take arguments that match the signature of the current //! function. @@ -871,50 +871,47 @@ impl<'a> Verifier<'a> { // Check special-purpose type constraints that can't be expressed in the normal opcode // constraints. fn typecheck_special(&self, inst: Inst, ctrl_type: Type) -> Result { - match self.func.dfg[inst] { - ir::InstructionData::Unary { opcode, arg } => { - let arg_type = self.func.dfg.value_type(arg); - match opcode { - Opcode::Bextend | Opcode::Uextend | Opcode::Sextend | Opcode::Fpromote => { - if arg_type.lane_count() != ctrl_type.lane_count() { - return err!( - inst, - "input {} and output {} must have same number of lanes", - arg_type, - ctrl_type - ); - } - if arg_type.lane_bits() >= ctrl_type.lane_bits() { - return err!( - inst, - "input {} must be smaller than output {}", - arg_type, - ctrl_type - ); - } + if let ir::InstructionData::Unary { opcode, arg } = self.func.dfg[inst] { + let arg_type = self.func.dfg.value_type(arg); + match opcode { + Opcode::Bextend | Opcode::Uextend | Opcode::Sextend | Opcode::Fpromote => { + if arg_type.lane_count() != ctrl_type.lane_count() { + return err!( + inst, + "input {} and output {} must have same number of lanes", + arg_type, + ctrl_type + ); } - Opcode::Breduce | Opcode::Ireduce | Opcode::Fdemote => { - if arg_type.lane_count() != ctrl_type.lane_count() { - return err!( - inst, - "input {} and output {} must have same number of lanes", - arg_type, - ctrl_type - ); - } - if arg_type.lane_bits() <= ctrl_type.lane_bits() { - return err!( - inst, - "input {} must be larger than output {}", - arg_type, - ctrl_type - ); - } + if arg_type.lane_bits() >= ctrl_type.lane_bits() { + return err!( + inst, + "input {} must be smaller than output {}", + arg_type, + ctrl_type + ); } - _ => {} } + Opcode::Breduce | Opcode::Ireduce | Opcode::Fdemote => { + if arg_type.lane_count() != ctrl_type.lane_count() { + return err!( + inst, + "input {} and output {} must have same number of lanes", + arg_type, + ctrl_type + ); + } + if arg_type.lane_bits() <= ctrl_type.lane_bits() { + return err!( + inst, + "input {} must be larger than output {}", + arg_type, + ctrl_type + ); + } + } + _ => {} } - _ => {} } Ok(()) } diff --git a/lib/filetests/src/concurrent.rs b/lib/filetests/src/concurrent.rs index 6a18bb2390..1ddf643258 100644 --- a/lib/filetests/src/concurrent.rs +++ b/lib/filetests/src/concurrent.rs @@ -70,7 +70,7 @@ impl ConcurrentRunner { assert!(self.request_tx.is_none(), "must shutdown before join"); for h in self.handles.drain(..) { match h.join() { - Ok(t) => timing::add_to_current(t), + Ok(t) => timing::add_to_current(&t), Err(e) => println!("worker panicked: {:?}", e), } } diff --git a/lib/filetests/src/lib.rs b/lib/filetests/src/lib.rs index 36d321358c..a6a43d4437 100644 --- a/lib/filetests/src/lib.rs +++ b/lib/filetests/src/lib.rs @@ -3,6 +3,11 @@ //! This crate contains the main test driver as well as implementations of the //! available filetest commands. +#![cfg_attr(feature="cargo-clippy", allow( + type_complexity, +// Rustfmt 0.9.0 is at odds with this lint: + block_in_if_condition_stmt))] + #[macro_use(dbg)] extern crate cretonne; extern crate cton_reader; @@ -44,7 +49,7 @@ type TestResult = Result; /// Directories are scanned recursively for test cases ending in `.cton`. These test cases are /// executed on background threads. /// -pub fn run(verbose: bool, files: Vec) -> TestResult { +pub fn run(verbose: bool, files: &[String]) -> TestResult { let mut runner = TestRunner::new(verbose); for path in files.iter().map(Path::new) { diff --git a/lib/filetests/src/runner.rs b/lib/filetests/src/runner.rs index ff40ed81e2..49078cff8e 100644 --- a/lib/filetests/src/runner.rs +++ b/lib/filetests/src/runner.rs @@ -45,7 +45,7 @@ impl Display for QueueEntry { f, "{}.{:03} {}", dur.as_secs(), - dur.subsec_nanos() / 1000000, + dur.subsec_nanos() / 1_000_000, p ) } @@ -135,7 +135,7 @@ impl TestRunner { // This lets us skip spurious extensionless files without statting everything // needlessly. if !dir.is_file() { - self.path_error(dir, err); + self.path_error(&dir, &err); } } Ok(entries) => { @@ -149,7 +149,7 @@ impl TestRunner { // libstd/sys/unix/fs.rs seems to suggest that breaking now would // be a good idea, or the iterator could keep returning the same // error forever. - self.path_error(dir, err); + self.path_error(&dir, &err); break; } Ok(entry) => { @@ -172,7 +172,7 @@ impl TestRunner { } /// Report an error related to a path. - fn path_error(&mut self, path: PathBuf, err: E) { + fn path_error(&mut self, path: &PathBuf, err: &E) { self.errors += 1; println!("{}: {}", path.to_string_lossy(), err); } diff --git a/lib/filetests/src/runone.rs b/lib/filetests/src/runone.rs index fcc01e4f95..dab44ff920 100644 --- a/lib/filetests/src/runone.rs +++ b/lib/filetests/src/runone.rs @@ -132,7 +132,7 @@ fn run_one_test<'a>( if !context.verified && test.needs_verifier() { verify_function(&func, context.flags_or_isa()).map_err( |e| { - pretty_verifier_error(&func, isa, e) + pretty_verifier_error(&func, isa, &e) }, )?; context.verified = true; diff --git a/lib/filetests/src/subtest.rs b/lib/filetests/src/subtest.rs index a9cf657d8e..39812ed228 100644 --- a/lib/filetests/src/subtest.rs +++ b/lib/filetests/src/subtest.rs @@ -1,4 +1,4 @@ -//! SubTest trait. +//! `SubTest` trait. use std::result; use std::borrow::Cow; diff --git a/lib/frontend/src/frontend.rs b/lib/frontend/src/frontend.rs index de89698f15..8cd2c5cc82 100644 --- a/lib/frontend/src/frontend.rs +++ b/lib/frontend/src/frontend.rs @@ -400,7 +400,7 @@ where /// /// This can be used to insert SSA code that doesn't need to access locals and that doesn't /// need to know about `FunctionBuilder` at all. - pub fn cursor<'f>(&'f mut self) -> FuncCursor<'f> { + pub fn cursor(&mut self) -> FuncCursor { self.ensure_inserted_ebb(); FuncCursor::new(self.func) .with_srcloc(self.srcloc) @@ -548,6 +548,8 @@ where /// Returns a displayable object for the function as it is. /// /// Useful for debug purposes. Use it with `None` for standard printing. + // Clippy thinks the lifetime that follows is needless, but rustc needs it + #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))] pub fn display<'b, I: Into>>(&'b self, isa: I) -> DisplayFunction { self.func.display(isa) } diff --git a/lib/frontend/src/lib.rs b/lib/frontend/src/lib.rs index f5b4514e56..1f2c2e0db8 100644 --- a/lib/frontend/src/lib.rs +++ b/lib/frontend/src/lib.rs @@ -131,6 +131,9 @@ trivial_numeric_casts, unused_extern_crates)] +#![cfg_attr(feature="cargo-clippy", + allow(new_without_default, redundant_field_names))] + extern crate cretonne; pub use frontend::{FunctionBuilderContext, FunctionBuilder}; diff --git a/lib/reader/src/lexer.rs b/lib/reader/src/lexer.rs index ca315d3b58..4b1a952d1b 100644 --- a/lib/reader/src/lexer.rs +++ b/lib/reader/src/lexer.rs @@ -53,7 +53,7 @@ pub struct LocatedToken<'a> { } /// Wrap up a `Token` with the given location. -fn token<'a>(token: Token<'a>, loc: Location) -> Result, LocatedError> { +fn token(token: Token, loc: Location) -> Result { Ok(LocatedToken { token, location: loc, diff --git a/lib/reader/src/lib.rs b/lib/reader/src/lib.rs index 85ea048950..d6c23cfa81 100644 --- a/lib/reader/src/lib.rs +++ b/lib/reader/src/lib.rs @@ -1,6 +1,6 @@ //! Cretonne file reader library. //! -//! The cton_reader library supports reading .cton files. This functionality is needed for testing +//! The `cton_reader` library supports reading .cton files. This functionality is needed for testing //! Cretonne, but is not essential for a JIT compiler. #![deny(missing_docs, diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index a9568942ed..2e320b31a7 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -37,7 +37,7 @@ pub fn parse_functions(text: &str) -> Result> { /// Parse the entire `text` as a test case file. /// /// The returned `TestFile` contains direct references to substrings of `text`. -pub fn parse_test<'a>(text: &'a str) -> Result> { +pub fn parse_test(text: &str) -> Result { let _tt = timing::parse_text(); let mut parser = Parser::new(text); // Gather the preamble comments. @@ -277,6 +277,10 @@ impl<'a> Parser<'a> { // Get the current lookahead token, after making sure there is one. fn token(&mut self) -> Option> { + // clippy says self.lookahead is immutable so this loop is either infinite or never + // running. I don't think this is true - self.lookahead is mutated in the loop body - so + // maybe this is a clippy bug? Either way, disable clippy for this. + #[cfg_attr(feature = "cargo-clippy", allow(while_immutable_condition))] while self.lookahead == None { match self.lex.next() { Some(Ok(lexer::LocatedToken { token, location })) => { @@ -957,7 +961,7 @@ impl<'a> Parser<'a> { isa.register_info() .parse_regunit(name) .map(ArgumentLoc::Reg) - .ok_or(self.error("invalid register name")) + .ok_or_else(|| self.error("invalid register name")) } else { err!(self.loc, "argument location requires exactly one isa") } @@ -1392,12 +1396,12 @@ impl<'a> Parser<'a> { match self.token() { Some(Token::Arrow) => { self.consume(); - self.parse_value_alias(results, ctx)?; + self.parse_value_alias(&results, ctx)?; } Some(Token::Equal) => { self.consume(); self.parse_instruction( - results, + &results, srcloc, encoding, result_locations, @@ -1408,7 +1412,7 @@ impl<'a> Parser<'a> { _ if !results.is_empty() => return err!(self.loc, "expected -> or ="), _ => { self.parse_instruction( - results, + &results, srcloc, encoding, result_locations, @@ -1512,7 +1516,7 @@ impl<'a> Parser<'a> { isa.register_info() .parse_regunit(name) .map(ValueLoc::Reg) - .ok_or(self.error("invalid register value location")) + .ok_or_else(|| self.error("invalid register value location")) } else { err!(self.loc, "value location requires exactly one isa") } @@ -1601,7 +1605,7 @@ impl<'a> Parser<'a> { // // value_alias ::= [inst-results] "->" Value(v) // - fn parse_value_alias(&mut self, results: Vec, ctx: &mut Context) -> Result<()> { + fn parse_value_alias(&mut self, results: &[Value], ctx: &mut Context) -> Result<()> { if results.len() != 1 { return err!(self.loc, "wrong number of aliases"); } @@ -1621,7 +1625,7 @@ impl<'a> Parser<'a> { // fn parse_instruction( &mut self, - results: Vec, + results: &[Value], srcloc: ir::SourceLoc, encoding: Option, result_locations: Option>, @@ -1629,7 +1633,7 @@ impl<'a> Parser<'a> { ebb: Ebb, ) -> Result<()> { // Define the result values. - for val in &results { + for val in results { ctx.map.def_value(*val, &self.loc)?; } @@ -1674,7 +1678,7 @@ impl<'a> Parser<'a> { let num_results = ctx.function.dfg.make_inst_results_for_parser( inst, ctrl_typevar, - &results, + results, ); ctx.function.layout.append_inst(inst, ebb); ctx.map.def_entity(inst.into(), &opcode_loc).expect( @@ -1784,11 +1788,9 @@ impl<'a> Parser<'a> { opcode ); } - } else { - // Treat it as a syntax error to speficy a typevar on a non-polymorphic opcode. - if ctrl_type != VOID { - return err!(self.loc, "{} does not take a typevar", opcode); - } + // Treat it as a syntax error to speficy a typevar on a non-polymorphic opcode. + } else if ctrl_type != VOID { + return err!(self.loc, "{} does not take a typevar", opcode); } Ok(ctrl_type) diff --git a/lib/reader/src/sourcemap.rs b/lib/reader/src/sourcemap.rs index 704c097855..36fb954fd9 100644 --- a/lib/reader/src/sourcemap.rs +++ b/lib/reader/src/sourcemap.rs @@ -13,7 +13,7 @@ use lexer::split_entity_name; use std::collections::HashMap; /// Mapping from entity names to source locations. -#[derive(Debug)] +#[derive(Debug, Default)] pub struct SourceMap { // Store locations for entities, including instructions. locations: HashMap, diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index 940725600a..42d232e6f5 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -36,6 +36,8 @@ use environ::{FuncEnvironment, GlobalValue}; use std::{i32, u32}; use std::vec::Vec; +// Clippy warns about "flags: _" but its important to document that the flags field is ignored +#[cfg_attr(feature = "cargo-clippy", allow(unneeded_field_pattern))] /// Translates wasm operators into Cretonne IL instructions. Returns `true` if it inserted /// a return. pub fn translate_operator( @@ -45,7 +47,7 @@ pub fn translate_operator( environ: &mut FE, ) { if !state.reachable { - return translate_unreachable_operator(op, builder, state); + return translate_unreachable_operator(&op, builder, state); } // This big match treats all Wasm code operators. @@ -198,9 +200,8 @@ pub fn translate_operator( builder.switch_to_block(frame.following_code()); builder.seal_block(frame.following_code()); // If it is a loop we also have to seal the body loop block - match frame { - ControlStackFrame::Loop { header, .. } => builder.seal_block(header), - _ => {} + if let ControlStackFrame::Loop { header, .. } = frame { + builder.seal_block(header) } state.stack.truncate(frame.original_stack_size()); state.stack.extend_from_slice( @@ -857,15 +858,17 @@ pub fn translate_operator( } } +// Clippy warns us of some fields we are deliberately ignoring +#[cfg_attr(feature = "cargo-clippy", allow(unneeded_field_pattern))] /// Deals with a Wasm instruction located in an unreachable portion of the code. Most of them /// are dropped but special ones like `End` or `Else` signal the potential end of the unreachable /// portion so the translation state muts be updated accordingly. fn translate_unreachable_operator( - op: Operator, + op: &Operator, builder: &mut FunctionBuilder, state: &mut TranslationState, ) { - match op { + match *op { Operator::If { ty: _ } => { // Push a placeholder control stack entry. The if isn't reachable, // so we don't have any branches anywhere. @@ -877,27 +880,25 @@ fn translate_unreachable_operator( } Operator::Else => { let i = state.control_stack.len() - 1; - match state.control_stack[i] { - ControlStackFrame::If { - branch_inst, - ref mut reachable_from_top, - .. - } => { - if *reachable_from_top { - // We have a branch from the top of the if to the else. - state.reachable = true; - // And because there's an else, there can no longer be a - // branch from the top directly to the end. - *reachable_from_top = false; + if let ControlStackFrame::If { + branch_inst, + ref mut reachable_from_top, + .. + } = state.control_stack[i] + { + if *reachable_from_top { + // We have a branch from the top of the if to the else. + state.reachable = true; + // And because there's an else, there can no longer be a + // branch from the top directly to the end. + *reachable_from_top = false; - // We change the target of the branch instruction - let else_ebb = builder.create_ebb(); - builder.change_jump_destination(branch_inst, else_ebb); - builder.seal_block(else_ebb); - builder.switch_to_block(else_ebb); - } + // We change the target of the branch instruction + let else_ebb = builder.create_ebb(); + builder.change_jump_destination(branch_inst, else_ebb); + builder.seal_block(else_ebb); + builder.switch_to_block(else_ebb); } - _ => {} } } Operator::End => { @@ -1057,10 +1058,10 @@ fn translate_br_if( builder.ins().brnz(val, br_destination, inputs); } -fn translate_br_if_args<'state>( +fn translate_br_if_args( relative_depth: u32, - state: &'state mut TranslationState, -) -> (ir::Ebb, &'state [ir::Value]) { + state: &mut TranslationState, +) -> (ir::Ebb, &[ir::Value]) { let i = state.control_stack.len() - 1 - (relative_depth as usize); let (return_count, br_destination) = { let frame = &mut state.control_stack[i]; diff --git a/lib/wasm/src/environ/dummy.rs b/lib/wasm/src/environ/dummy.rs index de941f3b9a..c99afd32d9 100644 --- a/lib/wasm/src/environ/dummy.rs +++ b/lib/wasm/src/environ/dummy.rs @@ -121,7 +121,7 @@ impl DummyEnvironment { } } -/// The FuncEnvironment implementation for use by the `DummyEnvironment`. +/// The `FuncEnvironment` implementation for use by the `DummyEnvironment`. pub struct DummyFuncEnvironment<'dummy_environment> { pub mod_info: &'dummy_environment DummyModuleInfo, } diff --git a/lib/wasm/src/lib.rs b/lib/wasm/src/lib.rs index 6e9a6a365a..f2a1adb7cb 100644 --- a/lib/wasm/src/lib.rs +++ b/lib/wasm/src/lib.rs @@ -12,6 +12,10 @@ #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![cfg_attr(feature="clippy", + plugin(clippy(conf_file="../../clippy.toml")))] +#![cfg_attr(feature="cargo-clippy", + allow(new_without_default, redundant_field_names))] extern crate wasmparser; extern crate cton_frontend; diff --git a/lib/wasm/tests/wasm_testsuite.rs b/lib/wasm/tests/wasm_testsuite.rs index 824a7606da..5d969c9cc2 100644 --- a/lib/wasm/tests/wasm_testsuite.rs +++ b/lib/wasm/tests/wasm_testsuite.rs @@ -25,7 +25,7 @@ fn testsuite() { // Ignore files starting with `.`, which could be editor temporary files if let Some(stem) = p.path().file_stem() { if let Some(stemstr) = stem.to_str() { - return !stemstr.starts_with("."); + return !stemstr.starts_with('.'); } } false @@ -35,7 +35,7 @@ fn testsuite() { let flags = Flags::new(&settings::builder()); for path in paths { let path = path.path(); - handle_module(path, &flags); + handle_module(&path, &flags); } } @@ -44,7 +44,7 @@ fn return_at_end() { let mut flag_builder = settings::builder(); flag_builder.enable("return_at_end").unwrap(); let flags = Flags::new(&flag_builder); - handle_module(PathBuf::from("../../wasmtests/return_at_end.wat"), &flags); + handle_module(&PathBuf::from("../../wasmtests/return_at_end.wat"), &flags); } fn read_wasm_file(path: PathBuf) -> Result, io::Error> { @@ -54,7 +54,7 @@ fn read_wasm_file(path: PathBuf) -> Result, io::Error> { Ok(buf) } -fn handle_module(path: PathBuf, flags: &Flags) { +fn handle_module(path: &PathBuf, flags: &Flags) { let data = match path.extension() { None => { panic!("the file extension is not wasm or wat"); @@ -103,7 +103,7 @@ fn handle_module(path: PathBuf, flags: &Flags) { translate_module(&data, &mut dummy_environ).unwrap(); for func in &dummy_environ.info.function_bodies { verifier::verify_function(func, flags) - .map_err(|err| panic!(pretty_verifier_error(func, None, err))) + .map_err(|err| panic!(pretty_verifier_error(func, None, &err))) .unwrap(); } } From e78735752024d73655e8538e165e735e19c41903 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 20 Mar 2018 15:22:22 -0700 Subject: [PATCH 36/72] Wrap build.py's contents in a main function. This prevents its local variables from becoming global variables. --- lib/cretonne/meta/build.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/cretonne/meta/build.py b/lib/cretonne/meta/build.py index a94b9ce706..8c83300604 100644 --- a/lib/cretonne/meta/build.py +++ b/lib/cretonne/meta/build.py @@ -14,19 +14,27 @@ import gen_legalizer import gen_registers import gen_binemit -parser = argparse.ArgumentParser(description='Generate sources for Cretonne.') -parser.add_argument('--out-dir', help='set output directory') -args = parser.parse_args() -out_dir = args.out_dir +def main(): + # type: () -> None + parser = argparse.ArgumentParser( + description='Generate sources for Cretonne.') + parser.add_argument('--out-dir', help='set output directory') -isas = isa.all_isas() + args = parser.parse_args() + out_dir = args.out_dir -gen_types.generate(out_dir) -gen_instr.generate(isas, out_dir) -gen_settings.generate(isas, out_dir) -gen_encoding.generate(isas, out_dir) -gen_legalizer.generate(isas, out_dir) -gen_registers.generate(isas, out_dir) -gen_binemit.generate(isas, out_dir) -gen_build_deps.generate() + isas = isa.all_isas() + + gen_types.generate(out_dir) + gen_instr.generate(isas, out_dir) + gen_settings.generate(isas, out_dir) + gen_encoding.generate(isas, out_dir) + gen_legalizer.generate(isas, out_dir) + gen_registers.generate(isas, out_dir) + gen_binemit.generate(isas, out_dir) + gen_build_deps.generate() + + +if __name__ == "__main__": + main() From 3ec7918ba1abb1cb05a2706d065f4fe1d8c3e058 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 20 Mar 2018 15:25:40 -0700 Subject: [PATCH 37/72] Tidy up a redundant import. --- lib/cretonne/meta/cdsl/isa.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cretonne/meta/cdsl/isa.py b/lib/cretonne/meta/cdsl/isa.py index 064a353117..77b071636a 100644 --- a/lib/cretonne/meta/cdsl/isa.py +++ b/lib/cretonne/meta/cdsl/isa.py @@ -12,7 +12,7 @@ from .instructions import InstructionGroup try: from typing import Tuple, Union, Any, Iterable, Sequence, List, Set, Dict, TYPE_CHECKING # noqa if TYPE_CHECKING: - from .instructions import MaybeBoundInst, InstructionGroup, InstructionFormat # noqa + from .instructions import MaybeBoundInst, InstructionFormat # noqa from .predicates import PredNode, PredKey # noqa from .settings import SettingGroup # noqa from .registers import RegBank # noqa From af8ac8f8caa6a1b7b6fa070bd14d899e0f93d848 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 20 Mar 2018 17:37:09 -0700 Subject: [PATCH 38/72] Avoid calling `analyze_branch()` when the `BranchInfo` is not needed. It's faster to just call `opcode().is_branch()`. --- lib/cretonne/src/regalloc/live_value_tracker.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/cretonne/src/regalloc/live_value_tracker.rs b/lib/cretonne/src/regalloc/live_value_tracker.rs index bedd0480e5..5cb3a6f694 100644 --- a/lib/cretonne/src/regalloc/live_value_tracker.rs +++ b/lib/cretonne/src/regalloc/live_value_tracker.rs @@ -6,7 +6,6 @@ use dominator_tree::DominatorTree; use entity::{EntityList, ListPool}; -use ir::instructions::BranchInfo; use ir::{Inst, Ebb, Value, DataFlowGraph, Layout, ExpandedProgramPoint}; use partition_slice::partition_slice; use regalloc::affinity::Affinity; @@ -261,9 +260,8 @@ impl LiveValueTracker { ) -> (&[LiveValue], &[LiveValue], &[LiveValue]) { // Save a copy of the live values before any branches or jumps that could be somebody's // immediate dominator. - match dfg.analyze_branch(inst) { - BranchInfo::NotABranch => {} - _ => self.save_idom_live_set(inst), + if dfg[inst].opcode().is_branch() { + self.save_idom_live_set(inst); } // Move killed values to the end of the vector. From 9602b78320be2ca588f710510d5b7805ec37530a Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 22 Mar 2018 16:55:18 -0700 Subject: [PATCH 39/72] Disable the LICM pass for now. There appear to be underlying problems with the way Cretonne handles value aliases, which are causing problems for LICM. Disable LICM until we have a chance to fix the underlying issues. Fixes #275. --- lib/cretonne/src/context.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/cretonne/src/context.rs b/lib/cretonne/src/context.rs index 5c2c884fdf..c6018dcd9e 100644 --- a/lib/cretonne/src/context.rs +++ b/lib/cretonne/src/context.rs @@ -92,8 +92,10 @@ impl Context { self.legalize(isa)?; if isa.flags().opt_level() == OptLevel::Best { self.compute_domtree(); + /* TODO: Re-enable LICM. self.compute_loop_analysis(); self.licm(isa)?; + */ self.simple_gvn(isa)?; } self.compute_domtree(); From aa73de8ca160426220de508d6901e05483770616 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 23 Mar 2018 03:46:42 -0700 Subject: [PATCH 40/72] Make code that tests for specific opcode families more consistent. --- lib/cretonne/src/legalizer/mod.rs | 26 +++++++++++++------------- lib/cretonne/src/verifier/locations.rs | 8 ++++---- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/cretonne/src/legalizer/mod.rs b/lib/cretonne/src/legalizer/mod.rs index 51198d05a0..ae40c42581 100644 --- a/lib/cretonne/src/legalizer/mod.rs +++ b/lib/cretonne/src/legalizer/mod.rs @@ -56,19 +56,19 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is let opcode = pos.func.dfg[inst].opcode(); // Check for ABI boundaries that need to be converted to the legalized signature. - if opcode.is_call() && boundary::handle_call_abi(inst, pos.func, cfg) { - // Go back and legalize the inserted argument conversion instructions. - pos.set_position(prev_pos); - continue; - } - - if opcode.is_return() && boundary::handle_return_abi(inst, pos.func, cfg) { - // Go back and legalize the inserted return value conversion instructions. - pos.set_position(prev_pos); - continue; - } - - if opcode.is_branch() { + if opcode.is_call() { + if boundary::handle_call_abi(inst, pos.func, cfg) { + // Go back and legalize the inserted argument conversion instructions. + pos.set_position(prev_pos); + continue; + } + } else if opcode.is_return() { + if boundary::handle_return_abi(inst, pos.func, cfg) { + // Go back and legalize the inserted return value conversion instructions. + pos.set_position(prev_pos); + continue; + } + } else if opcode.is_branch() { split::simplify_branch_arguments(&mut pos.func.dfg, inst); } diff --git a/lib/cretonne/src/verifier/locations.rs b/lib/cretonne/src/verifier/locations.rs index ae3c5cfb24..f2ad816924 100644 --- a/lib/cretonne/src/verifier/locations.rs +++ b/lib/cretonne/src/verifier/locations.rs @@ -69,10 +69,10 @@ impl<'a> LocationVerifier<'a> { let opcode = dfg[inst].opcode(); if opcode.is_return() { self.check_return_abi(inst, &divert)?; - } - - if opcode.is_branch() && !divert.is_empty() { - self.check_cfg_edges(inst, &divert)?; + } else if opcode.is_branch() { + if !divert.is_empty() { + self.check_cfg_edges(inst, &divert)?; + } } self.update_diversions(inst, &mut divert)?; From 51eea8b89dd715763ccd65fc722c16f0be8ef1c0 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 23 Mar 2018 12:46:23 -0700 Subject: [PATCH 41/72] Add some comments noting unimplemented features. While use of these features will trigger an `unimplemented!()`, it is nice to let users know in advance about features which aren't yet implemented. --- lib/cretonne/src/ir/heap.rs | 2 ++ lib/cretonne/src/isa/stack.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/lib/cretonne/src/ir/heap.rs b/lib/cretonne/src/ir/heap.rs index 7920ec344a..e2a5366a1a 100644 --- a/lib/cretonne/src/ir/heap.rs +++ b/lib/cretonne/src/ir/heap.rs @@ -25,6 +25,8 @@ pub struct HeapData { #[derive(Clone)] pub enum HeapBase { /// The heap base lives in a reserved register. + /// + /// This feature is not yet implemented. ReservedReg, /// The heap base is in a global variable. diff --git a/lib/cretonne/src/isa/stack.rs b/lib/cretonne/src/isa/stack.rs index e8a9b6981b..9e09a52808 100644 --- a/lib/cretonne/src/isa/stack.rs +++ b/lib/cretonne/src/isa/stack.rs @@ -68,6 +68,8 @@ pub enum StackBase { FP = 1, /// Use an explicit zone pointer in a general-purpose register. + /// + /// This feature is not yet implemented. Zone = 2, } From 80d2c5d9bff736c67ab3823505ae7b64f61a67fd Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Mon, 26 Mar 2018 16:48:20 -0700 Subject: [PATCH 42/72] Implement shift-immediate encodings for x86 (#283) * add x86 encodings for shift-immediate instructions implements encodings for ishl_imm, sshr_imm, and ushr_imm. uses 8-bit immediates. added tests for the encodings to intel/binary64.cton. Canonical versions come from llvm-mc. * translate test to use shift-immediates * shift immediate encodings: use enc_i32_i64 and note why the regular shift encodings cant use it above * add additional encoding tests for shift immediates this covers 32 bit mode, and 64 bit operations in 64 bit mode. --- .../isa/intel/baseline_clz_ctz_popcount.cton | 30 +++++++------------ cranelift/filetests/isa/intel/binary32.cton | 7 +++++ cranelift/filetests/isa/intel/binary64.cton | 30 +++++++++++++++++++ .../isa/intel/legalize-div-traps.cton | 4 +-- .../filetests/isa/intel/legalize-div.cton | 4 +-- lib/cretonne/meta/isa/intel/encodings.py | 8 +++++ 6 files changed, 59 insertions(+), 24 deletions(-) diff --git a/cranelift/filetests/isa/intel/baseline_clz_ctz_popcount.cton b/cranelift/filetests/isa/intel/baseline_clz_ctz_popcount.cton index 62a793de60..b87815aa12 100644 --- a/cranelift/filetests/isa/intel/baseline_clz_ctz_popcount.cton +++ b/cranelift/filetests/isa/intel/baseline_clz_ctz_popcount.cton @@ -47,28 +47,23 @@ ebb1(v20: i32): function %i64_popcount(i64) -> i64 { ebb0(v30: i64): v31 = popcnt v30; - ; check: iconst.i32 - ; check: ushr + ; check: ushr_imm ; check: iconst.i64 ; check: band ; check: isub - ; check: iconst.i32 - ; check: ushr + ; check: ushr_imm ; check: band ; check: isub - ; check: iconst.i32 - ; check: ushr + ; check: ushr_imm ; check: band ; check: isub - ; check: iconst.i32 - ; check: ushr + ; check: ushr_imm ; check: iadd ; check: iconst.i64 ; check: band ; check: iconst.i64 ; check: imul - ; check: iconst.i32 - ; check: ushr + ; check: ushr_imm return v31; } @@ -78,27 +73,22 @@ ebb0(v30: i64): function %i32_popcount(i32) -> i32 { ebb0(v40: i32): v41 = popcnt v40; - ; check: iconst.i32 - ; check: ushr + ; check: ushr_imm ; check: iconst.i32 ; check: band ; check: isub - ; check: iconst.i32 - ; check: ushr + ; check: ushr_imm ; check: band ; check: isub - ; check: iconst.i32 - ; check: ushr + ; check: ushr_imm ; check: band ; check: isub - ; check: iconst.i32 - ; check: ushr + ; check: ushr_imm ; check: iadd ; check: iconst.i32 ; check: band ; check: iconst.i32 ; check: imul - ; check: iconst.i32 - ; check: ushr + ; check: ushr_imm return v41; } diff --git a/cranelift/filetests/isa/intel/binary32.cton b/cranelift/filetests/isa/intel/binary32.cton index df98a86515..56301607cc 100644 --- a/cranelift/filetests/isa/intel/binary32.cton +++ b/cranelift/filetests/isa/intel/binary32.cton @@ -403,6 +403,13 @@ ebb0: ; asm: addl $-2147483648, %esp adjust_sp_imm -2147483648 ; bin: 81 c4 80000000 + ; Shift immediates + ; asm: shll $2, %esi + [-,%rsi] v513 = ishl_imm v2, 2 ; bin: c1 e6 02 + ; asm: sarl $5, %esi + [-,%rsi] v514 = sshr_imm v2, 5 ; bin: c1 fe 05 + ; asm: shrl $8, %esi + [-,%rsi] v515 = ushr_imm v2, 8 ; bin: c1 ee 08 ; asm: testl %ecx, %ecx ; asm: je ebb1 diff --git a/cranelift/filetests/isa/intel/binary64.cton b/cranelift/filetests/isa/intel/binary64.cton index 9eca950ee6..5741f18041 100644 --- a/cranelift/filetests/isa/intel/binary64.cton +++ b/cranelift/filetests/isa/intel/binary64.cton @@ -529,6 +529,21 @@ ebb0: ; asm: addq $-2147483648, %rsp adjust_sp_imm -2147483648 ; bin: 48 81 c4 80000000 + ; Shift immediates + ; asm: shlq $12, %rsi + [-,%rsi] v515 = ishl_imm v2, 12 ; bin: 48 c1 e6 0c + ; asm: shlq $13, %r8 + [-,%r8] v516 = ishl_imm v4, 13 ; bin: 49 c1 e0 0d + ; asm: sarq $32, %rsi + [-,%rsi] v517 = sshr_imm v2, 32 ; bin: 48 c1 fe 20 + ; asm: sarq $33, %r8 + [-,%r8] v518 = sshr_imm v4, 33 ; bin: 49 c1 f8 21 + ; asm: shrl $62, %rsi + [-,%rsi] v519 = ushr_imm v2, 62 ; bin: 48 c1 ee 3e + ; asm: shrl $63, %r8 + [-,%r8] v520 = ushr_imm v4, 63 ; bin: 49 c1 e8 3f + + ; asm: testq %rcx, %rcx ; asm: je ebb1 brz v1, ebb1 ; bin: 48 85 c9 74 1b @@ -653,6 +668,7 @@ ebb1: ; asm: cmpq $10000, %r10 [-,%eflags] v525 = ifcmp_imm v2, 10000 ; bin: 49 81 fa 00002710 + return } @@ -1053,6 +1069,19 @@ ebb0: ; asm: cmpl $10000, %r10d [-,%eflags] v525 = ifcmp_imm v3, 10000 ; bin: 41 81 fa 00002710 + ; asm: shll $2, %esi + [-,%rsi] v526 = ishl_imm v2, 2 ; bin: c1 e6 02 + ; asm: shll $12, %r10d + [-,%r10] v527 = ishl_imm v3, 12 ; bin: 41 c1 e2 0c + ; asm: sarl $5, %esi + [-,%rsi] v529 = sshr_imm v2, 5 ; bin: c1 fe 05 + ; asm: sarl $32, %r10d + [-,%r10] v530 = sshr_imm v3, 32 ; bin: 41 c1 fa 20 + ; asm: shrl $8, %esi + [-,%rsi] v532 = ushr_imm v2, 8 ; bin: c1 ee 08 + ; asm: shrl $31, %r10d + [-,%r10] v533 = ushr_imm v3, 31 ; bin: 41 c1 ea 1f + ; asm: testl %ecx, %ecx ; asm: je ebb1x brz v1, ebb1 ; bin: 85 c9 74 18 @@ -1082,6 +1111,7 @@ ebb1: ; asm: ebb2x: ebb2: jump ebb1 ; bin: eb fd + } ; Tests for i32/i8 conversion instructions. diff --git a/cranelift/filetests/isa/intel/legalize-div-traps.cton b/cranelift/filetests/isa/intel/legalize-div-traps.cton index fa070fba1a..3869e66325 100644 --- a/cranelift/filetests/isa/intel/legalize-div-traps.cton +++ b/cranelift/filetests/isa/intel/legalize-div-traps.cton @@ -40,7 +40,7 @@ ebb0(v0: i64, v1: i64): ; nextln: brif eq $fm1, $(m1=$EBB) ; nextln: $(fz=$V) = ifcmp_imm v1, 0 ; nextln: trapif eq $fz, int_divz - ; check: $(hi=$V) = sshr + ; check: $(hi=$V) = sshr_imm ; nextln: $(q=$V), $(r=$V) = x86_sdivmodx v0, $hi, v1 ; nextln: jump $(done=$EBB)($q) ; check: $m1: @@ -60,7 +60,7 @@ ebb0(v0: i64, v1: i64): v2 = srem v0, v1 ; nextln: $(fm1=$V) = ifcmp_imm v1, -1 ; nextln: brif eq $fm1, $(m1=$EBB) - ; check: $(hi=$V) = sshr + ; check: $(hi=$V) = sshr_imm ; nextln: $(d=$V), $(r=$V) = x86_sdivmodx v0, $hi, v1 ; nextln: jump $(done=$EBB)($r) ; check: $m1: diff --git a/cranelift/filetests/isa/intel/legalize-div.cton b/cranelift/filetests/isa/intel/legalize-div.cton index ec3f8ec5d3..d6179b2611 100644 --- a/cranelift/filetests/isa/intel/legalize-div.cton +++ b/cranelift/filetests/isa/intel/legalize-div.cton @@ -32,7 +32,7 @@ function %sdiv(i64, i64) -> i64 { ebb0(v0: i64, v1: i64): ; check: ebb0( v2 = sdiv v0, v1 - ; check: $(hi=$V) = sshr + ; check: $(hi=$V) = sshr_imm ; nextln: $(d=$V), $(r=$V) = x86_sdivmodx v0, $hi, v1 return v2 ; nextln: return $d @@ -46,7 +46,7 @@ ebb0(v0: i64, v1: i64): v2 = srem v0, v1 ; nextln: $(fm1=$V) = ifcmp_imm v1, -1 ; nextln: brif eq $fm1, $(m1=$EBB) - ; check: $(hi=$V) = sshr + ; check: $(hi=$V) = sshr_imm ; nextln: $(d=$V), $(r=$V) = x86_sdivmodx v0, $hi, v1 ; nextln: jump $(done=$EBB)($r) ; check: $m1: diff --git a/lib/cretonne/meta/isa/intel/encodings.py b/lib/cretonne/meta/isa/intel/encodings.py index 489e61be9f..afb544cb9a 100644 --- a/lib/cretonne/meta/isa/intel/encodings.py +++ b/lib/cretonne/meta/isa/intel/encodings.py @@ -164,11 +164,19 @@ for inst, rrr in [ (base.ishl, 4), (base.ushr, 5), (base.sshr, 7)]: + # Cannot use enc_i32_i64 for this pattern because instructions require + # .any suffix. X86_32.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr)) X86_64.enc(inst.i64.any, *r.rc.rex(0xd3, rrr=rrr, w=1)) X86_64.enc(inst.i32.any, *r.rc.rex(0xd3, rrr=rrr)) X86_64.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr)) +for inst, rrr in [ + (base.ishl_imm, 4), + (base.ushr_imm, 5), + (base.sshr_imm, 7)]: + enc_i32_i64(inst, r.rib, 0xc1, rrr=rrr) + # Population count. X86_32.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt) X86_64.enc(base.popcnt.i64, *r.urm.rex(0xf3, 0x0f, 0xb8, w=1), From bcd3309c155667afa91ad10c70b78046034a2b97 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 23 Mar 2018 13:10:28 -0700 Subject: [PATCH 43/72] Mention ``reserved_reg`` being unimplemented in the docs too. --- cranelift/docs/langref.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cranelift/docs/langref.rst b/cranelift/docs/langref.rst index 3a855c32b4..fb62111d0a 100644 --- a/cranelift/docs/langref.rst +++ b/cranelift/docs/langref.rst @@ -654,6 +654,8 @@ trap when accessed. address space reserved for the heap, not including the guard pages. :arg GuardBytes: Size of the guard pages in bytes. +The ``reserved_reg`` option is not yet implemented. + Dynamic heaps ~~~~~~~~~~~~~ @@ -672,6 +674,8 @@ is resized. The bound of a dynamic heap is stored in a global variable. :arg BoundGV: Global variable containing the current heap bound in bytes. :arg GuardBytes: Size of the guard pages in bytes. +The ``reserved_reg`` option is not yet implemented. + Heap examples ~~~~~~~~~~~~~ From 685cde98a4ef43e3ac43321887e40102655f11bb Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 23 Mar 2018 13:34:40 -0700 Subject: [PATCH 44/72] Mark loads from globals `aligned` and `notrap`. Mark loads from globals generated by cton_wasm or by legalization as `aligned` and `notrap`, since memory for these globals should be allocated by the runtime environment for that purpose. This reduces the number of potentially trapping instructions, which can reduce the amount of metadata required by embedding environments. --- cranelift/docs/langref.rst | 6 ++++++ cranelift/filetests/isa/intel/legalize-memory.cton | 6 +++--- lib/cretonne/meta/base/instructions.py | 3 +++ lib/cretonne/src/ir/globalvar.rs | 3 ++- lib/cretonne/src/ir/heap.rs | 6 ++++-- lib/cretonne/src/legalizer/globalvar.rs | 7 +++++-- lib/cretonne/src/legalizer/heap.rs | 12 ++++++++++-- lib/wasm/src/code_translator.rs | 14 ++++++++++---- lib/wasm/src/environ/dummy.rs | 5 ++++- 9 files changed, 47 insertions(+), 15 deletions(-) diff --git a/cranelift/docs/langref.rst b/cranelift/docs/langref.rst index fb62111d0a..fb716257bd 100644 --- a/cranelift/docs/langref.rst +++ b/cranelift/docs/langref.rst @@ -654,6 +654,9 @@ trap when accessed. address space reserved for the heap, not including the guard pages. :arg GuardBytes: Size of the guard pages in bytes. +When the base is a global variable, it must be :term:`accessible` and naturally +aligned for a pointer value. + The ``reserved_reg`` option is not yet implemented. Dynamic heaps @@ -674,6 +677,9 @@ is resized. The bound of a dynamic heap is stored in a global variable. :arg BoundGV: Global variable containing the current heap bound in bytes. :arg GuardBytes: Size of the guard pages in bytes. +When the base is a global variable, it must be :term:`accessible` and naturally +aligned for a pointer value. + The ``reserved_reg`` option is not yet implemented. Heap examples diff --git a/cranelift/filetests/isa/intel/legalize-memory.cton b/cranelift/filetests/isa/intel/legalize-memory.cton index 5b7246a2e3..1ba979deb1 100644 --- a/cranelift/filetests/isa/intel/legalize-memory.cton +++ b/cranelift/filetests/isa/intel/legalize-memory.cton @@ -23,7 +23,7 @@ function %deref(i64 vmctx) -> i64 { ebb1(v1: i64): v2 = global_addr.i64 gv2 ; check: $(a1=$V) = iadd_imm v1, -16 - ; check: $(p1=$V) = load.i64 $a1 + ; check: $(p1=$V) = load.i64 notrap aligned $a1 ; check: v2 = iadd_imm $p1, 32 return v2 ; check: return v2 @@ -55,7 +55,7 @@ ebb0(v0: i32, v999: i64): ; Checks here are assuming that no pipehole opts fold the load offsets. ; nextln: $(xoff=$V) = uextend.i64 v0 ; nextln: $(haddr=$V) = iadd_imm v999, 64 - ; nextln: $(hbase=$V) = load.i64 $haddr + ; nextln: $(hbase=$V) = load.i64 notrap aligned $haddr ; nextln: v1 = iadd $hbase, $xoff v2 = load.f32 v1+16 ; nextln: v2 = load.f32 v1+16 @@ -103,7 +103,7 @@ ebb0(v0: i32, v999: i64): ; Checks here are assuming that no pipehole opts fold the load offsets. ; nextln: $(xoff=$V) = uextend.i64 v0 ; nextln: $(haddr=$V) = iadd_imm.i64 v999, 64 - ; nextln: $(hbase=$V) = load.i64 $haddr + ; nextln: $(hbase=$V) = load.i64 notrap aligned $haddr ; nextln: v1 = iadd $hbase, $xoff v2 = load.f32 v1+0x7fff_ffff ; nextln: v2 = load.f32 v1+0x7fff_ffff diff --git a/lib/cretonne/meta/base/instructions.py b/lib/cretonne/meta/base/instructions.py index 8ba1aa65fa..c54f3ef570 100644 --- a/lib/cretonne/meta/base/instructions.py +++ b/lib/cretonne/meta/base/instructions.py @@ -588,6 +588,9 @@ stack_check = Instruction( Read the stack limit from ``GV`` and compare it to the stack pointer. If the stack pointer has reached or exceeded the limit, generate a trap with a ``stk_ovf`` code. + + The global variable must be accessible and naturally aligned for a + pointer-sized value. """, ins=GV, can_trap=True) diff --git a/lib/cretonne/src/ir/globalvar.rs b/lib/cretonne/src/ir/globalvar.rs index 78e1c6cb98..c8fc3b8ce1 100644 --- a/lib/cretonne/src/ir/globalvar.rs +++ b/lib/cretonne/src/ir/globalvar.rs @@ -17,7 +17,8 @@ pub enum GlobalVarData { /// Variable is part of a struct pointed to by another global variable. /// /// The `base` global variable is assumed to contain a pointer to a struct. This global - /// variable lives at an offset into the struct. + /// variable lives at an offset into the struct. The memory must be accessible, and + /// naturally aligned to hold a pointer value. Deref { /// The base pointer global variable. base: GlobalVar, diff --git a/lib/cretonne/src/ir/heap.rs b/lib/cretonne/src/ir/heap.rs index e2a5366a1a..b41565b25b 100644 --- a/lib/cretonne/src/ir/heap.rs +++ b/lib/cretonne/src/ir/heap.rs @@ -29,7 +29,8 @@ pub enum HeapBase { /// This feature is not yet implemented. ReservedReg, - /// The heap base is in a global variable. + /// The heap base is in a global variable. The variable must be accessible and naturally + /// aligned for a pointer. GlobalVar(GlobalVar), } @@ -38,7 +39,8 @@ pub enum HeapBase { pub enum HeapStyle { /// A dynamic heap can be relocated to a different base address when it is grown. Dynamic { - /// Global variable holding the current bound of the heap in bytes. + /// Global variable holding the current bound of the heap in bytes. It is + /// required to be accessible and naturally aligned for a pointer-sized integer. bound_gv: GlobalVar, }, diff --git a/lib/cretonne/src/legalizer/globalvar.rs b/lib/cretonne/src/legalizer/globalvar.rs index 5f6427822b..901b0da416 100644 --- a/lib/cretonne/src/legalizer/globalvar.rs +++ b/lib/cretonne/src/legalizer/globalvar.rs @@ -52,8 +52,11 @@ fn deref_addr(inst: ir::Inst, func: &mut ir::Function, base: ir::GlobalVar, offs pos.use_srcloc(inst); let base_addr = pos.ins().global_addr(ptr_ty, base); - // TODO: We could probably set both `notrap` and `aligned` on this load instruction. - let base_ptr = pos.ins().load(ptr_ty, ir::MemFlags::new(), base_addr, 0); + let mut mflags = ir::MemFlags::new(); + // Deref globals are required to be accessible and aligned. + mflags.set_notrap(); + mflags.set_aligned(); + let base_ptr = pos.ins().load(ptr_ty, mflags, base_addr, 0); pos.func.dfg.replace(inst).iadd_imm(base_ptr, offset); } diff --git a/lib/cretonne/src/legalizer/heap.rs b/lib/cretonne/src/legalizer/heap.rs index 37ce226351..0d6e7d385b 100644 --- a/lib/cretonne/src/legalizer/heap.rs +++ b/lib/cretonne/src/legalizer/heap.rs @@ -58,7 +58,11 @@ fn dynamic_addr( // Start with the bounds check. Trap if `offset + size > bound`. let bound_addr = pos.ins().global_addr(addr_ty, bound_gv); - let bound = pos.ins().load(offset_ty, MemFlags::new(), bound_addr, 0); + let mut mflags = MemFlags::new(); + // The bound variable is requied to be accessible and aligned. + mflags.set_notrap(); + mflags.set_aligned(); + let bound = pos.ins().load(offset_ty, mflags, bound_addr, 0); let oob; if size == 1 { @@ -175,7 +179,11 @@ fn offset_addr( ir::HeapBase::ReservedReg => unimplemented!(), ir::HeapBase::GlobalVar(base_gv) => { let base_addr = pos.ins().global_addr(addr_ty, base_gv); - let base = pos.ins().load(addr_ty, MemFlags::new(), base_addr, 0); + let mut mflags = MemFlags::new(); + // The base address variable is requied to be accessible and aligned. + mflags.set_notrap(); + mflags.set_aligned(); + let base = pos.ins().load(addr_ty, mflags, base_addr, 0); pos.func.dfg.replace(inst).iadd(base, offset); } } diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index 42d232e6f5..69111dc8e8 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -75,8 +75,9 @@ pub fn translate_operator( GlobalValue::Const(val) => val, GlobalValue::Memory { gv, ty } => { let addr = builder.ins().global_addr(environ.native_pointer(), gv); - // TODO: It is likely safe to set `aligned notrap` flags on a global load. - let flags = ir::MemFlags::new(); + let mut flags = ir::MemFlags::new(); + flags.set_notrap(); + flags.set_aligned(); builder.ins().load(ty, flags, addr, 0) } }; @@ -87,8 +88,9 @@ pub fn translate_operator( GlobalValue::Const(_) => panic!("global #{} is a constant", global_index), GlobalValue::Memory { gv, .. } => { let addr = builder.ins().global_addr(environ.native_pointer(), gv); - // TODO: It is likely safe to set `aligned notrap` flags on a global store. - let flags = ir::MemFlags::new(); + let mut flags = ir::MemFlags::new(); + flags.set_notrap(); + flags.set_aligned(); let val = state.pop1(); builder.ins().store(flags, val, addr, 0); } @@ -992,6 +994,9 @@ fn translate_load( // We don't yet support multiple linear memories. let heap = state.get_heap(builder.func, 0, environ); let (base, offset) = get_heap_addr(heap, addr32, offset, environ.native_pointer(), builder); + // Note that we don't set `is_aligned` here, even if the load instruction's + // alignment immediate says it's aligned, because WebAssembly's immediate + // field is just a hint, while Cretonne's aligned flag needs a guarantee. let flags = MemFlags::new(); let (load, dfg) = builder.ins().Load( opcode, @@ -1017,6 +1022,7 @@ fn translate_store( // We don't yet support multiple linear memories. let heap = state.get_heap(builder.func, 0, environ); let (base, offset) = get_heap_addr(heap, addr32, offset, environ.native_pointer(), builder); + // See the comments in `translate_load` about the flags. let flags = MemFlags::new(); builder.ins().Store( opcode, diff --git a/lib/wasm/src/environ/dummy.rs b/lib/wasm/src/environ/dummy.rs index c99afd32d9..bb21b7536a 100644 --- a/lib/wasm/src/environ/dummy.rs +++ b/lib/wasm/src/environ/dummy.rs @@ -209,7 +209,10 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ let ext = pos.ins().uextend(I64, callee); pos.ins().imul_imm(ext, 4) }; - let func_ptr = pos.ins().load(ptr, ir::MemFlags::new(), callee_offset, 0); + let mut mflags = ir::MemFlags::new(); + mflags.set_notrap(); + mflags.set_aligned(); + let func_ptr = pos.ins().load(ptr, mflags, callee_offset, 0); // Build a value list for the indirect call instruction containing the callee, call_args, // and the vmctx parameter. From 14faef7374141fe619fc7ad600255fb181a94aa9 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 26 Mar 2018 08:18:32 -0700 Subject: [PATCH 45/72] Derive Debug for LiveValue. --- lib/cretonne/src/regalloc/live_value_tracker.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/cretonne/src/regalloc/live_value_tracker.rs b/lib/cretonne/src/regalloc/live_value_tracker.rs index 5cb3a6f694..ee1f58944b 100644 --- a/lib/cretonne/src/regalloc/live_value_tracker.rs +++ b/lib/cretonne/src/regalloc/live_value_tracker.rs @@ -32,6 +32,7 @@ pub struct LiveValueTracker { } /// Information about a value that is live at the current program point. +#[derive(Debug)] pub struct LiveValue { /// The live value. pub value: Value, From ffe89cdc0a55fbd5611093d34f1633890b4f21f7 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 26 Mar 2018 21:34:15 -0700 Subject: [PATCH 46/72] Rename %eflags to %rflags. EFLAGS is a subregister of RFLAGS. For consistency with GPRs where we use the 64-bit names to refer to the registers, use the 64-bit name for RFLAGS as well. --- .../baseline_clz_ctz_popcount_encoding.cton | 24 ++++++------- .../filetests/isa/intel/binary32-float.cton | 14 ++++---- cranelift/filetests/isa/intel/binary32.cton | 16 ++++----- .../filetests/isa/intel/binary64-float.cton | 14 ++++---- cranelift/filetests/isa/intel/binary64.cton | 28 +++++++-------- lib/cretonne/meta/isa/intel/recipes.py | 36 +++++++++---------- lib/cretonne/meta/isa/intel/registers.py | 2 +- lib/cretonne/src/isa/intel/binemit.rs | 2 +- 8 files changed, 68 insertions(+), 68 deletions(-) diff --git a/cranelift/filetests/isa/intel/baseline_clz_ctz_popcount_encoding.cton b/cranelift/filetests/isa/intel/baseline_clz_ctz_popcount_encoding.cton index 0b7003449d..2e552b7145 100644 --- a/cranelift/filetests/isa/intel/baseline_clz_ctz_popcount_encoding.cton +++ b/cranelift/filetests/isa/intel/baseline_clz_ctz_popcount_encoding.cton @@ -15,56 +15,56 @@ ebb0: [-,%r11] v10 = iconst.i64 0x1234 ; asm: bsfq %r11, %rcx - [-,%rcx,%eflags] v11, v12 = x86_bsf v10 ; bin: 49 0f bc cb + [-,%rcx,%rflags] v11, v12 = x86_bsf v10 ; bin: 49 0f bc cb [-,%rdx] v14 = iconst.i64 0x5678 ; asm: bsfq %rdx, %r12 - [-,%r12,%eflags] v15, v16 = x86_bsf v14 ; bin: 4c 0f bc e2 + [-,%r12,%rflags] v15, v16 = x86_bsf v14 ; bin: 4c 0f bc e2 ; asm: bsfq %rdx, %rdi - [-,%rdi,%eflags] v17, v18 = x86_bsf v14 ; bin: 48 0f bc fa + [-,%rdi,%rflags] v17, v18 = x86_bsf v14 ; bin: 48 0f bc fa ; 32-bit wide bsf [-,%r11] v20 = iconst.i32 0x1234 ; asm: bsfl %r11d, %ecx - [-,%rcx,%eflags] v21, v22 = x86_bsf v20 ; bin: 41 0f bc cb + [-,%rcx,%rflags] v21, v22 = x86_bsf v20 ; bin: 41 0f bc cb [-,%rdx] v24 = iconst.i32 0x5678 ; asm: bsfl %edx, %r12d - [-,%r12,%eflags] v25, v26 = x86_bsf v24 ; bin: 44 0f bc e2 + [-,%r12,%rflags] v25, v26 = x86_bsf v24 ; bin: 44 0f bc e2 ; asm: bsfl %edx, %esi - [-,%rsi,%eflags] v27, v28 = x86_bsf v24 ; bin: 0f bc f2 + [-,%rsi,%rflags] v27, v28 = x86_bsf v24 ; bin: 0f bc f2 ; 64-bit wide bsr [-,%r11] v30 = iconst.i64 0x1234 ; asm: bsrq %r11, %rcx - [-,%rcx,%eflags] v31, v32 = x86_bsr v30 ; bin: 49 0f bd cb + [-,%rcx,%rflags] v31, v32 = x86_bsr v30 ; bin: 49 0f bd cb [-,%rdx] v34 = iconst.i64 0x5678 ; asm: bsrq %rdx, %r12 - [-,%r12,%eflags] v35, v36 = x86_bsr v34 ; bin: 4c 0f bd e2 + [-,%r12,%rflags] v35, v36 = x86_bsr v34 ; bin: 4c 0f bd e2 ; asm: bsrq %rdx, %rdi - [-,%rdi,%eflags] v37, v38 = x86_bsr v34 ; bin: 48 0f bd fa + [-,%rdi,%rflags] v37, v38 = x86_bsr v34 ; bin: 48 0f bd fa ; 32-bit wide bsr [-,%r11] v40 = iconst.i32 0x1234 ; asm: bsrl %r11d, %ecx - [-,%rcx,%eflags] v41, v42 = x86_bsr v40 ; bin: 41 0f bd cb + [-,%rcx,%rflags] v41, v42 = x86_bsr v40 ; bin: 41 0f bd cb [-,%rdx] v44 = iconst.i32 0x5678 ; asm: bsrl %edx, %r12d - [-,%r12,%eflags] v45, v46 = x86_bsr v44 ; bin: 44 0f bd e2 + [-,%r12,%rflags] v45, v46 = x86_bsr v44 ; bin: 44 0f bd e2 ; asm: bsrl %edx, %esi - [-,%rsi,%eflags] v47, v48 = x86_bsr v44 ; bin: 0f bd f2 + [-,%rsi,%rflags] v47, v48 = x86_bsr v44 ; bin: 0f bd f2 ; 64-bit wide cmov diff --git a/cranelift/filetests/isa/intel/binary32-float.cton b/cranelift/filetests/isa/intel/binary32-float.cton index 8f60cf20be..94db28d26e 100644 --- a/cranelift/filetests/isa/intel/binary32-float.cton +++ b/cranelift/filetests/isa/intel/binary32-float.cton @@ -221,11 +221,11 @@ ebb0: [-,%rdx] v307 = fcmp ule v11, v10 ; bin: 0f 2e d5 0f 96 c2 ; asm: ucomiss %xmm2, %xmm5 - [-,%eflags] v310 = ffcmp v10, v11 ; bin: 0f 2e ea + [-,%rflags] v310 = ffcmp v10, v11 ; bin: 0f 2e ea ; asm: ucomiss %xmm2, %xmm5 - [-,%eflags] v311 = ffcmp v11, v10 ; bin: 0f 2e d5 + [-,%rflags] v311 = ffcmp v11, v10 ; bin: 0f 2e d5 ; asm: ucomiss %xmm5, %xmm5 - [-,%eflags] v312 = ffcmp v10, v10 ; bin: 0f 2e ed + [-,%rflags] v312 = ffcmp v10, v10 ; bin: 0f 2e ed return } @@ -436,11 +436,11 @@ ebb0: [-,%rdx] v307 = fcmp ule v11, v10 ; bin: 66 0f 2e d5 0f 96 c2 ; asm: ucomisd %xmm2, %xmm5 - [-,%eflags] v310 = ffcmp v10, v11 ; bin: 66 0f 2e ea + [-,%rflags] v310 = ffcmp v10, v11 ; bin: 66 0f 2e ea ; asm: ucomisd %xmm2, %xmm5 - [-,%eflags] v311 = ffcmp v11, v10 ; bin: 66 0f 2e d5 + [-,%rflags] v311 = ffcmp v11, v10 ; bin: 66 0f 2e d5 ; asm: ucomisd %xmm5, %xmm5 - [-,%eflags] v312 = ffcmp v10, v10 ; bin: 66 0f 2e ed + [-,%rflags] v312 = ffcmp v10, v10 ; bin: 66 0f 2e ed return } @@ -448,7 +448,7 @@ ebb0: function %cpuflags_float(f32 [%xmm0]) { ebb0(v0: f32 [%xmm0]): ; asm: ucomiss %xmm0, %xmm0 - [-,%eflags] v1 = ffcmp v0, v0 ; bin: 0f 2e c0 + [-,%rflags] v1 = ffcmp v0, v0 ; bin: 0f 2e c0 jump ebb1 diff --git a/cranelift/filetests/isa/intel/binary32.cton b/cranelift/filetests/isa/intel/binary32.cton index 56301607cc..771bb19af2 100644 --- a/cranelift/filetests/isa/intel/binary32.cton +++ b/cranelift/filetests/isa/intel/binary32.cton @@ -473,9 +473,9 @@ ebb0: ebb1: ; asm: cmpl %esi, %ecx - [-,%eflags] v10 = ifcmp v1, v2 ; bin: 39 f1 + [-,%rflags] v10 = ifcmp v1, v2 ; bin: 39 f1 ; asm: cmpl %ecx, %esi - [-,%eflags] v11 = ifcmp v2, v1 ; bin: 39 ce + [-,%rflags] v11 = ifcmp v2, v1 ; bin: 39 ce ; asm: je ebb1 brif eq v11, ebb1 ; bin: 74 fa @@ -543,19 +543,19 @@ ebb1: ; Stack check. ; asm: cmpl %esp, %ecx - [-,%eflags] v40 = ifcmp_sp v1 ; bin: 39 e1 + [-,%rflags] v40 = ifcmp_sp v1 ; bin: 39 e1 ; asm: cmpl %esp, %esi - [-,%eflags] v41 = ifcmp_sp v2 ; bin: 39 e6 + [-,%rflags] v41 = ifcmp_sp v2 ; bin: 39 e6 ; asm: cmpl $-100, %ecx - [-,%eflags] v42 = ifcmp_imm v1, -100 ; bin: 83 f9 9c + [-,%rflags] v42 = ifcmp_imm v1, -100 ; bin: 83 f9 9c ; asm: cmpl $100, %esi - [-,%eflags] v43 = ifcmp_imm v2, 100 ; bin: 83 fe 64 + [-,%rflags] v43 = ifcmp_imm v2, 100 ; bin: 83 fe 64 ; asm: cmpl $-10000, %ecx - [-,%eflags] v44 = ifcmp_imm v1, -10000 ; bin: 81 f9 ffffd8f0 + [-,%rflags] v44 = ifcmp_imm v1, -10000 ; bin: 81 f9 ffffd8f0 ; asm: cmpl $10000, %esi - [-,%eflags] v45 = ifcmp_imm v2, 10000 ; bin: 81 fe 00002710 + [-,%rflags] v45 = ifcmp_imm v2, 10000 ; bin: 81 fe 00002710 return } diff --git a/cranelift/filetests/isa/intel/binary64-float.cton b/cranelift/filetests/isa/intel/binary64-float.cton index 69bfeb6c36..b362b7eb4a 100644 --- a/cranelift/filetests/isa/intel/binary64-float.cton +++ b/cranelift/filetests/isa/intel/binary64-float.cton @@ -235,11 +235,11 @@ ebb0: [-,%rdx] v307 = fcmp ule v11, v10 ; bin: 44 0f 2e d5 0f 96 c2 ; asm: ucomiss %xmm10, %xmm5 - [-,%eflags] v310 = ffcmp v10, v11 ; bin: 41 0f 2e ea + [-,%rflags] v310 = ffcmp v10, v11 ; bin: 41 0f 2e ea ; asm: ucomiss %xmm10, %xmm5 - [-,%eflags] v311 = ffcmp v11, v10 ; bin: 44 0f 2e d5 + [-,%rflags] v311 = ffcmp v11, v10 ; bin: 44 0f 2e d5 ; asm: ucomiss %xmm5, %xmm5 - [-,%eflags] v312 = ffcmp v10, v10 ; bin: 0f 2e ed + [-,%rflags] v312 = ffcmp v10, v10 ; bin: 0f 2e ed return } @@ -470,11 +470,11 @@ ebb0: [-,%rdx] v307 = fcmp ule v11, v10 ; bin: 66 44 0f 2e d5 0f 96 c2 ; asm: ucomisd %xmm10, %xmm5 - [-,%eflags] v310 = ffcmp v10, v11 ; bin: 66 41 0f 2e ea + [-,%rflags] v310 = ffcmp v10, v11 ; bin: 66 41 0f 2e ea ; asm: ucomisd %xmm10, %xmm5 - [-,%eflags] v311 = ffcmp v11, v10 ; bin: 66 44 0f 2e d5 + [-,%rflags] v311 = ffcmp v11, v10 ; bin: 66 44 0f 2e d5 ; asm: ucomisd %xmm5, %xmm5 - [-,%eflags] v312 = ffcmp v10, v10 ; bin: 66 0f 2e ed + [-,%rflags] v312 = ffcmp v10, v10 ; bin: 66 0f 2e ed return } @@ -482,7 +482,7 @@ ebb0: function %cpuflags_float(f32 [%xmm0]) { ebb0(v0: f32 [%xmm0]): ; asm: ucomiss %xmm0, %xmm0 - [-,%eflags] v1 = ffcmp v0, v0 ; bin: 0f 2e c0 + [-,%rflags] v1 = ffcmp v0, v0 ; bin: 0f 2e c0 jump ebb1 diff --git a/cranelift/filetests/isa/intel/binary64.cton b/cranelift/filetests/isa/intel/binary64.cton index 5741f18041..3c35bd2a0c 100644 --- a/cranelift/filetests/isa/intel/binary64.cton +++ b/cranelift/filetests/isa/intel/binary64.cton @@ -584,9 +584,9 @@ ebb0: ebb1: ; asm: cmpq %r10, %rcx - [-,%eflags] v10 = ifcmp v1, v2 ; bin: 4c 39 d1 + [-,%rflags] v10 = ifcmp v1, v2 ; bin: 4c 39 d1 ; asm: cmpq %rcx, %r10 - [-,%eflags] v11 = ifcmp v2, v1 ; bin: 49 39 ca + [-,%rflags] v11 = ifcmp v2, v1 ; bin: 49 39 ca ; asm: je ebb1 brif eq v11, ebb1 ; bin: 74 f8 @@ -654,19 +654,19 @@ ebb1: ; Stack check. ; asm: cmpq %rsp, %rcx - [-,%eflags] v40 = ifcmp_sp v1 ; bin: 48 39 e1 + [-,%rflags] v40 = ifcmp_sp v1 ; bin: 48 39 e1 ; asm: cmpq %rsp, %r10 - [-,%eflags] v41 = ifcmp_sp v2 ; bin: 49 39 e2 + [-,%rflags] v41 = ifcmp_sp v2 ; bin: 49 39 e2 ; asm: cmpq $-100, %rcx - [-,%eflags] v522 = ifcmp_imm v1, -100 ; bin: 48 83 f9 9c + [-,%rflags] v522 = ifcmp_imm v1, -100 ; bin: 48 83 f9 9c ; asm: cmpq $100, %r10 - [-,%eflags] v523 = ifcmp_imm v2, 100 ; bin: 49 83 fa 64 + [-,%rflags] v523 = ifcmp_imm v2, 100 ; bin: 49 83 fa 64 ; asm: cmpq $-10000, %rcx - [-,%eflags] v524 = ifcmp_imm v1, -10000 ; bin: 48 81 f9 ffffd8f0 + [-,%rflags] v524 = ifcmp_imm v1, -10000 ; bin: 48 81 f9 ffffd8f0 ; asm: cmpq $10000, %r10 - [-,%eflags] v525 = ifcmp_imm v2, 10000 ; bin: 49 81 fa 00002710 + [-,%rflags] v525 = ifcmp_imm v2, 10000 ; bin: 49 81 fa 00002710 return @@ -1055,19 +1055,19 @@ ebb0: regfill v1, ss1 -> %rcx ; bin: 8b 8c 24 00000408 ; asm: cmpl %esi, %ecx - [-,%eflags] v520 = ifcmp v1, v2 ; bin: 39 f1 + [-,%rflags] v520 = ifcmp v1, v2 ; bin: 39 f1 ; asm: cmpl %r10d, %esi - [-,%eflags] v521 = ifcmp v2, v3 ; bin: 44 39 d6 + [-,%rflags] v521 = ifcmp v2, v3 ; bin: 44 39 d6 ; asm: cmpl $-100, %ecx - [-,%eflags] v522 = ifcmp_imm v1, -100 ; bin: 83 f9 9c + [-,%rflags] v522 = ifcmp_imm v1, -100 ; bin: 83 f9 9c ; asm: cmpl $100, %r10d - [-,%eflags] v523 = ifcmp_imm v3, 100 ; bin: 41 83 fa 64 + [-,%rflags] v523 = ifcmp_imm v3, 100 ; bin: 41 83 fa 64 ; asm: cmpl $-10000, %ecx - [-,%eflags] v524 = ifcmp_imm v1, -10000 ; bin: 81 f9 ffffd8f0 + [-,%rflags] v524 = ifcmp_imm v1, -10000 ; bin: 81 f9 ffffd8f0 ; asm: cmpl $10000, %r10d - [-,%eflags] v525 = ifcmp_imm v3, 10000 ; bin: 41 81 fa 00002710 + [-,%rflags] v525 = ifcmp_imm v3, 10000 ; bin: 41 81 fa 00002710 ; asm: shll $2, %esi [-,%rsi] v526 = ishl_imm v2, 2 ; bin: c1 e6 02 diff --git a/lib/cretonne/meta/isa/intel/recipes.py b/lib/cretonne/meta/isa/intel/recipes.py index 9d015a25bb..5c37677f14 100644 --- a/lib/cretonne/meta/isa/intel/recipes.py +++ b/lib/cretonne/meta/isa/intel/recipes.py @@ -281,7 +281,7 @@ trap = TailRecipe( # Macro: conditional jump over a ud2. trapif = EncRecipe( - 'trapif', IntCondTrap, size=4, ins=FLAG.eflags, outs=(), + 'trapif', IntCondTrap, size=4, ins=FLAG.rflags, outs=(), clobbers_flags=False, emit=''' // Jump over a 2-byte ud2. @@ -293,7 +293,7 @@ trapif = EncRecipe( ''') trapff = EncRecipe( - 'trapff', FloatCondTrap, size=4, ins=FLAG.eflags, outs=(), + 'trapff', FloatCondTrap, size=4, ins=FLAG.rflags, outs=(), clobbers_flags=False, instp=floatccs(FloatCondTrap), emit=''' @@ -985,7 +985,7 @@ jmpd = TailRecipe( ''') brib = TailRecipe( - 'brib', BranchInt, size=1, ins=FLAG.eflags, outs=(), + 'brib', BranchInt, size=1, ins=FLAG.rflags, outs=(), branch_range=8, clobbers_flags=False, emit=''' @@ -994,7 +994,7 @@ brib = TailRecipe( ''') brid = TailRecipe( - 'brid', BranchInt, size=4, ins=FLAG.eflags, outs=(), + 'brid', BranchInt, size=4, ins=FLAG.rflags, outs=(), branch_range=32, clobbers_flags=False, emit=''' @@ -1003,7 +1003,7 @@ brid = TailRecipe( ''') brfb = TailRecipe( - 'brfb', BranchFloat, size=1, ins=FLAG.eflags, outs=(), + 'brfb', BranchFloat, size=1, ins=FLAG.rflags, outs=(), branch_range=8, clobbers_flags=False, instp=floatccs(BranchFloat), @@ -1013,7 +1013,7 @@ brfb = TailRecipe( ''') brfd = TailRecipe( - 'brfd', BranchFloat, size=4, ins=FLAG.eflags, outs=(), + 'brfd', BranchFloat, size=4, ins=FLAG.rflags, outs=(), branch_range=32, clobbers_flags=False, instp=floatccs(BranchFloat), @@ -1033,7 +1033,7 @@ brfd = TailRecipe( # seti = TailRecipe( - 'seti', IntCond, size=1, ins=FLAG.eflags, outs=GPR, + 'seti', IntCond, size=1, ins=FLAG.rflags, outs=GPR, requires_prefix=True, clobbers_flags=False, emit=''' @@ -1041,7 +1041,7 @@ seti = TailRecipe( modrm_r_bits(out_reg0, bits, sink); ''') seti_abcd = TailRecipe( - 'seti_abcd', IntCond, size=1, ins=FLAG.eflags, outs=ABCD, + 'seti_abcd', IntCond, size=1, ins=FLAG.rflags, outs=ABCD, when_prefixed=seti, clobbers_flags=False, emit=''' @@ -1050,7 +1050,7 @@ seti_abcd = TailRecipe( ''') setf = TailRecipe( - 'setf', FloatCond, size=1, ins=FLAG.eflags, outs=GPR, + 'setf', FloatCond, size=1, ins=FLAG.rflags, outs=GPR, requires_prefix=True, clobbers_flags=False, emit=''' @@ -1058,7 +1058,7 @@ setf = TailRecipe( modrm_r_bits(out_reg0, bits, sink); ''') setf_abcd = TailRecipe( - 'setf_abcd', FloatCond, size=1, ins=FLAG.eflags, outs=ABCD, + 'setf_abcd', FloatCond, size=1, ins=FLAG.rflags, outs=ABCD, when_prefixed=setf, clobbers_flags=False, emit=''' @@ -1072,7 +1072,7 @@ setf_abcd = TailRecipe( # 1 byte, modrm(r,r), is after the opcode # cmov = TailRecipe( - 'cmov', IntSelect, size=1, ins=(FLAG.eflags, GPR, GPR), outs=2, + 'cmov', IntSelect, size=1, ins=(FLAG.rflags, GPR, GPR), outs=2, requires_prefix=False, clobbers_flags=False, emit=''' @@ -1084,7 +1084,7 @@ cmov = TailRecipe( # Bit scan forwards and reverse # bsf_and_bsr = TailRecipe( - 'bsf_and_bsr', Unary, size=1, ins=GPR, outs=(GPR, FLAG.eflags), + 'bsf_and_bsr', Unary, size=1, ins=GPR, outs=(GPR, FLAG.rflags), requires_prefix=False, clobbers_flags=True, emit=''' @@ -1098,7 +1098,7 @@ bsf_and_bsr = TailRecipe( # XX /r, MR form. Compare two GPR registers and set flags. rcmp = TailRecipe( - 'rcmp', Binary, size=1, ins=(GPR, GPR), outs=FLAG.eflags, + 'rcmp', Binary, size=1, ins=(GPR, GPR), outs=FLAG.rflags, emit=''' PUT_OP(bits, rex2(in_reg0, in_reg1), sink); modrm_rr(in_reg0, in_reg1, sink); @@ -1106,7 +1106,7 @@ rcmp = TailRecipe( # XX /r, RM form. Compare two FPR registers and set flags. fcmp = TailRecipe( - 'fcmp', Binary, size=1, ins=(FPR, FPR), outs=FLAG.eflags, + 'fcmp', Binary, size=1, ins=(FPR, FPR), outs=FLAG.rflags, emit=''' PUT_OP(bits, rex2(in_reg1, in_reg0), sink); modrm_rr(in_reg1, in_reg0, sink); @@ -1114,7 +1114,7 @@ fcmp = TailRecipe( # XX /n, MI form with imm8. rcmpib = TailRecipe( - 'rcmpib', BinaryImm, size=2, ins=GPR, outs=FLAG.eflags, + 'rcmpib', BinaryImm, size=2, ins=GPR, outs=FLAG.rflags, instp=IsSignedInt(BinaryImm.imm, 8), emit=''' PUT_OP(bits, rex1(in_reg0), sink); @@ -1125,7 +1125,7 @@ rcmpib = TailRecipe( # XX /n, MI form with imm32. rcmpid = TailRecipe( - 'rcmpid', BinaryImm, size=5, ins=GPR, outs=FLAG.eflags, + 'rcmpid', BinaryImm, size=5, ins=GPR, outs=FLAG.rflags, instp=IsSignedInt(BinaryImm.imm, 32), emit=''' PUT_OP(bits, rex1(in_reg0), sink); @@ -1136,7 +1136,7 @@ rcmpid = TailRecipe( # Same as rcmp, but second operand is the stack pointer. rcmp_sp = TailRecipe( - 'rcmp_sp', Unary, size=1, ins=GPR, outs=FLAG.eflags, + 'rcmp_sp', Unary, size=1, ins=GPR, outs=FLAG.rflags, emit=''' PUT_OP(bits, rex2(in_reg0, RU::rsp.into()), sink); modrm_rr(in_reg0, RU::rsp.into(), sink); @@ -1302,7 +1302,7 @@ icscc = TailRecipe( # Same thing for floating point. # -# The ucomiss/ucomisd instructions set the EFLAGS bits CF/PF/CF like this: +# The ucomiss/ucomisd instructions set the FLAGS bits CF/PF/CF like this: # # ZPC OSA # UN 111 000 diff --git a/lib/cretonne/meta/isa/intel/registers.py b/lib/cretonne/meta/isa/intel/registers.py index 354001a102..a4832640cd 100644 --- a/lib/cretonne/meta/isa/intel/registers.py +++ b/lib/cretonne/meta/isa/intel/registers.py @@ -43,7 +43,7 @@ FlagRegs = RegBank( 'Flag registers', units=1, pressure_tracking=False, - names=['eflags']) + names=['rflags']) GPR = RegClass(IntRegs) # Certain types of deref encodings cannot be used with all registers. diff --git a/lib/cretonne/src/isa/intel/binemit.rs b/lib/cretonne/src/isa/intel/binemit.rs index 2d045a0882..ddd3405e18 100644 --- a/lib/cretonne/src/isa/intel/binemit.rs +++ b/lib/cretonne/src/isa/intel/binemit.rs @@ -257,7 +257,7 @@ fn icc2opc(cond: IntCC) -> u16 { /// Get the low 4 bits of an opcode for a floating point condition code. /// -/// The ucomiss/ucomisd instructions set the EFLAGS bits CF/PF/CF like this: +/// The ucomiss/ucomisd instructions set the FLAGS bits CF/PF/CF like this: /// /// ZPC OSA /// UN 111 000 From a661a8a9bb77cad40a8d86e224fd5089470aa3a3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 26 Mar 2018 21:54:36 -0700 Subject: [PATCH 47/72] Factor out common ways to call `encode` from a dfg or func. --- lib/cretonne/src/ir/dfg.rs | 8 +++++++- lib/cretonne/src/ir/function.rs | 9 ++++++++- lib/cretonne/src/legalizer/mod.rs | 8 ++------ lib/cretonne/src/verifier/mod.rs | 6 +----- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/lib/cretonne/src/ir/dfg.rs b/lib/cretonne/src/ir/dfg.rs index 344483a6d9..d23606ee13 100644 --- a/lib/cretonne/src/ir/dfg.rs +++ b/lib/cretonne/src/ir/dfg.rs @@ -1,7 +1,7 @@ //! Data flow graph tracking Instructions, Values, and EBBs. use entity::{PrimaryMap, EntityMap}; -use isa::TargetIsa; +use isa::{TargetIsa, Encoding, Legalize}; use ir; use ir::builder::ReplaceBuilder; use ir::extfunc::ExtFuncData; @@ -645,6 +645,12 @@ impl DataFlowGraph { self.value_type(self.first_result(inst)) } } + + /// Wrapper around `TargetIsa::encode` for encoding an existing instruction + /// in the `DataFlowGraph`. + pub fn encode(&self, inst: Inst, isa: &TargetIsa) -> Result { + isa.encode(&self, &self[inst], self.ctrl_typevar(inst)) + } } /// Allow immutable access to instructions via indexing. diff --git a/lib/cretonne/src/ir/function.rs b/lib/cretonne/src/ir/function.rs index 91ee7eca75..8ee332526f 100644 --- a/lib/cretonne/src/ir/function.rs +++ b/lib/cretonne/src/ir/function.rs @@ -10,7 +10,7 @@ use ir::{ExternalName, CallConv, Signature, DataFlowGraph, Layout}; use ir::{InstEncodings, ValueLocations, JumpTables, StackSlots, EbbOffsets, SourceLocs}; use ir::{Ebb, JumpTableData, JumpTable, StackSlotData, StackSlot, SigRef, ExtFuncData, FuncRef, GlobalVarData, GlobalVar, HeapData, Heap}; -use isa::{TargetIsa, EncInfo}; +use isa::{TargetIsa, EncInfo, Legalize}; use std::fmt; use write::write_function; @@ -176,6 +176,13 @@ impl Function { iter: self.layout.ebb_insts(ebb), } } + + /// Wrapper around `DataFlowGraph::encode` which assigns `inst` the resulting encoding. + pub fn update_encoding(&mut self, inst: ir::Inst, isa: &TargetIsa) -> Result<(), Legalize> { + self.dfg.encode(inst, isa).map( + |e| { self.encodings[inst] = e; }, + ) + } } /// Wrapper type capable of displaying a `Function` with correct ISA annotations. diff --git a/lib/cretonne/src/legalizer/mod.rs b/lib/cretonne/src/legalizer/mod.rs index ae40c42581..68f24ee0da 100644 --- a/lib/cretonne/src/legalizer/mod.rs +++ b/lib/cretonne/src/legalizer/mod.rs @@ -72,12 +72,8 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is split::simplify_branch_arguments(&mut pos.func.dfg, inst); } - match isa.encode( - &pos.func.dfg, - &pos.func.dfg[inst], - pos.func.dfg.ctrl_typevar(inst), - ) { - Ok(encoding) => pos.func.encodings[inst] = encoding, + match pos.func.update_encoding(inst, isa) { + Ok(()) => {} Err(action) => { // We should transform the instruction into legal equivalents. let changed = action(inst, pos.func, cfg, isa); diff --git a/lib/cretonne/src/verifier/mod.rs b/lib/cretonne/src/verifier/mod.rs index b19510a485..8b6eb5e972 100644 --- a/lib/cretonne/src/verifier/mod.rs +++ b/lib/cretonne/src/verifier/mod.rs @@ -1058,11 +1058,7 @@ impl<'a> Verifier<'a> { if let Some(text) = needs_enc { // This instruction needs an encoding, so generate an error. // Provide the ISA default encoding as a hint. - match isa.encode( - &self.func.dfg, - &self.func.dfg[inst], - self.func.dfg.ctrl_typevar(inst), - ) { + match self.func.dfg.encode(inst, isa) { Ok(enc) => { return err!( inst, From 3b0a9b9ecfdbf4a39806dbfc554826c3e3383c77 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 26 Mar 2018 21:58:46 -0700 Subject: [PATCH 48/72] Remove an unused argument. --- lib/cretonne/src/context.rs | 2 +- lib/cretonne/src/simple_gvn.rs | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/cretonne/src/context.rs b/lib/cretonne/src/context.rs index c6018dcd9e..8358f21545 100644 --- a/lib/cretonne/src/context.rs +++ b/lib/cretonne/src/context.rs @@ -191,7 +191,7 @@ impl Context { /// Perform simple GVN on the function. pub fn simple_gvn<'a, FOI: Into>>(&mut self, fisa: FOI) -> CtonResult { - do_simple_gvn(&mut self.func, &mut self.cfg, &mut self.domtree); + do_simple_gvn(&mut self.func, &mut self.domtree); self.verify_if(fisa) } diff --git a/lib/cretonne/src/simple_gvn.rs b/lib/cretonne/src/simple_gvn.rs index dd0fb3b1aa..1cd82e4b2c 100644 --- a/lib/cretonne/src/simple_gvn.rs +++ b/lib/cretonne/src/simple_gvn.rs @@ -1,7 +1,6 @@ //! A simple GVN pass. use cursor::{Cursor, FuncCursor}; -use flowgraph::ControlFlowGraph; use dominator_tree::DominatorTree; use ir::{InstructionData, Function, Inst, Opcode, Type}; use scoped_hash_map::ScopedHashMap; @@ -17,9 +16,8 @@ fn trivially_unsafe_for_gvn(opcode: Opcode) -> bool { /// Perform simple GVN on `func`. /// -pub fn do_simple_gvn(func: &mut Function, cfg: &mut ControlFlowGraph, domtree: &mut DominatorTree) { +pub fn do_simple_gvn(func: &mut Function, domtree: &mut DominatorTree) { let _tt = timing::gvn(); - debug_assert!(cfg.is_valid()); debug_assert!(domtree.is_valid()); let mut visible_values: ScopedHashMap<(InstructionData, Type), Inst> = ScopedHashMap::new(); From 79f02e42dd98a09a1e2cd6e05b7a97c1c273fa15 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 27 Mar 2018 11:21:37 -0700 Subject: [PATCH 49/72] Use movss/movsd rather than movd/movq for floating-point loads and stores. While there may be CPUs that have a domain crossing penalty here, this also helps the generated code look more like the code produced by other compilers. --- .../filetests/isa/intel/binary32-float.cton | 144 ++++++++-------- .../filetests/isa/intel/binary64-float.cton | 160 +++++++++--------- lib/cretonne/meta/isa/intel/encodings.py | 40 ++--- 3 files changed, 172 insertions(+), 172 deletions(-) diff --git a/cranelift/filetests/isa/intel/binary32-float.cton b/cranelift/filetests/isa/intel/binary32-float.cton index 94db28d26e..95e132cf6e 100644 --- a/cranelift/filetests/isa/intel/binary32-float.cton +++ b/cranelift/filetests/isa/intel/binary32-float.cton @@ -147,48 +147,48 @@ ebb0: ; Load/Store - ; asm: movd (%ecx), %xmm5 - [-,%xmm5] v100 = load.f32 v0 ; bin: 66 0f 6e 29 - ; asm: movd (%esi), %xmm2 - [-,%xmm2] v101 = load.f32 v1 ; bin: 66 0f 6e 16 - ; asm: movd 50(%ecx), %xmm5 - [-,%xmm5] v110 = load.f32 v0+50 ; bin: 66 0f 6e 69 32 - ; asm: movd -50(%esi), %xmm2 - [-,%xmm2] v111 = load.f32 v1-50 ; bin: 66 0f 6e 56 ce - ; asm: movd 10000(%ecx), %xmm5 - [-,%xmm5] v120 = load.f32 v0+10000 ; bin: 66 0f 6e a9 00002710 - ; asm: movd -10000(%esi), %xmm2 - [-,%xmm2] v121 = load.f32 v1-10000 ; bin: 66 0f 6e 96 ffffd8f0 + ; asm: movss (%ecx), %xmm5 + [-,%xmm5] v100 = load.f32 v0 ; bin: f3 0f 10 29 + ; asm: movss (%esi), %xmm2 + [-,%xmm2] v101 = load.f32 v1 ; bin: f3 0f 10 16 + ; asm: movss 50(%ecx), %xmm5 + [-,%xmm5] v110 = load.f32 v0+50 ; bin: f3 0f 10 69 32 + ; asm: movss -50(%esi), %xmm2 + [-,%xmm2] v111 = load.f32 v1-50 ; bin: f3 0f 10 56 ce + ; asm: movss 10000(%ecx), %xmm5 + [-,%xmm5] v120 = load.f32 v0+10000 ; bin: f3 0f 10 a9 00002710 + ; asm: movss -10000(%esi), %xmm2 + [-,%xmm2] v121 = load.f32 v1-10000 ; bin: f3 0f 10 96 ffffd8f0 - ; asm: movd %xmm5, (%ecx) - [-] store.f32 v100, v0 ; bin: 66 0f 7e 29 - ; asm: movd %xmm2, (%esi) - [-] store.f32 v101, v1 ; bin: 66 0f 7e 16 - ; asm: movd %xmm5, 50(%ecx) - [-] store.f32 v100, v0+50 ; bin: 66 0f 7e 69 32 - ; asm: movd %xmm2, -50(%esi) - [-] store.f32 v101, v1-50 ; bin: 66 0f 7e 56 ce - ; asm: movd %xmm5, 10000(%ecx) - [-] store.f32 v100, v0+10000 ; bin: 66 0f 7e a9 00002710 - ; asm: movd %xmm2, -10000(%esi) - [-] store.f32 v101, v1-10000 ; bin: 66 0f 7e 96 ffffd8f0 + ; asm: movss %xmm5, (%ecx) + [-] store.f32 v100, v0 ; bin: f3 0f 11 29 + ; asm: movss %xmm2, (%esi) + [-] store.f32 v101, v1 ; bin: f3 0f 11 16 + ; asm: movss %xmm5, 50(%ecx) + [-] store.f32 v100, v0+50 ; bin: f3 0f 11 69 32 + ; asm: movss %xmm2, -50(%esi) + [-] store.f32 v101, v1-50 ; bin: f3 0f 11 56 ce + ; asm: movss %xmm5, 10000(%ecx) + [-] store.f32 v100, v0+10000 ; bin: f3 0f 11 a9 00002710 + ; asm: movss %xmm2, -10000(%esi) + [-] store.f32 v101, v1-10000 ; bin: f3 0f 11 96 ffffd8f0 ; Spill / Fill. - ; asm: movd %xmm5, 1032(%esp) - [-,ss1] v200 = spill v100 ; bin: 66 0f 7e ac 24 00000408 - ; asm: movd %xmm2, 1032(%esp) - [-,ss1] v201 = spill v101 ; bin: 66 0f 7e 94 24 00000408 + ; asm: movss %xmm5, 1032(%esp) + [-,ss1] v200 = spill v100 ; bin: f3 0f 11 ac 24 00000408 + ; asm: movss %xmm2, 1032(%esp) + [-,ss1] v201 = spill v101 ; bin: f3 0f 11 94 24 00000408 - ; asm: movd 1032(%esp), %xmm5 - [-,%xmm5] v210 = fill v200 ; bin: 66 0f 6e ac 24 00000408 - ; asm: movd 1032(%esp), %xmm2 - [-,%xmm2] v211 = fill v201 ; bin: 66 0f 6e 94 24 00000408 + ; asm: movss 1032(%esp), %xmm5 + [-,%xmm5] v210 = fill v200 ; bin: f3 0f 10 ac 24 00000408 + ; asm: movss 1032(%esp), %xmm2 + [-,%xmm2] v211 = fill v201 ; bin: f3 0f 10 94 24 00000408 - ; asm: movd %xmm5, 1032(%rsp) - regspill v100, %xmm5 -> ss1 ; bin: 66 0f 7e ac 24 00000408 - ; asm: movd 1032(%rsp), %xmm5 - regfill v100, ss1 -> %xmm5 ; bin: 66 0f 6e ac 24 00000408 + ; asm: movss %xmm5, 1032(%rsp) + regspill v100, %xmm5 -> ss1 ; bin: f3 0f 11 ac 24 00000408 + ; asm: movss 1032(%rsp), %xmm5 + regfill v100, ss1 -> %xmm5 ; bin: f3 0f 10 ac 24 00000408 ; Comparisons. ; @@ -362,48 +362,48 @@ ebb0: ; Load/Store - ; asm: movq (%ecx), %xmm5 - [-,%xmm5] v100 = load.f64 v0 ; bin: f3 0f 7e 29 - ; asm: movq (%esi), %xmm2 - [-,%xmm2] v101 = load.f64 v1 ; bin: f3 0f 7e 16 - ; asm: movq 50(%ecx), %xmm5 - [-,%xmm5] v110 = load.f64 v0+50 ; bin: f3 0f 7e 69 32 - ; asm: movq -50(%esi), %xmm2 - [-,%xmm2] v111 = load.f64 v1-50 ; bin: f3 0f 7e 56 ce - ; asm: movq 10000(%ecx), %xmm5 - [-,%xmm5] v120 = load.f64 v0+10000 ; bin: f3 0f 7e a9 00002710 - ; asm: movq -10000(%esi), %xmm2 - [-,%xmm2] v121 = load.f64 v1-10000 ; bin: f3 0f 7e 96 ffffd8f0 + ; asm: movsd (%ecx), %xmm5 + [-,%xmm5] v100 = load.f64 v0 ; bin: f2 0f 10 29 + ; asm: movsd (%esi), %xmm2 + [-,%xmm2] v101 = load.f64 v1 ; bin: f2 0f 10 16 + ; asm: movsd 50(%ecx), %xmm5 + [-,%xmm5] v110 = load.f64 v0+50 ; bin: f2 0f 10 69 32 + ; asm: movsd -50(%esi), %xmm2 + [-,%xmm2] v111 = load.f64 v1-50 ; bin: f2 0f 10 56 ce + ; asm: movsd 10000(%ecx), %xmm5 + [-,%xmm5] v120 = load.f64 v0+10000 ; bin: f2 0f 10 a9 00002710 + ; asm: movsd -10000(%esi), %xmm2 + [-,%xmm2] v121 = load.f64 v1-10000 ; bin: f2 0f 10 96 ffffd8f0 - ; asm: movq %xmm5, (%ecx) - [-] store.f64 v100, v0 ; bin: 66 0f d6 29 - ; asm: movq %xmm2, (%esi) - [-] store.f64 v101, v1 ; bin: 66 0f d6 16 - ; asm: movq %xmm5, 50(%ecx) - [-] store.f64 v100, v0+50 ; bin: 66 0f d6 69 32 - ; asm: movq %xmm2, -50(%esi) - [-] store.f64 v101, v1-50 ; bin: 66 0f d6 56 ce - ; asm: movq %xmm5, 10000(%ecx) - [-] store.f64 v100, v0+10000 ; bin: 66 0f d6 a9 00002710 - ; asm: movq %xmm2, -10000(%esi) - [-] store.f64 v101, v1-10000 ; bin: 66 0f d6 96 ffffd8f0 + ; asm: movsd %xmm5, (%ecx) + [-] store.f64 v100, v0 ; bin: f2 0f 11 29 + ; asm: movsd %xmm2, (%esi) + [-] store.f64 v101, v1 ; bin: f2 0f 11 16 + ; asm: movsd %xmm5, 50(%ecx) + [-] store.f64 v100, v0+50 ; bin: f2 0f 11 69 32 + ; asm: movsd %xmm2, -50(%esi) + [-] store.f64 v101, v1-50 ; bin: f2 0f 11 56 ce + ; asm: movsd %xmm5, 10000(%ecx) + [-] store.f64 v100, v0+10000 ; bin: f2 0f 11 a9 00002710 + ; asm: movsd %xmm2, -10000(%esi) + [-] store.f64 v101, v1-10000 ; bin: f2 0f 11 96 ffffd8f0 ; Spill / Fill. - ; asm: movq %xmm5, 1032(%esp) - [-,ss1] v200 = spill v100 ; bin: 66 0f d6 ac 24 00000408 - ; asm: movq %xmm2, 1032(%esp) - [-,ss1] v201 = spill v101 ; bin: 66 0f d6 94 24 00000408 + ; asm: movsd %xmm5, 1032(%esp) + [-,ss1] v200 = spill v100 ; bin: f2 0f 11 ac 24 00000408 + ; asm: movsd %xmm2, 1032(%esp) + [-,ss1] v201 = spill v101 ; bin: f2 0f 11 94 24 00000408 - ; asm: movq 1032(%esp), %xmm5 - [-,%xmm5] v210 = fill v200 ; bin: f3 0f 7e ac 24 00000408 - ; asm: movq 1032(%esp), %xmm2 - [-,%xmm2] v211 = fill v201 ; bin: f3 0f 7e 94 24 00000408 + ; asm: movsd 1032(%esp), %xmm5 + [-,%xmm5] v210 = fill v200 ; bin: f2 0f 10 ac 24 00000408 + ; asm: movsd 1032(%esp), %xmm2 + [-,%xmm2] v211 = fill v201 ; bin: f2 0f 10 94 24 00000408 - ; asm: movq %xmm5, 1032(%rsp) - regspill v100, %xmm5 -> ss1 ; bin: 66 0f d6 ac 24 00000408 - ; asm: movq 1032(%rsp), %xmm5 - regfill v100, ss1 -> %xmm5 ; bin: f3 0f 7e ac 24 00000408 + ; asm: movsd %xmm5, 1032(%rsp) + regspill v100, %xmm5 -> ss1 ; bin: f2 0f 11 ac 24 00000408 + ; asm: movsd 1032(%rsp), %xmm5 + regfill v100, ss1 -> %xmm5 ; bin: f2 0f 10 ac 24 00000408 ; Comparisons. ; diff --git a/cranelift/filetests/isa/intel/binary64-float.cton b/cranelift/filetests/isa/intel/binary64-float.cton index b362b7eb4a..47db5b197f 100644 --- a/cranelift/filetests/isa/intel/binary64-float.cton +++ b/cranelift/filetests/isa/intel/binary64-float.cton @@ -157,52 +157,52 @@ ebb0: ; Load/Store - ; asm: movd (%r14), %xmm5 - [-,%xmm5] v100 = load.f32 v3 ; bin: 66 41 0f 6e 2e - ; asm: movd (%rax), %xmm10 - [-,%xmm10] v101 = load.f32 v2 ; bin: 66 44 0f 6e 10 - ; asm: movd 50(%r14), %xmm5 - [-,%xmm5] v110 = load.f32 v3+50 ; bin: 66 41 0f 6e 6e 32 - ; asm: movd -50(%rax), %xmm10 - [-,%xmm10] v111 = load.f32 v2-50 ; bin: 66 44 0f 6e 50 ce - ; asm: movd 10000(%r14), %xmm5 - [-,%xmm5] v120 = load.f32 v3+10000 ; bin: 66 41 0f 6e ae 00002710 - ; asm: movd -10000(%rax), %xmm10 - [-,%xmm10] v121 = load.f32 v2-10000 ; bin: 66 44 0f 6e 90 ffffd8f0 + ; asm: movss (%r14), %xmm5 + [-,%xmm5] v100 = load.f32 v3 ; bin: f3 41 0f 10 2e + ; asm: movss (%rax), %xmm10 + [-,%xmm10] v101 = load.f32 v2 ; bin: f3 44 0f 10 10 + ; asm: movss 50(%r14), %xmm5 + [-,%xmm5] v110 = load.f32 v3+50 ; bin: f3 41 0f 10 6e 32 + ; asm: movss -50(%rax), %xmm10 + [-,%xmm10] v111 = load.f32 v2-50 ; bin: f3 44 0f 10 50 ce + ; asm: movss 10000(%r14), %xmm5 + [-,%xmm5] v120 = load.f32 v3+10000 ; bin: f3 41 0f 10 ae 00002710 + ; asm: movss -10000(%rax), %xmm10 + [-,%xmm10] v121 = load.f32 v2-10000 ; bin: f3 44 0f 10 90 ffffd8f0 - ; asm: movd %xmm5, (%r14) - [-] store.f32 v100, v3 ; bin: 66 41 0f 7e 2e - ; asm: movd %xmm10, (%rax) - [-] store.f32 v101, v2 ; bin: 66 44 0f 7e 10 - ; asm: movd %xmm5, (%r13) - [-] store.f32 v100, v4 ; bin: 66 41 0f 7e 6d 00 - ; asm: movd %xmm10, (%r13) - [-] store.f32 v101, v4 ; bin: 66 45 0f 7e 55 00 - ; asm: movd %xmm5, 50(%r14) - [-] store.f32 v100, v3+50 ; bin: 66 41 0f 7e 6e 32 - ; asm: movd %xmm10, -50(%rax) - [-] store.f32 v101, v2-50 ; bin: 66 44 0f 7e 50 ce - ; asm: movd %xmm5, 10000(%r14) - [-] store.f32 v100, v3+10000 ; bin: 66 41 0f 7e ae 00002710 - ; asm: movd %xmm10, -10000(%rax) - [-] store.f32 v101, v2-10000 ; bin: 66 44 0f 7e 90 ffffd8f0 + ; asm: movss %xmm5, (%r14) + [-] store.f32 v100, v3 ; bin: f3 41 0f 11 2e + ; asm: movss %xmm10, (%rax) + [-] store.f32 v101, v2 ; bin: f3 44 0f 11 10 + ; asm: movss %xmm5, (%r13) + [-] store.f32 v100, v4 ; bin: f3 41 0f 11 6d 00 + ; asm: movss %xmm10, (%r13) + [-] store.f32 v101, v4 ; bin: f3 45 0f 11 55 00 + ; asm: movss %xmm5, 50(%r14) + [-] store.f32 v100, v3+50 ; bin: f3 41 0f 11 6e 32 + ; asm: movss %xmm10, -50(%rax) + [-] store.f32 v101, v2-50 ; bin: f3 44 0f 11 50 ce + ; asm: movss %xmm5, 10000(%r14) + [-] store.f32 v100, v3+10000 ; bin: f3 41 0f 11 ae 00002710 + ; asm: movss %xmm10, -10000(%rax) + [-] store.f32 v101, v2-10000 ; bin: f3 44 0f 11 90 ffffd8f0 ; Spill / Fill. - ; asm: movd %xmm5, 1032(%rsp) - [-,ss1] v200 = spill v100 ; bin: 66 0f 7e ac 24 00000408 - ; asm: movd %xmm10, 1032(%rsp) - [-,ss1] v201 = spill v101 ; bin: 66 44 0f 7e 94 24 00000408 + ; asm: movss %xmm5, 1032(%rsp) + [-,ss1] v200 = spill v100 ; bin: f3 0f 11 ac 24 00000408 + ; asm: movss %xmm10, 1032(%rsp) + [-,ss1] v201 = spill v101 ; bin: f3 44 0f 11 94 24 00000408 - ; asm: movd 1032(%rsp), %xmm5 - [-,%xmm5] v210 = fill v200 ; bin: 66 0f 6e ac 24 00000408 - ; asm: movd 1032(%rsp), %xmm10 - [-,%xmm10] v211 = fill v201 ; bin: 66 44 0f 6e 94 24 00000408 + ; asm: movss 1032(%rsp), %xmm5 + [-,%xmm5] v210 = fill v200 ; bin: f3 0f 10 ac 24 00000408 + ; asm: movss 1032(%rsp), %xmm10 + [-,%xmm10] v211 = fill v201 ; bin: f3 44 0f 10 94 24 00000408 - ; asm: movd %xmm5, 1032(%rsp) - regspill v100, %xmm5 -> ss1 ; bin: 66 0f 7e ac 24 00000408 - ; asm: movd 1032(%rsp), %xmm5 - regfill v100, ss1 -> %xmm5 ; bin: 66 0f 6e ac 24 00000408 + ; asm: movss %xmm5, 1032(%rsp) + regspill v100, %xmm5 -> ss1 ; bin: f3 0f 11 ac 24 00000408 + ; asm: movss 1032(%rsp), %xmm5 + regfill v100, ss1 -> %xmm5 ; bin: f3 0f 10 ac 24 00000408 ; Comparisons. ; @@ -392,52 +392,52 @@ ebb0: ; Load/Store - ; asm: movq (%r14), %xmm5 - [-,%xmm5] v100 = load.f64 v3 ; bin: f3 41 0f 7e 2e - ; asm: movq (%rax), %xmm10 - [-,%xmm10] v101 = load.f64 v2 ; bin: f3 44 0f 7e 10 - ; asm: movq 50(%r14), %xmm5 - [-,%xmm5] v110 = load.f64 v3+50 ; bin: f3 41 0f 7e 6e 32 - ; asm: movq -50(%rax), %xmm10 - [-,%xmm10] v111 = load.f64 v2-50 ; bin: f3 44 0f 7e 50 ce - ; asm: movq 10000(%r14), %xmm5 - [-,%xmm5] v120 = load.f64 v3+10000 ; bin: f3 41 0f 7e ae 00002710 - ; asm: movq -10000(%rax), %xmm10 - [-,%xmm10] v121 = load.f64 v2-10000 ; bin: f3 44 0f 7e 90 ffffd8f0 + ; asm: movsd (%r14), %xmm5 + [-,%xmm5] v100 = load.f64 v3 ; bin: f2 41 0f 10 2e + ; asm: movsd (%rax), %xmm10 + [-,%xmm10] v101 = load.f64 v2 ; bin: f2 44 0f 10 10 + ; asm: movsd 50(%r14), %xmm5 + [-,%xmm5] v110 = load.f64 v3+50 ; bin: f2 41 0f 10 6e 32 + ; asm: movsd -50(%rax), %xmm10 + [-,%xmm10] v111 = load.f64 v2-50 ; bin: f2 44 0f 10 50 ce + ; asm: movsd 10000(%r14), %xmm5 + [-,%xmm5] v120 = load.f64 v3+10000 ; bin: f2 41 0f 10 ae 00002710 + ; asm: movsd -10000(%rax), %xmm10 + [-,%xmm10] v121 = load.f64 v2-10000 ; bin: f2 44 0f 10 90 ffffd8f0 - ; asm: movq %xmm5, (%r14) - [-] store.f64 v100, v3 ; bin: 66 41 0f d6 2e - ; asm: movq %xmm10, (%rax) - [-] store.f64 v101, v2 ; bin: 66 44 0f d6 10 - ; asm: movq %xmm5, (%r13) - [-] store.f64 v100, v4 ; bin: 66 41 0f d6 6d 00 - ; asm: movq %xmm10, (%r13) - [-] store.f64 v101, v4 ; bin: 66 45 0f d6 55 00 - ; asm: movq %xmm5, 50(%r14) - [-] store.f64 v100, v3+50 ; bin: 66 41 0f d6 6e 32 - ; asm: movq %xmm10, -50(%rax) - [-] store.f64 v101, v2-50 ; bin: 66 44 0f d6 50 ce - ; asm: movq %xmm5, 10000(%r14) - [-] store.f64 v100, v3+10000 ; bin: 66 41 0f d6 ae 00002710 - ; asm: movq %xmm10, -10000(%rax) - [-] store.f64 v101, v2-10000 ; bin: 66 44 0f d6 90 ffffd8f0 + ; asm: movsd %xmm5, (%r14) + [-] store.f64 v100, v3 ; bin: f2 41 0f 11 2e + ; asm: movsd %xmm10, (%rax) + [-] store.f64 v101, v2 ; bin: f2 44 0f 11 10 + ; asm: movsd %xmm5, (%r13) + [-] store.f64 v100, v4 ; bin: f2 41 0f 11 6d 00 + ; asm: movsd %xmm10, (%r13) + [-] store.f64 v101, v4 ; bin: f2 45 0f 11 55 00 + ; asm: movsd %xmm5, 50(%r14) + [-] store.f64 v100, v3+50 ; bin: f2 41 0f 11 6e 32 + ; asm: movsd %xmm10, -50(%rax) + [-] store.f64 v101, v2-50 ; bin: f2 44 0f 11 50 ce + ; asm: movsd %xmm5, 10000(%r14) + [-] store.f64 v100, v3+10000 ; bin: f2 41 0f 11 ae 00002710 + ; asm: movsd %xmm10, -10000(%rax) + [-] store.f64 v101, v2-10000 ; bin: f2 44 0f 11 90 ffffd8f0 ; Spill / Fill. - ; asm: movq %xmm5, 1032(%rsp) - [-,ss1] v200 = spill v100 ; bin: 66 0f d6 ac 24 00000408 - ; asm: movq %xmm10, 1032(%rsp) - [-,ss1] v201 = spill v101 ; bin: 66 44 0f d6 94 24 00000408 + ; asm: movsd %xmm5, 1032(%rsp) + [-,ss1] v200 = spill v100 ; bin: f2 0f 11 ac 24 00000408 + ; asm: movsd %xmm10, 1032(%rsp) + [-,ss1] v201 = spill v101 ; bin: f2 44 0f 11 94 24 00000408 - ; asm: movq 1032(%rsp), %xmm5 - [-,%xmm5] v210 = fill v200 ; bin: f3 0f 7e ac 24 00000408 - ; asm: movq 1032(%rsp), %xmm10 - [-,%xmm10] v211 = fill v201 ; bin: f3 44 0f 7e 94 24 00000408 + ; asm: movsd 1032(%rsp), %xmm5 + [-,%xmm5] v210 = fill v200 ; bin: f2 0f 10 ac 24 00000408 + ; asm: movsd 1032(%rsp), %xmm10 + [-,%xmm10] v211 = fill v201 ; bin: f2 44 0f 10 94 24 00000408 - ; asm: movq %xmm5, 1032(%rsp) - regspill v100, %xmm5 -> ss1 ; bin: 66 0f d6 ac 24 00000408 - ; asm: movq 1032(%rsp), %xmm5 - regfill v100, ss1 -> %xmm5 ; bin: f3 0f 7e ac 24 00000408 + ; asm: movsd %xmm5, 1032(%rsp) + regspill v100, %xmm5 -> ss1 ; bin: f2 0f 11 ac 24 00000408 + ; asm: movsd 1032(%rsp), %xmm5 + regfill v100, ss1 -> %xmm5 ; bin: f2 0f 10 ac 24 00000408 ; Comparisons. ; diff --git a/lib/cretonne/meta/isa/intel/encodings.py b/lib/cretonne/meta/isa/intel/encodings.py index afb544cb9a..fca2ce8699 100644 --- a/lib/cretonne/meta/isa/intel/encodings.py +++ b/lib/cretonne/meta/isa/intel/encodings.py @@ -259,31 +259,31 @@ X86_64.enc(base.adjust_sp_imm, *r.adjustsp32.rex(0x81, w=1)) # Float loads and stores. # -enc_both(base.load.f32.any, r.fld, 0x66, 0x0f, 0x6e) -enc_both(base.load.f32.any, r.fldDisp8, 0x66, 0x0f, 0x6e) -enc_both(base.load.f32.any, r.fldDisp32, 0x66, 0x0f, 0x6e) +enc_both(base.load.f32.any, r.fld, 0xf3, 0x0f, 0x10) +enc_both(base.load.f32.any, r.fldDisp8, 0xf3, 0x0f, 0x10) +enc_both(base.load.f32.any, r.fldDisp32, 0xf3, 0x0f, 0x10) -enc_both(base.load.f64.any, r.fld, 0xf3, 0x0f, 0x7e) -enc_both(base.load.f64.any, r.fldDisp8, 0xf3, 0x0f, 0x7e) -enc_both(base.load.f64.any, r.fldDisp32, 0xf3, 0x0f, 0x7e) +enc_both(base.load.f64.any, r.fld, 0xf2, 0x0f, 0x10) +enc_both(base.load.f64.any, r.fldDisp8, 0xf2, 0x0f, 0x10) +enc_both(base.load.f64.any, r.fldDisp32, 0xf2, 0x0f, 0x10) -enc_both(base.store.f32.any, r.fst, 0x66, 0x0f, 0x7e) -enc_both(base.store.f32.any, r.fstDisp8, 0x66, 0x0f, 0x7e) -enc_both(base.store.f32.any, r.fstDisp32, 0x66, 0x0f, 0x7e) +enc_both(base.store.f32.any, r.fst, 0xf3, 0x0f, 0x11) +enc_both(base.store.f32.any, r.fstDisp8, 0xf3, 0x0f, 0x11) +enc_both(base.store.f32.any, r.fstDisp32, 0xf3, 0x0f, 0x11) -enc_both(base.store.f64.any, r.fst, 0x66, 0x0f, 0xd6) -enc_both(base.store.f64.any, r.fstDisp8, 0x66, 0x0f, 0xd6) -enc_both(base.store.f64.any, r.fstDisp32, 0x66, 0x0f, 0xd6) +enc_both(base.store.f64.any, r.fst, 0xf2, 0x0f, 0x11) +enc_both(base.store.f64.any, r.fstDisp8, 0xf2, 0x0f, 0x11) +enc_both(base.store.f64.any, r.fstDisp32, 0xf2, 0x0f, 0x11) -enc_both(base.fill.f32, r.ffillSib32, 0x66, 0x0f, 0x6e) -enc_both(base.regfill.f32, r.fregfill32, 0x66, 0x0f, 0x6e) -enc_both(base.fill.f64, r.ffillSib32, 0xf3, 0x0f, 0x7e) -enc_both(base.regfill.f64, r.fregfill32, 0xf3, 0x0f, 0x7e) +enc_both(base.fill.f32, r.ffillSib32, 0xf3, 0x0f, 0x10) +enc_both(base.regfill.f32, r.fregfill32, 0xf3, 0x0f, 0x10) +enc_both(base.fill.f64, r.ffillSib32, 0xf2, 0x0f, 0x10) +enc_both(base.regfill.f64, r.fregfill32, 0xf2, 0x0f, 0x10) -enc_both(base.spill.f32, r.fspillSib32, 0x66, 0x0f, 0x7e) -enc_both(base.regspill.f32, r.fregspill32, 0x66, 0x0f, 0x7e) -enc_both(base.spill.f64, r.fspillSib32, 0x66, 0x0f, 0xd6) -enc_both(base.regspill.f64, r.fregspill32, 0x66, 0x0f, 0xd6) +enc_both(base.spill.f32, r.fspillSib32, 0xf3, 0x0f, 0x11) +enc_both(base.regspill.f32, r.fregspill32, 0xf3, 0x0f, 0x11) +enc_both(base.spill.f64, r.fspillSib32, 0xf2, 0x0f, 0x11) +enc_both(base.regspill.f64, r.fregspill32, 0xf2, 0x0f, 0x11) # # Function addresses. From 0b5bb313cb1c2f552141390ae8e7a649a56a957d Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 27 Mar 2018 14:12:06 -0700 Subject: [PATCH 50/72] Mark CondCode's functions #[must_use]. It's easy to forget whether they mutate the value in place or return a new value. Marking them #[must_use] will catch cases where they are used incorrectly. --- lib/cretonne/src/ir/condcodes.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/cretonne/src/ir/condcodes.rs b/lib/cretonne/src/ir/condcodes.rs index 11c438b10a..61967a5871 100644 --- a/lib/cretonne/src/ir/condcodes.rs +++ b/lib/cretonne/src/ir/condcodes.rs @@ -13,12 +13,14 @@ pub trait CondCode: Copy { /// /// The inverse condition code produces the opposite result for all comparisons. /// That is, `cmp CC, x, y` is true if and only if `cmp CC.inverse(), x, y` is false. + #[must_use] fn inverse(self) -> Self; /// Get the reversed condition code for `self`. /// /// The reversed condition code produces the same result as swapping `x` and `y` in the /// comparison. That is, `cmp CC, x, y` is the same as `cmp CC.reverse(), y, x`. + #[must_use] fn reverse(self) -> Self; } From 7cce4be96a6021c38a50cfd26d285f69a8a7b99c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 27 Mar 2018 21:11:24 -0700 Subject: [PATCH 51/72] Fix an incorrect index in "cton-util wasm -s". --- cranelift/src/wasm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cranelift/src/wasm.rs b/cranelift/src/wasm.rs index efd93df77f..5f986ee5f2 100644 --- a/cranelift/src/wasm.rs +++ b/cranelift/src/wasm.rs @@ -170,7 +170,7 @@ fn handle_module( println!( "Function #{} bytecode size: {} bytes", func_index, - dummy_environ.func_bytecode_sizes[func_index] + dummy_environ.func_bytecode_sizes[def_index] ); } } else { From 7b51edd2858db121f582db6475b0f89403e54942 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Mar 2018 08:58:58 -0700 Subject: [PATCH 52/72] Fix spelling in a comment to be consistent with the code. --- lib/cretonne/src/regalloc/coalescing.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cretonne/src/regalloc/coalescing.rs b/lib/cretonne/src/regalloc/coalescing.rs index 2437fd1a03..f23d55433e 100644 --- a/lib/cretonne/src/regalloc/coalescing.rs +++ b/lib/cretonne/src/regalloc/coalescing.rs @@ -907,7 +907,7 @@ impl VirtualCopies { self.filter.clear(); } - /// Initialise virtual copies from the (interfering) values in a union-find virtual register + /// Initialize virtual copies from the (interfering) values in a union-find virtual register /// that is going to be broken up and reassembled iteratively. /// /// The values are assumed to be in domtree pre-order. From 8d560cf8ba38b57a42460431d47ffdb08cf95162 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Mar 2018 11:50:19 -0700 Subject: [PATCH 53/72] Fix Rust syntax in generated code. This code is not currently emitted, though it will be when there are more legalization rules. --- lib/cretonne/meta/gen_legalizer.py | 13 +++++++------ lib/cretonne/meta/test_gen_legalizer.py | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/cretonne/meta/gen_legalizer.py b/lib/cretonne/meta/gen_legalizer.py index 04c48ade51..9051337238 100644 --- a/lib/cretonne/meta/gen_legalizer.py +++ b/lib/cretonne/meta/gen_legalizer.py @@ -103,18 +103,19 @@ def emit_runtime_typecheck(check, fmt, type_sets): base_exp = build_derived_expr(tv.base) if (tv.derived_func == TypeVar.LANEOF): - return "{}.map(|t: Type| -> t.lane_type())".format(base_exp) + return "{}.map(|t: ir::Type| t.lane_type())".format(base_exp) elif (tv.derived_func == TypeVar.ASBOOL): - return "{}.map(|t: Type| -> t.as_bool())".format(base_exp) + return "{}.map(|t: ir::Type| t.as_bool())".format(base_exp) elif (tv.derived_func == TypeVar.HALFWIDTH): - return "{}.and_then(|t: Type| -> t.half_width())".format(base_exp) + return "{}.and_then(|t: ir::Type| t.half_width())".format(base_exp) elif (tv.derived_func == TypeVar.DOUBLEWIDTH): - return "{}.and_then(|t: Type| -> t.double_width())"\ + return "{}.and_then(|t: ir::Type| t.double_width())"\ .format(base_exp) elif (tv.derived_func == TypeVar.HALFVECTOR): - return "{}.and_then(|t: Type| -> t.half_vector())".format(base_exp) + return "{}.and_then(|t: ir::Type| t.half_vector())"\ + .format(base_exp) elif (tv.derived_func == TypeVar.DOUBLEVECTOR): - return "{}.and_then(|t: Type| -> t.by(2))".format(base_exp) + return "{}.and_then(|t: ir::Type| t.by(2))".format(base_exp) else: assert False, "Unknown derived function {}".format(tv.derived_func) diff --git a/lib/cretonne/meta/test_gen_legalizer.py b/lib/cretonne/meta/test_gen_legalizer.py index 793555a42c..3882bd0bf9 100644 --- a/lib/cretonne/meta/test_gen_legalizer.py +++ b/lib/cretonne/meta/test_gen_legalizer.py @@ -148,9 +148,9 @@ class TestRuntimeChecks(TestCase): self.v5 << vselect(self.v1, self.v3, self.v4), ) x = XForm(r, r) - tv2_exp = 'Some({}).map(|t: Type| -> t.as_bool())'\ + tv2_exp = 'Some({}).map(|t: ir::Type| t.as_bool())'\ .format(self.v2.get_typevar().name) - tv3_exp = 'Some({}).map(|t: Type| -> t.as_bool())'\ + tv3_exp = 'Some({}).map(|t: ir::Type| t.as_bool())'\ .format(self.v3.get_typevar().name) self.check_yo_check( From c3f044ff46c500969fd46926c441e723c78034c6 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Mar 2018 13:44:16 -0700 Subject: [PATCH 54/72] Note that the "widen" legalization group is not yet implemented. --- lib/cretonne/meta/base/legalize.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/cretonne/meta/base/legalize.py b/lib/cretonne/meta/base/legalize.py index ecc8d5a436..c2392269df 100644 --- a/lib/cretonne/meta/base/legalize.py +++ b/lib/cretonne/meta/base/legalize.py @@ -41,6 +41,8 @@ widen = XFormGroup('widen', """ The transformations in the 'widen' group work by expressing instructions in terms of larger types. + + This group is not yet implemented. """) expand = XFormGroup('expand', """ From 23ab07b54eddcfc7ea5b623e5eb7f5aacb160bf3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Mar 2018 14:11:16 -0700 Subject: [PATCH 55/72] Support legalizing bconst instructions on x86. --- cranelift/filetests/isa/intel/binary32.cton | 3 +++ cranelift/filetests/isa/intel/binary64.cton | 5 +++++ lib/cretonne/meta/isa/intel/encodings.py | 3 +++ lib/cretonne/meta/isa/intel/recipes.py | 14 +++++++++++++- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/cranelift/filetests/isa/intel/binary32.cton b/cranelift/filetests/isa/intel/binary32.cton index 771bb19af2..04f492c354 100644 --- a/cranelift/filetests/isa/intel/binary32.cton +++ b/cranelift/filetests/isa/intel/binary32.cton @@ -25,6 +25,9 @@ ebb0: ; asm: movl $2, %esi [-,%rsi] v2 = iconst.i32 2 ; bin: be 00000002 + ; asm: movb $1, %cl + [-,%rcx] v9007 = bconst.b1 true ; bin: b9 00000001 + ; Integer Register-Register Operations. ; asm: addl %esi, %ecx diff --git a/cranelift/filetests/isa/intel/binary64.cton b/cranelift/filetests/isa/intel/binary64.cton index 3c35bd2a0c..f7aab2f8f4 100644 --- a/cranelift/filetests/isa/intel/binary64.cton +++ b/cranelift/filetests/isa/intel/binary64.cton @@ -38,6 +38,11 @@ ebb0: ; asm: movq $0xffffffff88001122, %r14 # 32-bit sign-extended constant. [-,%r14] v5 = iconst.i64 0xffff_ffff_8800_1122 ; bin: 49 c7 c6 88001122 + ; asm: movb $1, %cl + [-,%rcx] v9007 = bconst.b1 true ; bin: b9 00000001 + ; asm: movb $1, %sil + [-,%r10] v9008 = bconst.b1 true ; bin: 41 ba 00000001 + ; Integer Register-Register Operations. ; asm: addq %rsi, %rcx diff --git a/lib/cretonne/meta/isa/intel/encodings.py b/lib/cretonne/meta/isa/intel/encodings.py index fca2ce8699..72ef7a362b 100644 --- a/lib/cretonne/meta/isa/intel/encodings.py +++ b/lib/cretonne/meta/isa/intel/encodings.py @@ -155,6 +155,9 @@ X86_64.enc(base.iconst.i64, *r.uid.rex(0xc7, rrr=0, w=1)) # Finally, the 0xb8 opcode takes an 8-byte immediate with a REX.W prefix. X86_64.enc(base.iconst.i64, *r.puiq.rex(0xb8, w=1)) +# bool constants. +enc_both(base.bconst.b1, r.puid_bool, 0xb8) + # Shifts and rotates. # Note that the dynamic shift amount is only masked by 5 or 6 bits; the 8-bit # and 16-bit shifts would need explicit masking. diff --git a/lib/cretonne/meta/isa/intel/recipes.py b/lib/cretonne/meta/isa/intel/recipes.py index 5c37677f14..2406ef6ade 100644 --- a/lib/cretonne/meta/isa/intel/recipes.py +++ b/lib/cretonne/meta/isa/intel/recipes.py @@ -5,7 +5,8 @@ from __future__ import absolute_import from cdsl.isa import EncRecipe from cdsl.predicates import IsSignedInt, IsEqual, Or from cdsl.registers import RegClass -from base.formats import Unary, UnaryImm, Binary, BinaryImm, MultiAry, NullAry +from base.formats import Unary, UnaryImm, UnaryBool, Binary, BinaryImm +from base.formats import MultiAry, NullAry from base.formats import Trap, Call, IndirectCall, Store, Load from base.formats import IntCompare, FloatCompare, IntCond, FloatCond from base.formats import IntSelect, IntCondTrap, FloatCondTrap @@ -506,6 +507,17 @@ puid = TailRecipe( sink.put4(imm as u32); ''') +# XX+rd id unary with bool immediate. Note no recipe predicate. +puid_bool = TailRecipe( + 'puid_bool', UnaryBool, size=4, ins=(), outs=GPR, + emit=''' + // The destination register is encoded in the low bits of the opcode. + // No ModR/M. + PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink); + let imm: u32 = if imm.into() { 1 } else { 0 }; + sink.put4(imm); + ''') + # XX+rd iq unary with 64-bit immediate. puiq = TailRecipe( 'puiq', UnaryImm, size=8, ins=(), outs=GPR, From db2be8ee01613d18ed73f8a96c506277b8766d95 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Mar 2018 20:09:49 -0700 Subject: [PATCH 56/72] Verifier: Diagnose an instruction using its own result values. --- .../verifier/defs_dominates_uses.cton | 16 ++++++ lib/cretonne/src/verifier/mod.rs | 56 ++++++++++++++++--- 2 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 cranelift/filetests/verifier/defs_dominates_uses.cton diff --git a/cranelift/filetests/verifier/defs_dominates_uses.cton b/cranelift/filetests/verifier/defs_dominates_uses.cton new file mode 100644 index 0000000000..1bc3819726 --- /dev/null +++ b/cranelift/filetests/verifier/defs_dominates_uses.cton @@ -0,0 +1,16 @@ +test verifier + +; Test verification that uses properly dominate defs. + +function %non_dominating(i32) -> i32 native { +ebb0(v0: i32): + v1 = iadd.i32 v2, v0 ; error: uses value from non-dominating + v2 = iadd.i32 v1, v0 + return v2 +} + +function %inst_uses_its_own_values(i32) -> i32 native { +ebb0(v0: i32): + v1 = iadd.i32 v1, v0 ; error: uses value from itself + return v1 +} diff --git a/lib/cretonne/src/verifier/mod.rs b/lib/cretonne/src/verifier/mod.rs index 8b6eb5e972..e916094bbb 100644 --- a/lib/cretonne/src/verifier/mod.rs +++ b/lib/cretonne/src/verifier/mod.rs @@ -268,7 +268,7 @@ impl<'a> Verifier<'a> { use ir::instructions::InstructionData::*; for &arg in self.func.dfg.inst_args(inst) { - self.verify_value(inst, arg)?; + self.verify_inst_arg(inst, arg)?; // All used values must be attached to something. let original = self.func.dfg.resolve_aliases(arg); @@ -278,7 +278,7 @@ impl<'a> Verifier<'a> { } for &res in self.func.dfg.inst_results(inst) { - self.verify_value(inst, res)?; + self.verify_inst_result(inst, res)?; } match self.func.dfg[inst] { @@ -446,8 +446,16 @@ impl<'a> Verifier<'a> { fn verify_value(&self, loc_inst: Inst, v: Value) -> Result { let dfg = &self.func.dfg; if !dfg.value_is_valid(v) { - return err!(loc_inst, "invalid value reference {}", v); + err!(loc_inst, "invalid value reference {}", v) + } else { + Ok(()) } + } + + fn verify_inst_arg(&self, loc_inst: Inst, v: Value) -> Result { + self.verify_value(loc_inst, v)?; + + let dfg = &self.func.dfg; let loc_ebb = self.func.layout.pp_ebb(loc_inst); let is_reachable = self.expected_domtree.is_reachable(loc_ebb); @@ -473,14 +481,23 @@ impl<'a> Verifier<'a> { ); } // Defining instruction dominates the instruction that uses the value. - if is_reachable && - !self.expected_domtree.dominates( + if is_reachable { + if !self.expected_domtree.dominates( def_inst, loc_inst, &self.func.layout, ) - { - return err!(loc_inst, "uses value from non-dominating {}", def_inst); + { + return err!(loc_inst, "uses value from non-dominating {}", def_inst); + } + if def_inst == loc_inst { + return err!( + loc_inst, + "uses value from itself {}, {}", + def_inst, + loc_inst + ); + } } } ValueDef::Param(ebb, _) => { @@ -512,6 +529,31 @@ impl<'a> Verifier<'a> { Ok(()) } + fn verify_inst_result(&self, loc_inst: Inst, v: Value) -> Result { + self.verify_value(loc_inst, v)?; + + match self.func.dfg.value_def(v) { + ValueDef::Result(def_inst, _) => { + if def_inst != loc_inst { + err!( + loc_inst, + "instruction result {} is not defined by the instruction", + v + ) + } else { + Ok(()) + } + } + ValueDef::Param(_, _) => { + err!( + loc_inst, + "instruction result {} is not defined by the instruction", + v + ) + } + } + } + fn domtree_integrity(&self, domtree: &DominatorTree) -> Result { // We consider two `DominatorTree`s to be equal if they return the same immediate // dominator for each EBB. Therefore the current domtree is valid if it matches the freshly From e5ec7242cc0d42af77fde124d4f269c720a37533 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Mar 2018 13:20:11 -0700 Subject: [PATCH 57/72] Fix handling of value aliases, and re-enable LICM. Value aliases aren't instructions, so they don't have a location in the CFG, so it's not meaningful to query whether a value alias is defined within a loop. --- cranelift/filetests/licm/reject.cton | 81 ++++++++++++++++++++++++++++ lib/cretonne/src/context.rs | 2 - lib/cretonne/src/licm.rs | 45 +++++++++++----- 3 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 cranelift/filetests/licm/reject.cton diff --git a/cranelift/filetests/licm/reject.cton b/cranelift/filetests/licm/reject.cton new file mode 100644 index 0000000000..052ae2b6f2 --- /dev/null +++ b/cranelift/filetests/licm/reject.cton @@ -0,0 +1,81 @@ +test licm + +function %other_side_effects(i32) -> i32 { + +ebb0(v0: i32): + jump ebb1(v0) + +ebb1(v1: i32): + regmove.i32 v0, %10 -> %20 +; check: ebb1(v1: i32): +; check: regmove.i32 v0, %10 -> %20 + v2 = iconst.i32 1 + brz v1, ebb2(v1) + v5 = isub v1, v2 + jump ebb1(v5) + +ebb2(v6: i32): + return v6 + +} + +function %cpu_flags(i32, i32) -> i32 { +ebb0(v0: i32, v1: i32): + jump ebb1(v0, v1) + +ebb1(v2: i32, v3: i32): + v4 = ifcmp.i32 v0, v1 + v5 = selectif.i32 eq v4, v2, v3 +; check: ebb1(v2: i32, v3: i32): +; check: ifcmp.i32 v0, v1 +; check: v5 = selectif.i32 eq v4, v2, v3 + v8 = iconst.i32 1 + brz v1, ebb2(v1) + v9 = isub v1, v8 + v10 = iadd v1, v8 + jump ebb1(v9, v10) + +ebb2(v6: i32): + return v6 +} + +function %spill(i32, i32) -> i32 { +ebb0(v0: i32, v1: i32): + v2 = spill.i32 v0 + jump ebb1(v0, v1) + +ebb1(v3: i32, v4: i32): + v5 = spill.i32 v1 + v6 = fill.i32 v2 + v7 = fill.i32 v5 +; check: ebb1(v3: i32, v4: i32): +; check: v5 = spill.i32 v1 +; check: v6 = fill.i32 v2 +; check: v7 = fill v5 + brz v1, ebb2(v1) + v9 = isub v1, v4 + jump ebb1(v9, v3) + +ebb2(v10: i32): + return v10 +} + +function %non_invariant_aliases(i32) -> i32 { + +ebb0(v0: i32): + jump ebb1(v0) + +ebb1(v1: i32): + v8 -> v1 + v9 -> v1 + v2 = iadd v8, v9 +; check: ebb1(v1: i32): +; check: v2 = iadd v8, v9 + brz v1, ebb2(v1) + v5 = isub v1, v2 + jump ebb1(v5) + +ebb2(v6: i32): + return v6 + +} diff --git a/lib/cretonne/src/context.rs b/lib/cretonne/src/context.rs index 8358f21545..fba2cd2cc3 100644 --- a/lib/cretonne/src/context.rs +++ b/lib/cretonne/src/context.rs @@ -92,10 +92,8 @@ impl Context { self.legalize(isa)?; if isa.flags().opt_level() == OptLevel::Best { self.compute_domtree(); - /* TODO: Re-enable LICM. self.compute_loop_analysis(); self.licm(isa)?; - */ self.simple_gvn(isa)?; } self.compute_domtree(); diff --git a/lib/cretonne/src/licm.rs b/lib/cretonne/src/licm.rs index 7887a39e4e..f0327296a1 100644 --- a/lib/cretonne/src/licm.rs +++ b/lib/cretonne/src/licm.rs @@ -1,7 +1,7 @@ //! A Loop Invariant Code Motion optimization pass use cursor::{Cursor, FuncCursor}; -use ir::{Function, Ebb, Inst, Value, Type, InstBuilder, Layout}; +use ir::{Function, Ebb, Inst, Value, Type, InstBuilder, Layout, Opcode, DataFlowGraph}; use flowgraph::ControlFlowGraph; use std::collections::HashSet; use dominator_tree::DominatorTree; @@ -27,10 +27,10 @@ pub fn do_licm( for lp in loop_analysis.loops() { // For each loop that we want to optimize we determine the set of loop-invariant // instructions - let invariant_inst = remove_loop_invariant_instructions(lp, func, cfg, loop_analysis); + let invariant_insts = remove_loop_invariant_instructions(lp, func, cfg, loop_analysis); // Then we create the loop's pre-header and fill it with the invariant instructions // Then we remove the invariant instructions from the loop body - if !invariant_inst.is_empty() { + if !invariant_insts.is_empty() { // If the loop has a natural pre-header we use it, otherwise we create it. let mut pos; match has_pre_header(&func.layout, cfg, domtree, loop_analysis.loop_header(lp)) { @@ -47,7 +47,7 @@ pub fn do_licm( }; // The last instruction of the pre-header is the termination instruction (usually // a jump) so we need to insert just before this. - for inst in invariant_inst { + for inst in invariant_insts { pos.insert_inst(inst); } } @@ -131,6 +131,29 @@ fn change_branch_jump_destination(inst: Inst, new_ebb: Ebb, func: &mut Function) } } +/// Test whether the given opcode is unsafe to even consider for LICM. +fn trivially_unsafe_for_licm(opcode: Opcode) -> bool { + opcode.can_load() || opcode.can_store() || opcode.is_call() || opcode.is_branch() || + opcode.is_terminator() || opcode.is_return() || + opcode.can_trap() || opcode.other_side_effects() || opcode.writes_cpu_flags() +} + +/// Test whether the given instruction is loop-invariant. +fn is_loop_invariant(inst: Inst, dfg: &DataFlowGraph, loop_values: &HashSet) -> bool { + if trivially_unsafe_for_licm(dfg[inst].opcode()) { + return false; + } + + let inst_args = dfg.inst_args(inst); + for arg in inst_args { + let arg = dfg.resolve_aliases(*arg); + if loop_values.contains(&arg) { + return false; + } + } + return true; +} + // Traverses a loop in reverse post-order from a header EBB and identify loop-invariant // instructions. These loop-invariant instructions are then removed from the code and returned // (in reverse post-order) for later use. @@ -141,7 +164,7 @@ fn remove_loop_invariant_instructions( loop_analysis: &LoopAnalysis, ) -> Vec { let mut loop_values: HashSet = HashSet::new(); - let mut invariant_inst: Vec = Vec::new(); + let mut invariant_insts: Vec = Vec::new(); let mut pos = FuncCursor::new(func); // We traverse the loop EBB in reverse post-order. for ebb in postorder_ebbs_loop(loop_analysis, cfg, lp).iter().rev() { @@ -151,15 +174,11 @@ fn remove_loop_invariant_instructions( } pos.goto_top(*ebb); #[cfg_attr(feature = "cargo-clippy", allow(block_in_if_condition_stmt))] - while let Some(inst) = pos.next_inst() { - if pos.func.dfg.has_results(inst) && - pos.func.dfg.inst_args(inst).into_iter().all(|arg| { - !loop_values.contains(arg) - }) - { + 'next_inst: while let Some(inst) = pos.next_inst() { + if is_loop_invariant(inst, &pos.func.dfg, &loop_values) { // If all the instruction's argument are defined outside the loop // then this instruction is loop-invariant - invariant_inst.push(inst); + invariant_insts.push(inst); // We remove it from the loop pos.remove_inst_and_step_back(); } else { @@ -171,7 +190,7 @@ fn remove_loop_invariant_instructions( } } } - invariant_inst + invariant_insts } /// Return ebbs from a loop in post-order, starting from an entry point in the block. From 592db1de7a2898be5fd3017db88378a0d427c327 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Mar 2018 13:28:59 -0700 Subject: [PATCH 58/72] Tighten up the parser's verification of value aliases. This prevents uses of undefined values from passsing through unnoticed, and ensures that all aliases are ultimately resolved, regardless of where they are defined. --- lib/cretonne/src/ir/dfg.rs | 70 ++++++++++++++++++++++++++++++++++---- lib/reader/src/parser.rs | 49 ++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 7 deletions(-) diff --git a/lib/cretonne/src/ir/dfg.rs b/lib/cretonne/src/ir/dfg.rs index d23606ee13..b8976b7267 100644 --- a/lib/cretonne/src/ir/dfg.rs +++ b/lib/cretonne/src/ir/dfg.rs @@ -121,8 +121,9 @@ impl DataFlowGraph { /// Resolve value aliases. /// -/// Find the original SSA value that `value` aliases. -fn resolve_aliases(values: &PrimaryMap, value: Value) -> Value { +/// Find the original SSA value that `value` aliases, or None if an +/// alias cycle is detected. +fn maybe_resolve_aliases(values: &PrimaryMap, value: Value) -> Option { let mut v = value; // Note that values may be empty here. @@ -130,10 +131,22 @@ fn resolve_aliases(values: &PrimaryMap, value: Value) -> Value if let ValueData::Alias { original, .. } = values[v] { v = original; } else { - return v; + return Some(v); } } - panic!("Value alias loop detected for {}", value); + + None +} + +/// Resolve value aliases. +/// +/// Find the original SSA value that `value` aliases. +fn resolve_aliases(values: &PrimaryMap, value: Value) -> Value { + if let Some(v) = maybe_resolve_aliases(values, value) { + v + } else { + panic!("Value alias loop detected for {}", value); + } } /// Handling values. @@ -238,6 +251,7 @@ impl DataFlowGraph { self.value_type(dest), ty ); + debug_assert_ne!(ty, types::VOID); self.values[dest] = ValueData::Alias { ty, original }; } @@ -282,6 +296,7 @@ impl DataFlowGraph { self.value_type(dest), ty ); + debug_assert_ne!(ty, types::VOID); self.values[dest] = ValueData::Alias { ty, original }; } @@ -865,8 +880,9 @@ impl DataFlowGraph { /// to create invalid values for index padding which may be reassigned later. #[cold] fn set_value_type_for_parser(&mut self, v: Value, t: Type) { - assert!( - self.value_type(v) == types::VOID, + assert_eq!( + self.value_type(v), + types::VOID, "this function is only for assigning types to previously invalid values" ); match self.values[v] { @@ -926,12 +942,38 @@ impl DataFlowGraph { /// aliases with specific values. #[cold] pub fn make_value_alias_for_parser(&mut self, src: Value, dest: Value) { - let ty = self.value_type(src); + assert_ne!(src, Value::reserved_value()); + assert_ne!(dest, Value::reserved_value()); + let ty = if self.values.is_valid(src) { + self.value_type(src) + } else { + // As a special case, if we can't resolve the aliasee yet, use VOID + // temporarily. It will be resolved later in parsing. + types::VOID + }; let data = ValueData::Alias { ty, original: src }; self.values[dest] = data; } + /// Compute the type of an alias. This is only for use in the parser. + /// Returns false if an alias cycle was encountered. + #[cold] + pub fn set_alias_type_for_parser(&mut self, v: Value) -> bool { + if let Some(resolved) = maybe_resolve_aliases(&self.values, v) { + let old_ty = self.value_type(v); + let new_ty = self.value_type(resolved); + if old_ty == types::VOID { + self.set_value_type_for_parser(v, new_ty); + } else { + assert_eq!(old_ty, new_ty); + } + true + } else { + false + } + } + /// Create an invalid value, to pad the index space. This is only for use by /// the parser to pad out the value index space. #[cold] @@ -942,6 +984,20 @@ impl DataFlowGraph { }; self.make_value(data); } + + /// Check if a value reference is valid, while being aware of aliases which + /// may be unresolved while parsing. + #[cold] + pub fn value_is_valid_for_parser(&self, v: Value) -> bool { + if !self.value_is_valid(v) { + return false; + } + if let ValueData::Alias { ty, .. } = self.values[v] { + ty != types::VOID + } else { + true + } + } } #[cfg(test)] diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index 2e320b31a7..384de9381b 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -86,6 +86,9 @@ struct Context<'a> { function: Function, map: SourceMap, + // Aliases to resolve once value definitions are known. + aliases: Vec, + // Reference to the unique_isa for things like parsing ISA-specific instruction encoding // information. This is only `Some` if exactly one set of `isa` directives were found in the // prologue (it is valid to have directives for multiple different ISAs, but in that case we @@ -99,6 +102,7 @@ impl<'a> Context<'a> { function: f, map: SourceMap::new(), unique_isa, + aliases: Vec::new(), } } @@ -1341,6 +1345,30 @@ impl<'a> Parser<'a> { while self.token() != Some(Token::RBrace) { self.parse_extended_basic_block(ctx)?; } + + // Now that we've seen all defined values in the function, ensure that + // all references refer to a definition. + for ebb in &ctx.function.layout { + for inst in ctx.function.layout.ebb_insts(ebb) { + for value in ctx.function.dfg.inst_args(inst) { + if !ctx.map.contains_value(*value) { + return err!( + ctx.map.location(AnyEntity::Inst(inst)).unwrap(), + "undefined operand value {}", + value + ); + } + } + } + } + + for alias in &ctx.aliases { + if !ctx.function.dfg.set_alias_type_for_parser(*alias) { + let loc = ctx.map.location(AnyEntity::Value(*alias)).unwrap(); + return err!(loc, "alias cycle involving {}", alias); + } + } + Ok(()) } @@ -1616,6 +1644,7 @@ impl<'a> Parser<'a> { results[0], ); ctx.map.def_value(results[0], &self.loc)?; + ctx.aliases.push(results[0]); Ok(()) } @@ -1758,6 +1787,26 @@ impl<'a> Parser<'a> { let ctrl_src_value = inst_data .typevar_operand(&ctx.function.dfg.value_lists) .expect("Constraints <-> Format inconsistency"); + if !ctx.map.contains_value(ctrl_src_value) { + return err!( + self.loc, + "type variable required for polymorphic opcode, e.g. '{}.{}'; \ + can't infer from {} which is not yet defined", + opcode, + constraints.ctrl_typeset().unwrap().example(), + ctrl_src_value + ); + } + if !ctx.function.dfg.value_is_valid_for_parser(ctrl_src_value) { + return err!( + self.loc, + "type variable required for polymorphic opcode, e.g. '{}.{}'; \ + can't infer from {} which is not yet resolved", + opcode, + constraints.ctrl_typeset().unwrap().example(), + ctrl_src_value + ); + } ctx.function.dfg.value_type(ctrl_src_value) } else if constraints.is_polymorphic() { // This opcode does not support type inference, so the explicit type From a297465c25f0e415061ad24f52cc6240a55248eb Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Mar 2018 13:29:17 -0700 Subject: [PATCH 59/72] Tidy up comment formatting. Convert several normal comments to documentation comments, and make separator comments consistent with other files. --- lib/cretonne/src/divconst_magic_numbers.rs | 18 +++++----- lib/cretonne/src/preopt.rs | 39 ++++++++++------------ lib/cretonne/src/write.rs | 12 ++----- 3 files changed, 29 insertions(+), 40 deletions(-) diff --git a/lib/cretonne/src/divconst_magic_numbers.rs b/lib/cretonne/src/divconst_magic_numbers.rs index f189e23d1a..01b5066b28 100644 --- a/lib/cretonne/src/divconst_magic_numbers.rs +++ b/lib/cretonne/src/divconst_magic_numbers.rs @@ -1,17 +1,15 @@ //! Compute "magic numbers" for division-by-constants transformations. +//! +//! Math helpers for division by (non-power-of-2) constants. This is based +//! on the presentation in "Hacker's Delight" by Henry Warren, 2003. There +//! are four cases: {unsigned, signed} x {32 bit, 64 bit}. The word size +//! makes little difference, but the signed-vs-unsigned aspect has a large +//! effect. Therefore everything is presented in the order U32 U64 S32 S64 +//! so as to emphasise the similarity of the U32 and U64 cases and the S32 +//! and S64 cases. #![allow(non_snake_case)] -//---------------------------------------------------------------------- -// -// Math helpers for division by (non-power-of-2) constants. This is based -// on the presentation in "Hacker's Delight" by Henry Warren, 2003. There -// are four cases: {unsigned, signed} x {32 bit, 64 bit}. The word size -// makes little difference, but the signed-vs-unsigned aspect has a large -// effect. Therefore everything is presented in the order U32 U64 S32 S64 -// so as to emphasise the similarity of the U32 and U64 cases and the S32 -// and S64 cases. - // Structures to hold the "magic numbers" computed. #[derive(PartialEq, Debug)] diff --git a/lib/cretonne/src/preopt.rs b/lib/cretonne/src/preopt.rs index 698631316e..9adce51369 100644 --- a/lib/cretonne/src/preopt.rs +++ b/lib/cretonne/src/preopt.rs @@ -19,8 +19,8 @@ use timing; // Simple math helpers -// if `x` is a power of two, or the negation thereof, return the power along -// with a boolean that indicates whether `x` is negative. Else return None. +/// if `x` is a power of two, or the negation thereof, return the power along +/// with a boolean that indicates whether `x` is negative. Else return None. #[inline] fn isPowerOf2_S32(x: i32) -> Option<(bool, u32)> { // We have to special-case this because abs(x) isn't representable. @@ -34,7 +34,7 @@ fn isPowerOf2_S32(x: i32) -> Option<(bool, u32)> { None } -// Same comments as for isPowerOf2_S64 apply. +/// Same comments as for isPowerOf2_S64 apply. #[inline] fn isPowerOf2_S64(x: i64) -> Option<(bool, u32)> { // We have to special-case this because abs(x) isn't representable. @@ -60,9 +60,9 @@ enum DivRemByConstInfo { RemS64(Value, i64), } -// Possibly create a DivRemByConstInfo from the given components, by -// figuring out which, if any, of the 8 cases apply, and also taking care to -// sanity-check the immediate. +/// Possibly create a DivRemByConstInfo from the given components, by +/// figuring out which, if any, of the 8 cases apply, and also taking care to +/// sanity-check the immediate. fn package_up_divrem_info( argL: Value, argL_ty: Type, @@ -108,9 +108,9 @@ fn package_up_divrem_info( None } -// Examine `idata` to see if it is a div or rem by a constant, and if so -// return the operands, signedness, operation size and div-vs-rem-ness in a -// handy bundle. +/// Examine `idata` to see if it is a div or rem by a constant, and if so +/// return the operands, signedness, operation size and div-vs-rem-ness in a +/// handy bundle. fn get_div_info(inst: Inst, dfg: &DataFlowGraph) -> Option { let idata: &InstructionData = &dfg[inst]; @@ -152,12 +152,12 @@ fn get_div_info(inst: Inst, dfg: &DataFlowGraph) -> Option { None } -// Actually do the transformation given a bundle containing the relevant -// information. `divrem_info` describes a div or rem by a constant, that -// `pos` currently points at, and `inst` is the associated instruction. -// `inst` is replaced by a sequence of other operations that calculate the -// same result. Note that there are various `divrem_info` cases where we -// cannot do any transformation, in which case `inst` is left unchanged. +/// Actually do the transformation given a bundle containing the relevant +/// information. `divrem_info` describes a div or rem by a constant, that +/// `pos` currently points at, and `inst` is the associated instruction. +/// `inst` is replaced by a sequence of other operations that calculate the +/// same result. Note that there are various `divrem_info` cases where we +/// cannot do any transformation, in which case `inst` is left unchanged. fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCursor, inst: Inst) { let isRem = match *divrem_info { DivRemByConstInfo::DivU32(_, _) | @@ -478,8 +478,8 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso // // General pattern-match helpers. -// Find out if `value` actually resolves to a constant, and if so what its -// value is. +/// Find out if `value` actually resolves to a constant, and if so what its +/// value is. fn get_const(value: Value, dfg: &DataFlowGraph) -> Option { match dfg.value_def(value) { ValueDef::Result(definingInst, resultNo) => { @@ -496,10 +496,7 @@ fn get_const(value: Value, dfg: &DataFlowGraph) -> Option { } -//---------------------------------------------------------------------- -// -// The main pre-opt pass. - +/// The main pre-opt pass. pub fn do_preopt(func: &mut Function) { let _tt = timing::preopt(); let mut pos = FuncCursor::new(func); diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index 50acbbf553..bbe8375b89 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -30,11 +30,9 @@ pub fn write_function(w: &mut Write, func: &Function, isa: Option<&TargetIsa>) - writeln!(w, "}}") } -// ====--------------------------------------------------------------------------------------====// +//---------------------------------------------------------------------- // // Function spec. -// -// ====--------------------------------------------------------------------------------------====// fn write_spec(w: &mut Write, func: &Function, regs: Option<&RegInfo>) -> Result { write!(w, "function {}{}", func.name, func.signature.display(regs)) @@ -90,11 +88,9 @@ fn write_preamble( Ok(any) } -// ====--------------------------------------------------------------------------------------====// +//---------------------------------------------------------------------- // // Basic blocks -// -// ====--------------------------------------------------------------------------------------====// pub fn write_arg(w: &mut Write, func: &Function, regs: Option<&RegInfo>, arg: Value) -> Result { write!(w, "{}: {}", arg, func.dfg.value_type(arg))?; @@ -158,11 +154,9 @@ pub fn write_ebb(w: &mut Write, func: &Function, isa: Option<&TargetIsa>, ebb: E } -// ====--------------------------------------------------------------------------------------====// +//---------------------------------------------------------------------- // // Instructions -// -// ====--------------------------------------------------------------------------------------====// // Should `inst` be printed with a type suffix? // From 57cd69d8b40f0e6184e6a7388e64e9a33601184f Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Mar 2018 14:15:01 -0700 Subject: [PATCH 60/72] Say "IR" instead of "IL". While the specifics of these terms are debatable, "IR" generally isn't incorrect in this context, and is the more widely recognized term at this time. See also the discussion in #267. Fixes #267. --- README.rst | 2 +- cranelift/docs/compare-llvm.rst | 20 +++++++-------- cranelift/docs/cton_domain.py | 16 ++++++------ cranelift/docs/langref.rst | 34 ++++++++++--------------- cranelift/docs/testing.rst | 8 +++--- cranelift/src/cat.rs | 2 +- cranelift/src/compile.rs | 4 +-- cranelift/src/cton-util.rs | 6 ++--- cranelift/src/print_cfg.rs | 2 +- cranelift/src/wasm.rs | 2 +- lib/cretonne/README.md | 2 +- lib/cretonne/meta/base/formats.py | 2 +- lib/cretonne/meta/base/settings.py | 4 +-- lib/cretonne/meta/cdsl/ast.py | 2 +- lib/cretonne/src/binemit/memorysink.rs | 2 +- lib/cretonne/src/ir/entities.rs | 6 ++--- lib/cretonne/src/ir/function.rs | 2 +- lib/cretonne/src/ir/instructions.rs | 2 +- lib/cretonne/src/ir/layout.rs | 3 +-- lib/cretonne/src/ir/libcall.rs | 2 +- lib/cretonne/src/ir/mod.rs | 2 +- lib/cretonne/src/ir/progpoint.rs | 2 +- lib/cretonne/src/ir/sourceloc.rs | 2 +- lib/cretonne/src/legalizer/globalvar.rs | 2 +- lib/cretonne/src/regalloc/diversion.rs | 2 +- lib/cretonne/src/result.rs | 4 +-- lib/cretonne/src/timing.rs | 4 +-- lib/cretonne/src/write.rs | 7 +++-- lib/filetests/src/test_legalizer.rs | 2 +- lib/filetests/src/test_print_cfg.rs | 2 +- lib/filetests/src/test_verifier.rs | 2 +- lib/frontend/Cargo.toml | 2 +- lib/frontend/README.md | 4 +-- lib/frontend/src/frontend.rs | 24 ++++++++--------- lib/frontend/src/lib.rs | 10 ++++---- lib/frontend/src/ssa.rs | 2 +- lib/reader/Cargo.toml | 2 +- lib/reader/src/parser.rs | 2 +- lib/wasm/Cargo.toml | 2 +- lib/wasm/README.md | 3 +-- lib/wasm/src/code_translator.rs | 4 +-- lib/wasm/src/environ/spec.rs | 2 +- lib/wasm/src/func_translator.rs | 8 +++--- lib/wasm/src/lib.rs | 4 +-- lib/wasm/src/module_translator.rs | 2 +- 45 files changed, 106 insertions(+), 119 deletions(-) diff --git a/README.rst b/README.rst index 12b889f56d..41e6a9284d 100644 --- a/README.rst +++ b/README.rst @@ -3,7 +3,7 @@ Cretonne Code Generator ======================= Cretonne is a low-level retargetable code generator. It translates a `target-independent -intermediate language `_ into executable +intermediate representation `_ into executable machine code. *This is a work in progress that is not yet functional.* diff --git a/cranelift/docs/compare-llvm.rst b/cranelift/docs/compare-llvm.rst index 0180f6cc92..4a622dbeda 100644 --- a/cranelift/docs/compare-llvm.rst +++ b/cranelift/docs/compare-llvm.rst @@ -16,8 +16,8 @@ highlighting some of the differences and similarities. Both projects: - Use an ISA-agnostic input language in order to mostly abstract away the differences between target instruction set architectures. - Depend extensively on SSA form. -- Have both textual and in-memory forms of their primary intermediate language. - (LLVM also has a binary bitcode format; Cretonne doesn't.) +- Have both textual and in-memory forms of their primary intermediate + representation. (LLVM also has a binary bitcode format; Cretonne doesn't.) - Can target multiple ISAs. - Can cross-compile by default without rebuilding the code generator. @@ -41,8 +41,8 @@ LLVM uses multiple intermediate representations as it translates a program to binary machine code: `LLVM IR `_ - This is the primary intermediate language which has textual, binary, and - in-memory representations. It serves two main purposes: + This is the primary intermediate representation which has textual, binary, and + in-memory forms. It serves two main purposes: - An ISA-agnostic, stable(ish) input language that front ends can generate easily. @@ -89,9 +89,9 @@ representation. Some target ISAs have a fast instruction selector that can translate simple code directly to MachineInstrs, bypassing SelectionDAG when possible. -:doc:`Cretonne ` uses a single intermediate language to cover these -levels of abstraction. This is possible in part because of Cretonne's smaller -scope. +:doc:`Cretonne ` uses a single intermediate representation to cover +these levels of abstraction. This is possible in part because of Cretonne's +smaller scope. - Cretonne does not provide assemblers and disassemblers, so it is not necessary to be able to represent every weird instruction in an ISA. Only @@ -102,7 +102,7 @@ scope. - SSA form is preserved throughout. After register allocation, each SSA value is annotated with an assigned ISA register or stack slot. -The Cretonne intermediate language is similar to LLVM IR, but at a slightly +The Cretonne intermediate representation is similar to LLVM IR, but at a slightly lower level of abstraction. Program structure @@ -112,12 +112,12 @@ In LLVM IR, the largest representable unit is the *module* which corresponds more or less to a C translation unit. It is a collection of functions and global variables that may contain references to external symbols too. -In Cretonne IL, the largest representable unit is the *function*. This is so +In Cretonne IR, the largest representable unit is the *function*. This is so that functions can easily be compiled in parallel without worrying about references to shared data structures. Cretonne does not have any inter-procedural optimizations like inlining. -An LLVM IR function is a graph of *basic blocks*. A Cretonne IL function is a +An LLVM IR function is a graph of *basic blocks*. A Cretonne IR function is a graph of *extended basic blocks* that may contain internal branch instructions. The main difference is that an LLVM conditional branch instruction has two target basic blocks---a true and a false edge. A Cretonne branch instruction diff --git a/cranelift/docs/cton_domain.py b/cranelift/docs/cton_domain.py index a03acf1160..2d6e45eeed 100644 --- a/cranelift/docs/cton_domain.py +++ b/cranelift/docs/cton_domain.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Sphinx domain for documenting compiler intermediate languages. +# Sphinx domain for documenting compiler intermediate representations. # # This defines a 'cton' Sphinx domain with the following directives and roles: # @@ -29,10 +29,10 @@ import sphinx.ext.autodoc class CtonObject(ObjectDescription): """ - Any kind of Cretonne IL object. + Any kind of Cretonne IR object. This is a shared base class for the different kinds of indexable objects - in the Cretonne IL reference. + in the Cretonne IR reference. """ option_spec = { 'noindex': directives.flag, @@ -98,7 +98,7 @@ def parse_type(name, signode): class CtonType(CtonObject): - """A Cretonne IL type description.""" + """A Cretonne IR type description.""" def handle_signature(self, sig, signode): """ @@ -112,7 +112,7 @@ class CtonType(CtonObject): return name def get_index_text(self, name): - return name + ' (IL type)' + return name + ' (IR type)' sep_equal = re.compile('\s*=\s*') @@ -127,7 +127,7 @@ def parse_params(s, signode): class CtonInst(CtonObject): - """A Cretonne IL instruction.""" + """A Cretonne IR instruction.""" doc_field_types = [ TypedField('argument', label=l_('Arguments'), @@ -176,11 +176,11 @@ class CtonInst(CtonObject): class CtonInstGroup(CtonObject): - """A Cretonne IL instruction group.""" + """A Cretonne IR instruction group.""" class CretonneDomain(Domain): - """Cretonne domain for intermediate language objects.""" + """Cretonne domain for IR objects.""" name = 'cton' label = 'Cretonne' diff --git a/cranelift/docs/langref.rst b/cranelift/docs/langref.rst index fb716257bd..162248c83e 100644 --- a/cranelift/docs/langref.rst +++ b/cranelift/docs/langref.rst @@ -5,19 +5,19 @@ Cretonne Language Reference .. default-domain:: cton .. highlight:: cton -The Cretonne intermediate language (:term:`IL`) has two equivalent -representations: an *in-memory data structure* that the code generator library -is using, and a *text format* which is used for test cases and debug output. -Files containing Cretonne textual IL have the ``.cton`` filename extension. +The Cretonne intermediate representation (:term:`IR`) has two primary forms: +an *in-memory data structure* that the code generator library is using, and a +*text format* which is used for test cases and debug output. +Files containing Cretonne textual IR have the ``.cton`` filename extension. -This reference uses the text format to describe IL semantics but glosses over +This reference uses the text format to describe IR semantics but glosses over the finer details of the lexical and syntactic structure of the format. Overall structure ================= -Cretonne compiles functions independently. A ``.cton`` IL file may contain +Cretonne compiles functions independently. A ``.cton`` IR file may contain multiple functions, and the programmatic API can create multiple function handles at the same time, but the functions don't share any data or reference each other directly. @@ -27,7 +27,7 @@ This is a simple C function that computes the average of an array of floats: .. literalinclude:: example.c :language: c -Here is the same function compiled into Cretonne IL: +Here is the same function compiled into Cretonne IR: .. literalinclude:: example.cton :language: cton @@ -77,7 +77,7 @@ variable value for the next iteration. The `cton_frontend` crate contains utilities for translating from programs containing multiple assignments to the same variables into SSA form for -Cretonne :term:`IL`. +Cretonne :term:`IR`. Such variables can also be presented to Cretonne as :term:`stack slot`\s. Stack slots are accessed with the :inst:`stack_store` and :inst:`stack_load` @@ -303,7 +303,7 @@ indicate the different kinds of immediate operands on an instruction. A floating point condition code. See the :inst:`fcmp` instruction for details. The two IEEE floating point immediate types :type:`ieee32` and :type:`ieee64` -are displayed as hexadecimal floating point literals in the textual :term:`IL` +are displayed as hexadecimal floating point literals in the textual :term:`IR` format. Decimal floating point literals are not allowed because some computer systems can round differently when converting to binary. The hexadecimal floating point format is mostly the same as the one used by C99, but extended @@ -563,7 +563,7 @@ runtime data structures. alignment for storing a pointer. Chains of ``deref`` global variables are possible, but cycles are not - allowed. They will be caught by the IL verifier. + allowed. They will be caught by the IR verifier. :arg BaseGV: Global variable containing the base pointer. :arg Offset: Byte offset from the loaded base pointer to the global @@ -1154,19 +1154,11 @@ Glossary The extended basic blocks which contain all the executable code in a function. The function body follows the function preamble. - intermediate language - IL - The language used to describe functions to Cretonne. This reference - describes the syntax and semantics of the Cretonne IL. The IL has two - forms: Textual and an in-memory intermediate representation - (:term:`IR`). - intermediate representation IR - The in-memory representation of :term:`IL`. The data structures - Cretonne uses to represent a program internally are called the - intermediate representation. Cretonne's IR can be converted to text - losslessly. + The language used to describe functions to Cretonne. This reference + describes the syntax and semantics of Cretonne IR. The IR has two + forms: Textual, and an in-memory data structure. stack slot A fixed size memory allocation in the current function's activation diff --git a/cranelift/docs/testing.rst b/cranelift/docs/testing.rst index 320cc37389..c14a74aeba 100644 --- a/cranelift/docs/testing.rst +++ b/cranelift/docs/testing.rst @@ -89,7 +89,7 @@ easier to provide substantial input functions for the compiler tests. File tests are :file:`*.cton` files in the :file:`filetests/` directory hierarchy. Each file has a header describing what to test followed by a number -of input functions in the :doc:`Cretonne textual intermediate language +of input functions in the :doc:`Cretonne textual intermediate representation `: .. productionlist:: @@ -166,7 +166,7 @@ Cretonne's tests don't need this. ---------- This is one of the simplest file tests, used for testing the conversion to and -from textual IL. The ``test cat`` command simply parses each function and +from textual IR. The ``test cat`` command simply parses each function and converts it back to text again. The text of each function is then matched against the associated filecheck directives. @@ -188,7 +188,7 @@ Example:: `test verifier` --------------- -Run each function through the IL verifier and check that it produces the +Run each function through the IR verifier and check that it produces the expected error messages. Expected error messages are indicated with an ``error:`` directive *on the @@ -351,4 +351,4 @@ Each function is passed through the full ``Context::compile()`` function which is normally used to compile code. This type of test often depends on assertions or verifier errors, but it is also possible to use filecheck directives which will be matched against the final form of the -Cretonne IL right before binary machine code emission. +Cretonne IR right before binary machine code emission. diff --git a/cranelift/src/cat.rs b/cranelift/src/cat.rs index 4d3d73ac2c..0fc5541db9 100644 --- a/cranelift/src/cat.rs +++ b/cranelift/src/cat.rs @@ -1,6 +1,6 @@ //! The `cat` sub-command. //! -//! Read a sequence of Cretonne IL files and print them again to stdout. This has the effect of +//! Read a sequence of Cretonne IR files and print them again to stdout. This has the effect of //! normalizing formatting and removing comments. use cton_reader::parse_functions; diff --git a/cranelift/src/compile.rs b/cranelift/src/compile.rs index a1cc244f5d..c21b989149 100644 --- a/cranelift/src/compile.rs +++ b/cranelift/src/compile.rs @@ -1,6 +1,4 @@ -//! CLI tool to compile cretonne IL into native code. -//! -//! Reads IR files into Cretonne IL and compiles it. +//! CLI tool to read Cretonne IR files and compile them into native code. use cton_reader::parse_test; use std::path::PathBuf; diff --git a/cranelift/src/cton-util.rs b/cranelift/src/cton-util.rs index 216eae458b..4dd9865d3d 100644 --- a/cranelift/src/cton-util.rs +++ b/cranelift/src/cton-util.rs @@ -38,12 +38,12 @@ Options: -T, --time-passes print pass timing report -t, --just-decode - just decode WebAssembly to Cretonne IL + just decode WebAssembly to Cretonne IR -s, --print-size prints generated code size -c, --check-translation - just checks the correctness of Cretonne IL translated from WebAssembly - -p, --print print the resulting Cretonne IL + just checks the correctness of Cretonne IR translated from WebAssembly + -p, --print print the resulting Cretonne IR -h, --help print this help message --set= configure Cretonne settings --isa= specify the Cretonne ISA diff --git a/cranelift/src/print_cfg.rs b/cranelift/src/print_cfg.rs index 65242cc8f8..846ee3e8fa 100644 --- a/cranelift/src/print_cfg.rs +++ b/cranelift/src/print_cfg.rs @@ -1,6 +1,6 @@ //! The `print-cfg` sub-command. //! -//! Read a series of Cretonne IL files and print their control flow graphs +//! Read a series of Cretonne IR files and print their control flow graphs //! in graphviz format. use CommandResult; diff --git a/cranelift/src/wasm.rs b/cranelift/src/wasm.rs index 5f986ee5f2..918deffd5a 100644 --- a/cranelift/src/wasm.rs +++ b/cranelift/src/wasm.rs @@ -1,6 +1,6 @@ //! CLI tool to use the functions provided by the [cretonne-wasm](../cton_wasm/index.html) crate. //! -//! Reads Wasm binary files, translates the functions' code to Cretonne IL. +//! Reads Wasm binary files, translates the functions' code to Cretonne IR. #![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments, cyclomatic_complexity))] use cton_wasm::{translate_module, DummyEnvironment, ModuleEnvironment}; diff --git a/lib/cretonne/README.md b/lib/cretonne/README.md index 73b2806f5d..c12dfbf5a9 100644 --- a/lib/cretonne/README.md +++ b/lib/cretonne/README.md @@ -1,2 +1,2 @@ This crate contains the core Cretonne code generator. It translates code from an -intermediate language into executable machine code. +intermediate representation into executable machine code. diff --git a/lib/cretonne/meta/base/formats.py b/lib/cretonne/meta/base/formats.py index b50824581b..595f09b9fa 100644 --- a/lib/cretonne/meta/base/formats.py +++ b/lib/cretonne/meta/base/formats.py @@ -2,7 +2,7 @@ The cretonne.formats defines all instruction formats. Every instruction format has a corresponding `InstructionData` variant in the -Rust representation of cretonne IL, so all instruction formats must be defined +Rust representation of Cretonne IR, so all instruction formats must be defined in this module. """ from __future__ import absolute_import diff --git a/lib/cretonne/meta/base/settings.py b/lib/cretonne/meta/base/settings.py index e8785fbc08..3bd90f107b 100644 --- a/lib/cretonne/meta/base/settings.py +++ b/lib/cretonne/meta/base/settings.py @@ -20,10 +20,10 @@ opt_level = EnumSetting( enable_verifier = BoolSetting( """ - Run the Cretonne IL verifier at strategic times during compilation. + Run the Cretonne IR verifier at strategic times during compilation. This makes compilation slower but catches many bugs. The verifier is - disabled by default, except when reading Cretonne IL from a text file. + disabled by default, except when reading Cretonne IR from a text file. """, default=True) diff --git a/lib/cretonne/meta/cdsl/ast.py b/lib/cretonne/meta/cdsl/ast.py index 38d633e17d..5eefe222f8 100644 --- a/lib/cretonne/meta/cdsl/ast.py +++ b/lib/cretonne/meta/cdsl/ast.py @@ -559,7 +559,7 @@ class Enumerator(Literal): is an AST leaf node representing one of the values. :param kind: The enumerated `ImmediateKind` containing the value. - :param value: The textual IL representation of the value. + :param value: The textual IR representation of the value. `Enumerator` nodes are not usually created directly. They are created by using the dot syntax on immediate kinds: `intcc.ult`. diff --git a/lib/cretonne/src/binemit/memorysink.rs b/lib/cretonne/src/binemit/memorysink.rs index 1d6758afe6..506ea8b5a4 100644 --- a/lib/cretonne/src/binemit/memorysink.rs +++ b/lib/cretonne/src/binemit/memorysink.rs @@ -20,7 +20,7 @@ use std::ptr::write_unaligned; /// A `CodeSink` that writes binary machine code directly into memory. /// -/// A `MemoryCodeSink` object should be used when emitting a Cretonne IL function into executable +/// A `MemoryCodeSink` object should be used when emitting a Cretonne IR function into executable /// memory. It writes machine code directly to a raw pointer without any bounds checking, so make /// sure to allocate enough memory for the whole function. The number of bytes required is returned /// by the `Context::compile()` function. diff --git a/lib/cretonne/src/ir/entities.rs b/lib/cretonne/src/ir/entities.rs index 1a4e772be4..0727721d6a 100644 --- a/lib/cretonne/src/ir/entities.rs +++ b/lib/cretonne/src/ir/entities.rs @@ -1,6 +1,6 @@ -//! IL entity references. +//! Cretonne IR entity references. //! -//! Instructions in Cretonne IL need to reference other entities in the function. This can be other +//! Instructions in Cretonne IR need to reference other entities in the function. This can be other //! parts of the function like extended basic blocks or stack slots, or it can be external entities //! that are declared in the function preamble in the text format. //! @@ -16,7 +16,7 @@ //! data structures use the `PackedOption` representation, while function arguments and //! return values prefer the more Rust-like `Option` variant. //! -//! The entity references all implement the `Display` trait in a way that matches the textual IL +//! The entity references all implement the `Display` trait in a way that matches the textual IR //! format. use std::fmt; diff --git a/lib/cretonne/src/ir/function.rs b/lib/cretonne/src/ir/function.rs index 8ee332526f..e52bb4c96f 100644 --- a/lib/cretonne/src/ir/function.rs +++ b/lib/cretonne/src/ir/function.rs @@ -55,7 +55,7 @@ pub struct Function { /// /// This information is only transiently available after the `binemit::relax_branches` function /// computes it, and it can easily be recomputed by calling that function. It is not included - /// in the textual IL format. + /// in the textual IR format. pub offsets: EbbOffsets, /// Source locations. diff --git a/lib/cretonne/src/ir/instructions.rs b/lib/cretonne/src/ir/instructions.rs index 68ee656e85..bb09e24834 100644 --- a/lib/cretonne/src/ir/instructions.rs +++ b/lib/cretonne/src/ir/instructions.rs @@ -1,7 +1,7 @@ //! Instruction formats and opcodes. //! //! The `instructions` module contains definitions for instruction formats, opcodes, and the -//! in-memory representation of IL instructions. +//! in-memory representation of IR instructions. //! //! A large part of this module is auto-generated from the instruction descriptions in the meta //! directory. diff --git a/lib/cretonne/src/ir/layout.rs b/lib/cretonne/src/ir/layout.rs index 2f4c378edd..c19cf6dd37 100644 --- a/lib/cretonne/src/ir/layout.rs +++ b/lib/cretonne/src/ir/layout.rs @@ -71,8 +71,7 @@ impl Layout { // within an EBB. The instruction sequence numbers are all between the sequence number of their // containing EBB and the following EBB. // -// The result is that sequence numbers work like BASIC line numbers for the textual representation -// of the IL. +// The result is that sequence numbers work like BASIC line numbers for the textual form of the IR. type SequenceNumber = u32; // Initial stride assigned to new sequence numbers. diff --git a/lib/cretonne/src/ir/libcall.rs b/lib/cretonne/src/ir/libcall.rs index 85133611be..6434197247 100644 --- a/lib/cretonne/src/ir/libcall.rs +++ b/lib/cretonne/src/ir/libcall.rs @@ -6,7 +6,7 @@ use std::str::FromStr; /// The name of a runtime library routine. /// -/// Runtime library calls are generated for Cretonne IL instructions that don't have an equivalent +/// Runtime library calls are generated for Cretonne IR instructions that don't have an equivalent /// ISA instruction or an easy macro expansion. A `LibCall` is used as a well-known name to refer to /// the runtime library routine. This way, Cretonne doesn't have to know about the naming /// convention in the embedding VM's runtime library. diff --git a/lib/cretonne/src/ir/mod.rs b/lib/cretonne/src/ir/mod.rs index 2144ad6811..4f4e671f30 100644 --- a/lib/cretonne/src/ir/mod.rs +++ b/lib/cretonne/src/ir/mod.rs @@ -1,4 +1,4 @@ -//! Representation of Cretonne IL functions. +//! Representation of Cretonne IR functions. pub mod types; pub mod entities; diff --git a/lib/cretonne/src/ir/progpoint.rs b/lib/cretonne/src/ir/progpoint.rs index ce5b108e54..8fea3193c6 100644 --- a/lib/cretonne/src/ir/progpoint.rs +++ b/lib/cretonne/src/ir/progpoint.rs @@ -12,7 +12,7 @@ use std::cmp; /// 1. An instruction or /// 2. An EBB header. /// -/// This corresponds more or less to the lines in the textual representation of Cretonne IL. +/// This corresponds more or less to the lines in the textual form of Cretonne IR. #[derive(PartialEq, Eq, Clone, Copy)] pub struct ProgramPoint(u32); diff --git a/lib/cretonne/src/ir/sourceloc.rs b/lib/cretonne/src/ir/sourceloc.rs index 36e5247488..768bbf99d5 100644 --- a/lib/cretonne/src/ir/sourceloc.rs +++ b/lib/cretonne/src/ir/sourceloc.rs @@ -7,7 +7,7 @@ use std::fmt; /// A source location. /// -/// This is an opaque 32-bit number attached to each Cretonne IL instruction. Cretonne does not +/// This is an opaque 32-bit number attached to each Cretonne IR instruction. Cretonne does not /// interpret source locations in any way, they are simply preserved from the input to the output. /// /// The default source location uses the all-ones bit pattern `!0`. It is used for instructions diff --git a/lib/cretonne/src/legalizer/globalvar.rs b/lib/cretonne/src/legalizer/globalvar.rs index 901b0da416..27494bfd87 100644 --- a/lib/cretonne/src/legalizer/globalvar.rs +++ b/lib/cretonne/src/legalizer/globalvar.rs @@ -45,7 +45,7 @@ fn vmctx_addr(inst: ir::Inst, func: &mut ir::Function, offset: i64) { /// Expand a `global_addr` instruction for a deref global. fn deref_addr(inst: ir::Inst, func: &mut ir::Function, base: ir::GlobalVar, offset: i64) { // We need to load a pointer from the `base` global variable, so insert a new `global_addr` - // instruction. This depends on the iterative legalization loop. Note that the IL verifier + // instruction. This depends on the iterative legalization loop. Note that the IR verifier // detects any cycles in the `deref` globals. let ptr_ty = func.dfg.value_type(func.dfg.first_result(inst)); let mut pos = FuncCursor::new(func).at_inst(inst); diff --git a/lib/cretonne/src/regalloc/diversion.rs b/lib/cretonne/src/regalloc/diversion.rs index 16eb0e9b50..68fd04754e 100644 --- a/lib/cretonne/src/regalloc/diversion.rs +++ b/lib/cretonne/src/regalloc/diversion.rs @@ -15,7 +15,7 @@ use std::vec::Vec; /// A diversion of a value from its original location to a new register or stack location. /// -/// In IL, a diversion is represented by a `regmove` instruction, possibly a chain of them for the +/// In IR, a diversion is represented by a `regmove` instruction, possibly a chain of them for the /// same value. /// /// When tracking diversions, the `from` field is the original assigned value location, and `to` is diff --git a/lib/cretonne/src/result.rs b/lib/cretonne/src/result.rs index aa209a0845..bd2ae5a101 100644 --- a/lib/cretonne/src/result.rs +++ b/lib/cretonne/src/result.rs @@ -15,9 +15,9 @@ pub enum CtonError { /// code. This should never happen for validated WebAssembly code. InvalidInput, - /// An IL verifier error. + /// An IR verifier error. /// - /// This always represents a bug, either in the code that generated IL for Cretonne, or a bug + /// This always represents a bug, either in the code that generated IR for Cretonne, or a bug /// in Cretonne itself. Verifier(verifier::Error), diff --git a/lib/cretonne/src/timing.rs b/lib/cretonne/src/timing.rs index 647e0a07aa..51cdd85bfa 100644 --- a/lib/cretonne/src/timing.rs +++ b/lib/cretonne/src/timing.rs @@ -41,11 +41,11 @@ define_passes!{ Pass, NUM_PASSES, DESCRIPTIONS; process_file: "Processing test file", - parse_text: "Parsing textual Cretonne IL", + parse_text: "Parsing textual Cretonne IR", wasm_translate_module: "Translate WASM module", wasm_translate_function: "Translate WASM function", - verifier: "Verify Cretonne IL", + verifier: "Verify Cretonne IR", verify_cssa: "Verify CSSA", verify_liveness: "Verify live ranges", verify_locations: "Verify value locations", diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index bbe8375b89..1081a87d77 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -1,8 +1,7 @@ -//! Converting Cretonne IL to text. +//! Converting Cretonne IR to text. //! -//! The `write` module provides the `write_function` function which converts an IL `Function` to an -//! equivalent textual representation. This textual representation can be read back by the -//! `cretonne-reader` crate. +//! The `write` module provides the `write_function` function which converts an IR `Function` to an +//! equivalent textual form. This textual form can be read back by the `cretonne-reader` crate. use ir::{Function, DataFlowGraph, Ebb, Inst, Value, ValueDef, Type, SigRef}; use isa::{TargetIsa, RegInfo}; diff --git a/lib/filetests/src/test_legalizer.rs b/lib/filetests/src/test_legalizer.rs index c8d03e4c2a..08f6c53ae4 100644 --- a/lib/filetests/src/test_legalizer.rs +++ b/lib/filetests/src/test_legalizer.rs @@ -1,4 +1,4 @@ -//! Test command for checking the IL legalizer. +//! Test command for checking the IR legalizer. //! //! The `test legalizer` test command runs each function through `legalize_function()` and sends //! the result to filecheck. diff --git a/lib/filetests/src/test_print_cfg.rs b/lib/filetests/src/test_print_cfg.rs index 470d293185..b043dc58b2 100644 --- a/lib/filetests/src/test_print_cfg.rs +++ b/lib/filetests/src/test_print_cfg.rs @@ -1,6 +1,6 @@ //! The `print-cfg` sub-command. //! -//! Read a series of Cretonne IL files and print their control flow graphs +//! Read a series of Cretonne IR files and print their control flow graphs //! in graphviz format. use std::borrow::Cow; diff --git a/lib/filetests/src/test_verifier.rs b/lib/filetests/src/test_verifier.rs index bb4375b59e..6db9c681ce 100644 --- a/lib/filetests/src/test_verifier.rs +++ b/lib/filetests/src/test_verifier.rs @@ -1,4 +1,4 @@ -//! Test command for checking the IL verifier. +//! Test command for checking the IR verifier. //! //! The `test verifier` test command looks for annotations on instructions like this: //! diff --git a/lib/frontend/Cargo.toml b/lib/frontend/Cargo.toml index 40f1833c71..0bef102c66 100644 --- a/lib/frontend/Cargo.toml +++ b/lib/frontend/Cargo.toml @@ -2,7 +2,7 @@ authors = ["The Cretonne Project Developers"] name = "cretonne-frontend" version = "0.4.1" -description = "Cretonne IL builder helper" +description = "Cretonne IR builder helper" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" repository = "https://github.com/Cretonne/cretonne" diff --git a/lib/frontend/README.md b/lib/frontend/README.md index 53248b68ab..cca2b12ab5 100644 --- a/lib/frontend/README.md +++ b/lib/frontend/README.md @@ -1,5 +1,5 @@ This crate provides a straightforward way to create a -[Cretonne](https://crates.io/crates/cretonne) IL function and fill it with +[Cretonne](https://crates.io/crates/cretonne) IR function and fill it with instructions translated from another language. It contains an SSA construction module that provides convenient methods for translating non-SSA variables into -SSA Cretonne IL values via `use_var` and `def_var` calls. +SSA Cretonne IR values via `use_var` and `def_var` calls. diff --git a/lib/frontend/src/frontend.rs b/lib/frontend/src/frontend.rs index 8cd2c5cc82..2706846124 100644 --- a/lib/frontend/src/frontend.rs +++ b/lib/frontend/src/frontend.rs @@ -1,4 +1,4 @@ -//! A frontend for building Cretonne IL from other languages. +//! A frontend for building Cretonne IR from other languages. use cretonne::cursor::{Cursor, FuncCursor}; use cretonne::ir; use cretonne::ir::{Ebb, Type, Value, Function, Inst, JumpTable, StackSlot, JumpTableData, @@ -10,7 +10,7 @@ use ssa::{SSABuilder, SideEffects, Block}; use cretonne::entity::{EntityRef, EntityMap, EntitySet}; use cretonne::packed_option::PackedOption; -/// Structure used for translating a series of functions into Cretonne IL. +/// Structure used for translating a series of functions into Cretonne IR. /// /// In order to reduce memory reallocations when compiling multiple functions, /// `FunctionBuilderContext` holds various data structures which are cleared between @@ -29,7 +29,7 @@ where } -/// Temporary object used to build a single Cretonne IL `Function`. +/// Temporary object used to build a single Cretonne IR `Function`. pub struct FunctionBuilder<'a, Variable: 'a> where Variable: EntityRef, @@ -103,7 +103,7 @@ where } /// Implementation of the [`InstBuilder`](../cretonne/ir/builder/trait.InstBuilder.html) that has -/// one convenience method per Cretonne IL instruction. +/// one convenience method per Cretonne IR instruction. pub struct FuncInstBuilder<'short, 'long: 'short, Variable: 'long> where Variable: EntityRef, @@ -191,7 +191,7 @@ impl<'short, 'long, Variable> InstBuilderBase<'short> for FuncInstBuilder<'short } } -/// This module allows you to create a function in Cretonne IL in a straightforward way, hiding +/// This module allows you to create a function in Cretonne IR in a straightforward way, hiding /// all the complexity of its internal representation. /// /// The module is parametrized by one type which is the representation of variables in your @@ -203,10 +203,10 @@ impl<'short, 'long, Variable> InstBuilderBase<'short> for FuncInstBuilder<'short /// - the last instruction of each block is a terminator instruction which has no natural successor, /// and those instructions can only appear at the end of extended blocks. /// -/// The parameters of Cretonne IL instructions are Cretonne IL values, which can only be created -/// as results of other Cretonne IL instructions. To be able to create variables redefined multiple +/// The parameters of Cretonne IR instructions are Cretonne IR values, which can only be created +/// as results of other Cretonne IR instructions. To be able to create variables redefined multiple /// times in your program, use the `def_var` and `use_var` command, that will maintain the -/// correspondence between your variables and Cretonne IL SSA values. +/// correspondence between your variables and Cretonne IR SSA values. /// /// The first block for which you call `switch_to_block` will be assumed to be the beginning of /// the function. @@ -220,7 +220,7 @@ impl<'short, 'long, Variable> InstBuilderBase<'short> for FuncInstBuilder<'short /// /// # Errors /// -/// The functions below will panic in debug mode whenever you try to modify the Cretonne IL +/// The functions below will panic in debug mode whenever you try to modify the Cretonne IR /// function in a way that violate the coherence of the code. For instance: switching to a new /// `Ebb` when you haven't filled the current one with a terminator instruction, inserting a /// return instruction with arguments that don't match the function's signature. @@ -311,7 +311,7 @@ where self.func_ctx.types[var] = ty; } - /// Returns the Cretonne IL value corresponding to the utilization at the current program + /// Returns the Cretonne IR value corresponding to the utilization at the current program /// position of a previously defined user variable. pub fn use_var(&mut self, var: Variable) -> Value { let ty = *self.func_ctx.types.get(var).expect( @@ -462,8 +462,8 @@ where } /// All the functions documented in the previous block are write-only and help you build a valid -/// Cretonne IL functions via multiple debug asserts. However, you might need to improve the -/// performance of your translation perform more complex transformations to your Cretonne IL +/// Cretonne IR functions via multiple debug asserts. However, you might need to improve the +/// performance of your translation perform more complex transformations to your Cretonne IR /// function. The functions below help you inspect the function you're creating and modify it /// in ways that can be unsafe if used incorrectly. impl<'a, Variable> FunctionBuilder<'a, Variable> diff --git a/lib/frontend/src/lib.rs b/lib/frontend/src/lib.rs index 1f2c2e0db8..c7defce3bb 100644 --- a/lib/frontend/src/lib.rs +++ b/lib/frontend/src/lib.rs @@ -1,15 +1,15 @@ -//! Cretonne IL builder library. +//! Cretonne IR builder library. //! -//! Provides a straightforward way to create a Cretonne IL function and fill it with instructions +//! Provides a straightforward way to create a Cretonne IR function and fill it with instructions //! translated from another language. Contains an SSA construction module that lets you translate -//! your non-SSA variables into SSA Cretonne IL values via `use_var` and `def_var` calls. +//! your non-SSA variables into SSA Cretonne IR values via `use_var` and `def_var` calls. //! //! To get started, create an [`FunctionBuilderContext`](struct.FunctionBuilderContext.html) and //! pass it as an argument to a [`FunctionBuilder`](struct.FunctionBuilder.html). //! //! # Example //! -//! Here is a pseudo-program we want to transform into Cretonne IL: +//! Here is a pseudo-program we want to transform into Cretonne IR: //! //! ```cton //! function(x) { @@ -29,7 +29,7 @@ //! } //! ``` //! -//! Here is how you build the corresponding Cretonne IL function using `FunctionBuilderContext`: +//! Here is how you build the corresponding Cretonne IR function using `FunctionBuilderContext`: //! //! ```rust //! extern crate cretonne; diff --git a/lib/frontend/src/ssa.rs b/lib/frontend/src/ssa.rs index bd4a8d89fd..af0d35695e 100644 --- a/lib/frontend/src/ssa.rs +++ b/lib/frontend/src/ssa.rs @@ -231,7 +231,7 @@ fn emit_zero(ty: Type, mut cur: FuncCursor) -> Value { } } /// The following methods are the API of the SSA builder. Here is how it should be used when -/// translating to Cretonne IL: +/// translating to Cretonne IR: /// /// - for each sequence of contiguous instructions (with no branches), create a corresponding /// basic block with `declare_ebb_body_block` or `declare_ebb_header_block` depending on the diff --git a/lib/reader/Cargo.toml b/lib/reader/Cargo.toml index 80fab0f499..d8259a2027 100644 --- a/lib/reader/Cargo.toml +++ b/lib/reader/Cargo.toml @@ -2,7 +2,7 @@ authors = ["The Cretonne Project Developers"] name = "cretonne-reader" version = "0.4.1" -description = "Cretonne textual IL reader" +description = "Cretonne textual IR reader" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" repository = "https://github.com/Cretonne/cretonne" diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index 384de9381b..b165756566 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -1782,7 +1782,7 @@ impl<'a> Parser<'a> { // explicit type specified. Look up `ctrl_value` to see if it was defined // already. // TBD: If it is defined in another block, the type should have been - // specified explicitly. It is unfortunate that the correctness of IL + // specified explicitly. It is unfortunate that the correctness of IR // depends on the layout of the blocks. let ctrl_src_value = inst_data .typevar_operand(&ctx.function.dfg.value_lists) diff --git a/lib/wasm/Cargo.toml b/lib/wasm/Cargo.toml index 0fcd2210f5..b532f29c55 100644 --- a/lib/wasm/Cargo.toml +++ b/lib/wasm/Cargo.toml @@ -2,7 +2,7 @@ name = "cretonne-wasm" version = "0.4.1" authors = ["The Cretonne Project Developers"] -description = "Translator from WebAssembly to Cretonne IL" +description = "Translator from WebAssembly to Cretonne IR" repository = "https://github.com/Cretonne/cretonne" license = "Apache-2.0" readme = "README.md" diff --git a/lib/wasm/README.md b/lib/wasm/README.md index f12f00d46a..946a41f26d 100644 --- a/lib/wasm/README.md +++ b/lib/wasm/README.md @@ -1,3 +1,2 @@ This crate performs the translation from a wasm module in binary format to the -in-memory representation of the [Cretonne](https://crates.io/crates/cretonne) -IL. +in-memory form of the [Cretonne](https://crates.io/crates/cretonne) IR. diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index 69111dc8e8..61b7118636 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -1,5 +1,5 @@ //! This module contains the bulk of the interesting code performing the translation between -//! WebAssembly and Cretonne IL. +//! WebAssembly and Cretonne IR. //! //! The translation is done in one pass, opcode by opcode. Two main data structures are used during //! code translations: the value stack and the control stack. The value stack mimics the execution @@ -38,7 +38,7 @@ use std::vec::Vec; // Clippy warns about "flags: _" but its important to document that the flags field is ignored #[cfg_attr(feature = "cargo-clippy", allow(unneeded_field_pattern))] -/// Translates wasm operators into Cretonne IL instructions. Returns `true` if it inserted +/// Translates wasm operators into Cretonne IR instructions. Returns `true` if it inserted /// a return. pub fn translate_operator( op: Operator, diff --git a/lib/wasm/src/environ/spec.rs b/lib/wasm/src/environ/spec.rs index 41583c1185..233188364a 100644 --- a/lib/wasm/src/environ/spec.rs +++ b/lib/wasm/src/environ/spec.rs @@ -26,7 +26,7 @@ pub enum GlobalValue { /// Environment affecting the translation of a single WebAssembly function. /// /// A `FuncEnvironment` trait object is required to translate a WebAssembly function to Cretonne -/// IL. The function environment provides information about the WebAssembly module as well as the +/// IR. The function environment provides information about the WebAssembly module as well as the /// runtime environment. pub trait FuncEnvironment { /// Get the flags for the current compilation. diff --git a/lib/wasm/src/func_translator.rs b/lib/wasm/src/func_translator.rs index 5ac69b07b8..dbb1fc9bcc 100644 --- a/lib/wasm/src/func_translator.rs +++ b/lib/wasm/src/func_translator.rs @@ -1,7 +1,7 @@ -//! Stand-alone WebAssembly to Cretonne IL translator. +//! Stand-alone WebAssembly to Cretonne IR translator. //! //! This module defines the `FuncTranslator` type which can translate a single WebAssembly -//! function to Cretonne IL guided by a `FuncEnvironment` which provides information about the +//! function to Cretonne IR guided by a `FuncEnvironment` which provides information about the //! WebAssembly module and the runtime environment. use code_translator::translate_operator; @@ -14,9 +14,9 @@ use environ::FuncEnvironment; use state::TranslationState; use wasmparser::{self, BinaryReader}; -/// WebAssembly to Cretonne IL function translator. +/// WebAssembly to Cretonne IR function translator. /// -/// A `FuncTranslator` is used to translate a binary WebAssembly function into Cretonne IL guided +/// A `FuncTranslator` is used to translate a binary WebAssembly function into Cretonne IR guided /// by a `FuncEnvironment` object. A single translator instance can be reused to translate multiple /// functions which will reduce heap allocation traffic. pub struct FuncTranslator { diff --git a/lib/wasm/src/lib.rs b/lib/wasm/src/lib.rs index f2a1adb7cb..cc35a19fbc 100644 --- a/lib/wasm/src/lib.rs +++ b/lib/wasm/src/lib.rs @@ -1,5 +1,5 @@ -//! Performs the translation from a wasm module in binary format to the in-memory representation -//! of the Cretonne IL. More particularly, it translates the code of all the functions bodies and +//! Performs translation from a wasm module in binary format to the in-memory form +//! of Cretonne IR. More particularly, it translates the code of all the functions bodies and //! interacts with an environment implementing the //! [`ModuleEnvironment`](trait.ModuleEnvironment.html) //! trait to deal with tables, globals and linear memory. diff --git a/lib/wasm/src/module_translator.rs b/lib/wasm/src/module_translator.rs index bb74db4276..171f720e12 100644 --- a/lib/wasm/src/module_translator.rs +++ b/lib/wasm/src/module_translator.rs @@ -10,7 +10,7 @@ use environ::ModuleEnvironment; use std::string::String; -/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cretonne IL +/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cretonne IR /// [`Function`](../cretonne/ir/function/struct.Function.html). /// Returns the functions and also the mappings for imported functions and signature between the /// indexes in the wasm module and the indexes inside each functions. From d566faa8fb1f626ef89eb351da3ec9a448c7736c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Mar 2018 16:16:35 -0700 Subject: [PATCH 61/72] Disable preopt at opt_level=fastest. --- lib/cretonne/src/context.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/cretonne/src/context.rs b/lib/cretonne/src/context.rs index fba2cd2cc3..54fce4b84a 100644 --- a/lib/cretonne/src/context.rs +++ b/lib/cretonne/src/context.rs @@ -88,7 +88,9 @@ impl Context { self.verify_if(isa)?; self.compute_cfg(); - self.preopt(isa)?; + if isa.flags().opt_level() != OptLevel::Fastest { + self.preopt(isa)?; + } self.legalize(isa)?; if isa.flags().opt_level() == OptLevel::Best { self.compute_domtree(); From 951ff11f85300df92e2c8a45d91bdf7923675c09 Mon Sep 17 00:00:00 2001 From: Tyler McMullen Date: Wed, 28 Mar 2018 22:48:03 -0700 Subject: [PATCH 62/72] [WIP] Add a Trap sink to code generation (#279) * First draft of TrapSink implementation. * Add trap sink calls to 'trapif' and 'trapff' recipes. * Add SourceLoc to trap sink calls, and add trap sink calls to all loads and stores. * Add IntegerDivisionByZero trap to div recipe. * Only emit load/store traps if 'notrap' flag is not set on the instruction. * Update filetest machinery to add new trap sink functionality. * Update filetests to include traps in output. * Add a few more trap outputs to filetests. * Add trap output to CLI tool. --- .../filetests/isa/intel/binary32-float.cton | 64 ++--- cranelift/filetests/isa/intel/binary32.cton | 124 ++++----- .../filetests/isa/intel/binary64-float.cton | 72 ++--- cranelift/filetests/isa/intel/binary64.cton | 246 +++++++++--------- cranelift/src/compile.rs | 15 +- lib/cretonne/meta/isa/intel/recipes.py | 53 +++- lib/cretonne/src/binemit/memorysink.rs | 21 +- lib/cretonne/src/binemit/mod.rs | 7 +- lib/cretonne/src/context.rs | 12 +- lib/cretonne/src/isa/intel/binemit.rs | 2 +- lib/filetests/src/test_binemit.rs | 4 + lib/filetests/src/test_compile.rs | 1 + 12 files changed, 358 insertions(+), 263 deletions(-) diff --git a/cranelift/filetests/isa/intel/binary32-float.cton b/cranelift/filetests/isa/intel/binary32-float.cton index 95e132cf6e..4477c4d8d3 100644 --- a/cranelift/filetests/isa/intel/binary32-float.cton +++ b/cranelift/filetests/isa/intel/binary32-float.cton @@ -148,30 +148,30 @@ ebb0: ; Load/Store ; asm: movss (%ecx), %xmm5 - [-,%xmm5] v100 = load.f32 v0 ; bin: f3 0f 10 29 + [-,%xmm5] v100 = load.f32 v0 ; bin: heap_oob f3 0f 10 29 ; asm: movss (%esi), %xmm2 - [-,%xmm2] v101 = load.f32 v1 ; bin: f3 0f 10 16 + [-,%xmm2] v101 = load.f32 v1 ; bin: heap_oob f3 0f 10 16 ; asm: movss 50(%ecx), %xmm5 - [-,%xmm5] v110 = load.f32 v0+50 ; bin: f3 0f 10 69 32 + [-,%xmm5] v110 = load.f32 v0+50 ; bin: heap_oob f3 0f 10 69 32 ; asm: movss -50(%esi), %xmm2 - [-,%xmm2] v111 = load.f32 v1-50 ; bin: f3 0f 10 56 ce + [-,%xmm2] v111 = load.f32 v1-50 ; bin: heap_oob f3 0f 10 56 ce ; asm: movss 10000(%ecx), %xmm5 - [-,%xmm5] v120 = load.f32 v0+10000 ; bin: f3 0f 10 a9 00002710 + [-,%xmm5] v120 = load.f32 v0+10000 ; bin: heap_oob f3 0f 10 a9 00002710 ; asm: movss -10000(%esi), %xmm2 - [-,%xmm2] v121 = load.f32 v1-10000 ; bin: f3 0f 10 96 ffffd8f0 + [-,%xmm2] v121 = load.f32 v1-10000 ; bin: heap_oob f3 0f 10 96 ffffd8f0 ; asm: movss %xmm5, (%ecx) - [-] store.f32 v100, v0 ; bin: f3 0f 11 29 + [-] store.f32 v100, v0 ; bin: heap_oob f3 0f 11 29 ; asm: movss %xmm2, (%esi) - [-] store.f32 v101, v1 ; bin: f3 0f 11 16 + [-] store.f32 v101, v1 ; bin: heap_oob f3 0f 11 16 ; asm: movss %xmm5, 50(%ecx) - [-] store.f32 v100, v0+50 ; bin: f3 0f 11 69 32 + [-] store.f32 v100, v0+50 ; bin: heap_oob f3 0f 11 69 32 ; asm: movss %xmm2, -50(%esi) - [-] store.f32 v101, v1-50 ; bin: f3 0f 11 56 ce + [-] store.f32 v101, v1-50 ; bin: heap_oob f3 0f 11 56 ce ; asm: movss %xmm5, 10000(%ecx) - [-] store.f32 v100, v0+10000 ; bin: f3 0f 11 a9 00002710 + [-] store.f32 v100, v0+10000 ; bin: heap_oob f3 0f 11 a9 00002710 ; asm: movss %xmm2, -10000(%esi) - [-] store.f32 v101, v1-10000 ; bin: f3 0f 11 96 ffffd8f0 + [-] store.f32 v101, v1-10000 ; bin: heap_oob f3 0f 11 96 ffffd8f0 ; Spill / Fill. @@ -363,30 +363,30 @@ ebb0: ; Load/Store ; asm: movsd (%ecx), %xmm5 - [-,%xmm5] v100 = load.f64 v0 ; bin: f2 0f 10 29 + [-,%xmm5] v100 = load.f64 v0 ; bin: heap_oob f2 0f 10 29 ; asm: movsd (%esi), %xmm2 - [-,%xmm2] v101 = load.f64 v1 ; bin: f2 0f 10 16 + [-,%xmm2] v101 = load.f64 v1 ; bin: heap_oob f2 0f 10 16 ; asm: movsd 50(%ecx), %xmm5 - [-,%xmm5] v110 = load.f64 v0+50 ; bin: f2 0f 10 69 32 + [-,%xmm5] v110 = load.f64 v0+50 ; bin: heap_oob f2 0f 10 69 32 ; asm: movsd -50(%esi), %xmm2 - [-,%xmm2] v111 = load.f64 v1-50 ; bin: f2 0f 10 56 ce + [-,%xmm2] v111 = load.f64 v1-50 ; bin: heap_oob f2 0f 10 56 ce ; asm: movsd 10000(%ecx), %xmm5 - [-,%xmm5] v120 = load.f64 v0+10000 ; bin: f2 0f 10 a9 00002710 + [-,%xmm5] v120 = load.f64 v0+10000 ; bin: heap_oob f2 0f 10 a9 00002710 ; asm: movsd -10000(%esi), %xmm2 - [-,%xmm2] v121 = load.f64 v1-10000 ; bin: f2 0f 10 96 ffffd8f0 + [-,%xmm2] v121 = load.f64 v1-10000 ; bin: heap_oob f2 0f 10 96 ffffd8f0 ; asm: movsd %xmm5, (%ecx) - [-] store.f64 v100, v0 ; bin: f2 0f 11 29 + [-] store.f64 v100, v0 ; bin: heap_oob f2 0f 11 29 ; asm: movsd %xmm2, (%esi) - [-] store.f64 v101, v1 ; bin: f2 0f 11 16 + [-] store.f64 v101, v1 ; bin: heap_oob f2 0f 11 16 ; asm: movsd %xmm5, 50(%ecx) - [-] store.f64 v100, v0+50 ; bin: f2 0f 11 69 32 + [-] store.f64 v100, v0+50 ; bin: heap_oob f2 0f 11 69 32 ; asm: movsd %xmm2, -50(%esi) - [-] store.f64 v101, v1-50 ; bin: f2 0f 11 56 ce + [-] store.f64 v101, v1-50 ; bin: heap_oob f2 0f 11 56 ce ; asm: movsd %xmm5, 10000(%ecx) - [-] store.f64 v100, v0+10000 ; bin: f2 0f 11 a9 00002710 + [-] store.f64 v100, v0+10000 ; bin: heap_oob f2 0f 11 a9 00002710 ; asm: movsd %xmm2, -10000(%esi) - [-] store.f64 v101, v1-10000 ; bin: f2 0f 11 96 ffffd8f0 + [-] store.f64 v101, v1-10000 ; bin: heap_oob f2 0f 11 96 ffffd8f0 ; Spill / Fill. @@ -471,21 +471,21 @@ ebb1: brff ule v1, ebb1 ; bin: 76 f0 ; asm: jp .+4; ud2 - trapff ord v1, user0 ; bin: 7a 02 0f 0b + trapff ord v1, user0 ; bin: 7a 02 user0 0f 0b ; asm: jnp .+4; ud2 - trapff uno v1, user0 ; bin: 7b 02 0f 0b + trapff uno v1, user0 ; bin: 7b 02 user0 0f 0b ; asm: je .+4; ud2 - trapff one v1, user0 ; bin: 74 02 0f 0b + trapff one v1, user0 ; bin: 74 02 user0 0f 0b ; asm: jne .+4; ud2 - trapff ueq v1, user0 ; bin: 75 02 0f 0b + trapff ueq v1, user0 ; bin: 75 02 user0 0f 0b ; asm: jna .+4; ud2 - trapff gt v1, user0 ; bin: 76 02 0f 0b + trapff gt v1, user0 ; bin: 76 02 user0 0f 0b ; asm: jnae .+4; ud2 - trapff ge v1, user0 ; bin: 72 02 0f 0b + trapff ge v1, user0 ; bin: 72 02 user0 0f 0b ; asm: jnb .+4; ud2 - trapff ult v1, user0 ; bin: 73 02 0f 0b + trapff ult v1, user0 ; bin: 73 02 user0 0f 0b ; asm: jnbe .+4; ud2 - trapff ule v1, user0 ; bin: 77 02 0f 0b + trapff ule v1, user0 ; bin: 77 02 user0 0f 0b ; asm: setnp %bl [-,%rbx] v10 = trueff ord v1 ; bin: 0f 9b c3 diff --git a/cranelift/filetests/isa/intel/binary32.cton b/cranelift/filetests/isa/intel/binary32.cton index 04f492c354..a3d0723be8 100644 --- a/cranelift/filetests/isa/intel/binary32.cton +++ b/cranelift/filetests/isa/intel/binary32.cton @@ -128,13 +128,13 @@ ebb0: ; asm: movl $2, %edx [-,%rdx] v53 = iconst.i32 2 ; bin: ba 00000002 ; asm: idivl %ecx - [-,%rax,%rdx] v54, v55 = x86_sdivmodx v52, v53, v1 ; bin: f7 f9 + [-,%rax,%rdx] v54, v55 = x86_sdivmodx v52, v53, v1 ; bin: int_divz f7 f9 ; asm: idivl %esi - [-,%rax,%rdx] v56, v57 = x86_sdivmodx v52, v53, v2 ; bin: f7 fe + [-,%rax,%rdx] v56, v57 = x86_sdivmodx v52, v53, v2 ; bin: int_divz f7 fe ; asm: divl %ecx - [-,%rax,%rdx] v58, v59 = x86_udivmodx v52, v53, v1 ; bin: f7 f1 + [-,%rax,%rdx] v58, v59 = x86_udivmodx v52, v53, v1 ; bin: int_divz f7 f1 ; asm: divl %esi - [-,%rax,%rdx] v60, v61 = x86_udivmodx v52, v53, v2 ; bin: f7 f6 + [-,%rax,%rdx] v60, v61 = x86_udivmodx v52, v53, v2 ; bin: int_divz f7 f6 ; Register copies. @@ -155,105 +155,105 @@ ebb0: ; Register indirect addressing with no displacement. ; asm: movl %ecx, (%esi) - store v1, v2 ; bin: 89 0e + store v1, v2 ; bin: heap_oob 89 0e ; asm: movl %esi, (%ecx) - store v2, v1 ; bin: 89 31 + store v2, v1 ; bin: heap_oob 89 31 ; asm: movw %cx, (%esi) - istore16 v1, v2 ; bin: 66 89 0e + istore16 v1, v2 ; bin: heap_oob 66 89 0e ; asm: movw %si, (%ecx) - istore16 v2, v1 ; bin: 66 89 31 + istore16 v2, v1 ; bin: heap_oob 66 89 31 ; asm: movb %cl, (%esi) - istore8 v1, v2 ; bin: 88 0e + istore8 v1, v2 ; bin: heap_oob 88 0e ; Can't store %sil in 32-bit mode (needs REX prefix). ; asm: movl (%ecx), %edi - [-,%rdi] v100 = load.i32 v1 ; bin: 8b 39 + [-,%rdi] v100 = load.i32 v1 ; bin: heap_oob 8b 39 ; asm: movl (%esi), %edx - [-,%rdx] v101 = load.i32 v2 ; bin: 8b 16 + [-,%rdx] v101 = load.i32 v2 ; bin: heap_oob 8b 16 ; asm: movzwl (%ecx), %edi - [-,%rdi] v102 = uload16.i32 v1 ; bin: 0f b7 39 + [-,%rdi] v102 = uload16.i32 v1 ; bin: heap_oob 0f b7 39 ; asm: movzwl (%esi), %edx - [-,%rdx] v103 = uload16.i32 v2 ; bin: 0f b7 16 + [-,%rdx] v103 = uload16.i32 v2 ; bin: heap_oob 0f b7 16 ; asm: movswl (%ecx), %edi - [-,%rdi] v104 = sload16.i32 v1 ; bin: 0f bf 39 + [-,%rdi] v104 = sload16.i32 v1 ; bin: heap_oob 0f bf 39 ; asm: movswl (%esi), %edx - [-,%rdx] v105 = sload16.i32 v2 ; bin: 0f bf 16 + [-,%rdx] v105 = sload16.i32 v2 ; bin: heap_oob 0f bf 16 ; asm: movzbl (%ecx), %edi - [-,%rdi] v106 = uload8.i32 v1 ; bin: 0f b6 39 + [-,%rdi] v106 = uload8.i32 v1 ; bin: heap_oob 0f b6 39 ; asm: movzbl (%esi), %edx - [-,%rdx] v107 = uload8.i32 v2 ; bin: 0f b6 16 + [-,%rdx] v107 = uload8.i32 v2 ; bin: heap_oob 0f b6 16 ; asm: movsbl (%ecx), %edi - [-,%rdi] v108 = sload8.i32 v1 ; bin: 0f be 39 + [-,%rdi] v108 = sload8.i32 v1 ; bin: heap_oob 0f be 39 ; asm: movsbl (%esi), %edx - [-,%rdx] v109 = sload8.i32 v2 ; bin: 0f be 16 + [-,%rdx] v109 = sload8.i32 v2 ; bin: heap_oob 0f be 16 ; Register-indirect with 8-bit signed displacement. ; asm: movl %ecx, 100(%esi) - store v1, v2+100 ; bin: 89 4e 64 + store v1, v2+100 ; bin: heap_oob 89 4e 64 ; asm: movl %esi, -100(%ecx) - store v2, v1-100 ; bin: 89 71 9c + store v2, v1-100 ; bin: heap_oob 89 71 9c ; asm: movw %cx, 100(%esi) - istore16 v1, v2+100 ; bin: 66 89 4e 64 + istore16 v1, v2+100 ; bin: heap_oob 66 89 4e 64 ; asm: movw %si, -100(%ecx) - istore16 v2, v1-100 ; bin: 66 89 71 9c + istore16 v2, v1-100 ; bin: heap_oob 66 89 71 9c ; asm: movb %cl, 100(%esi) - istore8 v1, v2+100 ; bin: 88 4e 64 + istore8 v1, v2+100 ; bin: heap_oob 88 4e 64 ; asm: movl 50(%ecx), %edi - [-,%rdi] v110 = load.i32 v1+50 ; bin: 8b 79 32 + [-,%rdi] v110 = load.i32 v1+50 ; bin: heap_oob 8b 79 32 ; asm: movl -50(%esi), %edx - [-,%rdx] v111 = load.i32 v2-50 ; bin: 8b 56 ce + [-,%rdx] v111 = load.i32 v2-50 ; bin: heap_oob 8b 56 ce ; asm: movzwl 50(%ecx), %edi - [-,%rdi] v112 = uload16.i32 v1+50 ; bin: 0f b7 79 32 + [-,%rdi] v112 = uload16.i32 v1+50 ; bin: heap_oob 0f b7 79 32 ; asm: movzwl -50(%esi), %edx - [-,%rdx] v113 = uload16.i32 v2-50 ; bin: 0f b7 56 ce + [-,%rdx] v113 = uload16.i32 v2-50 ; bin: heap_oob 0f b7 56 ce ; asm: movswl 50(%ecx), %edi - [-,%rdi] v114 = sload16.i32 v1+50 ; bin: 0f bf 79 32 + [-,%rdi] v114 = sload16.i32 v1+50 ; bin: heap_oob 0f bf 79 32 ; asm: movswl -50(%esi), %edx - [-,%rdx] v115 = sload16.i32 v2-50 ; bin: 0f bf 56 ce + [-,%rdx] v115 = sload16.i32 v2-50 ; bin: heap_oob 0f bf 56 ce ; asm: movzbl 50(%ecx), %edi - [-,%rdi] v116 = uload8.i32 v1+50 ; bin: 0f b6 79 32 + [-,%rdi] v116 = uload8.i32 v1+50 ; bin: heap_oob 0f b6 79 32 ; asm: movzbl -50(%esi), %edx - [-,%rdx] v117 = uload8.i32 v2-50 ; bin: 0f b6 56 ce + [-,%rdx] v117 = uload8.i32 v2-50 ; bin: heap_oob 0f b6 56 ce ; asm: movsbl 50(%ecx), %edi - [-,%rdi] v118 = sload8.i32 v1+50 ; bin: 0f be 79 32 + [-,%rdi] v118 = sload8.i32 v1+50 ; bin: heap_oob 0f be 79 32 ; asm: movsbl -50(%esi), %edx - [-,%rdx] v119 = sload8.i32 v2-50 ; bin: 0f be 56 ce + [-,%rdx] v119 = sload8.i32 v2-50 ; bin: heap_oob 0f be 56 ce ; Register-indirect with 32-bit signed displacement. ; asm: movl %ecx, 10000(%esi) - store v1, v2+10000 ; bin: 89 8e 00002710 + store v1, v2+10000 ; bin: heap_oob 89 8e 00002710 ; asm: movl %esi, -10000(%ecx) - store v2, v1-10000 ; bin: 89 b1 ffffd8f0 + store v2, v1-10000 ; bin: heap_oob 89 b1 ffffd8f0 ; asm: movw %cx, 10000(%esi) - istore16 v1, v2+10000 ; bin: 66 89 8e 00002710 + istore16 v1, v2+10000 ; bin: heap_oob 66 89 8e 00002710 ; asm: movw %si, -10000(%ecx) - istore16 v2, v1-10000 ; bin: 66 89 b1 ffffd8f0 + istore16 v2, v1-10000 ; bin: heap_oob 66 89 b1 ffffd8f0 ; asm: movb %cl, 10000(%esi) - istore8 v1, v2+10000 ; bin: 88 8e 00002710 + istore8 v1, v2+10000 ; bin: heap_oob 88 8e 00002710 ; asm: movl 50000(%ecx), %edi - [-,%rdi] v120 = load.i32 v1+50000 ; bin: 8b b9 0000c350 + [-,%rdi] v120 = load.i32 v1+50000 ; bin: heap_oob 8b b9 0000c350 ; asm: movl -50000(%esi), %edx - [-,%rdx] v121 = load.i32 v2-50000 ; bin: 8b 96 ffff3cb0 + [-,%rdx] v121 = load.i32 v2-50000 ; bin: heap_oob 8b 96 ffff3cb0 ; asm: movzwl 50000(%ecx), %edi - [-,%rdi] v122 = uload16.i32 v1+50000 ; bin: 0f b7 b9 0000c350 + [-,%rdi] v122 = uload16.i32 v1+50000 ; bin: heap_oob 0f b7 b9 0000c350 ; asm: movzwl -50000(%esi), %edx - [-,%rdx] v123 = uload16.i32 v2-50000 ; bin: 0f b7 96 ffff3cb0 + [-,%rdx] v123 = uload16.i32 v2-50000 ; bin: heap_oob 0f b7 96 ffff3cb0 ; asm: movswl 50000(%ecx), %edi - [-,%rdi] v124 = sload16.i32 v1+50000 ; bin: 0f bf b9 0000c350 + [-,%rdi] v124 = sload16.i32 v1+50000 ; bin: heap_oob 0f bf b9 0000c350 ; asm: movswl -50000(%esi), %edx - [-,%rdx] v125 = sload16.i32 v2-50000 ; bin: 0f bf 96 ffff3cb0 + [-,%rdx] v125 = sload16.i32 v2-50000 ; bin: heap_oob 0f bf 96 ffff3cb0 ; asm: movzbl 50000(%ecx), %edi - [-,%rdi] v126 = uload8.i32 v1+50000 ; bin: 0f b6 b9 0000c350 + [-,%rdi] v126 = uload8.i32 v1+50000 ; bin: heap_oob 0f b6 b9 0000c350 ; asm: movzbl -50000(%esi), %edx - [-,%rdx] v127 = uload8.i32 v2-50000 ; bin: 0f b6 96 ffff3cb0 + [-,%rdx] v127 = uload8.i32 v2-50000 ; bin: heap_oob 0f b6 96 ffff3cb0 ; asm: movsbl 50000(%ecx), %edi - [-,%rdi] v128 = sload8.i32 v1+50000 ; bin: 0f be b9 0000c350 + [-,%rdi] v128 = sload8.i32 v1+50000 ; bin: heap_oob 0f be b9 0000c350 ; asm: movsbl -50000(%esi), %edx - [-,%rdx] v129 = sload8.i32 v2-50000 ; bin: 0f be 96 ffff3cb0 + [-,%rdx] v129 = sload8.i32 v2-50000 ; bin: heap_oob 0f be 96 ffff3cb0 ; Bit-counting instructions. @@ -437,7 +437,7 @@ ebb1: ; asm: ebb2: ebb2: - trap user0 ; bin: 0f 0b + trap user0 ; bin: user0 0f 0b } ; Special branch encodings only for I32 mode. @@ -524,25 +524,25 @@ ebb1: ; The trapif instructions are encoded as macros: a conditional jump over a ud2. ; asm: jne .+4; ud2 - trapif eq v11, user0 ; bin: 75 02 0f 0b + trapif eq v11, user0 ; bin: 75 02 user0 0f 0b ; asm: je .+4; ud2 - trapif ne v11, user0 ; bin: 74 02 0f 0b + trapif ne v11, user0 ; bin: 74 02 user0 0f 0b ; asm: jnl .+4; ud2 - trapif slt v11, user0 ; bin: 7d 02 0f 0b + trapif slt v11, user0 ; bin: 7d 02 user0 0f 0b ; asm: jnge .+4; ud2 - trapif sge v11, user0 ; bin: 7c 02 0f 0b + trapif sge v11, user0 ; bin: 7c 02 user0 0f 0b ; asm: jng .+4; ud2 - trapif sgt v11, user0 ; bin: 7e 02 0f 0b + trapif sgt v11, user0 ; bin: 7e 02 user0 0f 0b ; asm: jnle .+4; ud2 - trapif sle v11, user0 ; bin: 7f 02 0f 0b + trapif sle v11, user0 ; bin: 7f 02 user0 0f 0b ; asm: jnb .+4; ud2 - trapif ult v11, user0 ; bin: 73 02 0f 0b + trapif ult v11, user0 ; bin: 73 02 user0 0f 0b ; asm: jnae .+4; ud2 - trapif uge v11, user0 ; bin: 72 02 0f 0b + trapif uge v11, user0 ; bin: 72 02 user0 0f 0b ; asm: jna .+4; ud2 - trapif ugt v11, user0 ; bin: 76 02 0f 0b + trapif ugt v11, user0 ; bin: 76 02 user0 0f 0b ; asm: jnbe .+4; ud2 - trapif ule v11, user0 ; bin: 77 02 0f 0b + trapif ule v11, user0 ; bin: 77 02 user0 0f 0b ; Stack check. ; asm: cmpl %esp, %ecx @@ -576,7 +576,7 @@ ebb0: ; asm: movzbl %cl, %esi [-,%rsi] v30 = uextend.i32 v11 ; bin: 0f b6 f1 - trap user0 ; bin: 0f 0b + trap user0 ; bin: user0 0f 0b } ; Tests for i32/i16 conversion instructions. @@ -592,5 +592,5 @@ ebb0: ; asm: movzwl %cx, %esi [-,%rsi] v30 = uextend.i32 v11 ; bin: 0f b7 f1 - trap user0 ; bin: 0f 0b + trap user0 ; bin: user0 0f 0b } diff --git a/cranelift/filetests/isa/intel/binary64-float.cton b/cranelift/filetests/isa/intel/binary64-float.cton index 47db5b197f..7053a1809e 100644 --- a/cranelift/filetests/isa/intel/binary64-float.cton +++ b/cranelift/filetests/isa/intel/binary64-float.cton @@ -158,34 +158,34 @@ ebb0: ; Load/Store ; asm: movss (%r14), %xmm5 - [-,%xmm5] v100 = load.f32 v3 ; bin: f3 41 0f 10 2e + [-,%xmm5] v100 = load.f32 v3 ; bin: heap_oob f3 41 0f 10 2e ; asm: movss (%rax), %xmm10 - [-,%xmm10] v101 = load.f32 v2 ; bin: f3 44 0f 10 10 + [-,%xmm10] v101 = load.f32 v2 ; bin: heap_oob f3 44 0f 10 10 ; asm: movss 50(%r14), %xmm5 - [-,%xmm5] v110 = load.f32 v3+50 ; bin: f3 41 0f 10 6e 32 + [-,%xmm5] v110 = load.f32 v3+50 ; bin: heap_oob f3 41 0f 10 6e 32 ; asm: movss -50(%rax), %xmm10 - [-,%xmm10] v111 = load.f32 v2-50 ; bin: f3 44 0f 10 50 ce + [-,%xmm10] v111 = load.f32 v2-50 ; bin: heap_oob f3 44 0f 10 50 ce ; asm: movss 10000(%r14), %xmm5 - [-,%xmm5] v120 = load.f32 v3+10000 ; bin: f3 41 0f 10 ae 00002710 + [-,%xmm5] v120 = load.f32 v3+10000 ; bin: heap_oob f3 41 0f 10 ae 00002710 ; asm: movss -10000(%rax), %xmm10 - [-,%xmm10] v121 = load.f32 v2-10000 ; bin: f3 44 0f 10 90 ffffd8f0 + [-,%xmm10] v121 = load.f32 v2-10000 ; bin: heap_oob f3 44 0f 10 90 ffffd8f0 ; asm: movss %xmm5, (%r14) - [-] store.f32 v100, v3 ; bin: f3 41 0f 11 2e + [-] store.f32 v100, v3 ; bin: heap_oob f3 41 0f 11 2e ; asm: movss %xmm10, (%rax) - [-] store.f32 v101, v2 ; bin: f3 44 0f 11 10 + [-] store.f32 v101, v2 ; bin: heap_oob f3 44 0f 11 10 ; asm: movss %xmm5, (%r13) - [-] store.f32 v100, v4 ; bin: f3 41 0f 11 6d 00 + [-] store.f32 v100, v4 ; bin: heap_oob f3 41 0f 11 6d 00 ; asm: movss %xmm10, (%r13) - [-] store.f32 v101, v4 ; bin: f3 45 0f 11 55 00 + [-] store.f32 v101, v4 ; bin: heap_oob f3 45 0f 11 55 00 ; asm: movss %xmm5, 50(%r14) - [-] store.f32 v100, v3+50 ; bin: f3 41 0f 11 6e 32 + [-] store.f32 v100, v3+50 ; bin: heap_oob f3 41 0f 11 6e 32 ; asm: movss %xmm10, -50(%rax) - [-] store.f32 v101, v2-50 ; bin: f3 44 0f 11 50 ce + [-] store.f32 v101, v2-50 ; bin: heap_oob f3 44 0f 11 50 ce ; asm: movss %xmm5, 10000(%r14) - [-] store.f32 v100, v3+10000 ; bin: f3 41 0f 11 ae 00002710 + [-] store.f32 v100, v3+10000 ; bin: heap_oob f3 41 0f 11 ae 00002710 ; asm: movss %xmm10, -10000(%rax) - [-] store.f32 v101, v2-10000 ; bin: f3 44 0f 11 90 ffffd8f0 + [-] store.f32 v101, v2-10000 ; bin: heap_oob f3 44 0f 11 90 ffffd8f0 ; Spill / Fill. @@ -393,34 +393,34 @@ ebb0: ; Load/Store ; asm: movsd (%r14), %xmm5 - [-,%xmm5] v100 = load.f64 v3 ; bin: f2 41 0f 10 2e + [-,%xmm5] v100 = load.f64 v3 ; bin: heap_oob f2 41 0f 10 2e ; asm: movsd (%rax), %xmm10 - [-,%xmm10] v101 = load.f64 v2 ; bin: f2 44 0f 10 10 + [-,%xmm10] v101 = load.f64 v2 ; bin: heap_oob f2 44 0f 10 10 ; asm: movsd 50(%r14), %xmm5 - [-,%xmm5] v110 = load.f64 v3+50 ; bin: f2 41 0f 10 6e 32 + [-,%xmm5] v110 = load.f64 v3+50 ; bin: heap_oob f2 41 0f 10 6e 32 ; asm: movsd -50(%rax), %xmm10 - [-,%xmm10] v111 = load.f64 v2-50 ; bin: f2 44 0f 10 50 ce + [-,%xmm10] v111 = load.f64 v2-50 ; bin: heap_oob f2 44 0f 10 50 ce ; asm: movsd 10000(%r14), %xmm5 - [-,%xmm5] v120 = load.f64 v3+10000 ; bin: f2 41 0f 10 ae 00002710 + [-,%xmm5] v120 = load.f64 v3+10000 ; bin: heap_oob f2 41 0f 10 ae 00002710 ; asm: movsd -10000(%rax), %xmm10 - [-,%xmm10] v121 = load.f64 v2-10000 ; bin: f2 44 0f 10 90 ffffd8f0 + [-,%xmm10] v121 = load.f64 v2-10000 ; bin: heap_oob f2 44 0f 10 90 ffffd8f0 ; asm: movsd %xmm5, (%r14) - [-] store.f64 v100, v3 ; bin: f2 41 0f 11 2e + [-] store.f64 v100, v3 ; bin: heap_oob f2 41 0f 11 2e ; asm: movsd %xmm10, (%rax) - [-] store.f64 v101, v2 ; bin: f2 44 0f 11 10 + [-] store.f64 v101, v2 ; bin: heap_oob f2 44 0f 11 10 ; asm: movsd %xmm5, (%r13) - [-] store.f64 v100, v4 ; bin: f2 41 0f 11 6d 00 + [-] store.f64 v100, v4 ; bin: heap_oob f2 41 0f 11 6d 00 ; asm: movsd %xmm10, (%r13) - [-] store.f64 v101, v4 ; bin: f2 45 0f 11 55 00 + [-] store.f64 v101, v4 ; bin: heap_oob f2 45 0f 11 55 00 ; asm: movsd %xmm5, 50(%r14) - [-] store.f64 v100, v3+50 ; bin: f2 41 0f 11 6e 32 + [-] store.f64 v100, v3+50 ; bin: heap_oob f2 41 0f 11 6e 32 ; asm: movsd %xmm10, -50(%rax) - [-] store.f64 v101, v2-50 ; bin: f2 44 0f 11 50 ce + [-] store.f64 v101, v2-50 ; bin: heap_oob f2 44 0f 11 50 ce ; asm: movsd %xmm5, 10000(%r14) - [-] store.f64 v100, v3+10000 ; bin: f2 41 0f 11 ae 00002710 + [-] store.f64 v100, v3+10000 ; bin: heap_oob f2 41 0f 11 ae 00002710 ; asm: movsd %xmm10, -10000(%rax) - [-] store.f64 v101, v2-10000 ; bin: f2 44 0f 11 90 ffffd8f0 + [-] store.f64 v101, v2-10000 ; bin: heap_oob f2 44 0f 11 90 ffffd8f0 ; Spill / Fill. @@ -505,21 +505,21 @@ ebb1: brff ule v1, ebb1 ; bin: 76 f0 ; asm: jp .+4; ud2 - trapff ord v1, user0 ; bin: 7a 02 0f 0b + trapff ord v1, user0 ; bin: 7a 02 user0 0f 0b ; asm: jnp .+4; ud2 - trapff uno v1, user0 ; bin: 7b 02 0f 0b + trapff uno v1, user0 ; bin: 7b 02 user0 0f 0b ; asm: je .+4; ud2 - trapff one v1, user0 ; bin: 74 02 0f 0b + trapff one v1, user0 ; bin: 74 02 user0 0f 0b ; asm: jne .+4; ud2 - trapff ueq v1, user0 ; bin: 75 02 0f 0b + trapff ueq v1, user0 ; bin: 75 02 user0 0f 0b ; asm: jna .+4; ud2 - trapff gt v1, user0 ; bin: 76 02 0f 0b + trapff gt v1, user0 ; bin: 76 02 user0 0f 0b ; asm: jnae .+4; ud2 - trapff ge v1, user0 ; bin: 72 02 0f 0b + trapff ge v1, user0 ; bin: 72 02 user0 0f 0b ; asm: jnb .+4; ud2 - trapff ult v1, user0 ; bin: 73 02 0f 0b + trapff ult v1, user0 ; bin: 73 02 user0 0f 0b ; asm: jnbe .+4; ud2 - trapff ule v1, user0 ; bin: 77 02 0f 0b + trapff ule v1, user0 ; bin: 77 02 user0 0f 0b ; asm: setnp %bl [-,%rbx] v10 = trueff ord v1 ; bin: 0f 9b c3 diff --git a/cranelift/filetests/isa/intel/binary64.cton b/cranelift/filetests/isa/intel/binary64.cton index f7aab2f8f4..1444c1e062 100644 --- a/cranelift/filetests/isa/intel/binary64.cton +++ b/cranelift/filetests/isa/intel/binary64.cton @@ -175,146 +175,146 @@ ebb0: ; Register indirect addressing with no displacement. ; asm: movq %rcx, (%r10) - store v1, v3 ; bin: 49 89 0a + store v1, v3 ; bin: heap_oob 49 89 0a ; asm: movq %r10, (%rcx) - store v3, v1 ; bin: 4c 89 11 + store v3, v1 ; bin: heap_oob 4c 89 11 ; asm: movl %ecx, (%r10) - istore32 v1, v3 ; bin: 41 89 0a + istore32 v1, v3 ; bin: heap_oob 41 89 0a ; asm: movl %r10d, (%rcx) - istore32 v3, v1 ; bin: 44 89 11 + istore32 v3, v1 ; bin: heap_oob 44 89 11 ; asm: movw %cx, (%r10) - istore16 v1, v3 ; bin: 66 41 89 0a + istore16 v1, v3 ; bin: heap_oob 66 41 89 0a ; asm: movw %r10w, (%rcx) - istore16 v3, v1 ; bin: 66 44 89 11 + istore16 v3, v1 ; bin: heap_oob 66 44 89 11 ; asm: movb %cl, (%r10) - istore8 v1, v3 ; bin: 41 88 0a + istore8 v1, v3 ; bin: heap_oob 41 88 0a ; asm: movb %r10b, (%rcx) - istore8 v3, v1 ; bin: 44 88 11 + istore8 v3, v1 ; bin: heap_oob 44 88 11 ; asm: movq (%rcx), %r14 - [-,%r14] v120 = load.i64 v1 ; bin: 4c 8b 31 + [-,%r14] v120 = load.i64 v1 ; bin: heap_oob 4c 8b 31 ; asm: movq (%r10), %rdx - [-,%rdx] v121 = load.i64 v3 ; bin: 49 8b 12 + [-,%rdx] v121 = load.i64 v3 ; bin: heap_oob 49 8b 12 ; asm: movl (%rcx), %r14d - [-,%r14] v122 = uload32.i64 v1 ; bin: 44 8b 31 + [-,%r14] v122 = uload32.i64 v1 ; bin: heap_oob 44 8b 31 ; asm: movl (%r10), %edx - [-,%rdx] v123 = uload32.i64 v3 ; bin: 41 8b 12 + [-,%rdx] v123 = uload32.i64 v3 ; bin: heap_oob 41 8b 12 ; asm: movslq (%rcx), %r14 - [-,%r14] v124 = sload32.i64 v1 ; bin: 4c 63 31 + [-,%r14] v124 = sload32.i64 v1 ; bin: heap_oob 4c 63 31 ; asm: movslq (%r10), %rdx - [-,%rdx] v125 = sload32.i64 v3 ; bin: 49 63 12 + [-,%rdx] v125 = sload32.i64 v3 ; bin: heap_oob 49 63 12 ; asm: movzwq (%rcx), %r14 - [-,%r14] v126 = uload16.i64 v1 ; bin: 4c 0f b7 31 + [-,%r14] v126 = uload16.i64 v1 ; bin: heap_oob 4c 0f b7 31 ; asm: movzwq (%r10), %rdx - [-,%rdx] v127 = uload16.i64 v3 ; bin: 49 0f b7 12 + [-,%rdx] v127 = uload16.i64 v3 ; bin: heap_oob 49 0f b7 12 ; asm: movswq (%rcx), %r14 - [-,%r14] v128 = sload16.i64 v1 ; bin: 4c 0f bf 31 + [-,%r14] v128 = sload16.i64 v1 ; bin: heap_oob 4c 0f bf 31 ; asm: movswq (%r10), %rdx - [-,%rdx] v129 = sload16.i64 v3 ; bin: 49 0f bf 12 + [-,%rdx] v129 = sload16.i64 v3 ; bin: heap_oob 49 0f bf 12 ; asm: movzbq (%rcx), %r14 - [-,%r14] v130 = uload8.i64 v1 ; bin: 4c 0f b6 31 + [-,%r14] v130 = uload8.i64 v1 ; bin: heap_oob 4c 0f b6 31 ; asm: movzbq (%r10), %rdx - [-,%rdx] v131 = uload8.i64 v3 ; bin: 49 0f b6 12 + [-,%rdx] v131 = uload8.i64 v3 ; bin: heap_oob 49 0f b6 12 ; asm: movsbq (%rcx), %r14 - [-,%r14] v132 = sload8.i64 v1 ; bin: 4c 0f be 31 + [-,%r14] v132 = sload8.i64 v1 ; bin: heap_oob 4c 0f be 31 ; asm: movsbq (%r10), %rdx - [-,%rdx] v133 = sload8.i64 v3 ; bin: 49 0f be 12 + [-,%rdx] v133 = sload8.i64 v3 ; bin: heap_oob 49 0f be 12 ; Register-indirect with 8-bit signed displacement. ; asm: movq %rcx, 100(%r10) - store v1, v3+100 ; bin: 49 89 4a 64 + store v1, v3+100 ; bin: heap_oob 49 89 4a 64 ; asm: movq %r10, -100(%rcx) - store v3, v1-100 ; bin: 4c 89 51 9c + store v3, v1-100 ; bin: heap_oob 4c 89 51 9c ; asm: movl %ecx, 100(%r10) - istore32 v1, v3+100 ; bin: 41 89 4a 64 + istore32 v1, v3+100 ; bin: heap_oob 41 89 4a 64 ; asm: movl %r10d, -100(%rcx) - istore32 v3, v1-100 ; bin: 44 89 51 9c + istore32 v3, v1-100 ; bin: heap_oob 44 89 51 9c ; asm: movw %cx, 100(%r10) - istore16 v1, v3+100 ; bin: 66 41 89 4a 64 + istore16 v1, v3+100 ; bin: heap_oob 66 41 89 4a 64 ; asm: movw %r10w, -100(%rcx) - istore16 v3, v1-100 ; bin: 66 44 89 51 9c + istore16 v3, v1-100 ; bin: heap_oob 66 44 89 51 9c ; asm: movb %cl, 100(%r10) - istore8 v1, v3+100 ; bin: 41 88 4a 64 + istore8 v1, v3+100 ; bin: heap_oob 41 88 4a 64 ; asm: movb %r10b, 100(%rcx) - istore8 v3, v1+100 ; bin: 44 88 51 64 + istore8 v3, v1+100 ; bin: heap_oob 44 88 51 64 ; asm: movq 50(%rcx), %r10 - [-,%r10] v140 = load.i64 v1+50 ; bin: 4c 8b 51 32 + [-,%r10] v140 = load.i64 v1+50 ; bin: heap_oob 4c 8b 51 32 ; asm: movq -50(%r10), %rdx - [-,%rdx] v141 = load.i64 v3-50 ; bin: 49 8b 52 ce + [-,%rdx] v141 = load.i64 v3-50 ; bin: heap_oob 49 8b 52 ce ; asm: movl 50(%rcx), %edi - [-,%rdi] v142 = uload32.i64 v1+50 ; bin: 8b 79 32 + [-,%rdi] v142 = uload32.i64 v1+50 ; bin: heap_oob 8b 79 32 ; asm: movl -50(%rsi), %edx - [-,%rdx] v143 = uload32.i64 v2-50 ; bin: 8b 56 ce + [-,%rdx] v143 = uload32.i64 v2-50 ; bin: heap_oob 8b 56 ce ; asm: movslq 50(%rcx), %rdi - [-,%rdi] v144 = sload32.i64 v1+50 ; bin: 48 63 79 32 + [-,%rdi] v144 = sload32.i64 v1+50 ; bin: heap_oob 48 63 79 32 ; asm: movslq -50(%rsi), %rdx - [-,%rdx] v145 = sload32.i64 v2-50 ; bin: 48 63 56 ce + [-,%rdx] v145 = sload32.i64 v2-50 ; bin: heap_oob 48 63 56 ce ; asm: movzwq 50(%rcx), %rdi - [-,%rdi] v146 = uload16.i64 v1+50 ; bin: 48 0f b7 79 32 + [-,%rdi] v146 = uload16.i64 v1+50 ; bin: heap_oob 48 0f b7 79 32 ; asm: movzwq -50(%rsi), %rdx - [-,%rdx] v147 = uload16.i64 v2-50 ; bin: 48 0f b7 56 ce + [-,%rdx] v147 = uload16.i64 v2-50 ; bin: heap_oob 48 0f b7 56 ce ; asm: movswq 50(%rcx), %rdi - [-,%rdi] v148 = sload16.i64 v1+50 ; bin: 48 0f bf 79 32 + [-,%rdi] v148 = sload16.i64 v1+50 ; bin: heap_oob 48 0f bf 79 32 ; asm: movswq -50(%rsi), %rdx - [-,%rdx] v149 = sload16.i64 v2-50 ; bin: 48 0f bf 56 ce + [-,%rdx] v149 = sload16.i64 v2-50 ; bin: heap_oob 48 0f bf 56 ce ; asm: movzbq 50(%rcx), %rdi - [-,%rdi] v150 = uload8.i64 v1+50 ; bin: 48 0f b6 79 32 + [-,%rdi] v150 = uload8.i64 v1+50 ; bin: heap_oob 48 0f b6 79 32 ; asm: movzbq -50(%rsi), %rdx - [-,%rdx] v151 = uload8.i64 v2-50 ; bin: 48 0f b6 56 ce + [-,%rdx] v151 = uload8.i64 v2-50 ; bin: heap_oob 48 0f b6 56 ce ; asm: movsbq 50(%rcx), %rdi - [-,%rdi] v152 = sload8.i64 v1+50 ; bin: 48 0f be 79 32 + [-,%rdi] v152 = sload8.i64 v1+50 ; bin: heap_oob 48 0f be 79 32 ; asm: movsbq -50(%rsi), %rdx - [-,%rdx] v153 = sload8.i64 v2-50 ; bin: 48 0f be 56 ce + [-,%rdx] v153 = sload8.i64 v2-50 ; bin: heap_oob 48 0f be 56 ce ; Register-indirect with 32-bit signed displacement. ; asm: movq %rcx, 10000(%r10) - store v1, v3+10000 ; bin: 49 89 8a 00002710 + store v1, v3+10000 ; bin: heap_oob 49 89 8a 00002710 ; asm: movq %r10, -10000(%rcx) - store v3, v1-10000 ; bin: 4c 89 91 ffffd8f0 + store v3, v1-10000 ; bin: heap_oob 4c 89 91 ffffd8f0 ; asm: movl %ecx, 10000(%rsi) - istore32 v1, v2+10000 ; bin: 89 8e 00002710 + istore32 v1, v2+10000 ; bin: heap_oob 89 8e 00002710 ; asm: movl %esi, -10000(%rcx) - istore32 v2, v1-10000 ; bin: 89 b1 ffffd8f0 + istore32 v2, v1-10000 ; bin: heap_oob 89 b1 ffffd8f0 ; asm: movw %cx, 10000(%rsi) - istore16 v1, v2+10000 ; bin: 66 89 8e 00002710 + istore16 v1, v2+10000 ; bin: heap_oob 66 89 8e 00002710 ; asm: movw %si, -10000(%rcx) - istore16 v2, v1-10000 ; bin: 66 89 b1 ffffd8f0 + istore16 v2, v1-10000 ; bin: heap_oob 66 89 b1 ffffd8f0 ; asm: movb %cl, 10000(%rsi) - istore8 v1, v2+10000 ; bin: 88 8e 00002710 + istore8 v1, v2+10000 ; bin: heap_oob 88 8e 00002710 ; asm: movb %sil, 10000(%rcx) - istore8 v2, v1+10000 ; bin: 40 88 b1 00002710 + istore8 v2, v1+10000 ; bin: heap_oob 40 88 b1 00002710 ; asm: movq 50000(%rcx), %r10 - [-,%r10] v160 = load.i64 v1+50000 ; bin: 4c 8b 91 0000c350 + [-,%r10] v160 = load.i64 v1+50000 ; bin: heap_oob 4c 8b 91 0000c350 ; asm: movq -50000(%r10), %rdx - [-,%rdx] v161 = load.i64 v3-50000 ; bin: 49 8b 92 ffff3cb0 + [-,%rdx] v161 = load.i64 v3-50000 ; bin: heap_oob 49 8b 92 ffff3cb0 ; asm: movl 50000(%rcx), %edi - [-,%rdi] v162 = uload32.i64 v1+50000 ; bin: 8b b9 0000c350 + [-,%rdi] v162 = uload32.i64 v1+50000 ; bin: heap_oob 8b b9 0000c350 ; asm: movl -50000(%rsi), %edx - [-,%rdx] v163 = uload32.i64 v2-50000 ; bin: 8b 96 ffff3cb0 + [-,%rdx] v163 = uload32.i64 v2-50000 ; bin: heap_oob 8b 96 ffff3cb0 ; asm: movslq 50000(%rcx), %rdi - [-,%rdi] v164 = sload32.i64 v1+50000 ; bin: 48 63 b9 0000c350 + [-,%rdi] v164 = sload32.i64 v1+50000 ; bin: heap_oob 48 63 b9 0000c350 ; asm: movslq -50000(%rsi), %rdx - [-,%rdx] v165 = sload32.i64 v2-50000 ; bin: 48 63 96 ffff3cb0 + [-,%rdx] v165 = sload32.i64 v2-50000 ; bin: heap_oob 48 63 96 ffff3cb0 ; asm: movzwq 50000(%rcx), %rdi - [-,%rdi] v166 = uload16.i64 v1+50000 ; bin: 48 0f b7 b9 0000c350 + [-,%rdi] v166 = uload16.i64 v1+50000 ; bin: heap_oob 48 0f b7 b9 0000c350 ; asm: movzwq -50000(%rsi), %rdx - [-,%rdx] v167 = uload16.i64 v2-50000 ; bin: 48 0f b7 96 ffff3cb0 + [-,%rdx] v167 = uload16.i64 v2-50000 ; bin: heap_oob 48 0f b7 96 ffff3cb0 ; asm: movswq 50000(%rcx), %rdi - [-,%rdi] v168 = sload16.i64 v1+50000 ; bin: 48 0f bf b9 0000c350 + [-,%rdi] v168 = sload16.i64 v1+50000 ; bin: heap_oob 48 0f bf b9 0000c350 ; asm: movswq -50000(%rsi), %rdx - [-,%rdx] v169 = sload16.i64 v2-50000 ; bin: 48 0f bf 96 ffff3cb0 + [-,%rdx] v169 = sload16.i64 v2-50000 ; bin: heap_oob 48 0f bf 96 ffff3cb0 ; asm: movzbq 50000(%rcx), %rdi - [-,%rdi] v170 = uload8.i64 v1+50000 ; bin: 48 0f b6 b9 0000c350 + [-,%rdi] v170 = uload8.i64 v1+50000 ; bin: heap_oob 48 0f b6 b9 0000c350 ; asm: movzbq -50000(%rsi), %rdx - [-,%rdx] v171 = uload8.i64 v2-50000 ; bin: 48 0f b6 96 ffff3cb0 + [-,%rdx] v171 = uload8.i64 v2-50000 ; bin: heap_oob 48 0f b6 96 ffff3cb0 ; asm: movsbq 50000(%rcx), %rdi - [-,%rdi] v172 = sload8.i64 v1+50000 ; bin: 48 0f be b9 0000c350 + [-,%rdi] v172 = sload8.i64 v1+50000 ; bin: heap_oob 48 0f be b9 0000c350 ; asm: movsbq -50000(%rsi), %rdx - [-,%rdx] v173 = sload8.i64 v2-50000 ; bin: 48 0f be 96 ffff3cb0 + [-,%rdx] v173 = sload8.i64 v2-50000 ; bin: heap_oob 48 0f be 96 ffff3cb0 ; More arithmetic. @@ -329,17 +329,17 @@ ebb0: [-,%rax] v190 = iconst.i64 1 [-,%rdx] v191 = iconst.i64 2 ; asm: idivq %rcx - [-,%rax,%rdx] v192, v193 = x86_sdivmodx v190, v191, v1 ; bin: 48 f7 f9 + [-,%rax,%rdx] v192, v193 = x86_sdivmodx v190, v191, v1 ; bin: int_divz 48 f7 f9 ; asm: idivq %rsi - [-,%rax,%rdx] v194, v195 = x86_sdivmodx v190, v191, v2 ; bin: 48 f7 fe + [-,%rax,%rdx] v194, v195 = x86_sdivmodx v190, v191, v2 ; bin: int_divz 48 f7 fe ; asm: idivq %r10 - [-,%rax,%rdx] v196, v197 = x86_sdivmodx v190, v191, v3 ; bin: 49 f7 fa + [-,%rax,%rdx] v196, v197 = x86_sdivmodx v190, v191, v3 ; bin: int_divz 49 f7 fa ; asm: divq %rcx - [-,%rax,%rdx] v198, v199 = x86_udivmodx v190, v191, v1 ; bin: 48 f7 f1 + [-,%rax,%rdx] v198, v199 = x86_udivmodx v190, v191, v1 ; bin: int_divz 48 f7 f1 ; asm: divq %rsi - [-,%rax,%rdx] v200, v201 = x86_udivmodx v190, v191, v2 ; bin: 48 f7 f6 + [-,%rax,%rdx] v200, v201 = x86_udivmodx v190, v191, v2 ; bin: int_divz 48 f7 f6 ; asm: divq %r10 - [-,%rax,%rdx] v202, v203 = x86_udivmodx v190, v191, v3 ; bin: 49 f7 f2 + [-,%rax,%rdx] v202, v203 = x86_udivmodx v190, v191, v3 ; bin: int_divz 49 f7 f2 ; double-length multiply instructions, 64 bit [-,%rax] v1001 = iconst.i64 1 @@ -637,25 +637,25 @@ ebb1: ; The trapif instructions are encoded as macros: a conditional jump over a ud2. ; asm: jne .+4; ud2 - trapif eq v11, user0 ; bin: 75 02 0f 0b + trapif eq v11, user0 ; bin: 75 02 user0 0f 0b ; asm: je .+4; ud2 - trapif ne v11, user0 ; bin: 74 02 0f 0b + trapif ne v11, user0 ; bin: 74 02 user0 0f 0b ; asm: jnl .+4; ud2 - trapif slt v11, user0 ; bin: 7d 02 0f 0b + trapif slt v11, user0 ; bin: 7d 02 user0 0f 0b ; asm: jnge .+4; ud2 - trapif sge v11, user0 ; bin: 7c 02 0f 0b + trapif sge v11, user0 ; bin: 7c 02 user0 0f 0b ; asm: jng .+4; ud2 - trapif sgt v11, user0 ; bin: 7e 02 0f 0b + trapif sgt v11, user0 ; bin: 7e 02 user0 0f 0b ; asm: jnle .+4; ud2 - trapif sle v11, user0 ; bin: 7f 02 0f 0b + trapif sle v11, user0 ; bin: 7f 02 user0 0f 0b ; asm: jnb .+4; ud2 - trapif ult v11, user0 ; bin: 73 02 0f 0b + trapif ult v11, user0 ; bin: 73 02 user0 0f 0b ; asm: jnae .+4; ud2 - trapif uge v11, user0 ; bin: 72 02 0f 0b + trapif uge v11, user0 ; bin: 72 02 user0 0f 0b ; asm: jna .+4; ud2 - trapif ugt v11, user0 ; bin: 76 02 0f 0b + trapif ugt v11, user0 ; bin: 76 02 user0 0f 0b ; asm: jnbe .+4; ud2 - trapif ule v11, user0 ; bin: 77 02 0f 0b + trapif ule v11, user0 ; bin: 77 02 user0 0f 0b ; Stack check. ; asm: cmpq %rsp, %rcx @@ -729,71 +729,71 @@ ebb0: ; Register indirect addressing with no displacement. ; asm: movl (%rcx), %edi - [-,%rdi] v10 = load.i32 v1 ; bin: 8b 39 + [-,%rdi] v10 = load.i32 v1 ; bin: heap_oob 8b 39 ; asm: movl (%rsi), %edx - [-,%rdx] v11 = load.i32 v2 ; bin: 8b 16 + [-,%rdx] v11 = load.i32 v2 ; bin: heap_oob 8b 16 ; asm: movzwl (%rcx), %edi - [-,%rdi] v12 = uload16.i32 v1 ; bin: 0f b7 39 + [-,%rdi] v12 = uload16.i32 v1 ; bin: heap_oob 0f b7 39 ; asm: movzwl (%rsi), %edx - [-,%rdx] v13 = uload16.i32 v2 ; bin: 0f b7 16 + [-,%rdx] v13 = uload16.i32 v2 ; bin: heap_oob 0f b7 16 ; asm: movswl (%rcx), %edi - [-,%rdi] v14 = sload16.i32 v1 ; bin: 0f bf 39 + [-,%rdi] v14 = sload16.i32 v1 ; bin: heap_oob 0f bf 39 ; asm: movswl (%rsi), %edx - [-,%rdx] v15 = sload16.i32 v2 ; bin: 0f bf 16 + [-,%rdx] v15 = sload16.i32 v2 ; bin: heap_oob 0f bf 16 ; asm: movzbl (%rcx), %edi - [-,%rdi] v16 = uload8.i32 v1 ; bin: 0f b6 39 + [-,%rdi] v16 = uload8.i32 v1 ; bin: heap_oob 0f b6 39 ; asm: movzbl (%rsi), %edx - [-,%rdx] v17 = uload8.i32 v2 ; bin: 0f b6 16 + [-,%rdx] v17 = uload8.i32 v2 ; bin: heap_oob 0f b6 16 ; asm: movsbl (%rcx), %edi - [-,%rdi] v18 = sload8.i32 v1 ; bin: 0f be 39 + [-,%rdi] v18 = sload8.i32 v1 ; bin: heap_oob 0f be 39 ; asm: movsbl (%rsi), %edx - [-,%rdx] v19 = sload8.i32 v2 ; bin: 0f be 16 + [-,%rdx] v19 = sload8.i32 v2 ; bin: heap_oob 0f be 16 ; Register-indirect with 8-bit signed displacement. ; asm: movl 50(%rcx), %edi - [-,%rdi] v20 = load.i32 v1+50 ; bin: 8b 79 32 + [-,%rdi] v20 = load.i32 v1+50 ; bin: heap_oob 8b 79 32 ; asm: movl -50(%rsi), %edx - [-,%rdx] v21 = load.i32 v2-50 ; bin: 8b 56 ce + [-,%rdx] v21 = load.i32 v2-50 ; bin: heap_oob 8b 56 ce ; asm: movzwl 50(%rcx), %edi - [-,%rdi] v22 = uload16.i32 v1+50 ; bin: 0f b7 79 32 + [-,%rdi] v22 = uload16.i32 v1+50 ; bin: heap_oob 0f b7 79 32 ; asm: movzwl -50(%rsi), %edx - [-,%rdx] v23 = uload16.i32 v2-50 ; bin: 0f b7 56 ce + [-,%rdx] v23 = uload16.i32 v2-50 ; bin: heap_oob 0f b7 56 ce ; asm: movswl 50(%rcx), %edi - [-,%rdi] v24 = sload16.i32 v1+50 ; bin: 0f bf 79 32 + [-,%rdi] v24 = sload16.i32 v1+50 ; bin: heap_oob 0f bf 79 32 ; asm: movswl -50(%rsi), %edx - [-,%rdx] v25 = sload16.i32 v2-50 ; bin: 0f bf 56 ce + [-,%rdx] v25 = sload16.i32 v2-50 ; bin: heap_oob 0f bf 56 ce ; asm: movzbl 50(%rcx), %edi - [-,%rdi] v26 = uload8.i32 v1+50 ; bin: 0f b6 79 32 + [-,%rdi] v26 = uload8.i32 v1+50 ; bin: heap_oob 0f b6 79 32 ; asm: movzbl -50(%rsi), %edx - [-,%rdx] v27 = uload8.i32 v2-50 ; bin: 0f b6 56 ce + [-,%rdx] v27 = uload8.i32 v2-50 ; bin: heap_oob 0f b6 56 ce ; asm: movsbl 50(%rcx), %edi - [-,%rdi] v28 = sload8.i32 v1+50 ; bin: 0f be 79 32 + [-,%rdi] v28 = sload8.i32 v1+50 ; bin: heap_oob 0f be 79 32 ; asm: movsbl -50(%rsi), %edx - [-,%rdx] v29 = sload8.i32 v2-50 ; bin: 0f be 56 ce + [-,%rdx] v29 = sload8.i32 v2-50 ; bin: heap_oob 0f be 56 ce ; Register-indirect with 32-bit signed displacement. ; asm: movl 50000(%rcx), %edi - [-,%rdi] v30 = load.i32 v1+50000 ; bin: 8b b9 0000c350 + [-,%rdi] v30 = load.i32 v1+50000 ; bin: heap_oob 8b b9 0000c350 ; asm: movl -50000(%rsi), %edx - [-,%rdx] v31 = load.i32 v2-50000 ; bin: 8b 96 ffff3cb0 + [-,%rdx] v31 = load.i32 v2-50000 ; bin: heap_oob 8b 96 ffff3cb0 ; asm: movzwl 50000(%rcx), %edi - [-,%rdi] v32 = uload16.i32 v1+50000 ; bin: 0f b7 b9 0000c350 + [-,%rdi] v32 = uload16.i32 v1+50000 ; bin: heap_oob 0f b7 b9 0000c350 ; asm: movzwl -50000(%rsi), %edx - [-,%rdx] v33 = uload16.i32 v2-50000 ; bin: 0f b7 96 ffff3cb0 + [-,%rdx] v33 = uload16.i32 v2-50000 ; bin: heap_oob 0f b7 96 ffff3cb0 ; asm: movswl 50000(%rcx), %edi - [-,%rdi] v34 = sload16.i32 v1+50000 ; bin: 0f bf b9 0000c350 + [-,%rdi] v34 = sload16.i32 v1+50000 ; bin: heap_oob 0f bf b9 0000c350 ; asm: movswl -50000(%rsi), %edx - [-,%rdx] v35 = sload16.i32 v2-50000 ; bin: 0f bf 96 ffff3cb0 + [-,%rdx] v35 = sload16.i32 v2-50000 ; bin: heap_oob 0f bf 96 ffff3cb0 ; asm: movzbl 50000(%rcx), %edi - [-,%rdi] v36 = uload8.i32 v1+50000 ; bin: 0f b6 b9 0000c350 + [-,%rdi] v36 = uload8.i32 v1+50000 ; bin: heap_oob 0f b6 b9 0000c350 ; asm: movzbl -50000(%rsi), %edx - [-,%rdx] v37 = uload8.i32 v2-50000 ; bin: 0f b6 96 ffff3cb0 + [-,%rdx] v37 = uload8.i32 v2-50000 ; bin: heap_oob 0f b6 96 ffff3cb0 ; asm: movsbl 50000(%rcx), %edi - [-,%rdi] v38 = sload8.i32 v1+50000 ; bin: 0f be b9 0000c350 + [-,%rdi] v38 = sload8.i32 v1+50000 ; bin: heap_oob 0f be b9 0000c350 ; asm: movsbl -50000(%rsi), %edx - [-,%rdx] v39 = sload8.i32 v2-50000 ; bin: 0f be 96 ffff3cb0 + [-,%rdx] v39 = sload8.i32 v2-50000 ; bin: heap_oob 0f be 96 ffff3cb0 ; Integer Register-Register Operations. @@ -924,17 +924,17 @@ ebb0: [-,%rax] v160 = iconst.i32 1 [-,%rdx] v161 = iconst.i32 2 ; asm: idivl %ecx - [-,%rax,%rdx] v162, v163 = x86_sdivmodx v160, v161, v1 ; bin: f7 f9 + [-,%rax,%rdx] v162, v163 = x86_sdivmodx v160, v161, v1 ; bin: int_divz f7 f9 ; asm: idivl %esi - [-,%rax,%rdx] v164, v165 = x86_sdivmodx v160, v161, v2 ; bin: f7 fe + [-,%rax,%rdx] v164, v165 = x86_sdivmodx v160, v161, v2 ; bin: int_divz f7 fe ; asm: idivl %r10d - [-,%rax,%rdx] v166, v167 = x86_sdivmodx v160, v161, v3 ; bin: 41 f7 fa + [-,%rax,%rdx] v166, v167 = x86_sdivmodx v160, v161, v3 ; bin: int_divz 41 f7 fa ; asm: divl %ecx - [-,%rax,%rdx] v168, v169 = x86_udivmodx v160, v161, v1 ; bin: f7 f1 + [-,%rax,%rdx] v168, v169 = x86_udivmodx v160, v161, v1 ; bin: int_divz f7 f1 ; asm: divl %esi - [-,%rax,%rdx] v170, v171 = x86_udivmodx v160, v161, v2 ; bin: f7 f6 + [-,%rax,%rdx] v170, v171 = x86_udivmodx v160, v161, v2 ; bin: int_divz f7 f6 ; asm: divl %r10d - [-,%rax,%rdx] v172, v173 = x86_udivmodx v160, v161, v3 ; bin: 41 f7 f2 + [-,%rax,%rdx] v172, v173 = x86_udivmodx v160, v161, v3 ; bin: int_divz 41 f7 f2 ; Bit-counting instructions. @@ -1144,7 +1144,7 @@ ebb0: ; asm: movzbl %r10b, %ecx [-,%rcx] v32 = uextend.i32 v13 ; bin: 41 0f b6 ca - trap user0 ; bin: 0f 0b + trap user0 ; bin: user0 0f 0b } ; Tests for i32/i16 conversion instructions. @@ -1172,7 +1172,7 @@ ebb0: ; asm: movzwl %r10w, %ecx [-,%rcx] v32 = uextend.i32 v13 ; bin: 41 0f b7 ca - trap user0 ; bin: 0f 0b + trap user0 ; bin: user0 0f 0b } ; Tests for i64/i8 conversion instructions. @@ -1200,7 +1200,7 @@ ebb0: ; asm: movzbl %r10b, %ecx [-,%rcx] v32 = uextend.i64 v13 ; bin: 41 0f b6 ca - trap user0 ; bin: 0f 0b + trap user0 ; bin: user0 0f 0b } ; Tests for i64/i16 conversion instructions. @@ -1228,7 +1228,7 @@ ebb0: ; asm: movzwl %r10w, %ecx [-,%rcx] v32 = uextend.i64 v13 ; bin: 41 0f b7 ca - trap user0 ; bin: 0f 0b + trap user0 ; bin: user0 0f 0b } ; Tests for i64/i32 conversion instructions. @@ -1256,5 +1256,5 @@ ebb0: ; asm: movl %r10d, %ecx [-,%rcx] v32 = uextend.i64 v13 ; bin: 44 89 d1 - trap user0 ; bin: 0f 0b + trap user0 ; bin: user0 0f 0b } diff --git a/cranelift/src/compile.rs b/cranelift/src/compile.rs index c21b989149..ccc049fa70 100644 --- a/cranelift/src/compile.rs +++ b/cranelift/src/compile.rs @@ -44,6 +44,18 @@ impl binemit::RelocSink for PrintRelocs { } } +struct PrintTraps { + flag_print: bool, +} + +impl binemit::TrapSink for PrintTraps { + fn trap(&mut self, offset: binemit::CodeOffset, _srcloc: ir::SourceLoc, code: ir::TrapCode) { + if self.flag_print { + println!("trap: {} at {}", code, offset); + } + } +} + pub fn run( files: Vec, flag_print: bool, @@ -94,8 +106,9 @@ fn handle_module( // Encode the result as machine code. let mut mem = Vec::new(); let mut relocs = PrintRelocs { flag_print }; + let mut traps = PrintTraps { flag_print }; mem.resize(size as usize, 0); - context.emit_to_memory(mem.as_mut_ptr(), &mut relocs, &*isa); + context.emit_to_memory(mem.as_mut_ptr(), &mut relocs, &mut traps, &*isa); if flag_print { print!(".byte "); diff --git a/lib/cretonne/meta/isa/intel/recipes.py b/lib/cretonne/meta/isa/intel/recipes.py index 2406ef6ade..bb3db3cba1 100644 --- a/lib/cretonne/meta/isa/intel/recipes.py +++ b/lib/cretonne/meta/isa/intel/recipes.py @@ -278,7 +278,10 @@ null = EncRecipe('null', Unary, size=0, ins=GPR, outs=0, emit='') # XX opcode, no ModR/M. trap = TailRecipe( 'trap', Trap, size=0, ins=(), outs=(), - emit='PUT_OP(bits, BASE_REX, sink);') + emit=''' + sink.trap(code, func.srclocs[inst]); + PUT_OP(bits, BASE_REX, sink); + ''') # Macro: conditional jump over a ud2. trapif = EncRecipe( @@ -289,6 +292,7 @@ trapif = EncRecipe( sink.put1(0x70 | (icc2opc(cond.inverse()) as u8)); sink.put1(2); // ud2. + sink.trap(code, func.srclocs[inst]); sink.put1(0x0f); sink.put1(0x0b); ''') @@ -302,6 +306,7 @@ trapff = EncRecipe( sink.put1(0x70 | (fcc2opc(cond.inverse()) as u8)); sink.put1(2); // ud2. + sink.trap(code, func.srclocs[inst]); sink.put1(0x0f); sink.put1(0x0b); ''') @@ -450,6 +455,7 @@ div = TailRecipe( 'div', Ternary, size=1, ins=(GPR.rax, GPR.rdx, GPR), outs=(GPR.rax, GPR.rdx), emit=''' + sink.trap(TrapCode::IntegerDivisionByZero, func.srclocs[inst]); PUT_OP(bits, rex1(in_reg2), sink); modrm_r_bits(in_reg2, bits, sink); ''') @@ -678,6 +684,9 @@ st = TailRecipe( instp=IsEqual(Store.offset, 0), clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg1, in_reg0), sink); modrm_rm(in_reg1, in_reg0, sink); ''') @@ -690,6 +699,9 @@ st_abcd = TailRecipe( when_prefixed=st, clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg1, in_reg0), sink); modrm_rm(in_reg1, in_reg0, sink); ''') @@ -700,6 +712,9 @@ fst = TailRecipe( instp=IsEqual(Store.offset, 0), clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg1, in_reg0), sink); modrm_rm(in_reg1, in_reg0, sink); ''') @@ -710,6 +725,9 @@ stDisp8 = TailRecipe( instp=IsSignedInt(Store.offset, 8), clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg1, in_reg0), sink); modrm_disp8(in_reg1, in_reg0, sink); let offset: i32 = offset.into(); @@ -721,6 +739,9 @@ stDisp8_abcd = TailRecipe( when_prefixed=stDisp8, clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg1, in_reg0), sink); modrm_disp8(in_reg1, in_reg0, sink); let offset: i32 = offset.into(); @@ -731,6 +752,9 @@ fstDisp8 = TailRecipe( instp=IsSignedInt(Store.offset, 8), clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg1, in_reg0), sink); modrm_disp8(in_reg1, in_reg0, sink); let offset: i32 = offset.into(); @@ -742,6 +766,9 @@ stDisp32 = TailRecipe( 'stDisp32', Store, size=5, ins=(GPR, GPR_DEREF_SAFE), outs=(), clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg1, in_reg0), sink); modrm_disp32(in_reg1, in_reg0, sink); let offset: i32 = offset.into(); @@ -752,6 +779,9 @@ stDisp32_abcd = TailRecipe( when_prefixed=stDisp32, clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg1, in_reg0), sink); modrm_disp32(in_reg1, in_reg0, sink); let offset: i32 = offset.into(); @@ -761,6 +791,9 @@ fstDisp32 = TailRecipe( 'fstDisp32', Store, size=5, ins=(FPR, GPR_DEREF_SAFE), outs=(), clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg1, in_reg0), sink); modrm_disp32(in_reg1, in_reg0, sink); let offset: i32 = offset.into(); @@ -827,6 +860,9 @@ ld = TailRecipe( instp=IsEqual(Load.offset, 0), clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg0, out_reg0), sink); modrm_rm(in_reg0, out_reg0, sink); ''') @@ -837,6 +873,9 @@ fld = TailRecipe( instp=IsEqual(Load.offset, 0), clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg0, out_reg0), sink); modrm_rm(in_reg0, out_reg0, sink); ''') @@ -847,6 +886,9 @@ ldDisp8 = TailRecipe( instp=IsSignedInt(Load.offset, 8), clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg0, out_reg0), sink); modrm_disp8(in_reg0, out_reg0, sink); let offset: i32 = offset.into(); @@ -859,6 +901,9 @@ fldDisp8 = TailRecipe( instp=IsSignedInt(Load.offset, 8), clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg0, out_reg0), sink); modrm_disp8(in_reg0, out_reg0, sink); let offset: i32 = offset.into(); @@ -871,6 +916,9 @@ ldDisp32 = TailRecipe( instp=IsSignedInt(Load.offset, 32), clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg0, out_reg0), sink); modrm_disp32(in_reg0, out_reg0, sink); let offset: i32 = offset.into(); @@ -883,6 +931,9 @@ fldDisp32 = TailRecipe( instp=IsSignedInt(Load.offset, 32), clobbers_flags=False, emit=''' + if !flags.notrap() { + sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]); + } PUT_OP(bits, rex2(in_reg0, out_reg0), sink); modrm_disp32(in_reg0, out_reg0, sink); let offset: i32 = offset.into(); diff --git a/lib/cretonne/src/binemit/memorysink.rs b/lib/cretonne/src/binemit/memorysink.rs index 506ea8b5a4..d4b07319ab 100644 --- a/lib/cretonne/src/binemit/memorysink.rs +++ b/lib/cretonne/src/binemit/memorysink.rs @@ -14,7 +14,7 @@ //! relocations to a `RelocSink` trait object. Relocations are less frequent than the //! `CodeSink::put*` methods, so the performance impact of the virtual callbacks is less severe. -use ir::{ExternalName, JumpTable}; +use ir::{ExternalName, JumpTable, TrapCode, SourceLoc}; use super::{CodeSink, CodeOffset, Reloc, Addend}; use std::ptr::write_unaligned; @@ -33,15 +33,21 @@ pub struct MemoryCodeSink<'a> { data: *mut u8, offset: isize, relocs: &'a mut RelocSink, + traps: &'a mut TrapSink, } impl<'a> MemoryCodeSink<'a> { /// Create a new memory code sink that writes a function to the memory pointed to by `data`. - pub fn new(data: *mut u8, relocs: &mut RelocSink) -> MemoryCodeSink { + pub fn new<'sink>( + data: *mut u8, + relocs: &'sink mut RelocSink, + traps: &'sink mut TrapSink, + ) -> MemoryCodeSink<'sink> { MemoryCodeSink { data, offset: 0, relocs, + traps, } } } @@ -58,6 +64,12 @@ pub trait RelocSink { fn reloc_jt(&mut self, CodeOffset, Reloc, JumpTable); } +/// A trait for receiving trap codes and offsets. +pub trait TrapSink { + /// Add trap information for a specific offset. + fn trap(&mut self, CodeOffset, SourceLoc, TrapCode); +} + impl<'a> CodeSink for MemoryCodeSink<'a> { fn offset(&self) -> CodeOffset { self.offset as CodeOffset @@ -105,4 +117,9 @@ impl<'a> CodeSink for MemoryCodeSink<'a> { let ofs = self.offset(); self.relocs.reloc_jt(ofs, rel, jt); } + + fn trap(&mut self, code: TrapCode, srcloc: SourceLoc) { + let ofs = self.offset(); + self.traps.trap(ofs, srcloc, code); + } } diff --git a/lib/cretonne/src/binemit/mod.rs b/lib/cretonne/src/binemit/mod.rs index bca1f6fa4d..8f6f3c2924 100644 --- a/lib/cretonne/src/binemit/mod.rs +++ b/lib/cretonne/src/binemit/mod.rs @@ -8,9 +8,9 @@ mod memorysink; pub use regalloc::RegDiversions; pub use self::relaxation::relax_branches; -pub use self::memorysink::{MemoryCodeSink, RelocSink}; +pub use self::memorysink::{MemoryCodeSink, RelocSink, TrapSink}; -use ir::{ExternalName, JumpTable, Function, Inst}; +use ir::{ExternalName, JumpTable, Function, Inst, TrapCode, SourceLoc}; use std::fmt; /// Offset in bytes from the beginning of the function. @@ -86,6 +86,9 @@ pub trait CodeSink { /// Add a relocation referencing a jump table. fn reloc_jt(&mut self, Reloc, JumpTable); + + /// Add trap information for the current offset. + fn trap(&mut self, TrapCode, SourceLoc); } /// Report a bad encoding error. diff --git a/lib/cretonne/src/context.rs b/lib/cretonne/src/context.rs index 54fce4b84a..92ea61c643 100644 --- a/lib/cretonne/src/context.rs +++ b/lib/cretonne/src/context.rs @@ -9,7 +9,7 @@ //! contexts concurrently. Typically, you would have one context per compilation thread and only a //! single ISA instance. -use binemit::{CodeOffset, relax_branches, MemoryCodeSink, RelocSink}; +use binemit::{CodeOffset, relax_branches, MemoryCodeSink, RelocSink, TrapSink}; use dominator_tree::DominatorTree; use flowgraph::ControlFlowGraph; use ir::Function; @@ -111,9 +111,15 @@ impl Context { /// code is returned by `compile` above. /// /// The machine code is not relocated. Instead, any relocations are emitted into `relocs`. - pub fn emit_to_memory(&self, mem: *mut u8, relocs: &mut RelocSink, isa: &TargetIsa) { + pub fn emit_to_memory( + &self, + mem: *mut u8, + relocs: &mut RelocSink, + traps: &mut TrapSink, + isa: &TargetIsa, + ) { let _tt = timing::binemit(); - isa.emit_function(&self.func, &mut MemoryCodeSink::new(mem, relocs)); + isa.emit_function(&self.func, &mut MemoryCodeSink::new(mem, relocs, traps)); } /// Run the verifier on the function. diff --git a/lib/cretonne/src/isa/intel/binemit.rs b/lib/cretonne/src/isa/intel/binemit.rs index ddd3405e18..5f2f9512ce 100644 --- a/lib/cretonne/src/isa/intel/binemit.rs +++ b/lib/cretonne/src/isa/intel/binemit.rs @@ -1,7 +1,7 @@ //! Emitting binary Intel machine code. use binemit::{CodeSink, Reloc, bad_encoding}; -use ir::{Function, Inst, Ebb, InstructionData, Opcode}; +use ir::{Function, Inst, Ebb, InstructionData, Opcode, TrapCode}; use ir::condcodes::{CondCode, IntCC, FloatCC}; use isa::{RegUnit, StackRef, StackBase, StackBaseMask}; use regalloc::RegDiversions; diff --git a/lib/filetests/src/test_binemit.rs b/lib/filetests/src/test_binemit.rs index c3284c1423..12a83c8356 100644 --- a/lib/filetests/src/test_binemit.rs +++ b/lib/filetests/src/test_binemit.rs @@ -102,6 +102,10 @@ impl binemit::CodeSink for TextSink { fn reloc_jt(&mut self, reloc: binemit::Reloc, jt: ir::JumpTable) { write!(self.text, "{}({}) ", reloc, jt).unwrap(); } + + fn trap(&mut self, code: ir::TrapCode, _srcloc: ir::SourceLoc) { + write!(self.text, "{} ", code).unwrap(); + } } impl SubTest for TestBinEmit { diff --git a/lib/filetests/src/test_compile.rs b/lib/filetests/src/test_compile.rs index 3772081a16..5e7a1b6109 100644 --- a/lib/filetests/src/test_compile.rs +++ b/lib/filetests/src/test_compile.rs @@ -111,4 +111,5 @@ impl binemit::CodeSink for SizeSink { ) { } fn reloc_jt(&mut self, _reloc: binemit::Reloc, _jt: ir::JumpTable) {} + fn trap(&mut self, _code: ir::TrapCode, _srcloc: ir::SourceLoc) {} } From 68b2040ba25f8b206c4af6fcf27662d83fc4beed Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Mar 2018 16:20:46 -0700 Subject: [PATCH 63/72] Document that opcodes.rs contains `InstructionData`. --- lib/cretonne/src/ir/instructions.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/cretonne/src/ir/instructions.rs b/lib/cretonne/src/ir/instructions.rs index bb09e24834..b25e5a069b 100644 --- a/lib/cretonne/src/ir/instructions.rs +++ b/lib/cretonne/src/ir/instructions.rs @@ -31,6 +31,7 @@ pub type ValueListPool = entity::ListPool; // Include code generated by `lib/cretonne/meta/gen_instr.py`. This file contains: // // - The `pub enum InstructionFormat` enum with all the instruction formats. +// - The `pub enum InstructionData` enum with all the instruction data fields. // - The `pub enum Opcode` definition with all known opcodes, // - The `const OPCODE_FORMAT: [InstructionFormat; N]` table. // - The private `fn opcode_name(Opcode) -> &'static str` function, and From 4af95e37a60a84db3ee19a45688ff956905ca8a1 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Mar 2018 16:22:05 -0700 Subject: [PATCH 64/72] Convert regular comments to documentation comments. --- lib/cretonne/src/dominator_tree.rs | 30 ++++++++--------- lib/cretonne/src/ir/dfg.rs | 24 +++++++------- lib/cretonne/src/ir/immediates.rs | 46 +++++++++++++-------------- lib/cretonne/src/ir/layout.rs | 46 +++++++++++++-------------- lib/cretonne/src/ir/types.rs | 4 +-- lib/cretonne/src/regalloc/spilling.rs | 4 +-- lib/filetests/src/concurrent.rs | 12 +++---- lib/filetests/src/runner.rs | 4 +-- lib/filetests/src/test_binemit.rs | 2 +- lib/filetests/src/test_compile.rs | 2 +- lib/frontend/src/ssa.rs | 12 +++---- lib/reader/src/parser.rs | 22 ++++++------- lib/wasm/src/code_translator.rs | 6 ++-- 13 files changed, 107 insertions(+), 107 deletions(-) diff --git a/lib/cretonne/src/dominator_tree.rs b/lib/cretonne/src/dominator_tree.rs index 823469d081..57f55781a3 100644 --- a/lib/cretonne/src/dominator_tree.rs +++ b/lib/cretonne/src/dominator_tree.rs @@ -11,28 +11,28 @@ use timing; use std::cmp::Ordering; use std::vec::Vec; -// RPO numbers are not first assigned in a contiguous way but as multiples of STRIDE, to leave -// room for modifications of the dominator tree. +/// RPO numbers are not first assigned in a contiguous way but as multiples of STRIDE, to leave +/// room for modifications of the dominator tree. const STRIDE: u32 = 4; -// Special RPO numbers used during `compute_postorder`. +/// Special RPO numbers used during `compute_postorder`. const DONE: u32 = 1; const SEEN: u32 = 2; -// Dominator tree node. We keep one of these per EBB. +/// Dominator tree node. We keep one of these per EBB. #[derive(Clone, Default)] struct DomNode { - // Number of this node in a reverse post-order traversal of the CFG, starting from 1. - // This number is monotonic in the reverse postorder but not contiguous, since we leave - // holes for later localized modifications of the dominator tree. - // Unreachable nodes get number 0, all others are positive. + /// Number of this node in a reverse post-order traversal of the CFG, starting from 1. + /// This number is monotonic in the reverse postorder but not contiguous, since we leave + /// holes for later localized modifications of the dominator tree. + /// Unreachable nodes get number 0, all others are positive. rpo_number: u32, - // The immediate dominator of this EBB, represented as the branch or jump instruction at the - // end of the dominating basic block. - // - // This is `None` for unreachable blocks and the entry block which doesn't have an immediate - // dominator. + /// The immediate dominator of this EBB, represented as the branch or jump instruction at the + /// end of the dominating basic block. + /// + /// This is `None` for unreachable blocks and the entry block which doesn't have an immediate + /// dominator. idom: PackedOption, } @@ -40,10 +40,10 @@ struct DomNode { pub struct DominatorTree { nodes: EntityMap, - // CFG post-order of all reachable EBBs. + /// CFG post-order of all reachable EBBs. postorder: Vec, - // Scratch memory used by `compute_postorder()`. + /// Scratch memory used by `compute_postorder()`. stack: Vec, valid: bool, diff --git a/lib/cretonne/src/ir/dfg.rs b/lib/cretonne/src/ir/dfg.rs index b8976b7267..d8cb9b2eb1 100644 --- a/lib/cretonne/src/ir/dfg.rs +++ b/lib/cretonne/src/ir/dfg.rs @@ -348,18 +348,18 @@ impl ValueDef { } } -// Internal table storage for extended values. +/// Internal table storage for extended values. #[derive(Clone, Debug)] enum ValueData { - // Value is defined by an instruction. + /// Value is defined by an instruction. Inst { ty: Type, num: u16, inst: Inst }, - // Value is an EBB parameter. + /// Value is an EBB parameter. Param { ty: Type, num: u16, ebb: Ebb }, - // Value is an alias of another value. - // An alias value can't be linked as an instruction result or EBB parameter. It is used as a - // placeholder when the original instruction or EBB has been rewritten or modified. + /// Value is an alias of another value. + /// An alias value can't be linked as an instruction result or EBB parameter. It is used as a + /// placeholder when the original instruction or EBB has been rewritten or modified. Alias { ty: Type, original: Value }, } @@ -829,14 +829,14 @@ impl DataFlowGraph { } } -// Contents of an extended basic block. -// -// Parameters on an extended basic block are values that dominate everything in the EBB. All -// branches to this EBB must provide matching arguments, and the arguments to the entry EBB must -// match the function arguments. +/// Contents of an extended basic block. +/// +/// Parameters on an extended basic block are values that dominate everything in the EBB. All +/// branches to this EBB must provide matching arguments, and the arguments to the entry EBB must +/// match the function arguments. #[derive(Clone)] struct EbbData { - // List of parameters to this EBB. + /// List of parameters to this EBB. params: ValueList, } diff --git a/lib/cretonne/src/ir/immediates.rs b/lib/cretonne/src/ir/immediates.rs index 2e6339cc01..b742c0032d 100644 --- a/lib/cretonne/src/ir/immediates.rs +++ b/lib/cretonne/src/ir/immediates.rs @@ -35,12 +35,12 @@ impl From for Imm64 { } } -// Hexadecimal with a multiple of 4 digits and group separators: -// -// 0xfff0 -// 0x0001_ffff -// 0xffff_ffff_fff8_4400 -// +/// Hexadecimal with a multiple of 4 digits and group separators: +/// +/// 0xfff0 +/// 0x0001_ffff +/// 0xffff_ffff_fff8_4400 +/// fn write_hex(x: i64, f: &mut Formatter) -> fmt::Result { let mut pos = (64 - x.leading_zeros() - 1) & 0xf0; write!(f, "0x{:04x}", (x >> pos) & 0xffff)?; @@ -280,16 +280,16 @@ pub struct Ieee32(u32); #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct Ieee64(u64); -// Format a floating point number in a way that is reasonably human-readable, and that can be -// converted back to binary without any rounding issues. The hexadecimal formatting of normal and -// subnormal numbers is compatible with C99 and the `printf "%a"` format specifier. The NaN and Inf -// formats are not supported by C99. -// -// The encoding parameters are: -// -// w - exponent field width in bits -// t - trailing significand field width in bits -// +/// Format a floating point number in a way that is reasonably human-readable, and that can be +/// converted back to binary without any rounding issues. The hexadecimal formatting of normal and +/// subnormal numbers is compatible with C99 and the `printf "%a"` format specifier. The NaN and Inf +/// formats are not supported by C99. +/// +/// The encoding parameters are: +/// +/// w - exponent field width in bits +/// t - trailing significand field width in bits +/// fn format_float(bits: u64, w: u8, t: u8, f: &mut Formatter) -> fmt::Result { debug_assert!(w > 0 && w <= 16, "Invalid exponent range"); debug_assert!(1 + w + t <= 64, "Too large IEEE format for u64"); @@ -358,13 +358,13 @@ fn format_float(bits: u64, w: u8, t: u8, f: &mut Formatter) -> fmt::Result { } } -// Parse a float using the same format as `format_float` above. -// -// The encoding parameters are: -// -// w - exponent field width in bits -// t - trailing significand field width in bits -// +/// Parse a float using the same format as `format_float` above. +/// +/// The encoding parameters are: +/// +/// w - exponent field width in bits +/// t - trailing significand field width in bits +/// fn parse_float(s: &str, w: u8, t: u8) -> Result { debug_assert!(w > 0 && w <= 16, "Invalid exponent range"); debug_assert!(1 + w + t <= 64, "Too large IEEE format for u64"); diff --git a/lib/cretonne/src/ir/layout.rs b/lib/cretonne/src/ir/layout.rs index c19cf6dd37..af0c99e0fe 100644 --- a/lib/cretonne/src/ir/layout.rs +++ b/lib/cretonne/src/ir/layout.rs @@ -26,18 +26,18 @@ use timing; /// #[derive(Clone)] pub struct Layout { - // Linked list nodes for the layout order of EBBs Forms a doubly linked list, terminated in - // both ends by `None`. + /// Linked list nodes for the layout order of EBBs Forms a doubly linked list, terminated in + /// both ends by `None`. ebbs: EntityMap, - // Linked list nodes for the layout order of instructions. Forms a double linked list per EBB, - // terminated in both ends by `None`. + /// Linked list nodes for the layout order of instructions. Forms a double linked list per EBB, + /// terminated in both ends by `None`. insts: EntityMap, - // First EBB in the layout order, or `None` when no EBBs have been laid out. + /// First EBB in the layout order, or `None` when no EBBs have been laid out. first_ebb: Option, - // Last EBB in the layout order, or `None` when no EBBs have been laid out. + /// Last EBB in the layout order, or `None` when no EBBs have been laid out. last_ebb: Option, } @@ -61,31 +61,31 @@ impl Layout { } } -// Sequence numbers. -// -// All instructions and EBBs are given a sequence number that can be used to quickly determine -// their relative position in the layout. The sequence numbers are not contiguous, but are assigned -// like line numbers in BASIC: 10, 20, 30, ... -// -// The EBB sequence numbers are strictly increasing, and so are the instruction sequence numbers -// within an EBB. The instruction sequence numbers are all between the sequence number of their -// containing EBB and the following EBB. -// -// The result is that sequence numbers work like BASIC line numbers for the textual form of the IR. +/// Sequence numbers. +/// +/// All instructions and EBBs are given a sequence number that can be used to quickly determine +/// their relative position in the layout. The sequence numbers are not contiguous, but are assigned +/// like line numbers in BASIC: 10, 20, 30, ... +/// +/// The EBB sequence numbers are strictly increasing, and so are the instruction sequence numbers +/// within an EBB. The instruction sequence numbers are all between the sequence number of their +/// containing EBB and the following EBB. +/// +/// The result is that sequence numbers work like BASIC line numbers for the textual form of the IR. type SequenceNumber = u32; -// Initial stride assigned to new sequence numbers. +/// Initial stride assigned to new sequence numbers. const MAJOR_STRIDE: SequenceNumber = 10; -// Secondary stride used when renumbering locally. +/// Secondary stride used when renumbering locally. const MINOR_STRIDE: SequenceNumber = 2; -// Limit on the sequence number range we'll renumber locally. If this limit is exceeded, we'll -// switch to a full function renumbering. +/// Limit on the sequence number range we'll renumber locally. If this limit is exceeded, we'll +/// switch to a full function renumbering. const LOCAL_LIMIT: SequenceNumber = 100 * MINOR_STRIDE; -// Compute the midpoint between `a` and `b`. -// Return `None` if the midpoint would be equal to either. +/// Compute the midpoint between `a` and `b`. +/// Return `None` if the midpoint would be equal to either. fn midpoint(a: SequenceNumber, b: SequenceNumber) -> Option { debug_assert!(a < b); // Avoid integer overflow. diff --git a/lib/cretonne/src/ir/types.rs b/lib/cretonne/src/ir/types.rs index 07cf97aefa..29a37f0cbf 100644 --- a/lib/cretonne/src/ir/types.rs +++ b/lib/cretonne/src/ir/types.rs @@ -24,10 +24,10 @@ pub struct Type(u8); /// a SIMD vector. pub const VOID: Type = Type(0); -// Start of the lane types. See also `meta/cdsl.types.py`. +/// Start of the lane types. See also `meta/cdsl.types.py`. const LANE_BASE: u8 = 0x70; -// Start of the 2-lane vector types. +/// Start of the 2-lane vector types. const VECTOR_BASE: u8 = LANE_BASE + 16; // Include code generated by `lib/cretonne/meta/gen_types.py`. This file contains constant diff --git a/lib/cretonne/src/regalloc/spilling.rs b/lib/cretonne/src/regalloc/spilling.rs index 3c3f805cbf..f616ea3b74 100644 --- a/lib/cretonne/src/regalloc/spilling.rs +++ b/lib/cretonne/src/regalloc/spilling.rs @@ -548,8 +548,8 @@ impl<'a> Context<'a> { } } -// Struct representing a register use of a value. -// Used to detect multiple uses of the same value with incompatible register constraints. +/// Struct representing a register use of a value. +/// Used to detect multiple uses of the same value with incompatible register constraints. #[derive(Clone, Copy)] struct RegUse { value: Value, diff --git a/lib/filetests/src/concurrent.rs b/lib/filetests/src/concurrent.rs index 1ddf643258..1db5aa6832 100644 --- a/lib/filetests/src/concurrent.rs +++ b/lib/filetests/src/concurrent.rs @@ -13,7 +13,7 @@ use std::time::Duration; use num_cpus; use {TestResult, runone}; -// Request sent to worker threads contains jobid and path. +/// Request sent to worker threads contains jobid and path. struct Request(usize, PathBuf); /// Reply from worker thread, @@ -25,13 +25,13 @@ pub enum Reply { /// Manage threads that run test jobs concurrently. pub struct ConcurrentRunner { - // Channel for sending requests to the worker threads. - // The workers are sharing the receiver with an `Arc>`. - // This is `None` when shutting down. + /// Channel for sending requests to the worker threads. + /// The workers are sharing the receiver with an `Arc>`. + /// This is `None` when shutting down. request_tx: Option>, - // Channel for receiving replies from the workers. - // Workers have their own `Sender`. + /// Channel for receiving replies from the workers. + /// Workers have their own `Sender`. reply_rx: Receiver, handles: Vec>, diff --git a/lib/filetests/src/runner.rs b/lib/filetests/src/runner.rs index 49078cff8e..d2d2db55c7 100644 --- a/lib/filetests/src/runner.rs +++ b/lib/filetests/src/runner.rs @@ -11,10 +11,10 @@ use std::time; use {TestResult, runone}; use concurrent::{ConcurrentRunner, Reply}; -// Timeout in seconds when we're not making progress. +/// Timeout in seconds when we're not making progress. const TIMEOUT_PANIC: usize = 10; -// Timeout for reporting slow tests without panicking. +/// Timeout for reporting slow tests without panicking. const TIMEOUT_SLOW: usize = 3; struct QueueEntry { diff --git a/lib/filetests/src/test_binemit.rs b/lib/filetests/src/test_binemit.rs index 12a83c8356..c22f1ed386 100644 --- a/lib/filetests/src/test_binemit.rs +++ b/lib/filetests/src/test_binemit.rs @@ -27,7 +27,7 @@ pub fn subtest(parsed: &TestCommand) -> Result> { } } -// Code sink that generates text. +/// Code sink that generates text. struct TextSink { offset: binemit::CodeOffset, text: String, diff --git a/lib/filetests/src/test_compile.rs b/lib/filetests/src/test_compile.rs index 5e7a1b6109..af2343f765 100644 --- a/lib/filetests/src/test_compile.rs +++ b/lib/filetests/src/test_compile.rs @@ -76,7 +76,7 @@ impl SubTest for TestCompile { } } -// Code sink that simply counts bytes. +/// Code sink that simply counts bytes. struct SizeSink { offset: binemit::CodeOffset, } diff --git a/lib/frontend/src/ssa.rs b/lib/frontend/src/ssa.rs index af0d35695e..6fa59e784d 100644 --- a/lib/frontend/src/ssa.rs +++ b/lib/frontend/src/ssa.rs @@ -77,12 +77,12 @@ impl SideEffects { } } -// Describes the current position of a basic block in the control flow graph. +/// Describes the current position of a basic block in the control flow graph. enum BlockData { - // A block at the top of an `Ebb`. + /// A block at the top of an `Ebb`. EbbHeader(EbbHeaderBlockData), - // A block inside an `Ebb` with an unique other block as its predecessor. - // The block is implicitly sealed at creation. + /// A block inside an `Ebb` with an unique other block as its predecessor. + /// The block is implicitly sealed at creation. EbbBody { predecessor: Block }, } @@ -179,7 +179,7 @@ where } } -// Small enum used for clarity in some functions. +/// Small enum used for clarity in some functions. #[derive(Debug)] enum ZeroOneOrMore { Zero(), @@ -194,7 +194,7 @@ enum UseVarCases { SealedMultiplePredecessors(Value, Ebb), } -// States for the `use_var`/`predecessors_lookup` state machine. +/// States for the `use_var`/`predecessors_lookup` state machine. enum Call { UseVar(Block), FinishSealedOnePredecessor(Block), diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index b165756566..f0fa723594 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -65,34 +65,34 @@ pub struct Parser<'a> { lex_error: Option, - // Current lookahead token. + /// Current lookahead token. lookahead: Option>, - // Location of lookahead. + /// Location of lookahead. loc: Location, - // Are we gathering any comments that we encounter? + /// Are we gathering any comments that we encounter? gathering_comments: bool, - // The gathered comments; claim them with `claim_gathered_comments`. + /// The gathered comments; claim them with `claim_gathered_comments`. gathered_comments: Vec<&'a str>, - // Comments collected so far. + /// Comments collected so far. comments: Vec>, } -// Context for resolving references when parsing a single function. +/// Context for resolving references when parsing a single function. struct Context<'a> { function: Function, map: SourceMap, - // Aliases to resolve once value definitions are known. + /// Aliases to resolve once value definitions are known. aliases: Vec, - // Reference to the unique_isa for things like parsing ISA-specific instruction encoding - // information. This is only `Some` if exactly one set of `isa` directives were found in the - // prologue (it is valid to have directives for multiple different ISAs, but in that case we - // couldn't know which ISA the provided encodings are intended for) + /// Reference to the unique_isa for things like parsing ISA-specific instruction encoding + /// information. This is only `Some` if exactly one set of `isa` directives were found in the + /// prologue (it is valid to have directives for multiple different ISAs, but in that case we + /// couldn't know which ISA the provided encodings are intended for) unique_isa: Option<&'a TargetIsa>, } diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index 61b7118636..97f67d6c48 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -944,7 +944,7 @@ fn translate_unreachable_operator( } } -// Get the address+offset to use for a heap access. +/// Get the address+offset to use for a heap access. fn get_heap_addr( heap: ir::Heap, addr32: ir::Value, @@ -981,7 +981,7 @@ fn get_heap_addr( } } -// Translate a load instruction. +/// Translate a load instruction. fn translate_load( offset: u32, opcode: ir::Opcode, @@ -1008,7 +1008,7 @@ fn translate_load( state.push1(dfg.first_result(load)); } -// Translate a store instruction. +/// Translate a store instruction. fn translate_store( offset: u32, opcode: ir::Opcode, From 5377092e5b851747fed03d385a666789664c509b Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Mar 2018 17:15:19 -0700 Subject: [PATCH 65/72] Use `#[cold]` rather than `#[inline(never)]`. This gives optimizers more information about likely branch probabilities. --- lib/cretonne/src/binemit/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cretonne/src/binemit/mod.rs b/lib/cretonne/src/binemit/mod.rs index 8f6f3c2924..6d2099ceba 100644 --- a/lib/cretonne/src/binemit/mod.rs +++ b/lib/cretonne/src/binemit/mod.rs @@ -92,7 +92,7 @@ pub trait CodeSink { } /// Report a bad encoding error. -#[inline(never)] +#[cold] pub fn bad_encoding(func: &Function, inst: Inst) -> ! { panic!( "Bad encoding {} for {}", From 6606b88136dc8706d5b9bc32c3f0cae1b9485389 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 30 Mar 2018 12:30:07 -0700 Subject: [PATCH 66/72] Optimize immediates and compare and branch sequences (#286) * Add a pre-opt optimization to change constants into immediates. This converts 'iadd' + 'iconst' into 'iadd_imm', and so on. * Optimize away redundant `bint` instructions. Cretonne has a concept of "Testable" values, which can be either boolean or integer. When the an instruction needing a "Testable" value receives the result of a `bint`, converting boolean to integer, eliminate the `bint`, as it's redundant. * Postopt: Optimize using CPU flags. This introduces a post-legalization optimization pass which converts compare+branch sequences to use flags values on CPUs which support it. * Define a form of x86's `urm` that doesn't clobber FLAGS. movzbl/movsbl/etc. don't clobber FLAGS; define a form of the `urm` recipe that represents this. * Implement a DCE pass. This pass deletes instructions with no side effects and no results that are used. * Clarify ambiguity about "32-bit" and "64-bit" in comments. * Add x86 encodings for icmp_imm. * Add a testcase for postopt CPU flags optimization. This covers the basic functionality of transforming compare+branch sequences to use CPU flags. * Pattern-match irsub_imm in preopt. --- cranelift/docs/testing.rst | 16 ++ cranelift/filetests/dce/basic.cton | 46 ++++ cranelift/filetests/isa/intel/binary32.cton | 2 +- cranelift/filetests/isa/intel/binary64.cton | 18 +- cranelift/filetests/postopt/basic.cton | 100 +++++++++ cranelift/filetests/preopt/simplify.cton | 80 +++++++ .../filetests/regalloc/coloring-227.cton | 2 +- cranelift/filetests/verifier/flags.cton | 76 +++---- lib/cretonne/meta/isa/intel/encodings.py | 52 +++-- lib/cretonne/meta/isa/intel/recipes.py | 77 ++++++- lib/cretonne/src/context.rs | 20 ++ lib/cretonne/src/dce.rs | 68 ++++++ lib/cretonne/src/ir/immediates.rs | 5 + lib/cretonne/src/isa/intel/mod.rs | 4 + lib/cretonne/src/isa/mod.rs | 5 + lib/cretonne/src/lib.rs | 2 + lib/cretonne/src/postopt.rs | 211 ++++++++++++++++++ lib/cretonne/src/preopt.rs | 137 ++++++++---- lib/cretonne/src/timing.rs | 2 + lib/filetests/src/lib.rs | 4 + lib/filetests/src/test_dce.rs | 53 +++++ lib/filetests/src/test_postopt.rs | 50 +++++ 22 files changed, 921 insertions(+), 109 deletions(-) create mode 100644 cranelift/filetests/dce/basic.cton create mode 100644 cranelift/filetests/postopt/basic.cton create mode 100644 cranelift/filetests/preopt/simplify.cton create mode 100644 lib/cretonne/src/dce.rs create mode 100644 lib/cretonne/src/postopt.rs create mode 100644 lib/filetests/src/test_dce.rs create mode 100644 lib/filetests/src/test_postopt.rs diff --git a/cranelift/docs/testing.rst b/cranelift/docs/testing.rst index c14a74aeba..db7efb1da1 100644 --- a/cranelift/docs/testing.rst +++ b/cranelift/docs/testing.rst @@ -334,6 +334,14 @@ Test the LICM pass. The LICM pass is run on each function, and then results are run through filecheck. +`test dce` +----------------- + +Test the DCE pass. + +The DCE pass is run on each function, and then results are run +through filecheck. + `test preopt` ----------------- @@ -342,6 +350,14 @@ Test the preopt pass. The preopt pass is run on each function, and then results are run through filecheck. +`test postopt` +----------------- + +Test the postopt pass. + +The postopt pass is run on each function, and then results are run +through filecheck. + `test compile` -------------- diff --git a/cranelift/filetests/dce/basic.cton b/cranelift/filetests/dce/basic.cton new file mode 100644 index 0000000000..436b4aee19 --- /dev/null +++ b/cranelift/filetests/dce/basic.cton @@ -0,0 +1,46 @@ +test dce + +function %simple() -> i32 { +ebb0: + v2 = iconst.i32 2 + v3 = iconst.i32 3 + return v3 +} +; sameln: function %simple +; nextln: ebb0: +; nextln: v3 = iconst.i32 3 +; nextln: return v3 +; nextln: } + +function %some_branching(i32, i32) -> i32 { +ebb0(v0: i32, v1: i32): + v3 = iconst.i32 70 + v4 = iconst.i32 71 + v5 = iconst.i32 72 + v8 = iconst.i32 73 + brz v0, ebb1 + jump ebb2(v8) + +ebb1: + v2 = iadd v0, v3 + return v0 + +ebb2(v9: i32): + v6 = iadd v1, v4 + v7 = iadd v6, v9 + return v7 +} +; sameln: function %some_branching +; nextln: ebb0(v0: i32, v1: i32): +; nextln: v4 = iconst.i32 71 +; nextln: v8 = iconst.i32 73 +; nextln: brz v0, ebb1 +; nextln: jump ebb2(v8) +; nextln: +; nextln: ebb1: +; nextln: return v0 +; nextln: +; nextln: ebb2(v9: i32): +; nextln: v6 = iadd.i32 v1, v4 +; nextln: v7 = iadd v6, v9 +; nextln: return v7 diff --git a/cranelift/filetests/isa/intel/binary32.cton b/cranelift/filetests/isa/intel/binary32.cton index a3d0723be8..2567fbe88c 100644 --- a/cranelift/filetests/isa/intel/binary32.cton +++ b/cranelift/filetests/isa/intel/binary32.cton @@ -1,4 +1,4 @@ -; binary emission of 32-bit code. +; binary emission of x86-32 code. test binemit set is_compressed isa intel haswell diff --git a/cranelift/filetests/isa/intel/binary64.cton b/cranelift/filetests/isa/intel/binary64.cton index 1444c1e062..1a47dc1cba 100644 --- a/cranelift/filetests/isa/intel/binary64.cton +++ b/cranelift/filetests/isa/intel/binary64.cton @@ -1,4 +1,4 @@ -; binary emission of 64-bit code. +; binary emission of x86-64 code. test binemit set is_64bit set is_compressed @@ -458,6 +458,14 @@ ebb0: ; asm: setbe %dl [-,%rdx] v319 = icmp ule v2, v3 ; bin: 4c 39 d6 0f 96 c2 + ; asm: cmpq $37, %rcx + ; asm: setl %bl + [-,%rbx] v320 = icmp_imm slt v1, 37 ; bin: 48 83 f9 25 0f 9c c3 + + ; asm: cmpq $100000, %rcx + ; asm: setl %bl + [-,%rbx] v321 = icmp_imm slt v1, 100000 ; bin: 48 81 f9 000186a0 0f 9c c3 + ; Bool-to-int conversions. ; asm: movzbq %bl, %rcx @@ -1031,6 +1039,14 @@ ebb0: ; asm: setbe %dl [-,%rdx] v319 = icmp ule v2, v3 ; bin: 44 39 d6 0f 96 c2 + ; asm: cmpl $37, %ecx + ; asm: setl %bl + [-,%rbx] v320 = icmp_imm slt v1, 37 ; bin: 83 f9 25 0f 9c c3 + + ; asm: cmpq $100000, %ecx + ; asm: setl %bl + [-,%rbx] v321 = icmp_imm slt v1, 100000 ; bin: 81 f9 000186a0 0f 9c c3 + ; Bool-to-int conversions. ; asm: movzbl %bl, %ecx diff --git a/cranelift/filetests/postopt/basic.cton b/cranelift/filetests/postopt/basic.cton new file mode 100644 index 0000000000..218d4dfee4 --- /dev/null +++ b/cranelift/filetests/postopt/basic.cton @@ -0,0 +1,100 @@ +test postopt +isa intel + +; Test that compare+branch sequences are folded effectively on x86. + +function %br_icmp(i32, i32) -> i32 { +ebb0(v0: i32, v1: i32): +[Op1icscc#39,%rdx] v2 = icmp slt v0, v1 +[Op1t8jccd_long#85] brnz v2, ebb1 +[Op1ret#c3] return v1 + +ebb1: +[Op1puid#b8,%rax] v8 = iconst.i32 3 +[Op1ret#c3] return v8 +} +; sameln: function %br_icmp +; nextln: ebb0(v0: i32, v1: i32): +; nextln: v9 = ifcmp v0, v1 +; nextln: v2 = trueif slt v9 +; nextln: brif slt v9, ebb1 +; nextln: return v1 +; nextln: +; nextln: ebb1: +; nextln: v8 = iconst.i32 3 +; nextln: return v8 +; nextln: } + +; Use brz instead of brnz, so the condition is inverted. + +function %br_icmp_inverse(i32, i32) -> i32 { +ebb0(v0: i32, v1: i32): +[Op1icscc#39,%rdx] v2 = icmp slt v0, v1 +[Op1t8jccd_long#84] brz v2, ebb1 +[Op1ret#c3] return v1 + +ebb1: +[Op1puid#b8,%rax] v8 = iconst.i32 3 +[Op1ret#c3] return v8 +} +; sameln: function %br_icmp_inverse +; nextln: ebb0(v0: i32, v1: i32): +; nextln: v9 = ifcmp v0, v1 +; nextln: v2 = trueif slt v9 +; nextln: brif sge v9, ebb1 +; nextln: return v1 +; nextln: +; nextln: ebb1: +; nextln: v8 = iconst.i32 3 +; nextln: return v8 +; nextln: } + +; Use icmp_imm instead of icmp. + +function %br_icmp_imm(i32, i32) -> i32 { +ebb0(v0: i32, v1: i32): +[Op1icsccib#7083] v2 = icmp_imm slt v0, 2 +[Op1t8jccd_long#84] brz v2, ebb1 +[Op1ret#c3] return v1 + +ebb1: +[Op1puid#b8,%rax] v8 = iconst.i32 3 +[Op1ret#c3] return v8 +} +; sameln: function %br_icmp_imm +; nextln: ebb0(v0: i32, v1: i32): +; nextln: v9 = ifcmp_imm v0, 2 +; nextln: v2 = trueif slt v9 +; nextln: brif sge v9, ebb1 +; nextln: return v1 +; nextln: +; nextln: ebb1: +; nextln: v8 = iconst.i32 3 +; nextln: return v8 +; nextln: } + +; Use fcmp instead of icmp. + +function %br_fcmp(f32, f32) -> f32 { +ebb0(v0: f32, v1: f32): +[Op2fcscc#42e,%rdx] v2 = fcmp gt v0, v1 +[Op1t8jccd_long#84] brz v2, ebb1 +[Op1ret#c3] return v1 + +ebb1: +[Op1puid#b8,%rax] v18 = iconst.i32 0x40a8_0000 +[Mp2frurm#56e,%xmm0] v8 = bitcast.f32 v18 +[Op1ret#c3] return v8 +} +; sameln: function %br_fcmp +; nextln: ebb0(v0: f32, v1: f32): +; nextln: v19 = ffcmp v0, v1 +; nextln: v2 = trueff gt v19 +; nextln: brff ule v19, ebb1 +; nextln: return v1 +; nextln: +; nextln: ebb1: +; nextln: v18 = iconst.i32 0x40a8_0000 +; nextln: v8 = bitcast.f32 v18 +; nextln: return v8 +; nextln: } diff --git a/cranelift/filetests/preopt/simplify.cton b/cranelift/filetests/preopt/simplify.cton new file mode 100644 index 0000000000..a2e67caf31 --- /dev/null +++ b/cranelift/filetests/preopt/simplify.cton @@ -0,0 +1,80 @@ +test preopt +isa intel + +function %iadd_imm(i32) -> i32 { +ebb0(v0: i32): + v1 = iconst.i32 2 + v2 = iadd v0, v1 + return v2 +} +; sameln: function %iadd_imm +; nextln: ebb0(v0: i32): +; nextln: v1 = iconst.i32 2 +; nextln: v2 = iadd_imm v0, 2 +; nextln: return v2 +; nextln: } + +function %isub_imm(i32) -> i32 { +ebb0(v0: i32): + v1 = iconst.i32 2 + v2 = isub v0, v1 + return v2 +} +; sameln: function %isub_imm +; nextln: ebb0(v0: i32): +; nextln: v1 = iconst.i32 2 +; nextln: v2 = iadd_imm v0, -2 +; nextln: return v2 +; nextln: } + +function %icmp_imm(i32) -> i32 { +ebb0(v0: i32): + v1 = iconst.i32 2 + v2 = icmp slt v0, v1 + v3 = bint.i32 v2 + return v3 +} +; sameln: function %icmp_imm +; nextln: ebb0(v0: i32): +; nextln: v1 = iconst.i32 2 +; nextln: v2 = icmp_imm slt v0, 2 +; nextln: v3 = bint.i32 v2 +; nextln: return v3 +; nextln: } + +function %brz_bint(i32) { +ebb0(v0: i32): + v3 = icmp_imm slt v0, 0 + v1 = bint.i32 v3 + v2 = select v1, v1, v1 + trapz v1, user0 + brz v1, ebb1 + jump ebb2 + +ebb1: + return + +ebb2: + return +} +; sameln: function %brz_bint +; nextln: (v0: i32): +; nextln: v3 = icmp_imm slt v0, 0 +; nextln: v1 = bint.i32 v3 +; nextln: v2 = select v3, v1, v1 +; nextln: trapz v3, user0 +; nextln: brz v3, ebb1 +; nextln: jump ebb2 + +function %irsub_imm(i32) -> i32 { +ebb0(v0: i32): + v1 = iconst.i32 2 + v2 = isub v1, v0 + return v2 +} +; sameln: function %irsub_imm +; nextln: ebb0(v0: i32): +; nextln: v1 = iconst.i32 2 +; nextln: v2 = irsub_imm v1, 2 +; nextln: return v2 +; nextln: } diff --git a/cranelift/filetests/regalloc/coloring-227.cton b/cranelift/filetests/regalloc/coloring-227.cton index 07681a7509..7e2dac2e50 100644 --- a/cranelift/filetests/regalloc/coloring-227.cton +++ b/cranelift/filetests/regalloc/coloring-227.cton @@ -21,7 +21,7 @@ function %pr227(i32 [%rdi], i32 [%rsi], i32 [%rdx], i32 [%rcx], i64 vmctx [%r8]) @0011 [RexOp1puid#b8] v9 = iconst.i32 0 @0015 [RexOp1puid#b8] v11 = iconst.i32 0 @0017 [RexOp1icscc#39] v12 = icmp.i32 eq v15, v11 -@0017 [RexOp2urm#4b6] v13 = bint.i32 v12 +@0017 [RexOp2urm_noflags#4b6] v13 = bint.i32 v12 @001a [RexOp1rr#21] v14 = band v9, v13 @001b [RexOp1tjccb#75] brnz v14, ebb6 @001d [RexOp1jmpb#eb] jump ebb7 diff --git a/cranelift/filetests/verifier/flags.cton b/cranelift/filetests/verifier/flags.cton index dff01244e2..b4a01621c4 100644 --- a/cranelift/filetests/verifier/flags.cton +++ b/cranelift/filetests/verifier/flags.cton @@ -4,65 +4,65 @@ isa intel ; Simple, correct use of CPU flags. function %simple(i32) -> i32 { ebb0(v0: i32): - [Op1rcmp#39] v1 = ifcmp v0, v0 - [Op2seti_abcd#490] v2 = trueif ugt v1 - [Op2urm_abcd#4b6] v3 = bint.i32 v2 - [Op1ret#c3] return v3 + [Op1rcmp#39] v1 = ifcmp v0, v0 + [Op2seti_abcd#490] v2 = trueif ugt v1 + [Op2urm_noflags_abcd#4b6] v3 = bint.i32 v2 + [Op1ret#c3] return v3 } ; Overlapping flag values of different types. function %overlap(i32, f32) -> i32 { ebb0(v0: i32, v1: f32): - [Op1rcmp#39] v2 = ifcmp v0, v0 - [Op2fcmp#42e] v3 = ffcmp v1, v1 - [Op2setf_abcd#490] v4 = trueff gt v3 ; error: conflicting live CPU flags: v2 and v3 - [Op2seti_abcd#490] v5 = trueif ugt v2 - [Op1rr#21] v6 = band v4, v5 - [Op2urm_abcd#4b6] v7 = bint.i32 v6 - [Op1ret#c3] return v7 + [Op1rcmp#39] v2 = ifcmp v0, v0 + [Op2fcmp#42e] v3 = ffcmp v1, v1 + [Op2setf_abcd#490] v4 = trueff gt v3 ; error: conflicting live CPU flags: v2 and v3 + [Op2seti_abcd#490] v5 = trueif ugt v2 + [Op1rr#21] v6 = band v4, v5 + [Op2urm_noflags_abcd#4b6] v7 = bint.i32 v6 + [Op1ret#c3] return v7 } ; CPU flags clobbered by arithmetic. function %clobbered(i32) -> i32 { ebb0(v0: i32): - [Op1rcmp#39] v1 = ifcmp v0, v0 - [Op1rr#01] v2 = iadd v0, v0 ; error: encoding clobbers live CPU flags in v1 - [Op2seti_abcd#490] v3 = trueif ugt v1 - [Op2urm_abcd#4b6] v4 = bint.i32 v3 - [Op1ret#c3] return v4 + [Op1rcmp#39] v1 = ifcmp v0, v0 + [Op1rr#01] v2 = iadd v0, v0 ; error: encoding clobbers live CPU flags in v1 + [Op2seti_abcd#490] v3 = trueif ugt v1 + [Op2urm_noflags_abcd#4b6] v4 = bint.i32 v3 + [Op1ret#c3] return v4 } ; CPU flags not clobbered by load. function %live_across_load(i32) -> i32 { ebb0(v0: i32): - [Op1rcmp#39] v1 = ifcmp v0, v0 - [Op1ld#8b] v2 = load.i32 v0 - [Op2seti_abcd#490] v3 = trueif ugt v1 - [Op2urm_abcd#4b6] v4 = bint.i32 v3 - [Op1ret#c3] return v4 + [Op1rcmp#39] v1 = ifcmp v0, v0 + [Op1ld#8b] v2 = load.i32 v0 + [Op2seti_abcd#490] v3 = trueif ugt v1 + [Op2urm_noflags_abcd#4b6] v4 = bint.i32 v3 + [Op1ret#c3] return v4 } ; Correct use of CPU flags across EBB. function %live_across_ebb(i32) -> i32 { - ebb0(v0: i32): - [Op1rcmp#39] v1 = ifcmp v0, v0 - [Op1jmpb#eb] jump ebb1 - ebb1: - [Op2seti_abcd#490] v2 = trueif ugt v1 - [Op2urm_abcd#4b6] v3 = bint.i32 v2 - [Op1ret#c3] return v3 + ebb0(v0: i32): + [Op1rcmp#39] v1 = ifcmp v0, v0 + [Op1jmpb#eb] jump ebb1 + ebb1: + [Op2seti_abcd#490] v2 = trueif ugt v1 + [Op2urm_noflags_abcd#4b6] v3 = bint.i32 v2 + [Op1ret#c3] return v3 } function %live_across_ebb_backwards(i32) -> i32 { - ebb0(v0: i32): - [Op1jmpb#eb] jump ebb2 - ebb1: - [Op2seti_abcd#490] v2 = trueif ugt v1 - [Op2urm_abcd#4b6] v3 = bint.i32 v2 - [Op1ret#c3] return v3 - ebb2: - [Op1rcmp#39] v1 = ifcmp v0, v0 - [Op1jmpb#eb] jump ebb1 + ebb0(v0: i32): + [Op1jmpb#eb] jump ebb2 + ebb1: + [Op2seti_abcd#490] v2 = trueif ugt v1 + [Op2urm_noflags_abcd#4b6] v3 = bint.i32 v2 + [Op1ret#c3] return v3 + ebb2: + [Op1rcmp#39] v1 = ifcmp v0, v0 + [Op1jmpb#eb] jump ebb1 } ; Flags live into loop. @@ -73,4 +73,4 @@ function %live_into_loop(i32) -> i32 { ebb1: [Op2seti_abcd#490] v2 = trueif ugt v1 [Op1jmpb#eb] jump ebb1 -} \ No newline at end of file +} diff --git a/lib/cretonne/meta/isa/intel/encodings.py b/lib/cretonne/meta/isa/intel/encodings.py index 72ef7a362b..0fc507bac5 100644 --- a/lib/cretonne/meta/isa/intel/encodings.py +++ b/lib/cretonne/meta/isa/intel/encodings.py @@ -378,6 +378,8 @@ X86_64.enc(base.trapff, r.trapff, 0) # Comparisons # enc_i32_i64(base.icmp, r.icscc, 0x39) +enc_i32_i64(base.icmp_imm, r.icsccib, 0x83, rrr=7) +enc_i32_i64(base.icmp_imm, r.icsccid, 0x81, rrr=7) enc_i32_i64(base.ifcmp, r.rcmp, 0x39) enc_i32_i64(base.ifcmp_imm, r.rcmpib, 0x83, rrr=7) enc_i32_i64(base.ifcmp_imm, r.rcmpid, 0x81, rrr=7) @@ -409,11 +411,13 @@ enc_i32_i64(x86.bsr, r.bsf_and_bsr, 0x0F, 0xBD) # # This assumes that b1 is represented as an 8-bit low register with the value 0 # or 1. -X86_32.enc(base.bint.i32.b1, *r.urm_abcd(0x0f, 0xb6)) -X86_64.enc(base.bint.i64.b1, *r.urm.rex(0x0f, 0xb6)) # zext to i64 implicit. -X86_64.enc(base.bint.i64.b1, *r.urm_abcd(0x0f, 0xb6)) # zext to i64 implicit. -X86_64.enc(base.bint.i32.b1, *r.urm.rex(0x0f, 0xb6)) -X86_64.enc(base.bint.i32.b1, *r.urm_abcd(0x0f, 0xb6)) +# +# Encode movzbq as movzbl, because it's equivalent and shorter. +X86_32.enc(base.bint.i32.b1, *r.urm_noflags_abcd(0x0f, 0xb6)) +X86_64.enc(base.bint.i64.b1, *r.urm_noflags.rex(0x0f, 0xb6)) +X86_64.enc(base.bint.i64.b1, *r.urm_noflags_abcd(0x0f, 0xb6)) +X86_64.enc(base.bint.i32.b1, *r.urm_noflags.rex(0x0f, 0xb6)) +X86_64.enc(base.bint.i32.b1, *r.urm_noflags_abcd(0x0f, 0xb6)) # Numerical conversions. @@ -430,41 +434,41 @@ X86_64.enc(base.ireduce.i32.i64, r.null, 0) # instructions for %al/%ax/%eax to %ax/%eax/%rax. # movsbl -X86_32.enc(base.sextend.i32.i8, *r.urm(0x0f, 0xbe)) -X86_64.enc(base.sextend.i32.i8, *r.urm.rex(0x0f, 0xbe)) -X86_64.enc(base.sextend.i32.i8, *r.urm(0x0f, 0xbe)) +X86_32.enc(base.sextend.i32.i8, *r.urm_noflags(0x0f, 0xbe)) +X86_64.enc(base.sextend.i32.i8, *r.urm_noflags.rex(0x0f, 0xbe)) +X86_64.enc(base.sextend.i32.i8, *r.urm_noflags(0x0f, 0xbe)) # movswl -X86_32.enc(base.sextend.i32.i16, *r.urm(0x0f, 0xbf)) -X86_64.enc(base.sextend.i32.i16, *r.urm.rex(0x0f, 0xbf)) -X86_64.enc(base.sextend.i32.i16, *r.urm(0x0f, 0xbf)) +X86_32.enc(base.sextend.i32.i16, *r.urm_noflags(0x0f, 0xbf)) +X86_64.enc(base.sextend.i32.i16, *r.urm_noflags.rex(0x0f, 0xbf)) +X86_64.enc(base.sextend.i32.i16, *r.urm_noflags(0x0f, 0xbf)) # movsbq -X86_64.enc(base.sextend.i64.i8, *r.urm.rex(0x0f, 0xbe, w=1)) +X86_64.enc(base.sextend.i64.i8, *r.urm_noflags.rex(0x0f, 0xbe, w=1)) # movswq -X86_64.enc(base.sextend.i64.i16, *r.urm.rex(0x0f, 0xbf, w=1)) +X86_64.enc(base.sextend.i64.i16, *r.urm_noflags.rex(0x0f, 0xbf, w=1)) # movslq -X86_64.enc(base.sextend.i64.i32, *r.urm.rex(0x63, w=1)) +X86_64.enc(base.sextend.i64.i32, *r.urm_noflags.rex(0x63, w=1)) # movzbl -X86_32.enc(base.uextend.i32.i8, *r.urm(0x0f, 0xb6)) -X86_64.enc(base.uextend.i32.i8, *r.urm.rex(0x0f, 0xb6)) -X86_64.enc(base.uextend.i32.i8, *r.urm(0x0f, 0xb6)) +X86_32.enc(base.uextend.i32.i8, *r.urm_noflags(0x0f, 0xb6)) +X86_64.enc(base.uextend.i32.i8, *r.urm_noflags.rex(0x0f, 0xb6)) +X86_64.enc(base.uextend.i32.i8, *r.urm_noflags(0x0f, 0xb6)) # movzwl -X86_32.enc(base.uextend.i32.i16, *r.urm(0x0f, 0xb7)) -X86_64.enc(base.uextend.i32.i16, *r.urm.rex(0x0f, 0xb7)) -X86_64.enc(base.uextend.i32.i16, *r.urm(0x0f, 0xb7)) +X86_32.enc(base.uextend.i32.i16, *r.urm_noflags(0x0f, 0xb7)) +X86_64.enc(base.uextend.i32.i16, *r.urm_noflags.rex(0x0f, 0xb7)) +X86_64.enc(base.uextend.i32.i16, *r.urm_noflags(0x0f, 0xb7)) # movzbq, encoded as movzbl because it's equivalent and shorter -X86_64.enc(base.uextend.i64.i8, *r.urm.rex(0x0f, 0xb6)) -X86_64.enc(base.uextend.i64.i8, *r.urm(0x0f, 0xb6)) +X86_64.enc(base.uextend.i64.i8, *r.urm_noflags.rex(0x0f, 0xb6)) +X86_64.enc(base.uextend.i64.i8, *r.urm_noflags(0x0f, 0xb6)) # movzwq, encoded as movzwl because it's equivalent and shorter -X86_64.enc(base.uextend.i64.i16, *r.urm.rex(0x0f, 0xb7)) -X86_64.enc(base.uextend.i64.i16, *r.urm(0x0f, 0xb7)) +X86_64.enc(base.uextend.i64.i16, *r.urm_noflags.rex(0x0f, 0xb7)) +X86_64.enc(base.uextend.i64.i16, *r.urm_noflags(0x0f, 0xb7)) # A 32-bit register copy clears the high 32 bits. X86_64.enc(base.uextend.i64.i32, *r.umr.rex(0x89)) diff --git a/lib/cretonne/meta/isa/intel/recipes.py b/lib/cretonne/meta/isa/intel/recipes.py index bb3db3cba1..54df437c67 100644 --- a/lib/cretonne/meta/isa/intel/recipes.py +++ b/lib/cretonne/meta/isa/intel/recipes.py @@ -8,7 +8,8 @@ from cdsl.registers import RegClass from base.formats import Unary, UnaryImm, UnaryBool, Binary, BinaryImm from base.formats import MultiAry, NullAry from base.formats import Trap, Call, IndirectCall, Store, Load -from base.formats import IntCompare, FloatCompare, IntCond, FloatCond +from base.formats import IntCompare, IntCompareImm, FloatCompare +from base.formats import IntCond, FloatCond from base.formats import IntSelect, IntCondTrap, FloatCondTrap from base.formats import Jump, Branch, BranchInt, BranchFloat from base.formats import Ternary, FuncAddr, UnaryGlobalVar @@ -364,7 +365,7 @@ rfumr = TailRecipe( ''') # XX /r, but for a unary operator with separate input/output register. -# RM form. +# RM form. Clobbers FLAGS. urm = TailRecipe( 'urm', Unary, size=1, ins=GPR, outs=GPR, emit=''' @@ -372,10 +373,19 @@ urm = TailRecipe( modrm_rr(in_reg0, out_reg0, sink); ''') -# XX /r. Same as urm, but input limited to ABCD. -urm_abcd = TailRecipe( - 'urm_abcd', Unary, size=1, ins=ABCD, outs=GPR, - when_prefixed=urm, +# XX /r. Same as urm, but doesn't clobber FLAGS. +urm_noflags = TailRecipe( + 'urm_noflags', Unary, size=1, ins=GPR, outs=GPR, + clobbers_flags=False, + emit=''' + PUT_OP(bits, rex2(in_reg0, out_reg0), sink); + modrm_rr(in_reg0, out_reg0, sink); + ''') + +# XX /r. Same as urm_noflags, but input limited to ABCD. +urm_noflags_abcd = TailRecipe( + 'urm_noflags_abcd', Unary, size=1, ins=ABCD, outs=GPR, + when_prefixed=urm_noflags, emit=''' PUT_OP(bits, rex2(in_reg0, out_reg0), sink); modrm_rr(in_reg0, out_reg0, sink); @@ -1360,6 +1370,61 @@ icscc = TailRecipe( modrm_rr(out_reg0, 0, sink); ''') +icsccib = TailRecipe( + 'icsccib', IntCompareImm, size=2 + 3, ins=GPR, outs=ABCD, + instp=IsSignedInt(IntCompareImm.imm, 8), + emit=''' + // Comparison instruction. + PUT_OP(bits, rex1(in_reg0), sink); + modrm_r_bits(in_reg0, bits, sink); + let imm: i64 = imm.into(); + sink.put1(imm as u8); + // `setCC` instruction, no REX. + use ir::condcodes::IntCC::*; + let setcc = match cond { + Equal => 0x94, + NotEqual => 0x95, + SignedLessThan => 0x9c, + SignedGreaterThanOrEqual => 0x9d, + SignedGreaterThan => 0x9f, + SignedLessThanOrEqual => 0x9e, + UnsignedLessThan => 0x92, + UnsignedGreaterThanOrEqual => 0x93, + UnsignedGreaterThan => 0x97, + UnsignedLessThanOrEqual => 0x96, + }; + sink.put1(0x0f); + sink.put1(setcc); + modrm_rr(out_reg0, 0, sink); + ''') + +icsccid = TailRecipe( + 'icsccid', IntCompareImm, size=5 + 3, ins=GPR, outs=ABCD, + instp=IsSignedInt(IntCompareImm.imm, 32), + emit=''' + // Comparison instruction. + PUT_OP(bits, rex1(in_reg0), sink); + modrm_r_bits(in_reg0, bits, sink); + let imm: i64 = imm.into(); + sink.put4(imm as u32); + // `setCC` instruction, no REX. + use ir::condcodes::IntCC::*; + let setcc = match cond { + Equal => 0x94, + NotEqual => 0x95, + SignedLessThan => 0x9c, + SignedGreaterThanOrEqual => 0x9d, + SignedGreaterThan => 0x9f, + SignedLessThanOrEqual => 0x9e, + UnsignedLessThan => 0x92, + UnsignedGreaterThanOrEqual => 0x93, + UnsignedGreaterThan => 0x97, + UnsignedLessThanOrEqual => 0x96, + }; + sink.put1(0x0f); + sink.put1(setcc); + modrm_rr(out_reg0, 0, sink); + ''') # Make a FloatCompare instruction predicate with the supported condition codes. diff --git a/lib/cretonne/src/context.rs b/lib/cretonne/src/context.rs index 92ea61c643..2441f19d02 100644 --- a/lib/cretonne/src/context.rs +++ b/lib/cretonne/src/context.rs @@ -21,9 +21,11 @@ use result::{CtonError, CtonResult}; use settings::{FlagsOrIsa, OptLevel}; use unreachable_code::eliminate_unreachable_code; use verifier; +use dce::do_dce; use simple_gvn::do_simple_gvn; use licm::do_licm; use preopt::do_preopt; +use postopt::do_postopt; use timing; /// Persistent data structures and compilation pipeline. @@ -92,6 +94,9 @@ impl Context { self.preopt(isa)?; } self.legalize(isa)?; + if isa.flags().opt_level() != OptLevel::Fastest { + self.postopt(isa)?; + } if isa.flags().opt_level() == OptLevel::Best { self.compute_domtree(); self.compute_loop_analysis(); @@ -100,6 +105,7 @@ impl Context { } self.compute_domtree(); self.eliminate_unreachable_code(isa)?; + self.dce(isa)?; self.regalloc(isa)?; self.prologue_epilogue(isa)?; self.relax_branches(isa) @@ -153,6 +159,13 @@ impl Context { } } + /// Perform dead-code elimination on the function. + pub fn dce<'a, FOI: Into>>(&mut self, fisa: FOI) -> CtonResult { + do_dce(&mut self.func, &mut self.domtree); + self.verify_if(fisa)?; + Ok(()) + } + /// Perform pre-legalization rewrites on the function. pub fn preopt(&mut self, isa: &TargetIsa) -> CtonResult { do_preopt(&mut self.func); @@ -170,6 +183,13 @@ impl Context { self.verify_if(isa) } + /// Perform post-legalization rewrites on the function. + pub fn postopt(&mut self, isa: &TargetIsa) -> CtonResult { + do_postopt(&mut self.func, isa); + self.verify_if(isa)?; + Ok(()) + } + /// Compute the control flow graph. pub fn compute_cfg(&mut self) { self.cfg.compute(&self.func) diff --git a/lib/cretonne/src/dce.rs b/lib/cretonne/src/dce.rs new file mode 100644 index 0000000000..6e34bad74f --- /dev/null +++ b/lib/cretonne/src/dce.rs @@ -0,0 +1,68 @@ +//! A Dead-Code Elimination (DCE) pass. +//! +//! Dead code here means instructions that have no side effects and have no +//! result values used by other instructions. + +use cursor::{Cursor, FuncCursor}; +use dominator_tree::DominatorTree; +use entity::EntityRef; +use ir::{Function, Inst, Opcode, DataFlowGraph}; +use ir::instructions::InstructionData; +use timing; +use std::vec::Vec; + +/// Test whether the given opcode is unsafe to even consider for DCE. +fn trivially_unsafe_for_dce(opcode: Opcode) -> bool { + opcode.is_call() || opcode.is_branch() || opcode.is_terminator() || + opcode.is_return() || opcode.can_trap() || opcode.other_side_effects() || + opcode.can_store() +} + +/// Preserve instructions with used result values. +fn any_inst_results_used(inst: Inst, live: &[bool], dfg: &DataFlowGraph) -> bool { + dfg.inst_results(inst).iter().any(|v| live[v.index()]) +} + +/// Load instructions without the `notrap` flag are defined to trap when +/// operating on inaccessible memory, so we can't DCE them even if the +/// loaded value is unused. +fn is_load_with_defined_trapping(opcode: Opcode, data: &InstructionData) -> bool { + if !opcode.can_load() { + return false; + } + match *data { + InstructionData::StackLoad { .. } => false, + InstructionData::Load { flags, .. } => !flags.notrap(), + _ => true, + } +} + +/// Perform DCE on `func`. +pub fn do_dce(func: &mut Function, domtree: &mut DominatorTree) { + let _tt = timing::dce(); + debug_assert!(domtree.is_valid()); + + let mut live = Vec::with_capacity(func.dfg.num_values()); + live.resize(func.dfg.num_values(), false); + + for &ebb in domtree.cfg_postorder().iter() { + let mut pos = FuncCursor::new(func).at_bottom(ebb); + while let Some(inst) = pos.prev_inst() { + { + let data = &pos.func.dfg[inst]; + let opcode = data.opcode(); + if trivially_unsafe_for_dce(opcode) || + is_load_with_defined_trapping(opcode, &data) || + any_inst_results_used(inst, &live, &pos.func.dfg) + { + for arg in pos.func.dfg.inst_args(inst) { + let v = pos.func.dfg.resolve_aliases(*arg); + live[v.index()] = true; + } + continue; + } + } + pos.remove_inst(); + } + } +} diff --git a/lib/cretonne/src/ir/immediates.rs b/lib/cretonne/src/ir/immediates.rs index b742c0032d..6026cecf26 100644 --- a/lib/cretonne/src/ir/immediates.rs +++ b/lib/cretonne/src/ir/immediates.rs @@ -21,6 +21,11 @@ impl Imm64 { pub fn new(x: i64) -> Imm64 { Imm64(x) } + + /// Return self negated. + pub fn wrapping_neg(self) -> Imm64 { + Imm64(self.0.wrapping_neg()) + } } impl Into for Imm64 { diff --git a/lib/cretonne/src/isa/intel/mod.rs b/lib/cretonne/src/isa/intel/mod.rs index 578dac2d16..04ff149654 100644 --- a/lib/cretonne/src/isa/intel/mod.rs +++ b/lib/cretonne/src/isa/intel/mod.rs @@ -58,6 +58,10 @@ impl TargetIsa for Isa { &self.shared_flags } + fn uses_cpu_flags(&self) -> bool { + true + } + fn register_info(&self) -> RegInfo { registers::INFO.clone() } diff --git a/lib/cretonne/src/isa/mod.rs b/lib/cretonne/src/isa/mod.rs index aefe93a05d..1a7714fc76 100644 --- a/lib/cretonne/src/isa/mod.rs +++ b/lib/cretonne/src/isa/mod.rs @@ -158,6 +158,11 @@ pub trait TargetIsa: fmt::Display { /// Get the ISA-independent flags that were used to make this trait object. fn flags(&self) -> &settings::Flags; + /// Does the CPU implement scalar comparisons using a CPU flags register? + fn uses_cpu_flags(&self) -> bool { + false + } + /// Get a data structure describing the registers in this ISA. fn register_info(&self) -> RegInfo; diff --git a/lib/cretonne/src/lib.rs b/lib/cretonne/src/lib.rs index 0f731b9620..cde427df9f 100644 --- a/lib/cretonne/src/lib.rs +++ b/lib/cretonne/src/lib.rs @@ -68,11 +68,13 @@ mod abi; mod bitset; mod constant_hash; mod context; +mod dce; mod divconst_magic_numbers; mod iterators; mod legalizer; mod licm; mod partition_slice; +mod postopt; mod predicates; mod preopt; mod ref_slice; diff --git a/lib/cretonne/src/postopt.rs b/lib/cretonne/src/postopt.rs new file mode 100644 index 0000000000..a95baefd3a --- /dev/null +++ b/lib/cretonne/src/postopt.rs @@ -0,0 +1,211 @@ +//! A post-legalization rewriting pass. + +#![allow(non_snake_case)] + +use cursor::{Cursor, EncCursor}; +use ir::dfg::ValueDef; +use ir::{Function, InstructionData, Value, InstBuilder, Ebb, Inst}; +use ir::condcodes::{CondCode, IntCC, FloatCC}; +use ir::instructions::{Opcode, ValueList}; +use ir::immediates::Imm64; +use isa::TargetIsa; +use timing; + +/// Information collected about a compare+branch sequence. +struct CmpBrInfo { + /// The branch instruction. + br_inst: Inst, + /// The icmp, icmp_imm, or fcmp instruction. + cmp_inst: Inst, + /// The destination of the branch. + destination: Ebb, + /// The arguments of the branch. + args: ValueList, + /// The first argument to the comparison. The second is in the `kind` field. + cmp_arg: Value, + /// If the branch is `brz` rather than `brnz`, we need to invert the condition + /// before the branch. + invert_branch_cond: bool, + /// The kind of comparison, and the second argument. + kind: CmpBrKind, +} + +enum CmpBrKind { + Icmp { cond: IntCC, arg: Value }, + IcmpImm { cond: IntCC, imm: Imm64 }, + Fcmp { cond: FloatCC, arg: Value }, +} + +/// Optimize comparisons to use flags values, to avoid materializing conditions +/// in integer registers. +/// +/// For example, optimize icmp/fcmp brz/brnz sequences into ifcmp/ffcmp brif/brff +/// sequences. +fn optimize_cpu_flags( + pos: &mut EncCursor, + inst: Inst, + last_flags_clobber: Option, + isa: &TargetIsa, +) { + // Look for compare and branch patterns. + // This code could be considerably simplified with non-lexical lifetimes. + let info = match pos.func.dfg[inst] { + InstructionData::Branch { + opcode, + destination, + ref args, + } => { + let first_arg = args.first(&pos.func.dfg.value_lists).unwrap(); + let invert_branch_cond = match opcode { + Opcode::Brz => true, + Opcode::Brnz => false, + _ => panic!(), + }; + if let ValueDef::Result(cond_inst, _) = pos.func.dfg.value_def(first_arg) { + match pos.func.dfg[cond_inst] { + InstructionData::IntCompare { + cond, + args: cmp_args, + .. + } => { + CmpBrInfo { + br_inst: inst, + cmp_inst: cond_inst, + destination, + args: args.clone(), + cmp_arg: cmp_args[0], + invert_branch_cond, + kind: CmpBrKind::Icmp { + cond, + arg: cmp_args[1], + }, + } + } + InstructionData::IntCompareImm { + cond, + arg: cmp_arg, + imm: cmp_imm, + .. + } => { + CmpBrInfo { + br_inst: inst, + cmp_inst: cond_inst, + destination, + args: args.clone(), + cmp_arg, + invert_branch_cond, + kind: CmpBrKind::IcmpImm { cond, imm: cmp_imm }, + } + } + InstructionData::FloatCompare { + cond, + args: cmp_args, + .. + } => { + CmpBrInfo { + br_inst: inst, + cmp_inst: cond_inst, + destination, + args: args.clone(), + cmp_arg: cmp_args[0], + invert_branch_cond, + kind: CmpBrKind::Fcmp { + cond, + arg: cmp_args[1], + }, + } + } + _ => return, + } + } else { + return; + } + } + // TODO: trapif, trueif, selectif, and their ff counterparts. + _ => return, + }; + + // If any instructions clobber the flags between the comparison and the branch, + // don't optimize them. + if last_flags_clobber != Some(info.cmp_inst) { + return; + } + + // We found a compare+branch pattern. Transform it to use flags. + let args = info.args.as_slice(&pos.func.dfg.value_lists)[1..].to_vec(); + pos.goto_inst(info.cmp_inst); + match info.kind { + CmpBrKind::Icmp { mut cond, arg } => { + let flags = pos.ins().ifcmp(info.cmp_arg, arg); + pos.func.dfg.replace(info.cmp_inst).trueif(cond, flags); + if info.invert_branch_cond { + cond = cond.inverse(); + } + pos.func.dfg.replace(info.br_inst).brif( + cond, + flags, + info.destination, + &args, + ); + } + CmpBrKind::IcmpImm { mut cond, imm } => { + let flags = pos.ins().ifcmp_imm(info.cmp_arg, imm); + pos.func.dfg.replace(info.cmp_inst).trueif(cond, flags); + if info.invert_branch_cond { + cond = cond.inverse(); + } + pos.func.dfg.replace(info.br_inst).brif( + cond, + flags, + info.destination, + &args, + ); + } + CmpBrKind::Fcmp { mut cond, arg } => { + let flags = pos.ins().ffcmp(info.cmp_arg, arg); + pos.func.dfg.replace(info.cmp_inst).trueff(cond, flags); + if info.invert_branch_cond { + cond = cond.inverse(); + } + pos.func.dfg.replace(info.br_inst).brff( + cond, + flags, + info.destination, + &args, + ); + } + } + pos.func.update_encoding(info.cmp_inst, isa).is_ok(); + pos.func.update_encoding(info.br_inst, isa).is_ok(); +} + + +//---------------------------------------------------------------------- +// +// The main post-opt pass. + +pub fn do_postopt(func: &mut Function, isa: &TargetIsa) { + let _tt = timing::postopt(); + let mut pos = EncCursor::new(func, isa); + while let Some(_ebb) = pos.next_ebb() { + let mut last_flags_clobber = None; + while let Some(inst) = pos.next_inst() { + if isa.uses_cpu_flags() { + // Optimize instructions to make use of flags. + optimize_cpu_flags(&mut pos, inst, last_flags_clobber, isa); + + // Track the most recent seen instruction that clobbers the flags. + if let Some(constraints) = + isa.encoding_info().operand_constraints( + pos.func.encodings[inst], + ) + { + if constraints.clobbers_flags { + last_flags_clobber = Some(inst) + } + } + + } + } + } +} diff --git a/lib/cretonne/src/preopt.rs b/lib/cretonne/src/preopt.rs index 9adce51369..34dab71c4a 100644 --- a/lib/cretonne/src/preopt.rs +++ b/lib/cretonne/src/preopt.rs @@ -127,28 +127,6 @@ fn get_div_info(inst: Inst, dfg: &DataFlowGraph) -> Option { return package_up_divrem_info(arg, argL_ty, imm.into(), isSigned, isRem); } - // TODO: should we actually bother to do this (that is, manually match - // the case that the second argument is an iconst)? Or should we assume - // that some previous constant propagation pass has pushed all such - // immediates to their use points, creating BinaryImm instructions - // instead? For now we take the conservative approach. - if let InstructionData::Binary { opcode, args } = *idata { - let (isSigned, isRem) = match opcode { - Opcode::Udiv => (false, false), - Opcode::Urem => (false, true), - Opcode::Sdiv => (true, false), - Opcode::Srem => (true, true), - _other => return None, - }; - let argR: Value = args[1]; - if let Some(simm64) = get_const(argR, dfg) { - let argL: Value = args[0]; - // Pull the operation size (type) from the left arg - let argL_ty = dfg.value_type(argL); - return package_up_divrem_info(argL, argL_ty, simm64, isSigned, isRem); - } - } - None } @@ -473,25 +451,106 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso } } - -//---------------------------------------------------------------------- -// -// General pattern-match helpers. - -/// Find out if `value` actually resolves to a constant, and if so what its -/// value is. -fn get_const(value: Value, dfg: &DataFlowGraph) -> Option { - match dfg.value_def(value) { - ValueDef::Result(definingInst, resultNo) => { - let definingIData: &InstructionData = &dfg[definingInst]; - if let InstructionData::UnaryImm { opcode, imm } = *definingIData { - if opcode == Opcode::Iconst && resultNo == 0 { - return Some(imm.into()); +/// Apply basic simplifications. +/// +/// This folds constants with arithmetic to form `_imm` instructions, and other +/// minor simplifications. +fn simplify(pos: &mut FuncCursor, inst: Inst) { + match pos.func.dfg[inst] { + InstructionData::Binary { opcode, args } => { + if let ValueDef::Result(iconst_inst, _) = pos.func.dfg.value_def(args[1]) { + if let InstructionData::UnaryImm { + opcode: Opcode::Iconst, + mut imm, + } = pos.func.dfg[iconst_inst] + { + let new_opcode = match opcode { + Opcode::Iadd => Opcode::IaddImm, + Opcode::Imul => Opcode::ImulImm, + Opcode::Sdiv => Opcode::SdivImm, + Opcode::Udiv => Opcode::UdivImm, + Opcode::Srem => Opcode::SremImm, + Opcode::Urem => Opcode::UremImm, + Opcode::Band => Opcode::BandImm, + Opcode::Bor => Opcode::BorImm, + Opcode::Bxor => Opcode::BxorImm, + Opcode::Rotl => Opcode::RotlImm, + Opcode::Rotr => Opcode::RotrImm, + Opcode::Ishl => Opcode::IshlImm, + Opcode::Ushr => Opcode::UshrImm, + Opcode::Sshr => Opcode::SshrImm, + Opcode::Isub => { + imm = imm.wrapping_neg(); + Opcode::IaddImm + } + _ => return, + }; + let ty = pos.func.dfg.ctrl_typevar(inst); + pos.func.dfg.replace(inst).BinaryImm( + new_opcode, + ty, + imm, + args[0], + ); + } + } else if let ValueDef::Result(iconst_inst, _) = pos.func.dfg.value_def(args[0]) { + if let InstructionData::UnaryImm { + opcode: Opcode::Iconst, + mut imm, + } = pos.func.dfg[iconst_inst] + { + let new_opcode = match opcode { + Opcode::Isub => Opcode::IrsubImm, + _ => return, + }; + let ty = pos.func.dfg.ctrl_typevar(inst); + pos.func.dfg.replace(inst).BinaryImm( + new_opcode, + ty, + imm, + args[0], + ); } } - None } - ValueDef::Param(_definingEbb, _paramNo) => None, + InstructionData::IntCompare { opcode, cond, args } => { + debug_assert_eq!(opcode, Opcode::Icmp); + if let ValueDef::Result(iconst_inst, _) = pos.func.dfg.value_def(args[1]) { + if let InstructionData::UnaryImm { + opcode: Opcode::Iconst, + imm, + } = pos.func.dfg[iconst_inst] + { + pos.func.dfg.replace(inst).icmp_imm(cond, args[0], imm); + } + } + } + InstructionData::CondTrap { .. } | + InstructionData::Branch { .. } | + InstructionData::Ternary { opcode: Opcode::Select, .. } => { + // Fold away a redundant `bint`. + let maybe = { + let args = pos.func.dfg.inst_args(inst); + if let ValueDef::Result(def_inst, _) = pos.func.dfg.value_def(args[0]) { + if let InstructionData::Unary { + opcode: Opcode::Bint, + arg: bool_val, + } = pos.func.dfg[def_inst] + { + Some(bool_val) + } else { + None + } + } else { + None + } + }; + if let Some(bool_val) = maybe { + let args = pos.func.dfg.inst_args_mut(inst); + args[0] = bool_val; + } + } + _ => {} } } @@ -503,6 +562,8 @@ pub fn do_preopt(func: &mut Function) { while let Some(_ebb) = pos.next_ebb() { while let Some(inst) = pos.next_inst() { + // Apply basic simplifications. + simplify(&mut pos, inst); //-- BEGIN -- division by constants ---------------- diff --git a/lib/cretonne/src/timing.rs b/lib/cretonne/src/timing.rs index 51cdd85bfa..2626445921 100644 --- a/lib/cretonne/src/timing.rs +++ b/lib/cretonne/src/timing.rs @@ -55,7 +55,9 @@ define_passes!{ flowgraph: "Control flow graph", domtree: "Dominator tree", loop_analysis: "Loop analysis", + postopt: "Post-legalization rewriting", preopt: "Pre-legalization rewriting", + dce: "Dead code elimination", legalize: "Legalization", gvn: "Global value numbering", licm: "Loop invariant code motion", diff --git a/lib/filetests/src/lib.rs b/lib/filetests/src/lib.rs index a6a43d4437..66bb7023ec 100644 --- a/lib/filetests/src/lib.rs +++ b/lib/filetests/src/lib.rs @@ -28,9 +28,11 @@ mod match_directive; mod test_binemit; mod test_cat; mod test_compile; +mod test_dce; mod test_domtree; mod test_legalizer; mod test_licm; +mod test_postopt; mod test_preopt; mod test_print_cfg; mod test_regalloc; @@ -73,9 +75,11 @@ fn new_subtest(parsed: &TestCommand) -> subtest::Result> { "binemit" => test_binemit::subtest(parsed), "cat" => test_cat::subtest(parsed), "compile" => test_compile::subtest(parsed), + "dce" => test_dce::subtest(parsed), "domtree" => test_domtree::subtest(parsed), "legalizer" => test_legalizer::subtest(parsed), "licm" => test_licm::subtest(parsed), + "postopt" => test_postopt::subtest(parsed), "preopt" => test_preopt::subtest(parsed), "print-cfg" => test_print_cfg::subtest(parsed), "regalloc" => test_regalloc::subtest(parsed), diff --git a/lib/filetests/src/test_dce.rs b/lib/filetests/src/test_dce.rs new file mode 100644 index 0000000000..5a57d83e3e --- /dev/null +++ b/lib/filetests/src/test_dce.rs @@ -0,0 +1,53 @@ +//! Test command for testing the DCE pass. +//! +//! The `dce` test command runs each function through the DCE pass after ensuring +//! that all instructions are legal for the target. +//! +//! The resulting function is sent to `filecheck`. + +use cretonne::ir::Function; +use cretonne; +use cretonne::print_errors::pretty_error; +use cton_reader::TestCommand; +use subtest::{SubTest, Context, Result, run_filecheck}; +use std::borrow::Cow; +use std::fmt::Write; + +struct TestDCE; + +pub fn subtest(parsed: &TestCommand) -> Result> { + assert_eq!(parsed.command, "dce"); + if !parsed.options.is_empty() { + Err(format!("No options allowed on {}", parsed)) + } else { + Ok(Box::new(TestDCE)) + } +} + +impl SubTest for TestDCE { + fn name(&self) -> Cow { + Cow::from("dce") + } + + fn is_mutating(&self) -> bool { + true + } + + fn run(&self, func: Cow, context: &Context) -> Result<()> { + // Create a compilation context, and drop in the function. + let mut comp_ctx = cretonne::Context::new(); + comp_ctx.func = func.into_owned(); + + comp_ctx.flowgraph(); + comp_ctx.compute_loop_analysis(); + comp_ctx.dce(context.flags_or_isa()).map_err(|e| { + pretty_error(&comp_ctx.func, context.isa, Into::into(e)) + })?; + + let mut text = String::new(); + write!(&mut text, "{}", &comp_ctx.func).map_err( + |e| e.to_string(), + )?; + run_filecheck(&text, context) + } +} diff --git a/lib/filetests/src/test_postopt.rs b/lib/filetests/src/test_postopt.rs new file mode 100644 index 0000000000..34ffb3f462 --- /dev/null +++ b/lib/filetests/src/test_postopt.rs @@ -0,0 +1,50 @@ +//! Test command for testing the postopt pass. +//! +//! The resulting function is sent to `filecheck`. + +use cretonne::ir::Function; +use cretonne; +use cretonne::print_errors::pretty_error; +use cton_reader::TestCommand; +use subtest::{SubTest, Context, Result, run_filecheck}; +use std::borrow::Cow; +use std::fmt::Write; + +struct TestPostopt; + +pub fn subtest(parsed: &TestCommand) -> Result> { + assert_eq!(parsed.command, "postopt"); + if !parsed.options.is_empty() { + Err(format!("No options allowed on {}", parsed)) + } else { + Ok(Box::new(TestPostopt)) + } +} + +impl SubTest for TestPostopt { + fn name(&self) -> Cow { + Cow::from("postopt") + } + + fn is_mutating(&self) -> bool { + true + } + + fn run(&self, func: Cow, context: &Context) -> Result<()> { + // Create a compilation context, and drop in the function. + let mut comp_ctx = cretonne::Context::new(); + comp_ctx.func = func.into_owned(); + let isa = context.isa.expect("postopt needs an ISA"); + + comp_ctx.flowgraph(); + comp_ctx.postopt(isa).map_err(|e| { + pretty_error(&comp_ctx.func, context.isa, Into::into(e)) + })?; + + let mut text = String::new(); + write!(&mut text, "{}", &comp_ctx.func).map_err( + |e| e.to_string(), + )?; + run_filecheck(&text, context) + } +} From 9e4ab7dc868346af30e7b00d850c3d3b5197f9c8 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 30 Mar 2018 12:32:14 -0700 Subject: [PATCH 67/72] Rename CallConv::Native to CallConv::SystemV. (#291) To keep cross-compiling straightforward, Cretonne shouldn't have any behavior that depends on the host. This renames the "Native" calling convention to "SystemV", which has a defined meaning for each target, so that it's clear that the calling convention doesn't change depending on what host Cretonne is running on. --- cranelift/docs/callex.cton | 2 +- cranelift/docs/example.cton | 2 +- cranelift/docs/langref.rst | 6 +-- cranelift/filetests/domtree/loops.cton | 2 +- cranelift/filetests/domtree/loops2.cton | 2 +- cranelift/filetests/isa/intel/abi-bool.cton | 2 +- cranelift/filetests/isa/intel/abi32.cton | 12 +++--- cranelift/filetests/isa/intel/abi64.cton | 12 +++--- .../filetests/isa/intel/legalize-libcall.cton | 4 +- .../isa/intel/prologue-epilogue.cton | 2 +- cranelift/filetests/isa/riscv/abi-e.cton | 4 +- cranelift/filetests/isa/riscv/abi.cton | 24 +++++------ .../filetests/isa/riscv/legalize-abi.cton | 4 +- .../filetests/isa/riscv/parse-encoding.cton | 30 +++++++------- cranelift/filetests/licm/complex.cton | 2 +- cranelift/filetests/parser/branch.cton | 12 +++--- cranelift/filetests/parser/call.cton | 10 ++--- .../parser/instruction_encoding.cton | 2 +- cranelift/filetests/parser/keywords.cton | 2 +- cranelift/filetests/parser/rewrite.cton | 4 +- cranelift/filetests/parser/tiny.cton | 28 ++++++------- cranelift/filetests/regalloc/coalesce.cton | 2 +- .../filetests/regalloc/coalescing-207.cton | 12 +++--- .../filetests/regalloc/coalescing-216.cton | 2 +- .../filetests/regalloc/coloring-227.cton | 2 +- cranelift/filetests/regalloc/ghost-param.cton | 2 +- .../filetests/regalloc/global-fixed.cton | 2 +- .../filetests/regalloc/intel-regres.cton | 2 +- .../regalloc/output-interference.cton | 2 +- cranelift/filetests/regalloc/reload-208.cton | 6 +-- cranelift/filetests/regalloc/reload.cton | 2 +- .../filetests/regalloc/schedule-moves.cton | 4 +- .../filetests/regalloc/spill-noregs.cton | 2 +- cranelift/filetests/regalloc/spill.cton | 4 +- .../verifier/defs_dominates_uses.cton | 4 +- lib/cretonne/src/ir/extfunc.rs | 13 +++--- lib/cretonne/src/ir/function.rs | 6 +-- lib/cretonne/src/isa/intel/abi.rs | 16 ++++---- lib/cretonne/src/legalizer/libcall.rs | 4 +- lib/cretonne/src/write.rs | 12 +++--- lib/frontend/src/frontend.rs | 2 +- lib/frontend/src/lib.rs | 2 +- lib/reader/src/parser.rs | 40 +++++++++---------- lib/wasm/src/sections_translator.rs | 2 +- 44 files changed, 157 insertions(+), 156 deletions(-) diff --git a/cranelift/docs/callex.cton b/cranelift/docs/callex.cton index 6690e78f90..837f9ea6e7 100644 --- a/cranelift/docs/callex.cton +++ b/cranelift/docs/callex.cton @@ -1,6 +1,6 @@ test verifier -function %gcd(i32 uext, i32 uext) -> i32 uext native { +function %gcd(i32 uext, i32 uext) -> i32 uext system_v { fn1 = function %divmod(i32 uext, i32 uext) -> i32 uext, i32 uext ebb1(v1: i32, v2: i32): diff --git a/cranelift/docs/example.cton b/cranelift/docs/example.cton index a36fef3238..09e0c9cb5f 100644 --- a/cranelift/docs/example.cton +++ b/cranelift/docs/example.cton @@ -1,6 +1,6 @@ test verifier -function %average(i32, i32) -> f32 native { +function %average(i32, i32) -> f32 system_v { ss1 = explicit_slot 8 ; Stack slot for ``sum``. ebb1(v1: i32, v2: i32): diff --git a/cranelift/docs/langref.rst b/cranelift/docs/langref.rst index 162248c83e..edcc039c86 100644 --- a/cranelift/docs/langref.rst +++ b/cranelift/docs/langref.rst @@ -400,11 +400,11 @@ convention: param : type [paramext] [paramspecial] paramext : "uext" | "sext" paramspecial : "sret" | "link" | "fp" | "csr" | "vmctx" - callconv : "native" | "spiderwasm" + callconv : "system_v" | "spiderwasm" Parameters and return values have flags whose meaning is mostly target -dependent. They make it possible to call native functions on the target -platform. When calling other Cretonne functions, the flags are not necessary. +dependent. These flags support interfacing with code produced by other +compilers. Functions that are called directly must be declared in the :term:`function preamble`: diff --git a/cranelift/filetests/domtree/loops.cton b/cranelift/filetests/domtree/loops.cton index 70c62d4130..fda2984e94 100644 --- a/cranelift/filetests/domtree/loops.cton +++ b/cranelift/filetests/domtree/loops.cton @@ -59,7 +59,7 @@ function %test(i32) { ; nextln: ebb5: ; nextln: } -function %loop2(i32) native { +function %loop2(i32) system_v { ebb0(v0: i32): brz v0, ebb1 ; dominates: ebb1 ebb3 ebb4 ebb5 jump ebb2 ; dominates: ebb2 diff --git a/cranelift/filetests/domtree/loops2.cton b/cranelift/filetests/domtree/loops2.cton index 029cea922a..80e00ca278 100644 --- a/cranelift/filetests/domtree/loops2.cton +++ b/cranelift/filetests/domtree/loops2.cton @@ -43,7 +43,7 @@ function %loop1(i32) { ; nextln: ebb9: ; nextln: } -function %loop2(i32) native { +function %loop2(i32) system_v { ebb0(v0: i32): brz v0, ebb1 ; dominates: ebb1 ebb3 ebb4 ebb5 jump ebb2 ; dominates: ebb2 diff --git a/cranelift/filetests/isa/intel/abi-bool.cton b/cranelift/filetests/isa/intel/abi-bool.cton index bc1a1ba1d5..6a53cdbb3c 100644 --- a/cranelift/filetests/isa/intel/abi-bool.cton +++ b/cranelift/filetests/isa/intel/abi-bool.cton @@ -2,7 +2,7 @@ test compile set is_64bit=1 isa intel haswell -function %foo(i64, i64, i64, i32) -> b1 native { +function %foo(i64, i64, i64, i32) -> b1 system_v { ebb3(v0: i64, v1: i64, v2: i64, v3: i32): v5 = icmp ne v2, v2 v8 = iconst.i64 0 diff --git a/cranelift/filetests/isa/intel/abi32.cton b/cranelift/filetests/isa/intel/abi32.cton index c7e399960c..b949af16f7 100644 --- a/cranelift/filetests/isa/intel/abi32.cton +++ b/cranelift/filetests/isa/intel/abi32.cton @@ -5,14 +5,14 @@ isa intel ; regex: V=v\d+ function %f() { - sig0 = (i32) -> i32 native - ; check: sig0 = (i32 [0]) -> i32 [%rax] native + sig0 = (i32) -> i32 system_v + ; check: sig0 = (i32 [0]) -> i32 [%rax] system_v - sig1 = (i64) -> b1 native - ; check: sig1 = (i32 [0], i32 [4]) -> b1 [%rax] native + sig1 = (i64) -> b1 system_v + ; check: sig1 = (i32 [0], i32 [4]) -> b1 [%rax] system_v - sig2 = (f32, i64) -> f64 native - ; check: sig2 = (f32 [0], i32 [4], i32 [8]) -> f64 [%xmm0] native + sig2 = (f32, i64) -> f64 system_v + ; check: sig2 = (f32 [0], i32 [4], i32 [8]) -> f64 [%xmm0] system_v ebb0: return diff --git a/cranelift/filetests/isa/intel/abi64.cton b/cranelift/filetests/isa/intel/abi64.cton index d56a31d479..8aa6a49b0f 100644 --- a/cranelift/filetests/isa/intel/abi64.cton +++ b/cranelift/filetests/isa/intel/abi64.cton @@ -6,14 +6,14 @@ isa intel ; regex: V=v\d+ function %f() { - sig0 = (i32) -> i32 native - ; check: sig0 = (i32 [%rdi]) -> i32 [%rax] native + sig0 = (i32) -> i32 system_v + ; check: sig0 = (i32 [%rdi]) -> i32 [%rax] system_v - sig1 = (i64) -> b1 native - ; check: sig1 = (i64 [%rdi]) -> b1 [%rax] native + sig1 = (i64) -> b1 system_v + ; check: sig1 = (i64 [%rdi]) -> b1 [%rax] system_v - sig2 = (f32, i64) -> f64 native - ; check: sig2 = (f32 [%xmm0], i64 [%rdi]) -> f64 [%xmm0] native + sig2 = (f32, i64) -> f64 system_v + ; check: sig2 = (f32 [%xmm0], i64 [%rdi]) -> f64 [%xmm0] system_v ebb0: return diff --git a/cranelift/filetests/isa/intel/legalize-libcall.cton b/cranelift/filetests/isa/intel/legalize-libcall.cton index 562efb6beb..c15587fc7f 100644 --- a/cranelift/filetests/isa/intel/legalize-libcall.cton +++ b/cranelift/filetests/isa/intel/legalize-libcall.cton @@ -9,7 +9,7 @@ ebb0(v0: f32): v1 = floor v0 return v1 } -; check: function %floor(f32 [%xmm0]) -> f32 [%xmm0] native { -; check: sig0 = (f32) -> f32 native +; check: function %floor(f32 [%xmm0]) -> f32 [%xmm0] system_v { +; check: sig0 = (f32) -> f32 system_v ; check: fn0 = sig0 %FloorF32 ; check: v1 = call fn0(v0) diff --git a/cranelift/filetests/isa/intel/prologue-epilogue.cton b/cranelift/filetests/isa/intel/prologue-epilogue.cton index fc53f72008..cd774fe6bd 100644 --- a/cranelift/filetests/isa/intel/prologue-epilogue.cton +++ b/cranelift/filetests/isa/intel/prologue-epilogue.cton @@ -9,7 +9,7 @@ ebb0: return } -; check: function %foo(i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15]) -> i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15] native { +; check: function %foo(i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15]) -> i64 fp [%rbp], i64 csr [%rbx], i64 csr [%r12], i64 csr [%r13], i64 csr [%r14], i64 csr [%r15] system_v { ; nextln: ss0 = explicit_slot 168, offset -224 ; nextln: ss1 = incoming_arg 56, offset -56 ; check: ebb0(v0: i64 [%rbp], v1: i64 [%rbx], v2: i64 [%r12], v3: i64 [%r13], v4: i64 [%r14], v5: i64 [%r15]): diff --git a/cranelift/filetests/isa/riscv/abi-e.cton b/cranelift/filetests/isa/riscv/abi-e.cton index df06402283..50100ebf4e 100644 --- a/cranelift/filetests/isa/riscv/abi-e.cton +++ b/cranelift/filetests/isa/riscv/abi-e.cton @@ -7,8 +7,8 @@ isa riscv enable_e function %f() { ; Spilling into the stack args after %x15 since %16 and up are not ; available in RV32E. - sig0 = (i64, i64, i64, i64) -> i64 native - ; check: sig0 = (i32 [%x10], i32 [%x11], i32 [%x12], i32 [%x13], i32 [%x14], i32 [%x15], i32 [0], i32 [4]) -> i32 [%x10], i32 [%x11] native + sig0 = (i64, i64, i64, i64) -> i64 system_v + ; check: sig0 = (i32 [%x10], i32 [%x11], i32 [%x12], i32 [%x13], i32 [%x14], i32 [%x15], i32 [0], i32 [4]) -> i32 [%x10], i32 [%x11] system_v ebb0: return } diff --git a/cranelift/filetests/isa/riscv/abi.cton b/cranelift/filetests/isa/riscv/abi.cton index c57c09fd97..12371ac537 100644 --- a/cranelift/filetests/isa/riscv/abi.cton +++ b/cranelift/filetests/isa/riscv/abi.cton @@ -5,27 +5,27 @@ isa riscv ; regex: V=v\d+ function %f() { - sig0 = (i32) -> i32 native - ; check: sig0 = (i32 [%x10]) -> i32 [%x10] native + sig0 = (i32) -> i32 system_v + ; check: sig0 = (i32 [%x10]) -> i32 [%x10] system_v - sig1 = (i64) -> b1 native - ; check: sig1 = (i32 [%x10], i32 [%x11]) -> b1 [%x10] native + sig1 = (i64) -> b1 system_v + ; check: sig1 = (i32 [%x10], i32 [%x11]) -> b1 [%x10] system_v ; The i64 argument must go in an even-odd register pair. - sig2 = (f32, i64) -> f64 native - ; check: sig2 = (f32 [%f10], i32 [%x12], i32 [%x13]) -> f64 [%f10] native + sig2 = (f32, i64) -> f64 system_v + ; check: sig2 = (f32 [%f10], i32 [%x12], i32 [%x13]) -> f64 [%f10] system_v ; Spilling into the stack args. - sig3 = (f64, f64, f64, f64, f64, f64, f64, i64) -> f64 native - ; check: sig3 = (f64 [%f10], f64 [%f11], f64 [%f12], f64 [%f13], f64 [%f14], f64 [%f15], f64 [%f16], i32 [0], i32 [4]) -> f64 [%f10] native + sig3 = (f64, f64, f64, f64, f64, f64, f64, i64) -> f64 system_v + ; check: sig3 = (f64 [%f10], f64 [%f11], f64 [%f12], f64 [%f13], f64 [%f14], f64 [%f15], f64 [%f16], i32 [0], i32 [4]) -> f64 [%f10] system_v ; Splitting vectors. - sig4 = (i32x4) native - ; check: sig4 = (i32 [%x10], i32 [%x11], i32 [%x12], i32 [%x13]) native + sig4 = (i32x4) system_v + ; check: sig4 = (i32 [%x10], i32 [%x11], i32 [%x12], i32 [%x13]) system_v ; Splitting vectors, then splitting ints. - sig5 = (i64x4) native - ; check: sig5 = (i32 [%x10], i32 [%x11], i32 [%x12], i32 [%x13], i32 [%x14], i32 [%x15], i32 [%x16], i32 [%x17]) native + sig5 = (i64x4) system_v + ; check: sig5 = (i32 [%x10], i32 [%x11], i32 [%x12], i32 [%x13], i32 [%x14], i32 [%x15], i32 [%x16], i32 [%x17]) system_v ebb0: return diff --git a/cranelift/filetests/isa/riscv/legalize-abi.cton b/cranelift/filetests/isa/riscv/legalize-abi.cton index 3234407052..44865120ea 100644 --- a/cranelift/filetests/isa/riscv/legalize-abi.cton +++ b/cranelift/filetests/isa/riscv/legalize-abi.cton @@ -106,7 +106,7 @@ ebb0(v0: i64x4): } function %indirect(i32) { - sig1 = () native + sig1 = () system_v ebb0(v0: i32): call_indirect sig1, v0() return @@ -114,7 +114,7 @@ ebb0(v0: i32): ; The first argument to call_indirect doesn't get altered. function %indirect_arg(i32, f32x2) { - sig1 = (f32x2) native + sig1 = (f32x2) system_v ebb0(v0: i32, v1: f32x2): call_indirect sig1, v0(v1) ; check: call_indirect sig1, v0($V, $V) diff --git a/cranelift/filetests/isa/riscv/parse-encoding.cton b/cranelift/filetests/isa/riscv/parse-encoding.cton index e955ad296a..0fc0879f38 100644 --- a/cranelift/filetests/isa/riscv/parse-encoding.cton +++ b/cranelift/filetests/isa/riscv/parse-encoding.cton @@ -3,32 +3,32 @@ test legalizer isa riscv function %parse_encoding(i32 [%x5]) -> i32 [%x10] { - ; check: function %parse_encoding(i32 [%x5], i32 link [%x1]) -> i32 [%x10], i32 link [%x1] native { + ; check: function %parse_encoding(i32 [%x5], i32 link [%x1]) -> i32 [%x10], i32 link [%x1] system_v { - sig0 = (i32 [%x10]) -> i32 [%x10] native - ; check: sig0 = (i32 [%x10]) -> i32 [%x10] native + sig0 = (i32 [%x10]) -> i32 [%x10] system_v + ; check: sig0 = (i32 [%x10]) -> i32 [%x10] system_v - sig1 = (i32 [%x10], i32 [%x11]) -> b1 [%x10] native - ; check: sig1 = (i32 [%x10], i32 [%x11]) -> b1 [%x10] native + sig1 = (i32 [%x10], i32 [%x11]) -> b1 [%x10] system_v + ; check: sig1 = (i32 [%x10], i32 [%x11]) -> b1 [%x10] system_v - sig2 = (f32 [%f10], i32 [%x12], i32 [%x13]) -> f64 [%f10] native - ; check: sig2 = (f32 [%f10], i32 [%x12], i32 [%x13]) -> f64 [%f10] native + sig2 = (f32 [%f10], i32 [%x12], i32 [%x13]) -> f64 [%f10] system_v + ; check: sig2 = (f32 [%f10], i32 [%x12], i32 [%x13]) -> f64 [%f10] system_v ; Arguments on stack where not necessary - sig3 = (f64 [%f10], i32 [0], i32 [4]) -> f64 [%f10] native - ; check: sig3 = (f64 [%f10], i32 [0], i32 [4]) -> f64 [%f10] native + sig3 = (f64 [%f10], i32 [0], i32 [4]) -> f64 [%f10] system_v + ; check: sig3 = (f64 [%f10], i32 [0], i32 [4]) -> f64 [%f10] system_v ; Stack argument before register argument - sig4 = (f32 [72], i32 [%x10]) native - ; check: sig4 = (f32 [72], i32 [%x10]) native + sig4 = (f32 [72], i32 [%x10]) system_v + ; check: sig4 = (f32 [72], i32 [%x10]) system_v ; Return value on stack - sig5 = () -> f32 [0] native - ; check: sig5 = () -> f32 [0] native + sig5 = () -> f32 [0] system_v + ; check: sig5 = () -> f32 [0] system_v ; function + signature - fn0 = function %bar(i32 [%x10]) -> b1 [%x10] native - ; check: sig6 = (i32 [%x10]) -> b1 [%x10] native + fn0 = function %bar(i32 [%x10]) -> b1 [%x10] system_v + ; check: sig6 = (i32 [%x10]) -> b1 [%x10] system_v ; nextln: fn0 = sig6 %bar ebb0(v0: i32): diff --git a/cranelift/filetests/licm/complex.cton b/cranelift/filetests/licm/complex.cton index e9012b1a4f..3b339574a8 100644 --- a/cranelift/filetests/licm/complex.cton +++ b/cranelift/filetests/licm/complex.cton @@ -1,6 +1,6 @@ test licm -function %complex(i32) -> i32 native { +function %complex(i32) -> i32 system_v { ebb0(v0: i32): jump ebb1(v0) diff --git a/cranelift/filetests/parser/branch.cton b/cranelift/filetests/parser/branch.cton index 868b92d024..4e35147a6b 100644 --- a/cranelift/filetests/parser/branch.cton +++ b/cranelift/filetests/parser/branch.cton @@ -9,7 +9,7 @@ ebb0: ebb1: jump ebb0() } -; sameln: function %minimal() native { +; sameln: function %minimal() system_v { ; nextln: ebb0: ; nextln: jump ebb1 ; nextln: @@ -25,7 +25,7 @@ ebb0(v90: i32): ebb1(v91: i32): jump ebb0(v91) } -; sameln: function %onearg(i32) native { +; sameln: function %onearg(i32) system_v { ; nextln: ebb0(v90: i32): ; nextln: jump ebb1(v90) ; nextln: @@ -41,7 +41,7 @@ ebb0(v90: i32, v91: f32): ebb1(v92: i32, v93: f32): jump ebb0(v92, v93) } -; sameln: function %twoargs(i32, f32) native { +; sameln: function %twoargs(i32, f32) system_v { ; nextln: ebb0(v90: i32, v91: f32): ; nextln: jump ebb1(v90, v91) ; nextln: @@ -57,7 +57,7 @@ ebb0(v90: i32): ebb1: brnz v90, ebb1() } -; sameln: function %minimal(i32) native { +; sameln: function %minimal(i32) system_v { ; nextln: ebb0(v90: i32): ; nextln: brz v90, ebb1 ; nextln: @@ -72,7 +72,7 @@ ebb0(v90: i32, v91: f32): ebb1(v92: i32, v93: f32): brnz v90, ebb0(v92, v93) } -; sameln: function %twoargs(i32, f32) native { +; sameln: function %twoargs(i32, f32) system_v { ; nextln: ebb0(v90: i32, v91: f32): ; nextln: brz v90, ebb1(v90, v91) ; nextln: @@ -94,7 +94,7 @@ ebb30: ebb40: trap user4 } -; sameln: function %jumptable(i32) native { +; sameln: function %jumptable(i32) system_v { ; check: jt2 = jump_table 0, 0, ebb10, ebb40, ebb20, ebb30 ; check: jt200 = jump_table 0 ; check: ebb10(v3: i32): diff --git a/cranelift/filetests/parser/call.cton b/cranelift/filetests/parser/call.cton index 77543800d0..3413696caf 100644 --- a/cranelift/filetests/parser/call.cton +++ b/cranelift/filetests/parser/call.cton @@ -5,7 +5,7 @@ function %mini() { ebb1: return } -; sameln: function %mini() native { +; sameln: function %mini() system_v { ; nextln: ebb1: ; nextln: return ; nextln: } @@ -29,10 +29,10 @@ function %signatures() { fn5 = sig11 %foo fn8 = function %bar(i32) -> b1 } -; sameln: function %signatures() native { -; check: sig10 = () native +; sameln: function %signatures() system_v { +; check: sig10 = () system_v ; check: sig11 = (i32, f64) -> i32, b1 spiderwasm -; check: sig12 = (i32) -> b1 native +; check: sig12 = (i32) -> b1 system_v ; not: fn0 ; check: fn5 = sig11 %foo ; check: fn8 = sig12 %bar @@ -88,7 +88,7 @@ function %special1(i32 sret, i32 fp, i32 csr, i32 link) -> i32 link, i32 fp, i32 ebb0(v1: i32, v2: i32, v3: i32, v4: i32): return v4, v2, v3, v1 } -; check: function %special1(i32 sret, i32 fp, i32 csr, i32 link) -> i32 link, i32 fp, i32 csr, i32 sret native { +; check: function %special1(i32 sret, i32 fp, i32 csr, i32 link) -> i32 link, i32 fp, i32 csr, i32 sret system_v { ; check: ebb0(v1: i32, v2: i32, v3: i32, v4: i32): ; check: return v4, v2, v3, v1 ; check: } diff --git a/cranelift/filetests/parser/instruction_encoding.cton b/cranelift/filetests/parser/instruction_encoding.cton index a16c24a364..e0a2de789a 100644 --- a/cranelift/filetests/parser/instruction_encoding.cton +++ b/cranelift/filetests/parser/instruction_encoding.cton @@ -13,7 +13,7 @@ ebb1(v0: i32 [%x8], v1: i32): @55 v9 = iadd v8, v7 @a5 [Iret#5] return v0, v8 } -; sameln: function %foo(i32, i32) native { +; sameln: function %foo(i32, i32) system_v { ; nextln: ebb1(v0: i32 [%x8], v1: i32): ; nextln: [-,-]$WS v2 = iadd v0, v1 ; nextln: [-]$WS trap heap_oob diff --git a/cranelift/filetests/parser/keywords.cton b/cranelift/filetests/parser/keywords.cton index a4b894574e..aaf8403c0a 100644 --- a/cranelift/filetests/parser/keywords.cton +++ b/cranelift/filetests/parser/keywords.cton @@ -2,4 +2,4 @@ test cat ; 'function' is not a keyword, and can be used as the name of a function too. function %function() {} -; check: function %function() native +; check: function %function() system_v diff --git a/cranelift/filetests/parser/rewrite.cton b/cranelift/filetests/parser/rewrite.cton index a62157082a..679f00d2bc 100644 --- a/cranelift/filetests/parser/rewrite.cton +++ b/cranelift/filetests/parser/rewrite.cton @@ -9,7 +9,7 @@ ebb100(v20: i32): v9200 = f64const 0x4.0p0 trap user4 } -; sameln: function %defs() native { +; sameln: function %defs() system_v { ; nextln: ebb100(v20: i32): ; nextln: v1000 = iconst.i32x8 5 ; nextln: v9200 = f64const 0x1.0000000000000p2 @@ -23,7 +23,7 @@ ebb100(v20: i32): v200 = iadd v20, v1000 jump ebb100(v1000) } -; sameln: function %use_value() native { +; sameln: function %use_value() system_v { ; nextln: ebb100(v20: i32): ; nextln: v1000 = iadd_imm v20, 5 ; nextln: v200 = iadd v20, v1000 diff --git a/cranelift/filetests/parser/tiny.cton b/cranelift/filetests/parser/tiny.cton index 0c619565a0..e800d44c26 100644 --- a/cranelift/filetests/parser/tiny.cton +++ b/cranelift/filetests/parser/tiny.cton @@ -5,7 +5,7 @@ function %minimal() { ebb0: trap user0 } -; sameln: function %minimal() native { +; sameln: function %minimal() system_v { ; nextln: ebb0: ; nextln: trap user0 ; nextln: } @@ -18,7 +18,7 @@ ebb0: v1 = iconst.i8 6 v2 = ishl v0, v1 } -; sameln: function %ivalues() native { +; sameln: function %ivalues() system_v { ; nextln: ebb0: ; nextln: v0 = iconst.i32 2 ; nextln: v1 = iconst.i8 6 @@ -34,7 +34,7 @@ ebb0: v2 = bextend.b32 v1 v3 = bxor v0, v2 } -; sameln: function %bvalues() native { +; sameln: function %bvalues() system_v { ; nextln: ebb0: ; nextln: v0 = bconst.b32 true ; nextln: v1 = bconst.b8 false @@ -47,17 +47,17 @@ function %select() { ebb0(v90: i32, v91: i32, v92: b1): v0 = select v92, v90, v91 } -; sameln: function %select() native { +; sameln: function %select() system_v { ; nextln: ebb0(v90: i32, v91: i32, v92: b1): ; nextln: v0 = select v92, v90, v91 ; nextln: } ; Polymorphic instruction controlled by third operand. -function %selectif() native { +function %selectif() system_v { ebb0(v95: i32, v96: i32, v97: b1): v98 = selectif.i32 eq v97, v95, v96 } -; sameln: function %selectif() native { +; sameln: function %selectif() system_v { ; nextln: ebb0(v95: i32, v96: i32, v97: b1): ; nextln: v98 = selectif.i32 eq v97, v95, v96 ; nextln: } @@ -69,7 +69,7 @@ ebb0: v1 = extractlane v0, 3 v2 = insertlane v0, 1, v1 } -; sameln: function %lanes() native { +; sameln: function %lanes() system_v { ; nextln: ebb0: ; nextln: v0 = iconst.i32x4 2 ; nextln: v1 = extractlane v0, 3 @@ -85,7 +85,7 @@ ebb0(v90: i32, v91: i32): v3 = irsub_imm v91, 45 br_icmp eq v90, v91, ebb0(v91, v90) } -; sameln: function %icmp(i32, i32) native { +; sameln: function %icmp(i32, i32) system_v { ; nextln: ebb0(v90: i32, v91: i32): ; nextln: v0 = icmp eq v90, v91 ; nextln: v1 = icmp ult v90, v91 @@ -101,7 +101,7 @@ ebb0(v90: f32, v91: f32): v1 = fcmp uno v90, v91 v2 = fcmp lt v90, v91 } -; sameln: function %fcmp(f32, f32) native { +; sameln: function %fcmp(f32, f32) system_v { ; nextln: ebb0(v90: f32, v91: f32): ; nextln: v0 = fcmp eq v90, v91 ; nextln: v1 = fcmp uno v90, v91 @@ -115,7 +115,7 @@ ebb0(v90: i32, v91: f32): v0 = bitcast.i8x4 v90 v1 = bitcast.i32 v91 } -; sameln: function %bitcast(i32, f32) native { +; sameln: function %bitcast(i32, f32) system_v { ; nextln: ebb0(v90: i32, v91: f32): ; nextln: v0 = bitcast.i8x4 v90 ; nextln: v1 = bitcast.i32 v91 @@ -135,7 +135,7 @@ ebb0: stack_store v1, ss10+2 stack_store v2, ss2 } -; sameln: function %stack() native { +; sameln: function %stack() system_v { ; check: ss2 = explicit_slot 4 ; check: ss3 = incoming_arg 4, offset 8 ; check: ss4 = outgoing_arg 4 @@ -162,7 +162,7 @@ ebb0(v1: i32): store aligned v3, v1+12 store notrap aligned v3, v1-12 } -; sameln: function %memory(i32) native { +; sameln: function %memory(i32) system_v { ; nextln: ebb0(v1: i32): ; nextln: v2 = load.i64 v1 ; nextln: v3 = load.i64 aligned v1 @@ -187,7 +187,7 @@ ebb0(v1: i32): regfill v1, ss0 -> %10 return } -; sameln: function %diversion(i32) native { +; sameln: function %diversion(i32) system_v { ; nextln: ss0 = spill_slot 4 ; check: ebb0(v1: i32): ; nextln: regmove v1, %10 -> %20 @@ -204,7 +204,7 @@ ebb0: copy_special %20 -> %10 return } -; sameln: function %copy_special() native { +; sameln: function %copy_special() system_v { ; nextln: ebb0: ; nextln: copy_special %10 -> %20 ; nextln: copy_special %20 -> %10 diff --git a/cranelift/filetests/regalloc/coalesce.cton b/cranelift/filetests/regalloc/coalesce.cton index b2700b01dd..04782fc1fc 100644 --- a/cranelift/filetests/regalloc/coalesce.cton +++ b/cranelift/filetests/regalloc/coalesce.cton @@ -109,7 +109,7 @@ ebb1(v10: i32): return v11 } -function %gvn_unremovable_phi(i32) native { +function %gvn_unremovable_phi(i32) system_v { ebb0(v0: i32): v2 = iconst.i32 0 jump ebb2(v2, v0) diff --git a/cranelift/filetests/regalloc/coalescing-207.cton b/cranelift/filetests/regalloc/coalescing-207.cton index 8641c87354..c4d348e10b 100644 --- a/cranelift/filetests/regalloc/coalescing-207.cton +++ b/cranelift/filetests/regalloc/coalescing-207.cton @@ -5,12 +5,12 @@ isa intel haswell ; Reported as https://github.com/Cretonne/cretonne/issues/207 ; ; The coalescer creates a virtual register with two interfering values. -function %pr207(i64 vmctx, i32, i32) -> i32 native { +function %pr207(i64 vmctx, i32, i32) -> i32 system_v { gv0 = vmctx-8 heap0 = static gv0, min 0, bound 0x5000, guard 0x0040_0000 - sig0 = (i64 vmctx, i32, i32) -> i32 native - sig1 = (i64 vmctx, i32, i32, i32) -> i32 native - sig2 = (i64 vmctx, i32, i32, i32) -> i32 native + sig0 = (i64 vmctx, i32, i32) -> i32 system_v + sig1 = (i64 vmctx, i32, i32, i32) -> i32 system_v + sig2 = (i64 vmctx, i32, i32, i32) -> i32 system_v fn0 = sig0 u0:2 fn1 = sig1 u0:0 fn2 = sig2 u0:1 @@ -1034,10 +1034,10 @@ ebb92(v767: i32): } ; Same problem from musl.wasm. -function %musl(f64 [%xmm0], i64 vmctx [%rdi]) -> f64 [%xmm0] native { +function %musl(f64 [%xmm0], i64 vmctx [%rdi]) -> f64 [%xmm0] system_v { gv0 = vmctx heap0 = static gv0, min 0, bound 0x0001_0000_0000, guard 0x8000_0000 - sig0 = (f64 [%xmm0], i32 [%rdi], i64 vmctx [%rsi]) -> f64 [%xmm0] native + sig0 = (f64 [%xmm0], i32 [%rdi], i64 vmctx [%rsi]) -> f64 [%xmm0] system_v fn0 = sig0 u0:517 ebb0(v0: f64, v1: i64): diff --git a/cranelift/filetests/regalloc/coalescing-216.cton b/cranelift/filetests/regalloc/coalescing-216.cton index de44d53d5b..a6cf7b3b42 100644 --- a/cranelift/filetests/regalloc/coalescing-216.cton +++ b/cranelift/filetests/regalloc/coalescing-216.cton @@ -5,7 +5,7 @@ isa intel haswell ; Reported as https://github.com/Cretonne/cretonne/issues/216 from the Binaryen fuzzer. ; ; The (old) coalescer creates a virtual register with two identical values. -function %pr216(i32 [%rdi], i64 vmctx [%rsi]) -> i64 [%rax] native { +function %pr216(i32 [%rdi], i64 vmctx [%rsi]) -> i64 [%rax] system_v { ebb0(v0: i32, v1: i64): v3 = iconst.i64 0 v5 = iconst.i32 0 diff --git a/cranelift/filetests/regalloc/coloring-227.cton b/cranelift/filetests/regalloc/coloring-227.cton index 7e2dac2e50..accfb3528b 100644 --- a/cranelift/filetests/regalloc/coloring-227.cton +++ b/cranelift/filetests/regalloc/coloring-227.cton @@ -2,7 +2,7 @@ test regalloc set is_64bit isa intel haswell -function %pr227(i32 [%rdi], i32 [%rsi], i32 [%rdx], i32 [%rcx], i64 vmctx [%r8]) native { +function %pr227(i32 [%rdi], i32 [%rsi], i32 [%rdx], i32 [%rcx], i64 vmctx [%r8]) system_v { gv0 = vmctx heap0 = static gv0, min 0, bound 0x0001_0000_0000, guard 0x8000_0000 diff --git a/cranelift/filetests/regalloc/ghost-param.cton b/cranelift/filetests/regalloc/ghost-param.cton index 8b0ba6c2ab..c4ce229360 100644 --- a/cranelift/filetests/regalloc/ghost-param.cton +++ b/cranelift/filetests/regalloc/ghost-param.cton @@ -9,7 +9,7 @@ isa intel haswell ; ; Test case by binaryen fuzzer! -function %pr215(i64 vmctx [%rdi]) native { +function %pr215(i64 vmctx [%rdi]) system_v { ebb0(v0: i64): v10 = iconst.i64 0 v1 = bitcast.f64 v10 diff --git a/cranelift/filetests/regalloc/global-fixed.cton b/cranelift/filetests/regalloc/global-fixed.cton index a332311b6e..14b9d8fecc 100644 --- a/cranelift/filetests/regalloc/global-fixed.cton +++ b/cranelift/filetests/regalloc/global-fixed.cton @@ -2,7 +2,7 @@ test regalloc set is_64bit=1 isa intel haswell -function %foo() native { +function %foo() system_v { ebb4: v3 = iconst.i32 0 jump ebb3 diff --git a/cranelift/filetests/regalloc/intel-regres.cton b/cranelift/filetests/regalloc/intel-regres.cton index 50384d6349..0f76e8f2d0 100644 --- a/cranelift/filetests/regalloc/intel-regres.cton +++ b/cranelift/filetests/regalloc/intel-regres.cton @@ -11,7 +11,7 @@ isa intel ; This ended up confusong the constraint solver which had not made a record of ; the fixed register assignment for v9 since it was already in the correct ; register. -function %pr147(i32) -> i32 native { +function %pr147(i32) -> i32 system_v { ebb0(v0: i32): v1 = iconst.i32 0 v2 = iconst.i32 1 diff --git a/cranelift/filetests/regalloc/output-interference.cton b/cranelift/filetests/regalloc/output-interference.cton index 666c13c0d7..4a5b90c856 100644 --- a/cranelift/filetests/regalloc/output-interference.cton +++ b/cranelift/filetests/regalloc/output-interference.cton @@ -2,7 +2,7 @@ test regalloc set is_64bit=1 isa intel haswell -function %test(i64) -> i64 native { +function %test(i64) -> i64 system_v { ebb0(v0: i64): v2 = iconst.i64 12 ; This division clobbers two of its fixed input registers on Intel. diff --git a/cranelift/filetests/regalloc/reload-208.cton b/cranelift/filetests/regalloc/reload-208.cton index 1897a03c5d..70dc1c4523 100644 --- a/cranelift/filetests/regalloc/reload-208.cton +++ b/cranelift/filetests/regalloc/reload-208.cton @@ -11,11 +11,11 @@ isa intel haswell ; ; The problem was the reload pass rewriting EBB arguments on "brnz v9, ebb3(v9)" -function %pr208(i64 vmctx [%rdi]) native { +function %pr208(i64 vmctx [%rdi]) system_v { gv0 = vmctx-8 heap0 = static gv0, min 0, bound 0x5000, guard 0x0040_0000 - sig0 = (i64 vmctx [%rdi]) -> i32 [%rax] native - sig1 = (i64 vmctx [%rdi], i32 [%rsi]) native + sig0 = (i64 vmctx [%rdi]) -> i32 [%rax] system_v + sig1 = (i64 vmctx [%rdi], i32 [%rsi]) system_v fn0 = sig0 u0:1 fn1 = sig1 u0:3 diff --git a/cranelift/filetests/regalloc/reload.cton b/cranelift/filetests/regalloc/reload.cton index 68a6e8a149..5e62db3213 100644 --- a/cranelift/filetests/regalloc/reload.cton +++ b/cranelift/filetests/regalloc/reload.cton @@ -5,7 +5,7 @@ isa riscv enable_e ; Check that we can handle a function return value that got spilled. function %spill_return() -> i32 { - fn0 = function %foo() -> i32 native + fn0 = function %foo() -> i32 system_v ebb0: v0 = call fn0() diff --git a/cranelift/filetests/regalloc/schedule-moves.cton b/cranelift/filetests/regalloc/schedule-moves.cton index e3bae45be3..6ba78db893 100644 --- a/cranelift/filetests/regalloc/schedule-moves.cton +++ b/cranelift/filetests/regalloc/schedule-moves.cton @@ -1,7 +1,7 @@ test regalloc isa intel haswell -function %pr165() native { +function %pr165() system_v { ebb0: v0 = iconst.i32 0x0102_0304 v1 = iconst.i32 0x1102_0304 @@ -19,7 +19,7 @@ ebb0: ; Same as above, but use so many registers that spilling is required. ; Note: This is also a candidate for using xchg instructions. -function %emergency_spill() native { +function %emergency_spill() system_v { ebb0: v0 = iconst.i32 0x0102_0304 v1 = iconst.i32 0x1102_0304 diff --git a/cranelift/filetests/regalloc/spill-noregs.cton b/cranelift/filetests/regalloc/spill-noregs.cton index de4fa618bf..733606b828 100644 --- a/cranelift/filetests/regalloc/spill-noregs.cton +++ b/cranelift/filetests/regalloc/spill-noregs.cton @@ -13,7 +13,7 @@ isa intel ; ; The spiller was not releasing register pressure for dead EBB parameters. -function %pr223(i32 [%rdi], i64 vmctx [%rsi]) -> i64 [%rax] native { +function %pr223(i32 [%rdi], i64 vmctx [%rsi]) -> i64 [%rax] system_v { ebb0(v0: i32, v1: i64): v2 = iconst.i32 0 v3 = iconst.i64 0 diff --git a/cranelift/filetests/regalloc/spill.cton b/cranelift/filetests/regalloc/spill.cton index 8d18baa525..fb822e1a6f 100644 --- a/cranelift/filetests/regalloc/spill.cton +++ b/cranelift/filetests/regalloc/spill.cton @@ -93,7 +93,7 @@ ebb0(v0: i32): ; The same value used as indirect callee and argument. function %doubleuse_icall1(i32) { - sig0 = (i32) native + sig0 = (i32) system_v ebb0(v0: i32): ; not:copy call_indirect sig0, v0(v0) @@ -102,7 +102,7 @@ ebb0(v0: i32): ; The same value used as indirect callee and two arguments. function %doubleuse_icall2(i32) { - sig0 = (i32, i32) native + sig0 = (i32, i32) system_v ebb0(v0: i32): ; check: $(c=$V) = copy v0 call_indirect sig0, v0(v0, v0) diff --git a/cranelift/filetests/verifier/defs_dominates_uses.cton b/cranelift/filetests/verifier/defs_dominates_uses.cton index 1bc3819726..ba3dc98eb4 100644 --- a/cranelift/filetests/verifier/defs_dominates_uses.cton +++ b/cranelift/filetests/verifier/defs_dominates_uses.cton @@ -2,14 +2,14 @@ test verifier ; Test verification that uses properly dominate defs. -function %non_dominating(i32) -> i32 native { +function %non_dominating(i32) -> i32 system_v { ebb0(v0: i32): v1 = iadd.i32 v2, v0 ; error: uses value from non-dominating v2 = iadd.i32 v1, v0 return v2 } -function %inst_uses_its_own_values(i32) -> i32 native { +function %inst_uses_its_own_values(i32) -> i32 system_v { ebb0(v0: i32): v1 = iadd.i32 v1, v0 ; error: uses value from itself return v1 diff --git a/lib/cretonne/src/ir/extfunc.rs b/lib/cretonne/src/ir/extfunc.rs index f8fe767970..08fa28cf5c 100644 --- a/lib/cretonne/src/ir/extfunc.rs +++ b/lib/cretonne/src/ir/extfunc.rs @@ -343,10 +343,11 @@ impl fmt::Display for ExtFuncData { /// determined by a `(TargetIsa, CallConv)` tuple. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum CallConv { - /// The C calling convention. + /// The System V-style calling convention. /// - /// This is the native calling convention that a C compiler would use on the platform. - Native, + /// This is the System V-style calling convention that a C compiler would + /// use on many platforms. + SystemV, /// A JIT-compiled WebAssembly function in the SpiderMonkey VM. SpiderWASM, @@ -356,7 +357,7 @@ impl fmt::Display for CallConv { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::CallConv::*; f.write_str(match *self { - Native => "native", + SystemV => "system_v", SpiderWASM => "spiderwasm", }) } @@ -368,7 +369,7 @@ impl FromStr for CallConv { fn from_str(s: &str) -> Result { use self::CallConv::*; match s { - "native" => Ok(Native), + "system_v" => Ok(SystemV), "spiderwasm" => Ok(SpiderWASM), _ => Err(()), } @@ -410,7 +411,7 @@ mod tests { #[test] fn call_conv() { - for &cc in &[CallConv::Native, CallConv::SpiderWASM] { + for &cc in &[CallConv::SystemV, CallConv::SpiderWASM] { assert_eq!(Ok(cc), cc.to_string().parse()) } } diff --git a/lib/cretonne/src/ir/function.rs b/lib/cretonne/src/ir/function.rs index e52bb4c96f..d122e73360 100644 --- a/lib/cretonne/src/ir/function.rs +++ b/lib/cretonne/src/ir/function.rs @@ -86,7 +86,7 @@ impl Function { /// Clear all data structures in this function. pub fn clear(&mut self) { - self.signature.clear(ir::CallConv::Native); + self.signature.clear(ir::CallConv::SystemV); self.stack_slots.clear(); self.global_vars.clear(); self.heaps.clear(); @@ -99,9 +99,9 @@ impl Function { self.srclocs.clear(); } - /// Create a new empty, anonymous function with a native calling convention. + /// Create a new empty, anonymous function with a SystemV calling convention. pub fn new() -> Self { - Self::with_name_signature(ExternalName::default(), Signature::new(CallConv::Native)) + Self::with_name_signature(ExternalName::default(), Signature::new(CallConv::SystemV)) } /// Creates a jump table in the function, to be used by `br_table` instructions. diff --git a/lib/cretonne/src/isa/intel/abi.rs b/lib/cretonne/src/isa/intel/abi.rs index 0a14566b50..e2c79e0377 100644 --- a/lib/cretonne/src/isa/intel/abi.rs +++ b/lib/cretonne/src/isa/intel/abi.rs @@ -171,7 +171,7 @@ pub fn callee_saved_registers(flags: &shared_settings::Flags) -> &'static [RU] { pub fn prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> result::CtonResult { match func.signature.call_conv { - ir::CallConv::Native => native_prologue_epilogue(func, isa), + ir::CallConv::SystemV => system_v_prologue_epilogue(func, isa), ir::CallConv::SpiderWASM => spiderwasm_prologue_epilogue(func, isa), } } @@ -194,7 +194,7 @@ pub fn spiderwasm_prologue_epilogue( } /// Insert a System V-compatible prologue and epilogue. -pub fn native_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> result::CtonResult { +pub fn system_v_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> result::CtonResult { // The original 32-bit x86 ELF ABI had a 4-byte aligned stack pointer, but // newer versions use a 16-byte aligned stack pointer. let stack_align = 16; @@ -242,17 +242,17 @@ pub fn native_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> res // Set up the cursor and insert the prologue let entry_ebb = func.layout.entry_block().expect("missing entry block"); let mut pos = EncCursor::new(func, isa).at_first_insertion_point(entry_ebb); - insert_native_prologue(&mut pos, local_stack_size, csr_type, csrs); + insert_system_v_prologue(&mut pos, local_stack_size, csr_type, csrs); // Reset the cursor and insert the epilogue let mut pos = pos.at_position(CursorPosition::Nowhere); - insert_native_epilogues(&mut pos, local_stack_size, csr_type, csrs); + insert_system_v_epilogues(&mut pos, local_stack_size, csr_type, csrs); Ok(()) } /// Insert the prologue for a given function. -fn insert_native_prologue( +fn insert_system_v_prologue( pos: &mut EncCursor, stack_size: i64, csr_type: ir::types::Type, @@ -286,7 +286,7 @@ fn insert_native_prologue( } /// Find all `return` instructions and insert epilogues before them. -fn insert_native_epilogues( +fn insert_system_v_epilogues( pos: &mut EncCursor, stack_size: i64, csr_type: ir::types::Type, @@ -296,14 +296,14 @@ fn insert_native_epilogues( pos.goto_last_inst(ebb); if let Some(inst) = pos.current_inst() { if pos.func.dfg[inst].opcode().is_return() { - insert_native_epilogue(inst, stack_size, pos, csr_type, csrs); + insert_system_v_epilogue(inst, stack_size, pos, csr_type, csrs); } } } } /// Insert an epilogue given a specific `return` instruction. -fn insert_native_epilogue( +fn insert_system_v_epilogue( inst: ir::Inst, stack_size: i64, pos: &mut EncCursor, diff --git a/lib/cretonne/src/legalizer/libcall.rs b/lib/cretonne/src/legalizer/libcall.rs index 156a05b813..c4d063bd3c 100644 --- a/lib/cretonne/src/legalizer/libcall.rs +++ b/lib/cretonne/src/legalizer/libcall.rs @@ -44,8 +44,8 @@ fn find_funcref(libcall: ir::LibCall, func: &ir::Function) -> Option ir::FuncRef { - // Start with a native calling convention. We'll give the ISA a chance to change it. - let mut sig = ir::Signature::new(ir::CallConv::Native); + // Start with a system_v calling convention. We'll give the ISA a chance to change it. + let mut sig = ir::Signature::new(ir::CallConv::SystemV); for &v in func.dfg.inst_args(inst) { sig.params.push(ir::AbiParam::new(func.dfg.value_type(v))); } diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index 1081a87d77..f6e7d90ff2 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -465,34 +465,34 @@ mod tests { #[test] fn basic() { let mut f = Function::new(); - assert_eq!(f.to_string(), "function u0:0() native {\n}\n"); + assert_eq!(f.to_string(), "function u0:0() system_v {\n}\n"); f.name = ExternalName::testcase("foo"); - assert_eq!(f.to_string(), "function %foo() native {\n}\n"); + assert_eq!(f.to_string(), "function %foo() system_v {\n}\n"); f.create_stack_slot(StackSlotData::new(StackSlotKind::ExplicitSlot, 4)); assert_eq!( f.to_string(), - "function %foo() native {\n ss0 = explicit_slot 4\n}\n" + "function %foo() system_v {\n ss0 = explicit_slot 4\n}\n" ); let ebb = f.dfg.make_ebb(); f.layout.append_ebb(ebb); assert_eq!( f.to_string(), - "function %foo() native {\n ss0 = explicit_slot 4\n\nebb0:\n}\n" + "function %foo() system_v {\n ss0 = explicit_slot 4\n\nebb0:\n}\n" ); f.dfg.append_ebb_param(ebb, types::I8); assert_eq!( f.to_string(), - "function %foo() native {\n ss0 = explicit_slot 4\n\nebb0(v0: i8):\n}\n" + "function %foo() system_v {\n ss0 = explicit_slot 4\n\nebb0(v0: i8):\n}\n" ); f.dfg.append_ebb_param(ebb, types::F32.by(4).unwrap()); assert_eq!( f.to_string(), - "function %foo() native {\n ss0 = explicit_slot 4\n\nebb0(v0: i8, v1: f32x4):\n}\n" + "function %foo() system_v {\n ss0 = explicit_slot 4\n\nebb0(v0: i8, v1: f32x4):\n}\n" ); } } diff --git a/lib/frontend/src/frontend.rs b/lib/frontend/src/frontend.rs index 2706846124..bd01ce1893 100644 --- a/lib/frontend/src/frontend.rs +++ b/lib/frontend/src/frontend.rs @@ -600,7 +600,7 @@ mod tests { use Variable; fn sample_function(lazy_seal: bool) { - let mut sig = Signature::new(CallConv::Native); + let mut sig = Signature::new(CallConv::SystemV); sig.returns.push(AbiParam::new(I32)); sig.params.push(AbiParam::new(I32)); diff --git a/lib/frontend/src/lib.rs b/lib/frontend/src/lib.rs index c7defce3bb..628195428a 100644 --- a/lib/frontend/src/lib.rs +++ b/lib/frontend/src/lib.rs @@ -43,7 +43,7 @@ //! use cretonne::verifier::verify_function; //! //! fn main() { -//! let mut sig = Signature::new(CallConv::Native); +//! let mut sig = Signature::new(CallConv::SystemV); //! sig.returns.push(AbiParam::new(I32)); //! sig.params.push(AbiParam::new(I32)); //! let mut fn_builder_ctx = FunctionBuilderContext::::new(); diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index f0fa723594..c9da49d9ee 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -187,7 +187,7 @@ impl<'a> Context<'a> { fn add_sig(&mut self, sig: SigRef, data: Signature, loc: &Location) -> Result<()> { while self.function.dfg.signatures.next_key().index() <= sig.index() { self.function.import_signature( - Signature::new(CallConv::Native), + Signature::new(CallConv::SystemV), ); } self.function.dfg.signatures[sig] = data; @@ -871,8 +871,8 @@ impl<'a> Parser<'a> { // signature ::= * "(" [paramlist] ")" ["->" retlist] [callconv] // fn parse_signature(&mut self, unique_isa: Option<&TargetIsa>) -> Result { - // Calling convention defaults to `native`, but can be changed. - let mut sig = Signature::new(CallConv::Native); + // Calling convention defaults to `system_v`, but can be changed. + let mut sig = Signature::new(CallConv::SystemV); self.match_token( Token::LPar, @@ -2429,7 +2429,7 @@ mod tests { #[test] fn aliases() { let (func, details) = Parser::new( - "function %qux() native { + "function %qux() system_v { ebb0: v4 = iconst.i8 6 v3 -> v4 @@ -2453,10 +2453,10 @@ mod tests { #[test] fn signature() { - let sig = Parser::new("()native").parse_signature(None).unwrap(); + let sig = Parser::new("()system_v").parse_signature(None).unwrap(); assert_eq!(sig.params.len(), 0); assert_eq!(sig.returns.len(), 0); - assert_eq!(sig.call_conv, CallConv::Native); + assert_eq!(sig.call_conv, CallConv::SystemV); let sig2 = Parser::new("(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 spiderwasm") .parse_signature(None) @@ -2470,7 +2470,7 @@ mod tests { // Old-style signature without a calling convention. assert_eq!( Parser::new("()").parse_signature(None).unwrap().to_string(), - "() native" + "() system_v" ); assert_eq!( Parser::new("() notacc") @@ -2507,7 +2507,7 @@ mod tests { #[test] fn stack_slot_decl() { let (func, _) = Parser::new( - "function %foo() native { + "function %foo() system_v { ss3 = incoming_arg 13 ss1 = spill_slot 1 }", @@ -2530,7 +2530,7 @@ mod tests { // Catch duplicate definitions. assert_eq!( Parser::new( - "function %bar() native { + "function %bar() system_v { ss1 = spill_slot 13 ss1 = spill_slot 1 }", @@ -2544,7 +2544,7 @@ mod tests { #[test] fn ebb_header() { let (func, _) = Parser::new( - "function %ebbs() native { + "function %ebbs() system_v { ebb0: ebb4(v3: i32): }", @@ -2567,7 +2567,7 @@ mod tests { fn comments() { let (func, Details { comments, .. }) = Parser::new( "; before - function %comment() native { ; decl + function %comment() system_v { ; decl ss10 = outgoing_arg 13 ; stackslot. ; Still stackslot. jt10 = jump_table ebb0 @@ -2610,7 +2610,7 @@ mod tests { test verify set enable_float=false ; still preamble - function %comment() native {}", + function %comment() system_v {}", ).unwrap(); assert_eq!(tf.commands.len(), 2); assert_eq!(tf.commands[0].command, "cfg"); @@ -2635,7 +2635,7 @@ mod tests { assert!( parse_test( "isa - function %foo() native {}", + function %foo() system_v {}", ).is_err() ); @@ -2643,14 +2643,14 @@ mod tests { parse_test( "isa riscv set enable_float=false - function %foo() native {}", + function %foo() system_v {}", ).is_err() ); match parse_test( "set enable_float=false isa riscv - function %foo() native {}", + function %foo() system_v {}", ).unwrap() .isa_spec { IsaSpec::None(_) => panic!("Expected some ISA"), @@ -2665,7 +2665,7 @@ mod tests { fn user_function_name() { // Valid characters in the name: let func = Parser::new( - "function u1:2() native { + "function u1:2() system_v { ebb0: trap int_divz }", @@ -2676,7 +2676,7 @@ mod tests { // Invalid characters in the name: let mut parser = Parser::new( - "function u123:abc() native { + "function u123:abc() system_v { ebb0: trap stk_ovf }", @@ -2685,7 +2685,7 @@ mod tests { // Incomplete function names should not be valid: let mut parser = Parser::new( - "function u() native { + "function u() system_v { ebb0: trap int_ovf }", @@ -2693,7 +2693,7 @@ mod tests { assert!(parser.parse_function(None).is_err()); let mut parser = Parser::new( - "function u0() native { + "function u0() system_v { ebb0: trap int_ovf }", @@ -2701,7 +2701,7 @@ mod tests { assert!(parser.parse_function(None).is_err()); let mut parser = Parser::new( - "function u0:() native { + "function u0:() system_v { ebb0: trap int_ovf }", diff --git a/lib/wasm/src/sections_translator.rs b/lib/wasm/src/sections_translator.rs index 1bf7c9441c..05f655ba82 100644 --- a/lib/wasm/src/sections_translator.rs +++ b/lib/wasm/src/sections_translator.rs @@ -36,7 +36,7 @@ pub fn parse_function_signatures( ref params, ref returns, }) => { - let mut sig = Signature::new(CallConv::Native); + let mut sig = Signature::new(CallConv::SystemV); sig.params.extend(params.iter().map(|ty| { let cret_arg: cretonne::ir::Type = type_to_type(ty).expect( "only numeric types are supported in function signatures", From 72b7a4b3efdfcf2cf87286347847447418bea80e Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 30 Mar 2018 11:33:44 -0700 Subject: [PATCH 68/72] Add `iter()` and `values()` functions to `PrimaryMap` and `EntityMap`. `iter()` iterates over both keys and values, while `values()` iterates over just values. Also add `_mut()` versions. These replace the otherwise common idiom of iterating with `keys()` and using indexing to get the values, allowing for simpler code. --- lib/cretonne/src/entity/iter.rs | 109 +++++++++++++++++++++++++ lib/cretonne/src/entity/map.rs | 23 +++++- lib/cretonne/src/entity/mod.rs | 2 + lib/cretonne/src/entity/primary.rs | 100 +++++++++++++++++++++-- lib/cretonne/src/ir/stackslot.rs | 23 +++++- lib/cretonne/src/legalizer/boundary.rs | 6 +- lib/cretonne/src/legalizer/libcall.rs | 4 +- lib/cretonne/src/stack_layout.rs | 10 +-- lib/cretonne/src/write.rs | 28 +++---- lib/filetests/src/test_binemit.rs | 4 +- lib/frontend/src/frontend.rs | 8 +- 11 files changed, 274 insertions(+), 43 deletions(-) create mode 100644 lib/cretonne/src/entity/iter.rs diff --git a/lib/cretonne/src/entity/iter.rs b/lib/cretonne/src/entity/iter.rs new file mode 100644 index 0000000000..156021ee86 --- /dev/null +++ b/lib/cretonne/src/entity/iter.rs @@ -0,0 +1,109 @@ +//! A double-ended iterator over entity references and entities. + +use entity::EntityRef; +use std::marker::PhantomData; +use std::slice; + +/// Iterate over all keys in order. +pub struct Iter<'a, K: EntityRef, V> +where + V: 'a, +{ + pos: usize, + iter: slice::Iter<'a, V>, + unused: PhantomData, +} + +impl<'a, K: EntityRef, V> Iter<'a, K, V> { + /// Create an `Iter` iterator that visits the `PrimaryMap` keys and values + /// of `iter`. + pub fn new(key: K, iter: slice::Iter<'a, V>) -> Self { + Self { + pos: key.index(), + iter, + unused: PhantomData, + } + } +} + +impl<'a, K: EntityRef, V> Iterator for Iter<'a, K, V> { + type Item = (K, &'a V); + + fn next(&mut self) -> Option { + if let Some(next) = self.iter.next() { + let pos = self.pos; + self.pos += 1; + Some((K::new(pos), next)) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl<'a, K: EntityRef, V> DoubleEndedIterator for Iter<'a, K, V> { + fn next_back(&mut self) -> Option { + if let Some(next_back) = self.iter.next_back() { + Some((K::new(self.pos), next_back)) + } else { + None + } + } +} + +impl<'a, K: EntityRef, V> ExactSizeIterator for Iter<'a, K, V> {} + +/// Iterate over all keys in order. +pub struct IterMut<'a, K: EntityRef, V> +where + V: 'a, +{ + pos: usize, + iter: slice::IterMut<'a, V>, + unused: PhantomData, +} + +impl<'a, K: EntityRef, V> IterMut<'a, K, V> { + /// Create an `IterMut` iterator that visits the `PrimaryMap` keys and values + /// of `iter`. + pub fn new(key: K, iter: slice::IterMut<'a, V>) -> Self { + Self { + pos: key.index(), + iter, + unused: PhantomData, + } + } +} + +impl<'a, K: EntityRef, V> Iterator for IterMut<'a, K, V> { + type Item = (K, &'a mut V); + + fn next(&mut self) -> Option { + if let Some(next) = self.iter.next() { + let pos = self.pos; + self.pos += 1; + Some((K::new(pos), next)) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl<'a, K: EntityRef, V> DoubleEndedIterator for IterMut<'a, K, V> { + fn next_back(&mut self) -> Option { + if let Some(next_back) = self.iter.next_back() { + Some((K::new(self.pos), next_back)) + } else { + None + } + } +} + +impl<'a, K: EntityRef, V> ExactSizeIterator for IterMut<'a, K, V> {} diff --git a/lib/cretonne/src/entity/map.rs b/lib/cretonne/src/entity/map.rs index f251c2f831..3aac22b44f 100644 --- a/lib/cretonne/src/entity/map.rs +++ b/lib/cretonne/src/entity/map.rs @@ -1,9 +1,10 @@ //! Densely numbered entity references as mapping keys. -use entity::{EntityRef, Keys}; +use entity::{EntityRef, Keys, Iter, IterMut}; use std::marker::PhantomData; use std::ops::{Index, IndexMut}; use std::vec::Vec; +use std::slice; /// A mapping `K -> V` for densely indexed entity references. /// @@ -68,11 +69,31 @@ where self.elems.clear() } + /// Iterate over all the keys and values in this map. + pub fn iter(&self) -> Iter { + Iter::new(K::new(0), self.elems.iter()) + } + + /// Iterate over all the keys and values in this map, mutable edition. + pub fn iter_mut(&mut self) -> IterMut { + IterMut::new(K::new(0), self.elems.iter_mut()) + } + /// Iterate over all the keys in this map. pub fn keys(&self) -> Keys { Keys::new(self.elems.len()) } + /// Iterate over all the keys in this map. + pub fn values(&self) -> slice::Iter { + self.elems.iter() + } + + /// Iterate over all the keys in this map, mutable edition. + pub fn values_mut(&mut self) -> slice::IterMut { + self.elems.iter_mut() + } + /// Resize the map to have `n` entries by adding default entries as needed. pub fn resize(&mut self, n: usize) { self.elems.resize(n, self.default.clone()); diff --git a/lib/cretonne/src/entity/mod.rs b/lib/cretonne/src/entity/mod.rs index 6457e47f56..c4004f126d 100644 --- a/lib/cretonne/src/entity/mod.rs +++ b/lib/cretonne/src/entity/mod.rs @@ -30,6 +30,7 @@ //! `Vec`. mod keys; +mod iter; mod list; mod map; mod primary; @@ -37,6 +38,7 @@ mod sparse; mod set; pub use self::keys::Keys; +pub use self::iter::{Iter, IterMut}; pub use self::list::{EntityList, ListPool}; pub use self::map::EntityMap; pub use self::primary::PrimaryMap; diff --git a/lib/cretonne/src/entity/primary.rs b/lib/cretonne/src/entity/primary.rs index c06b818355..8671bdf809 100644 --- a/lib/cretonne/src/entity/primary.rs +++ b/lib/cretonne/src/entity/primary.rs @@ -1,8 +1,9 @@ //! Densely numbered entity references as mapping keys. -use entity::{EntityRef, Keys}; +use entity::{EntityRef, Keys, Iter, IterMut}; use std::marker::PhantomData; use std::ops::{Index, IndexMut}; use std::vec::Vec; +use std::slice; /// A primary mapping `K -> V` allocating dense entity references. /// @@ -59,6 +60,26 @@ where Keys::new(self.elems.len()) } + /// Iterate over all the values in this map. + pub fn values(&self) -> slice::Iter { + self.elems.iter() + } + + /// Iterate over all the values in this map, mutable edition. + pub fn values_mut(&mut self) -> slice::IterMut { + self.elems.iter_mut() + } + + /// Iterate over all the keys and values in this map. + pub fn iter(&self) -> Iter { + Iter::new(K::new(0), self.elems.iter()) + } + + /// Iterate over all the keys and values in this map, mutable edition. + pub fn iter_mut(&mut self) -> IterMut { + IterMut::new(K::new(0), self.elems.iter_mut()) + } + /// Remove all entries from this map. pub fn clear(&mut self) { self.elems.clear() @@ -133,13 +154,80 @@ mod tests { #[test] fn push() { let mut m = PrimaryMap::new(); - let k1: E = m.push(12); - let k2 = m.push(33); + let k0: E = m.push(12); + let k1 = m.push(33); - assert_eq!(m[k1], 12); - assert_eq!(m[k2], 33); + assert_eq!(m[k0], 12); + assert_eq!(m[k1], 33); let v: Vec = m.keys().collect(); - assert_eq!(v, [k1, k2]); + assert_eq!(v, [k0, k1]); + } + + #[test] + fn iter() { + let mut m: PrimaryMap = PrimaryMap::new(); + m.push(12); + m.push(33); + + let mut i = 0; + for (key, value) in m.iter() { + assert_eq!(key.index(), i); + match i { + 0 => assert_eq!(*value, 12), + 1 => assert_eq!(*value, 33), + _ => panic!(), + } + i += 1; + } + i = 0; + for (key_mut, value_mut) in m.iter_mut() { + assert_eq!(key_mut.index(), i); + match i { + 0 => assert_eq!(*value_mut, 12), + 1 => assert_eq!(*value_mut, 33), + _ => panic!(), + } + i += 1; + } + } + + #[test] + fn keys() { + let mut m: PrimaryMap = PrimaryMap::new(); + m.push(12); + m.push(33); + + let mut i = 0; + for key in m.keys() { + assert_eq!(key.index(), i); + i += 1; + } + } + + #[test] + fn values() { + let mut m: PrimaryMap = PrimaryMap::new(); + m.push(12); + m.push(33); + + let mut i = 0; + for value in m.values() { + match i { + 0 => assert_eq!(*value, 12), + 1 => assert_eq!(*value, 33), + _ => panic!(), + } + i += 1; + } + i = 0; + for value_mut in m.values_mut() { + match i { + 0 => assert_eq!(*value_mut, 12), + 1 => assert_eq!(*value_mut, 33), + _ => panic!(), + } + i += 1; + } } } diff --git a/lib/cretonne/src/ir/stackslot.rs b/lib/cretonne/src/ir/stackslot.rs index 5f73fb4b37..bc87e11a82 100644 --- a/lib/cretonne/src/ir/stackslot.rs +++ b/lib/cretonne/src/ir/stackslot.rs @@ -3,11 +3,12 @@ //! The `StackSlotData` struct keeps track of a single stack slot in a function. //! -use entity::{PrimaryMap, Keys}; +use entity::{PrimaryMap, Keys, Iter, IterMut}; use ir::{Type, StackSlot}; use packed_option::PackedOption; use std::cmp; use std::fmt; +use std::slice; use std::ops::{Index, IndexMut}; use std::str::FromStr; use std::vec::Vec; @@ -208,6 +209,26 @@ impl StackSlots { self.slots[ss].offset = Some(offset); } + /// Get an iterator over all the stack slot keys. + pub fn iter(&self) -> Iter { + self.slots.iter() + } + + /// Get an iterator over all the stack slot keys, mutable edition. + pub fn iter_mut(&mut self) -> IterMut { + self.slots.iter_mut() + } + + /// Get an iterator over all the stack slot records. + pub fn values(&self) -> slice::Iter { + self.slots.values() + } + + /// Get an iterator over all the stack slot records, mutable edition. + pub fn values_mut(&mut self) -> slice::IterMut { + self.slots.values_mut() + } + /// Get an iterator over all the stack slot keys. pub fn keys(&self) -> Keys { self.slots.keys() diff --git a/lib/cretonne/src/legalizer/boundary.rs b/lib/cretonne/src/legalizer/boundary.rs index 0c5479650c..e1e4a17956 100644 --- a/lib/cretonne/src/legalizer/boundary.rs +++ b/lib/cretonne/src/legalizer/boundary.rs @@ -35,9 +35,9 @@ use std::vec::Vec; pub fn legalize_signatures(func: &mut Function, isa: &TargetIsa) { isa.legalize_signature(&mut func.signature, true); func.signature.compute_argument_bytes(); - for sig in func.dfg.signatures.keys() { - isa.legalize_signature(&mut func.dfg.signatures[sig], false); - func.dfg.signatures[sig].compute_argument_bytes(); + for sig_data in func.dfg.signatures.values_mut() { + isa.legalize_signature(sig_data, false); + sig_data.compute_argument_bytes(); } if let Some(entry) = func.layout.entry_block() { diff --git a/lib/cretonne/src/legalizer/libcall.rs b/lib/cretonne/src/legalizer/libcall.rs index c4d063bd3c..2bb0f1292c 100644 --- a/lib/cretonne/src/legalizer/libcall.rs +++ b/lib/cretonne/src/legalizer/libcall.rs @@ -29,8 +29,8 @@ pub fn expand_as_libcall(inst: ir::Inst, func: &mut ir::Function) -> bool { fn find_funcref(libcall: ir::LibCall, func: &ir::Function) -> Option { // We're assuming that all libcall function decls are at the end. // If we get this wrong, worst case we'll have duplicate libcall decls which is harmless. - for fref in func.dfg.ext_funcs.keys().rev() { - match func.dfg.ext_funcs[fref].name { + for (fref, func_data) in func.dfg.ext_funcs.iter().rev() { + match func_data.name { ir::ExternalName::LibCall(lc) => { if lc == libcall { return Some(fref); diff --git a/lib/cretonne/src/stack_layout.rs b/lib/cretonne/src/stack_layout.rs index f1cf35f150..0cf6e77527 100644 --- a/lib/cretonne/src/stack_layout.rs +++ b/lib/cretonne/src/stack_layout.rs @@ -39,9 +39,7 @@ pub fn layout_stack(frame: &mut StackSlots, alignment: StackSize) -> Result max_size { return Err(CtonError::ImplLimitExceeded); } @@ -72,9 +70,7 @@ pub fn layout_stack(frame: &mut StackSlots, alignment: StackSize) -> Result Result result::Result { let mut any = false; - for ss in func.stack_slots.keys() { + for (ss, slot) in func.stack_slots.iter() { any = true; - writeln!(w, " {} = {}", ss, func.stack_slots[ss])?; + writeln!(w, " {} = {}", ss, slot)?; } - for gv in func.global_vars.keys() { + for (gv, gv_data) in func.global_vars.iter() { any = true; - writeln!(w, " {} = {}", gv, func.global_vars[gv])?; + writeln!(w, " {} = {}", gv, gv_data)?; } - for heap in func.heaps.keys() { + for (heap, heap_data) in func.heaps.iter() { any = true; - writeln!(w, " {} = {}", heap, func.heaps[heap])?; + writeln!(w, " {} = {}", heap, heap_data)?; } // Write out all signatures before functions since function declarations can refer to // signatures. - for sig in func.dfg.signatures.keys() { + for (sig, sig_data) in func.dfg.signatures.iter() { any = true; - writeln!( - w, - " {} = {}", - sig, - func.dfg.signatures[sig].display(regs) - )?; + writeln!(w, " {} = {}", sig, sig_data.display(regs))?; } - for fnref in func.dfg.ext_funcs.keys() { + for (fnref, ext_func) in func.dfg.ext_funcs.iter() { any = true; - let ext_func = &func.dfg.ext_funcs[fnref]; if ext_func.signature != SigRef::reserved_value() { writeln!(w, " {} = {}", fnref, ext_func)?; } } - for jt in func.jump_tables.keys() { + for (jt, jt_data) in func.jump_tables.iter() { any = true; - writeln!(w, " {} = {}", jt, func.jump_tables[jt])?; + writeln!(w, " {} = {}", jt, jt_data)?; } Ok(any) diff --git a/lib/filetests/src/test_binemit.rs b/lib/filetests/src/test_binemit.rs index c22f1ed386..81e48f84fe 100644 --- a/lib/filetests/src/test_binemit.rs +++ b/lib/filetests/src/test_binemit.rs @@ -130,8 +130,8 @@ impl SubTest for TestBinEmit { // Fix the stack frame layout so we can test spill/fill encodings. let min_offset = func.stack_slots - .keys() - .map(|ss| func.stack_slots[ss].offset.unwrap()) + .values() + .map(|slot| slot.offset.unwrap()) .min(); func.stack_slots.frame_size = min_offset.map(|off| (-off) as u32); diff --git a/lib/frontend/src/frontend.rs b/lib/frontend/src/frontend.rs index bd01ce1893..37d2fe0206 100644 --- a/lib/frontend/src/frontend.rs +++ b/lib/frontend/src/frontend.rs @@ -439,14 +439,14 @@ where pub fn finalize(&mut self) { // Check that all the `Ebb`s are filled and sealed. debug_assert!( - self.func_ctx.ebbs.keys().all(|ebb| { - self.func_ctx.ebbs[ebb].pristine || self.func_ctx.ssa.is_sealed(ebb) + self.func_ctx.ebbs.iter().all(|(ebb, ebb_data)| { + ebb_data.pristine || self.func_ctx.ssa.is_sealed(ebb) }), "all blocks should be sealed before dropping a FunctionBuilder" ); debug_assert!( - self.func_ctx.ebbs.keys().all(|ebb| { - self.func_ctx.ebbs[ebb].pristine || self.func_ctx.ebbs[ebb].filled + self.func_ctx.ebbs.values().all(|ebb_data| { + ebb_data.pristine || ebb_data.filled }), "all blocks should be filled before dropping a FunctionBuilder" ); From d7c66a8ec183fc16773ca66b6a308aeb2e9828e4 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 27 Mar 2018 12:22:02 -0700 Subject: [PATCH 69/72] Don't run the DCE pass when optimization is disabled. The main purpose of the DCE pass is to clean up dead code left behind by the optimizer, so it's not valuable to run it when the optimizer isn't being run. --- lib/cretonne/src/context.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/cretonne/src/context.rs b/lib/cretonne/src/context.rs index 2441f19d02..5324248142 100644 --- a/lib/cretonne/src/context.rs +++ b/lib/cretonne/src/context.rs @@ -105,7 +105,9 @@ impl Context { } self.compute_domtree(); self.eliminate_unreachable_code(isa)?; - self.dce(isa)?; + if isa.flags().opt_level() != OptLevel::Fastest { + self.dce(isa)?; + } self.regalloc(isa)?; self.prologue_epilogue(isa)?; self.relax_branches(isa) From 8d5fecd324fb935d75013bd11b72e8bdb63a3502 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 30 Mar 2018 13:17:15 -0700 Subject: [PATCH 70/72] Format with stable rustfmt-preview, then with rustfmt-0.9 again. --- cranelift/src/compile.rs | 2 +- cranelift/src/cton-util.rs | 6 +- cranelift/src/rsfilecheck.rs | 2 +- lib/cretonne/build.rs | 1 - lib/cretonne/src/abi.rs | 2 +- lib/cretonne/src/bforest/map.rs | 2 +- lib/cretonne/src/bforest/mod.rs | 4 +- lib/cretonne/src/bforest/node.rs | 2 +- lib/cretonne/src/bforest/path.rs | 6 +- lib/cretonne/src/bforest/set.rs | 2 +- lib/cretonne/src/binemit/memorysink.rs | 4 +- lib/cretonne/src/binemit/mod.rs | 2 +- lib/cretonne/src/binemit/relaxation.rs | 2 +- lib/cretonne/src/bitset.rs | 4 +- lib/cretonne/src/cfg_printer.rs | 2 +- lib/cretonne/src/constant_hash.rs | 1 - lib/cretonne/src/context.rs | 2 +- lib/cretonne/src/cursor.rs | 1 - lib/cretonne/src/dce.rs | 2 +- lib/cretonne/src/divconst_magic_numbers.rs | 4 +- lib/cretonne/src/dominator_tree.rs | 17 ++-- lib/cretonne/src/entity/list.rs | 2 +- lib/cretonne/src/entity/map.rs | 2 +- lib/cretonne/src/entity/mod.rs | 2 +- lib/cretonne/src/entity/primary.rs | 2 +- lib/cretonne/src/entity/sparse.rs | 2 +- lib/cretonne/src/flowgraph.rs | 4 +- lib/cretonne/src/ir/builder.rs | 9 +- lib/cretonne/src/ir/dfg.rs | 12 +-- lib/cretonne/src/ir/extfunc.rs | 4 +- lib/cretonne/src/ir/function.rs | 12 +-- lib/cretonne/src/ir/immediates.rs | 3 - lib/cretonne/src/ir/instructions.rs | 20 ++-- lib/cretonne/src/ir/layout.rs | 5 +- lib/cretonne/src/ir/mod.rs | 20 ++-- lib/cretonne/src/ir/progpoint.rs | 2 +- lib/cretonne/src/ir/stackslot.rs | 4 +- lib/cretonne/src/ir/types.rs | 2 +- lib/cretonne/src/isa/arm32/abi.rs | 2 +- lib/cretonne/src/isa/arm32/binemit.rs | 2 +- lib/cretonne/src/isa/arm32/mod.rs | 4 +- lib/cretonne/src/isa/arm32/registers.rs | 2 +- lib/cretonne/src/isa/arm64/abi.rs | 2 +- lib/cretonne/src/isa/arm64/binemit.rs | 2 +- lib/cretonne/src/isa/arm64/mod.rs | 4 +- lib/cretonne/src/isa/constraints.rs | 3 +- lib/cretonne/src/isa/enc_tables.rs | 4 +- lib/cretonne/src/isa/encoding.rs | 2 +- lib/cretonne/src/isa/intel/abi.rs | 11 +-- lib/cretonne/src/isa/intel/binemit.rs | 8 +- lib/cretonne/src/isa/intel/enc_tables.rs | 6 +- lib/cretonne/src/isa/intel/mod.rs | 4 +- lib/cretonne/src/isa/mod.rs | 8 +- lib/cretonne/src/isa/riscv/abi.rs | 6 +- lib/cretonne/src/isa/riscv/binemit.rs | 4 +- lib/cretonne/src/isa/riscv/mod.rs | 6 +- lib/cretonne/src/isa/riscv/registers.rs | 2 +- lib/cretonne/src/isa/riscv/settings.rs | 12 +-- lib/cretonne/src/isa/stack.rs | 2 +- lib/cretonne/src/legalizer/boundary.rs | 4 +- lib/cretonne/src/legalizer/mod.rs | 1 - lib/cretonne/src/legalizer/split.rs | 3 +- lib/cretonne/src/lib.rs | 9 +- lib/cretonne/src/licm.rs | 3 +- lib/cretonne/src/loop_analysis.rs | 9 +- lib/cretonne/src/postopt.rs | 78 +++++++--------- lib/cretonne/src/preopt.rs | 11 +-- lib/cretonne/src/regalloc/affinity.rs | 2 +- lib/cretonne/src/regalloc/allocatable_set.rs | 2 +- lib/cretonne/src/regalloc/coalescing.rs | 5 +- lib/cretonne/src/regalloc/coloring.rs | 13 +-- lib/cretonne/src/regalloc/context.rs | 3 +- lib/cretonne/src/regalloc/diversion.rs | 4 +- .../src/regalloc/live_value_tracker.rs | 2 +- lib/cretonne/src/regalloc/liveness.rs | 7 +- lib/cretonne/src/regalloc/liverange.rs | 7 +- lib/cretonne/src/regalloc/pressure.rs | 6 +- lib/cretonne/src/regalloc/reload.rs | 6 +- lib/cretonne/src/regalloc/solver.rs | 7 +- lib/cretonne/src/regalloc/spilling.rs | 16 ++-- lib/cretonne/src/regalloc/virtregs.rs | 4 +- lib/cretonne/src/scoped_hash_map.rs | 2 +- lib/cretonne/src/settings.rs | 24 ++--- lib/cretonne/src/simple_gvn.rs | 2 +- lib/cretonne/src/stack_layout.rs | 6 +- lib/cretonne/src/timing.rs | 7 +- lib/cretonne/src/verifier/cssa.rs | 2 +- lib/cretonne/src/verifier/flags.rs | 2 +- lib/cretonne/src/verifier/liveness.rs | 2 +- lib/cretonne/src/verifier/mod.rs | 9 +- lib/cretonne/src/write.rs | 9 +- lib/filetests/src/concurrent.rs | 4 +- lib/filetests/src/runner.rs | 4 +- lib/filetests/src/runone.rs | 5 +- lib/filetests/src/subtest.rs | 4 +- lib/filetests/src/test_binemit.rs | 30 ++---- lib/filetests/src/test_cat.rs | 2 +- lib/filetests/src/test_compile.rs | 2 +- lib/filetests/src/test_dce.rs | 2 +- lib/filetests/src/test_domtree.rs | 8 +- lib/filetests/src/test_legalizer.rs | 2 +- lib/filetests/src/test_licm.rs | 2 +- lib/filetests/src/test_postopt.rs | 2 +- lib/filetests/src/test_preopt.rs | 2 +- lib/filetests/src/test_print_cfg.rs | 2 +- lib/filetests/src/test_regalloc.rs | 2 +- lib/filetests/src/test_simple_gvn.rs | 2 +- lib/filetests/src/test_verifier.rs | 2 +- lib/frontend/src/frontend.rs | 33 +++---- lib/frontend/src/lib.rs | 10 +- lib/frontend/src/ssa.rs | 7 +- lib/native/src/lib.rs | 4 +- lib/reader/src/isaspec.rs | 4 +- lib/reader/src/lexer.rs | 6 +- lib/reader/src/lib.rs | 10 +- lib/reader/src/parser.rs | 91 ++++++++----------- lib/reader/src/sourcemap.rs | 4 +- lib/wasm/src/code_translator.rs | 14 +-- lib/wasm/src/environ/dummy.rs | 4 +- lib/wasm/src/environ/mod.rs | 2 +- lib/wasm/src/environ/spec.rs | 4 +- lib/wasm/src/func_translator.rs | 6 +- lib/wasm/src/lib.rs | 20 ++-- lib/wasm/src/module_translator.rs | 10 +- lib/wasm/src/sections_translator.rs | 10 +- lib/wasm/src/state.rs | 2 +- lib/wasm/tests/wasm_testsuite.rs | 2 +- 127 files changed, 381 insertions(+), 479 deletions(-) diff --git a/cranelift/src/compile.rs b/cranelift/src/compile.rs index ccc049fa70..f2272494cf 100644 --- a/cranelift/src/compile.rs +++ b/cranelift/src/compile.rs @@ -7,7 +7,7 @@ use cretonne::settings::FlagsOrIsa; use cretonne::{binemit, ir}; use cretonne::print_errors::pretty_error; use std::path::Path; -use utils::{read_to_string, parse_sets_and_isa}; +use utils::{parse_sets_and_isa, read_to_string}; struct PrintRelocs { flag_print: bool, diff --git a/cranelift/src/cton-util.rs b/cranelift/src/cton-util.rs index 4dd9865d3d..42887640df 100644 --- a/cranelift/src/cton-util.rs +++ b/cranelift/src/cton-util.rs @@ -1,15 +1,15 @@ extern crate cretonne; +extern crate cton_filetests; extern crate cton_reader; extern crate cton_wasm; -extern crate cton_filetests; extern crate docopt; +extern crate filecheck; #[macro_use] extern crate serde_derive; -extern crate filecheck; extern crate tempdir; extern crate term; -use cretonne::{VERSION, timing}; +use cretonne::{timing, VERSION}; use docopt::Docopt; use std::io::{self, Write}; use std::process; diff --git a/cranelift/src/rsfilecheck.rs b/cranelift/src/rsfilecheck.rs index 58b9cb9e53..f71571b513 100644 --- a/cranelift/src/rsfilecheck.rs +++ b/cranelift/src/rsfilecheck.rs @@ -4,7 +4,7 @@ use CommandResult; use utils::read_to_string; -use filecheck::{CheckerBuilder, Checker, NO_VARIABLES}; +use filecheck::{Checker, CheckerBuilder, NO_VARIABLES}; use std::io::{self, Read}; pub fn run(files: &[String], verbose: bool) -> CommandResult { diff --git a/lib/cretonne/build.rs b/lib/cretonne/build.rs index 69be14de94..e13e9349a5 100644 --- a/lib/cretonne/build.rs +++ b/lib/cretonne/build.rs @@ -18,7 +18,6 @@ // The build script expects to be run from the directory where this build.rs file lives. The // current directory is used to find the sources. - use std::env; use std::process; diff --git a/lib/cretonne/src/abi.rs b/lib/cretonne/src/abi.rs index b69821e657..2ba3f7b7a1 100644 --- a/lib/cretonne/src/abi.rs +++ b/lib/cretonne/src/abi.rs @@ -3,7 +3,7 @@ //! This module provides functions and data structures that are useful for implementing the //! `TargetIsa::legalize_signature()` method. -use ir::{ArgumentLoc, AbiParam, ArgumentExtension, Type}; +use ir::{AbiParam, ArgumentExtension, ArgumentLoc, Type}; use std::cmp::Ordering; use std::vec::Vec; diff --git a/lib/cretonne/src/bforest/map.rs b/lib/cretonne/src/bforest/map.rs index edf301aa4c..23b4625555 100644 --- a/lib/cretonne/src/bforest/map.rs +++ b/lib/cretonne/src/bforest/map.rs @@ -2,7 +2,7 @@ use packed_option::PackedOption; use std::marker::PhantomData; -use super::{INNER_SIZE, Comparator, Forest, NodePool, Node, NodeData, Path}; +use super::{Comparator, Forest, Node, NodeData, NodePool, Path, INNER_SIZE}; /// Tag type defining forest types for a map. struct MapTypes(PhantomData<(K, V, C)>); diff --git a/lib/cretonne/src/bforest/mod.rs b/lib/cretonne/src/bforest/mod.rs index ff1b94cc0f..bc22cf88c0 100644 --- a/lib/cretonne/src/bforest/mod.rs +++ b/lib/cretonne/src/bforest/mod.rs @@ -22,8 +22,8 @@ mod path; mod pool; mod set; -pub use self::map::{MapForest, Map, MapCursor, MapIter}; -pub use self::set::{SetForest, Set, SetCursor, SetIter}; +pub use self::map::{Map, MapCursor, MapForest, MapIter}; +pub use self::set::{Set, SetCursor, SetForest, SetIter}; use self::node::NodeData; use self::path::Path; diff --git a/lib/cretonne/src/bforest/node.rs b/lib/cretonne/src/bforest/node.rs index d5c46f54bd..61fb6e994d 100644 --- a/lib/cretonne/src/bforest/node.rs +++ b/lib/cretonne/src/bforest/node.rs @@ -2,7 +2,7 @@ use std::borrow::{Borrow, BorrowMut}; use std::fmt; -use super::{Forest, Node, INNER_SIZE, SetValue, slice_insert, slice_shift}; +use super::{slice_insert, slice_shift, Forest, Node, SetValue, INNER_SIZE}; /// B+-tree node. /// diff --git a/lib/cretonne/src/bforest/path.rs b/lib/cretonne/src/bforest/path.rs index 34f165d86c..a2d15173a3 100644 --- a/lib/cretonne/src/bforest/path.rs +++ b/lib/cretonne/src/bforest/path.rs @@ -2,7 +2,7 @@ use std::borrow::Borrow; use std::marker::PhantomData; -use super::{Forest, Node, NodeData, NodePool, MAX_PATH, Comparator, slice_insert, slice_shift}; +use super::{slice_insert, slice_shift, Comparator, Forest, Node, NodeData, NodePool, MAX_PATH}; use super::node::Removed; #[cfg(test)] @@ -414,7 +414,6 @@ impl Path { } } - /// Given that the current leaf node is in an unhealthy (underflowed or even empty) status, /// balance it with sibling nodes. /// @@ -529,7 +528,6 @@ impl Path { // current entry[level] was one off the end of the node, it will now point at a proper // entry. debug_assert!(usize::from(self.entry[level]) < pool[self.node[level]].entries()); - } else if usize::from(self.entry[level]) >= pool[self.node[level]].entries() { // There's no right sibling at this level, so the node can't be rebalanced. // Check if we are in an off-the-end position. @@ -703,7 +701,7 @@ impl fmt::Display for Path { mod test { use std::cmp::Ordering; use super::*; - use super::super::{Forest, NodePool, NodeData}; + use super::super::{Forest, NodeData, NodePool}; struct TC(); diff --git a/lib/cretonne/src/bforest/set.rs b/lib/cretonne/src/bforest/set.rs index dd7f63ca17..374c26ad2b 100644 --- a/lib/cretonne/src/bforest/set.rs +++ b/lib/cretonne/src/bforest/set.rs @@ -2,7 +2,7 @@ use packed_option::PackedOption; use std::marker::PhantomData; -use super::{INNER_SIZE, Comparator, Forest, NodePool, Node, NodeData, Path, SetValue}; +use super::{Comparator, Forest, Node, NodeData, NodePool, Path, SetValue, INNER_SIZE}; /// Tag type defining forest types for a set. struct SetTypes(PhantomData<(K, C)>); diff --git a/lib/cretonne/src/binemit/memorysink.rs b/lib/cretonne/src/binemit/memorysink.rs index d4b07319ab..5a9fa8a298 100644 --- a/lib/cretonne/src/binemit/memorysink.rs +++ b/lib/cretonne/src/binemit/memorysink.rs @@ -14,8 +14,8 @@ //! relocations to a `RelocSink` trait object. Relocations are less frequent than the //! `CodeSink::put*` methods, so the performance impact of the virtual callbacks is less severe. -use ir::{ExternalName, JumpTable, TrapCode, SourceLoc}; -use super::{CodeSink, CodeOffset, Reloc, Addend}; +use ir::{ExternalName, JumpTable, SourceLoc, TrapCode}; +use super::{Addend, CodeOffset, CodeSink, Reloc}; use std::ptr::write_unaligned; /// A `CodeSink` that writes binary machine code directly into memory. diff --git a/lib/cretonne/src/binemit/mod.rs b/lib/cretonne/src/binemit/mod.rs index 6d2099ceba..20ff429756 100644 --- a/lib/cretonne/src/binemit/mod.rs +++ b/lib/cretonne/src/binemit/mod.rs @@ -10,7 +10,7 @@ pub use regalloc::RegDiversions; pub use self::relaxation::relax_branches; pub use self::memorysink::{MemoryCodeSink, RelocSink, TrapSink}; -use ir::{ExternalName, JumpTable, Function, Inst, TrapCode, SourceLoc}; +use ir::{ExternalName, Function, Inst, JumpTable, SourceLoc, TrapCode}; use std::fmt; /// Offset in bytes from the beginning of the function. diff --git a/lib/cretonne/src/binemit/relaxation.rs b/lib/cretonne/src/binemit/relaxation.rs index 24a78ceebd..8123c5b92f 100644 --- a/lib/cretonne/src/binemit/relaxation.rs +++ b/lib/cretonne/src/binemit/relaxation.rs @@ -30,7 +30,7 @@ use binemit::CodeOffset; use cursor::{Cursor, FuncCursor}; use ir::{Function, InstructionData, Opcode}; -use isa::{TargetIsa, EncInfo}; +use isa::{EncInfo, TargetIsa}; use iterators::IteratorExtras; use result::CtonError; diff --git a/lib/cretonne/src/bitset.rs b/lib/cretonne/src/bitset.rs index f212790be0..f0a7271957 100644 --- a/lib/cretonne/src/bitset.rs +++ b/lib/cretonne/src/bitset.rs @@ -6,8 +6,8 @@ //! If you would like to add support for larger bitsets in the future, you need to change the trait //! bound Into and the u32 in the implementation of `max_bits()`. use std::mem::size_of; -use std::ops::{Shl, BitOr, Sub, Add}; -use std::convert::{Into, From}; +use std::ops::{Add, BitOr, Shl, Sub}; +use std::convert::{From, Into}; /// A small bitset built on a single primitive integer type #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/lib/cretonne/src/cfg_printer.rs b/lib/cretonne/src/cfg_printer.rs index 736d12f0fc..46b8754e3e 100644 --- a/lib/cretonne/src/cfg_printer.rs +++ b/lib/cretonne/src/cfg_printer.rs @@ -1,6 +1,6 @@ //! The `CFGPrinter` utility. -use std::fmt::{Result, Write, Display, Formatter}; +use std::fmt::{Display, Formatter, Result, Write}; use flowgraph::ControlFlowGraph; use ir::Function; diff --git a/lib/cretonne/src/constant_hash.rs b/lib/cretonne/src/constant_hash.rs index d049d8e752..0dd2895ad3 100644 --- a/lib/cretonne/src/constant_hash.rs +++ b/lib/cretonne/src/constant_hash.rs @@ -18,7 +18,6 @@ pub trait Table { fn key(&self, idx: usize) -> Option; } - /// Look for `key` in `table`. /// /// The provided `hash` value must have been computed from `key` using the same hash function that diff --git a/lib/cretonne/src/context.rs b/lib/cretonne/src/context.rs index 5324248142..c7841f9366 100644 --- a/lib/cretonne/src/context.rs +++ b/lib/cretonne/src/context.rs @@ -9,7 +9,7 @@ //! contexts concurrently. Typically, you would have one context per compilation thread and only a //! single ISA instance. -use binemit::{CodeOffset, relax_branches, MemoryCodeSink, RelocSink, TrapSink}; +use binemit::{relax_branches, CodeOffset, MemoryCodeSink, RelocSink, TrapSink}; use dominator_tree::DominatorTree; use flowgraph::ControlFlowGraph; use ir::Function; diff --git a/lib/cretonne/src/cursor.rs b/lib/cretonne/src/cursor.rs index 42f5e1e741..082889a693 100644 --- a/lib/cretonne/src/cursor.rs +++ b/lib/cretonne/src/cursor.rs @@ -637,7 +637,6 @@ impl<'c, 'f> ir::InstInserterBase<'c> for &'c mut FuncCursor<'f> { } } - /// Encoding cursor. /// /// An `EncCursor` can be used to insert instructions that are immediately assigned an encoding. diff --git a/lib/cretonne/src/dce.rs b/lib/cretonne/src/dce.rs index 6e34bad74f..b78d260ecb 100644 --- a/lib/cretonne/src/dce.rs +++ b/lib/cretonne/src/dce.rs @@ -6,7 +6,7 @@ use cursor::{Cursor, FuncCursor}; use dominator_tree::DominatorTree; use entity::EntityRef; -use ir::{Function, Inst, Opcode, DataFlowGraph}; +use ir::{DataFlowGraph, Function, Inst, Opcode}; use ir::instructions::InstructionData; use timing; use std::vec::Vec; diff --git a/lib/cretonne/src/divconst_magic_numbers.rs b/lib/cretonne/src/divconst_magic_numbers.rs index 01b5066b28..80a59aed8b 100644 --- a/lib/cretonne/src/divconst_magic_numbers.rs +++ b/lib/cretonne/src/divconst_magic_numbers.rs @@ -220,8 +220,8 @@ pub fn magicS64(d: i64) -> MS64 { #[cfg(test)] mod tests { - use super::{magicU32, magicU64, magicS32, magicS64}; - use super::{MU32, MU64, MS32, MS64}; + use super::{magicS32, magicS64, magicU32, magicU64}; + use super::{MS32, MS64, MU32, MU64}; fn mkMU32(mulBy: u32, doAdd: bool, shiftBy: i32) -> MU32 { MU32 { diff --git a/lib/cretonne/src/dominator_tree.rs b/lib/cretonne/src/dominator_tree.rs index 57f55781a3..574697c1ba 100644 --- a/lib/cretonne/src/dominator_tree.rs +++ b/lib/cretonne/src/dominator_tree.rs @@ -1,8 +1,8 @@ //! A Dominator Tree represented as mappings of Ebbs to their immediate dominator. use entity::EntityMap; -use flowgraph::{ControlFlowGraph, BasicBlock}; -use ir::{Ebb, Inst, Value, Function, Layout, ProgramOrder, ExpandedProgramPoint}; +use flowgraph::{BasicBlock, ControlFlowGraph}; +use ir::{Ebb, ExpandedProgramPoint, Function, Inst, Layout, ProgramOrder, Value}; use ir::instructions::BranchInfo; use packed_option::PackedOption; use std::cmp; @@ -144,12 +144,12 @@ impl DominatorTree { { let (mut ebb_b, mut inst_b) = match b.into() { ExpandedProgramPoint::Ebb(ebb) => (ebb, None), - ExpandedProgramPoint::Inst(inst) => { - ( - layout.inst_ebb(inst).expect("Instruction not in layout."), - Some(inst), - ) - } + ExpandedProgramPoint::Inst(inst) => ( + layout.inst_ebb(inst).expect( + "Instruction not in layout.", + ), + Some(inst), + ), }; let rpo_a = self.nodes[a].rpo_number; @@ -460,7 +460,6 @@ impl DominatorTree { rpo_number: new_ebb_rpo, idom: Some(split_jump_inst).into(), }; - } // Insert new_ebb just after ebb in the RPO. This function checks diff --git a/lib/cretonne/src/entity/list.rs b/lib/cretonne/src/entity/list.rs index ad03dc6c85..2c743e169b 100644 --- a/lib/cretonne/src/entity/list.rs +++ b/lib/cretonne/src/entity/list.rs @@ -480,7 +480,7 @@ impl EntityList { #[cfg(test)] mod tests { use super::*; - use super::{sclass_size, sclass_for_length}; + use super::{sclass_for_length, sclass_size}; use ir::Inst; use entity::EntityRef; diff --git a/lib/cretonne/src/entity/map.rs b/lib/cretonne/src/entity/map.rs index 3aac22b44f..88b355585b 100644 --- a/lib/cretonne/src/entity/map.rs +++ b/lib/cretonne/src/entity/map.rs @@ -1,6 +1,6 @@ //! Densely numbered entity references as mapping keys. -use entity::{EntityRef, Keys, Iter, IterMut}; +use entity::{EntityRef, Iter, IterMut, Keys}; use std::marker::PhantomData; use std::ops::{Index, IndexMut}; use std::vec::Vec; diff --git a/lib/cretonne/src/entity/mod.rs b/lib/cretonne/src/entity/mod.rs index c4004f126d..9aeab1449d 100644 --- a/lib/cretonne/src/entity/mod.rs +++ b/lib/cretonne/src/entity/mod.rs @@ -43,7 +43,7 @@ pub use self::list::{EntityList, ListPool}; pub use self::map::EntityMap; pub use self::primary::PrimaryMap; pub use self::set::EntitySet; -pub use self::sparse::{SparseSet, SparseMap, SparseMapValue}; +pub use self::sparse::{SparseMap, SparseMapValue, SparseSet}; /// A type wrapping a small integer index should implement `EntityRef` so it can be used as the key /// of an `EntityMap` or `SparseMap`. diff --git a/lib/cretonne/src/entity/primary.rs b/lib/cretonne/src/entity/primary.rs index 8671bdf809..a442928d77 100644 --- a/lib/cretonne/src/entity/primary.rs +++ b/lib/cretonne/src/entity/primary.rs @@ -1,5 +1,5 @@ //! Densely numbered entity references as mapping keys. -use entity::{EntityRef, Keys, Iter, IterMut}; +use entity::{EntityRef, Iter, IterMut, Keys}; use std::marker::PhantomData; use std::ops::{Index, IndexMut}; use std::vec::Vec; diff --git a/lib/cretonne/src/entity/sparse.rs b/lib/cretonne/src/entity/sparse.rs index 488fd55393..6894c89498 100644 --- a/lib/cretonne/src/entity/sparse.rs +++ b/lib/cretonne/src/entity/sparse.rs @@ -7,7 +7,7 @@ //! > Briggs, Torczon, *An efficient representation for sparse sets*, //! ACM Letters on Programming Languages and Systems, Volume 2, Issue 1-4, March-Dec. 1993. -use entity::{EntityRef, EntityMap}; +use entity::{EntityMap, EntityRef}; use std::mem; use std::slice; use std::u32; diff --git a/lib/cretonne/src/flowgraph.rs b/lib/cretonne/src/flowgraph.rs index dce60162a4..3ed295d6f0 100644 --- a/lib/cretonne/src/flowgraph.rs +++ b/lib/cretonne/src/flowgraph.rs @@ -24,7 +24,7 @@ //! and `(Ebb0, jmp Ebb2)` respectively. use bforest; -use ir::{Function, Inst, Ebb}; +use ir::{Ebb, Function, Inst}; use ir::instructions::BranchInfo; use entity::EntityMap; use std::mem; @@ -203,7 +203,7 @@ pub type SuccIter<'a> = bforest::SetIter<'a, Ebb, ()>; mod tests { use super::*; use cursor::{Cursor, FuncCursor}; - use ir::{Function, InstBuilder, types}; + use ir::{types, Function, InstBuilder}; use std::vec::Vec; #[test] diff --git a/lib/cretonne/src/ir/builder.rs b/lib/cretonne/src/ir/builder.rs index 7e1480186d..6308f3e1bd 100644 --- a/lib/cretonne/src/ir/builder.rs +++ b/lib/cretonne/src/ir/builder.rs @@ -5,8 +5,8 @@ use ir; use ir::types; -use ir::{InstructionData, DataFlowGraph}; -use ir::{Opcode, Type, Inst, Value}; +use ir::{DataFlowGraph, InstructionData}; +use ir::{Inst, Opcode, Type, Value}; use isa; /// Base trait for instruction builders. @@ -145,8 +145,9 @@ where } impl<'f, IIB, Array> InstBuilderBase<'f> for InsertReuseBuilder<'f, IIB, Array> - where IIB: InstInserterBase<'f>, - Array: AsRef<[Option]> +where + IIB: InstInserterBase<'f>, + Array: AsRef<[Option]>, { fn data_flow_graph(&self) -> &DataFlowGraph { self.inserter.data_flow_graph() diff --git a/lib/cretonne/src/ir/dfg.rs b/lib/cretonne/src/ir/dfg.rs index d8cb9b2eb1..48faf3b5ac 100644 --- a/lib/cretonne/src/ir/dfg.rs +++ b/lib/cretonne/src/ir/dfg.rs @@ -1,13 +1,13 @@ //! Data flow graph tracking Instructions, Values, and EBBs. -use entity::{PrimaryMap, EntityMap}; -use isa::{TargetIsa, Encoding, Legalize}; +use entity::{EntityMap, PrimaryMap}; +use isa::{Encoding, Legalize, TargetIsa}; use ir; use ir::builder::ReplaceBuilder; use ir::extfunc::ExtFuncData; -use ir::instructions::{InstructionData, CallInfo, BranchInfo}; +use ir::instructions::{BranchInfo, CallInfo, InstructionData}; use ir::types; -use ir::{Ebb, Inst, Value, Type, SigRef, Signature, FuncRef, ValueList, ValueListPool}; +use ir::{Ebb, FuncRef, Inst, SigRef, Signature, Type, Value, ValueList, ValueListPool}; use packed_option::ReservedValue; use write::write_operands; use std::fmt; @@ -775,7 +775,6 @@ impl DataFlowGraph { } } - /// Append an existing value to `ebb`'s parameters. /// /// The appended value can't already be attached to something else. @@ -863,7 +862,6 @@ impl<'a> fmt::Display for DisplayInst<'a> { write!(f, " = ")?; } - let typevar = dfg.ctrl_typevar(inst); if typevar.is_void() { write!(f, "{}", dfg[inst].opcode())?; @@ -1005,7 +1003,7 @@ mod tests { use super::*; use cursor::{Cursor, FuncCursor}; use ir::types; - use ir::{Function, Opcode, InstructionData, TrapCode}; + use ir::{Function, InstructionData, Opcode, TrapCode}; use std::string::ToString; #[test] diff --git a/lib/cretonne/src/ir/extfunc.rs b/lib/cretonne/src/ir/extfunc.rs index 08fa28cf5c..45c44c952a 100644 --- a/lib/cretonne/src/ir/extfunc.rs +++ b/lib/cretonne/src/ir/extfunc.rs @@ -5,7 +5,7 @@ //! //! This module declares the data types used to represent external functions and call signatures. -use ir::{Type, ExternalName, SigRef, ArgumentLoc}; +use ir::{ArgumentLoc, ExternalName, SigRef, Type}; use isa::{RegInfo, RegUnit}; use std::cmp; use std::fmt; @@ -379,7 +379,7 @@ impl FromStr for CallConv { #[cfg(test)] mod tests { use super::*; - use ir::types::{I32, F32, B8}; + use ir::types::{B8, F32, I32}; use std::string::ToString; #[test] diff --git a/lib/cretonne/src/ir/function.rs b/lib/cretonne/src/ir/function.rs index d122e73360..5010e0caae 100644 --- a/lib/cretonne/src/ir/function.rs +++ b/lib/cretonne/src/ir/function.rs @@ -4,13 +4,13 @@ //! instructions. use binemit::CodeOffset; -use entity::{PrimaryMap, EntityMap}; +use entity::{EntityMap, PrimaryMap}; use ir; -use ir::{ExternalName, CallConv, Signature, DataFlowGraph, Layout}; -use ir::{InstEncodings, ValueLocations, JumpTables, StackSlots, EbbOffsets, SourceLocs}; -use ir::{Ebb, JumpTableData, JumpTable, StackSlotData, StackSlot, SigRef, ExtFuncData, FuncRef, - GlobalVarData, GlobalVar, HeapData, Heap}; -use isa::{TargetIsa, EncInfo, Legalize}; +use ir::{CallConv, DataFlowGraph, ExternalName, Layout, Signature}; +use ir::{EbbOffsets, InstEncodings, JumpTables, SourceLocs, StackSlots, ValueLocations}; +use ir::{Ebb, ExtFuncData, FuncRef, GlobalVar, GlobalVarData, Heap, HeapData, JumpTable, + JumpTableData, SigRef, StackSlot, StackSlotData}; +use isa::{EncInfo, Legalize, TargetIsa}; use std::fmt; use write::write_function; diff --git a/lib/cretonne/src/ir/immediates.rs b/lib/cretonne/src/ir/immediates.rs index 6026cecf26..3dd09bd0bd 100644 --- a/lib/cretonne/src/ir/immediates.rs +++ b/lib/cretonne/src/ir/immediates.rs @@ -184,7 +184,6 @@ impl Display for Uimm32 { } else { write_hex(i64::from(self.0), f) } - } } @@ -249,7 +248,6 @@ impl Display for Offset32 { } else { write_hex(val, f) } - } } @@ -461,7 +459,6 @@ fn parse_float(s: &str, w: u8, t: u8) -> Result { None => return Err("Invalid character"), } } - } } diff --git a/lib/cretonne/src/ir/instructions.rs b/lib/cretonne/src/ir/instructions.rs index b25e5a069b..94293b517b 100644 --- a/lib/cretonne/src/ir/instructions.rs +++ b/lib/cretonne/src/ir/instructions.rs @@ -12,7 +12,7 @@ use std::ops::{Deref, DerefMut}; use std::vec::Vec; use ir; -use ir::{Value, Type, Ebb, JumpTable, SigRef, FuncRef}; +use ir::{Ebb, FuncRef, JumpTable, SigRef, Type, Value}; use ir::types; use isa; @@ -73,7 +73,7 @@ impl FromStr for Opcode { /// Parse an Opcode name from a string. fn from_str(s: &str) -> Result { - use constant_hash::{Table, simple_hash, probe}; + use constant_hash::{probe, simple_hash, Table}; impl<'a> Table<&'a str> for [Option] { fn len(&self) -> usize { @@ -512,16 +512,12 @@ impl OperandConstraint { LaneOf => Bound(ctrl_type.lane_type()), AsBool => Bound(ctrl_type.as_bool()), HalfWidth => Bound(ctrl_type.half_width().expect("invalid type for half_width")), - DoubleWidth => { - Bound(ctrl_type.double_width().expect( - "invalid type for double_width", - )) - } - HalfVector => { - Bound(ctrl_type.half_vector().expect( - "invalid type for half_vector", - )) - } + DoubleWidth => Bound(ctrl_type.double_width().expect( + "invalid type for double_width", + )), + HalfVector => Bound(ctrl_type.half_vector().expect( + "invalid type for half_vector", + )), DoubleVector => Bound(ctrl_type.by(2).expect("invalid type for double_vector")), } } diff --git a/lib/cretonne/src/ir/layout.rs b/lib/cretonne/src/ir/layout.rs index af0c99e0fe..78db62530b 100644 --- a/lib/cretonne/src/ir/layout.rs +++ b/lib/cretonne/src/ir/layout.rs @@ -5,10 +5,10 @@ use entity::EntityMap; use ir::{Ebb, Inst}; -use ir::progpoint::{ProgramOrder, ExpandedProgramPoint}; +use ir::progpoint::{ExpandedProgramPoint, ProgramOrder}; use packed_option::PackedOption; use std::cmp; -use std::iter::{Iterator, IntoIterator}; +use std::iter::{IntoIterator, Iterator}; use timing; /// The `Layout` struct determines the layout of EBBs and instructions in a function. It does not @@ -734,7 +734,6 @@ impl<'f> DoubleEndedIterator for Insts<'f> { } } - #[cfg(test)] mod tests { use cursor::{Cursor, CursorPosition}; diff --git a/lib/cretonne/src/ir/mod.rs b/lib/cretonne/src/ir/mod.rs index 4f4e671f30..0d805cb3de 100644 --- a/lib/cretonne/src/ir/mod.rs +++ b/lib/cretonne/src/ir/mod.rs @@ -22,29 +22,29 @@ mod sourceloc; mod trapcode; mod valueloc; -pub use ir::builder::{InstBuilder, InstBuilderBase, InstInserterBase, InsertBuilder}; +pub use ir::builder::{InsertBuilder, InstBuilder, InstBuilderBase, InstInserterBase}; pub use ir::dfg::{DataFlowGraph, ValueDef}; -pub use ir::entities::{Ebb, Inst, Value, StackSlot, GlobalVar, JumpTable, FuncRef, SigRef, Heap}; -pub use ir::extfunc::{Signature, CallConv, AbiParam, ArgumentExtension, ArgumentPurpose, - ExtFuncData}; +pub use ir::entities::{Ebb, FuncRef, GlobalVar, Heap, Inst, JumpTable, SigRef, StackSlot, Value}; +pub use ir::extfunc::{AbiParam, ArgumentExtension, ArgumentPurpose, CallConv, ExtFuncData, + Signature}; pub use ir::extname::ExternalName; pub use ir::function::Function; pub use ir::globalvar::GlobalVarData; -pub use ir::heap::{HeapData, HeapStyle, HeapBase}; -pub use ir::instructions::{Opcode, InstructionData, VariableArgs, ValueList, ValueListPool}; +pub use ir::heap::{HeapBase, HeapData, HeapStyle}; +pub use ir::instructions::{InstructionData, Opcode, ValueList, ValueListPool, VariableArgs}; pub use ir::jumptable::JumpTableData; pub use ir::layout::Layout; pub use ir::libcall::LibCall; pub use ir::memflags::MemFlags; -pub use ir::progpoint::{ProgramPoint, ProgramOrder, ExpandedProgramPoint}; +pub use ir::progpoint::{ExpandedProgramPoint, ProgramOrder, ProgramPoint}; pub use ir::sourceloc::SourceLoc; -pub use ir::stackslot::{StackSlots, StackSlotKind, StackSlotData}; +pub use ir::stackslot::{StackSlotData, StackSlotKind, StackSlots}; pub use ir::trapcode::TrapCode; pub use ir::types::Type; -pub use ir::valueloc::{ValueLoc, ArgumentLoc}; +pub use ir::valueloc::{ArgumentLoc, ValueLoc}; use binemit; -use entity::{PrimaryMap, EntityMap}; +use entity::{EntityMap, PrimaryMap}; use isa; /// Map of value locations. diff --git a/lib/cretonne/src/ir/progpoint.rs b/lib/cretonne/src/ir/progpoint.rs index 8fea3193c6..6eab7ec743 100644 --- a/lib/cretonne/src/ir/progpoint.rs +++ b/lib/cretonne/src/ir/progpoint.rs @@ -147,7 +147,7 @@ pub trait ProgramOrder { mod tests { use super::*; use entity::EntityRef; - use ir::{Inst, Ebb}; + use ir::{Ebb, Inst}; use std::string::ToString; #[test] diff --git a/lib/cretonne/src/ir/stackslot.rs b/lib/cretonne/src/ir/stackslot.rs index bc87e11a82..fd484915fd 100644 --- a/lib/cretonne/src/ir/stackslot.rs +++ b/lib/cretonne/src/ir/stackslot.rs @@ -3,8 +3,8 @@ //! The `StackSlotData` struct keeps track of a single stack slot in a function. //! -use entity::{PrimaryMap, Keys, Iter, IterMut}; -use ir::{Type, StackSlot}; +use entity::{Iter, IterMut, Keys, PrimaryMap}; +use ir::{StackSlot, Type}; use packed_option::PackedOption; use std::cmp; use std::fmt; diff --git a/lib/cretonne/src/ir/types.rs b/lib/cretonne/src/ir/types.rs index 29a37f0cbf..496312b1c4 100644 --- a/lib/cretonne/src/ir/types.rs +++ b/lib/cretonne/src/ir/types.rs @@ -1,7 +1,7 @@ //! Common types for the Cretonne code generator. use std::default::Default; -use std::fmt::{self, Display, Debug, Formatter}; +use std::fmt::{self, Debug, Display, Formatter}; /// The type of an SSA value. /// diff --git a/lib/cretonne/src/isa/arm32/abi.rs b/lib/cretonne/src/isa/arm32/abi.rs index 47efbc97bf..020a525ac5 100644 --- a/lib/cretonne/src/isa/arm32/abi.rs +++ b/lib/cretonne/src/isa/arm32/abi.rs @@ -4,7 +4,7 @@ use ir; use isa::RegClass; use regalloc::AllocatableSet; use settings as shared_settings; -use super::registers::{S, D, Q, GPR}; +use super::registers::{D, GPR, Q, S}; /// Legalize `sig`. pub fn legalize_signature( diff --git a/lib/cretonne/src/isa/arm32/binemit.rs b/lib/cretonne/src/isa/arm32/binemit.rs index 78fa2fd657..9f50e63993 100644 --- a/lib/cretonne/src/isa/arm32/binemit.rs +++ b/lib/cretonne/src/isa/arm32/binemit.rs @@ -1,6 +1,6 @@ //! Emitting binary ARM32 machine code. -use binemit::{CodeSink, bad_encoding}; +use binemit::{bad_encoding, CodeSink}; use ir::{Function, Inst}; use regalloc::RegDiversions; diff --git a/lib/cretonne/src/isa/arm32/mod.rs b/lib/cretonne/src/isa/arm32/mod.rs index 02e0d5f1af..11271fe3d9 100644 --- a/lib/cretonne/src/isa/arm32/mod.rs +++ b/lib/cretonne/src/isa/arm32/mod.rs @@ -6,11 +6,11 @@ mod binemit; mod enc_tables; mod registers; -use binemit::{CodeSink, MemoryCodeSink, emit_function}; +use binemit::{emit_function, CodeSink, MemoryCodeSink}; use super::super::settings as shared_settings; use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings}; use isa::Builder as IsaBuilder; -use isa::{TargetIsa, RegInfo, RegClass, EncInfo}; +use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; use ir; use regalloc; use std::fmt; diff --git a/lib/cretonne/src/isa/arm32/registers.rs b/lib/cretonne/src/isa/arm32/registers.rs index e2c4813bdd..305890b29e 100644 --- a/lib/cretonne/src/isa/arm32/registers.rs +++ b/lib/cretonne/src/isa/arm32/registers.rs @@ -6,7 +6,7 @@ include!(concat!(env!("OUT_DIR"), "/registers-arm32.rs")); #[cfg(test)] mod tests { - use super::{INFO, GPR, S, D}; + use super::{D, GPR, INFO, S}; use isa::RegUnit; use std::string::{String, ToString}; diff --git a/lib/cretonne/src/isa/arm64/abi.rs b/lib/cretonne/src/isa/arm64/abi.rs index 14af59ab18..9dba70c42f 100644 --- a/lib/cretonne/src/isa/arm64/abi.rs +++ b/lib/cretonne/src/isa/arm64/abi.rs @@ -4,7 +4,7 @@ use ir; use isa::RegClass; use regalloc::AllocatableSet; use settings as shared_settings; -use super::registers::{GPR, FPR}; +use super::registers::{FPR, GPR}; /// Legalize `sig`. pub fn legalize_signature( diff --git a/lib/cretonne/src/isa/arm64/binemit.rs b/lib/cretonne/src/isa/arm64/binemit.rs index a4b79cda55..dd0654067e 100644 --- a/lib/cretonne/src/isa/arm64/binemit.rs +++ b/lib/cretonne/src/isa/arm64/binemit.rs @@ -1,6 +1,6 @@ //! Emitting binary ARM64 machine code. -use binemit::{CodeSink, bad_encoding}; +use binemit::{bad_encoding, CodeSink}; use ir::{Function, Inst}; use regalloc::RegDiversions; diff --git a/lib/cretonne/src/isa/arm64/mod.rs b/lib/cretonne/src/isa/arm64/mod.rs index 8239cb01e9..485b008574 100644 --- a/lib/cretonne/src/isa/arm64/mod.rs +++ b/lib/cretonne/src/isa/arm64/mod.rs @@ -6,11 +6,11 @@ mod binemit; mod enc_tables; mod registers; -use binemit::{CodeSink, MemoryCodeSink, emit_function}; +use binemit::{emit_function, CodeSink, MemoryCodeSink}; use super::super::settings as shared_settings; use isa::enc_tables::{lookup_enclist, Encodings}; use isa::Builder as IsaBuilder; -use isa::{TargetIsa, RegInfo, RegClass, EncInfo}; +use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; use ir; use regalloc; use std::fmt; diff --git a/lib/cretonne/src/isa/constraints.rs b/lib/cretonne/src/isa/constraints.rs index f831c0e187..4ab22a6026 100644 --- a/lib/cretonne/src/isa/constraints.rs +++ b/lib/cretonne/src/isa/constraints.rs @@ -9,7 +9,7 @@ use binemit::CodeOffset; use isa::{RegClass, RegUnit}; -use ir::{Function, ValueLoc, Inst}; +use ir::{Function, Inst, ValueLoc}; use regalloc::RegDiversions; /// Register constraint for a single value operand or instruction result. @@ -205,6 +205,5 @@ mod tests { // Backward limit assert!(t1.contains(1000, 748)); assert!(!t1.contains(1000, 746)); - } } diff --git a/lib/cretonne/src/isa/enc_tables.rs b/lib/cretonne/src/isa/enc_tables.rs index 7453b7c044..c987606fa6 100644 --- a/lib/cretonne/src/isa/enc_tables.rs +++ b/lib/cretonne/src/isa/enc_tables.rs @@ -3,8 +3,8 @@ //! This module contains types and functions for working with the encoding tables generated by //! `lib/cretonne/meta/gen_encoding.py`. -use constant_hash::{Table, probe}; -use ir::{Type, Opcode, DataFlowGraph, InstructionData}; +use constant_hash::{probe, Table}; +use ir::{DataFlowGraph, InstructionData, Opcode, Type}; use isa::{Encoding, Legalize}; use settings::PredicateView; use std::ops::Range; diff --git a/lib/cretonne/src/isa/encoding.rs b/lib/cretonne/src/isa/encoding.rs index b82137a6b8..1b850d5c64 100644 --- a/lib/cretonne/src/isa/encoding.rs +++ b/lib/cretonne/src/isa/encoding.rs @@ -1,7 +1,7 @@ //! The `Encoding` struct. use binemit::CodeOffset; -use isa::constraints::{RecipeConstraints, BranchRange}; +use isa::constraints::{BranchRange, RecipeConstraints}; use std::fmt; /// Bits needed to encode an instruction as binary machine code. diff --git a/lib/cretonne/src/isa/intel/abi.rs b/lib/cretonne/src/isa/intel/abi.rs index e2c79e0377..46ad7679e6 100644 --- a/lib/cretonne/src/isa/intel/abi.rs +++ b/lib/cretonne/src/isa/intel/abi.rs @@ -4,17 +4,16 @@ use ir; use isa::{RegClass, RegUnit, TargetIsa}; use regalloc::AllocatableSet; use settings as shared_settings; -use super::registers::{GPR, FPR, RU}; -use abi::{ArgAction, ValueConversion, ArgAssigner, legalize_args}; -use ir::{AbiParam, ArgumentPurpose, ArgumentLoc, ArgumentExtension, CallConv, InstBuilder}; -use ir::stackslot::{StackSize, StackOffset}; +use super::registers::{FPR, GPR, RU}; +use abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion}; +use ir::{AbiParam, ArgumentExtension, ArgumentLoc, ArgumentPurpose, CallConv, InstBuilder}; +use ir::stackslot::{StackOffset, StackSize}; use ir::immediates::Imm64; use stack_layout::layout_stack; use std::i32; -use cursor::{Cursor, EncCursor, CursorPosition}; +use cursor::{Cursor, CursorPosition, EncCursor}; use result; - /// Argument registers for x86-64 static ARG_GPRS: [RU; 6] = [RU::rdi, RU::rsi, RU::rdx, RU::rcx, RU::r8, RU::r9]; diff --git a/lib/cretonne/src/isa/intel/binemit.rs b/lib/cretonne/src/isa/intel/binemit.rs index 5f2f9512ce..5ec1d7175f 100644 --- a/lib/cretonne/src/isa/intel/binemit.rs +++ b/lib/cretonne/src/isa/intel/binemit.rs @@ -1,9 +1,9 @@ //! Emitting binary Intel machine code. -use binemit::{CodeSink, Reloc, bad_encoding}; -use ir::{Function, Inst, Ebb, InstructionData, Opcode, TrapCode}; -use ir::condcodes::{CondCode, IntCC, FloatCC}; -use isa::{RegUnit, StackRef, StackBase, StackBaseMask}; +use binemit::{bad_encoding, CodeSink, Reloc}; +use ir::{Ebb, Function, Inst, InstructionData, Opcode, TrapCode}; +use ir::condcodes::{CondCode, FloatCC, IntCC}; +use isa::{RegUnit, StackBase, StackBaseMask, StackRef}; use regalloc::RegDiversions; use super::registers::RU; diff --git a/lib/cretonne/src/isa/intel/enc_tables.rs b/lib/cretonne/src/isa/intel/enc_tables.rs index d3f62adf7c..b8461c0008 100644 --- a/lib/cretonne/src/isa/intel/enc_tables.rs +++ b/lib/cretonne/src/isa/intel/enc_tables.rs @@ -22,7 +22,6 @@ fn expand_sdivrem( cfg: &mut ControlFlowGraph, isa: &isa::TargetIsa, ) { - let (x, y, is_srem) = match func.dfg[inst] { ir::InstructionData::Binary { opcode: ir::Opcode::Sdiv, @@ -113,7 +112,6 @@ fn expand_udivrem( _cfg: &mut ControlFlowGraph, isa: &isa::TargetIsa, ) { - let (x, y, is_urem) = match func.dfg[inst] { ir::InstructionData::Binary { opcode: ir::Opcode::Udiv, @@ -324,7 +322,7 @@ fn expand_fcvt_to_sint( cfg: &mut ControlFlowGraph, _isa: &isa::TargetIsa, ) { - use ir::condcodes::{IntCC, FloatCC}; + use ir::condcodes::{FloatCC, IntCC}; use ir::immediates::{Ieee32, Ieee64}; let x; @@ -423,7 +421,7 @@ fn expand_fcvt_to_uint( cfg: &mut ControlFlowGraph, _isa: &isa::TargetIsa, ) { - use ir::condcodes::{IntCC, FloatCC}; + use ir::condcodes::{FloatCC, IntCC}; use ir::immediates::{Ieee32, Ieee64}; let x; diff --git a/lib/cretonne/src/isa/intel/mod.rs b/lib/cretonne/src/isa/intel/mod.rs index 04ff149654..aa6f2a0a01 100644 --- a/lib/cretonne/src/isa/intel/mod.rs +++ b/lib/cretonne/src/isa/intel/mod.rs @@ -6,11 +6,11 @@ mod binemit; mod enc_tables; mod registers; -use binemit::{CodeSink, MemoryCodeSink, emit_function}; +use binemit::{emit_function, CodeSink, MemoryCodeSink}; use super::super::settings as shared_settings; use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings}; use isa::Builder as IsaBuilder; -use isa::{TargetIsa, RegInfo, RegClass, EncInfo}; +use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; use ir; use regalloc; use result; diff --git a/lib/cretonne/src/isa/mod.rs b/lib/cretonne/src/isa/mod.rs index 1a7714fc76..8c141126af 100644 --- a/lib/cretonne/src/isa/mod.rs +++ b/lib/cretonne/src/isa/mod.rs @@ -40,9 +40,9 @@ //! The configured target ISA trait object is a `Box` which can be used for multiple //! concurrent function compilations. -pub use isa::constraints::{RecipeConstraints, OperandConstraint, ConstraintKind, BranchRange}; -pub use isa::encoding::{Encoding, EncInfo}; -pub use isa::registers::{RegInfo, RegUnit, RegClass, RegClassIndex, regs_overlap}; +pub use isa::constraints::{BranchRange, ConstraintKind, OperandConstraint, RecipeConstraints}; +pub use isa::encoding::{EncInfo, Encoding}; +pub use isa::registers::{regs_overlap, RegClass, RegClassIndex, RegInfo, RegUnit}; pub use isa::stack::{StackBase, StackBaseMask, StackRef}; use binemit; @@ -249,7 +249,7 @@ pub trait TargetIsa: fmt::Display { let _tt = timing::prologue_epilogue(); // This default implementation is unlikely to be good enough. use stack_layout::layout_stack; - use ir::stackslot::{StackSize, StackOffset}; + use ir::stackslot::{StackOffset, StackSize}; let word_size = if self.flags().is_64bit() { 8 } else { 4 }; diff --git a/lib/cretonne/src/isa/riscv/abi.rs b/lib/cretonne/src/isa/riscv/abi.rs index 1db377b0ef..4eff90c954 100644 --- a/lib/cretonne/src/isa/riscv/abi.rs +++ b/lib/cretonne/src/isa/riscv/abi.rs @@ -5,12 +5,12 @@ //! //! This doesn't support the soft-float ABI at the moment. -use abi::{ArgAction, ValueConversion, ArgAssigner, legalize_args}; -use ir::{self, Type, AbiParam, ArgumentLoc, ArgumentExtension, ArgumentPurpose}; +use abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion}; +use ir::{self, AbiParam, ArgumentExtension, ArgumentLoc, ArgumentPurpose, Type}; use isa::RegClass; use regalloc::AllocatableSet; use settings as shared_settings; -use super::registers::{GPR, FPR}; +use super::registers::{FPR, GPR}; use super::settings; use std::i32; diff --git a/lib/cretonne/src/isa/riscv/binemit.rs b/lib/cretonne/src/isa/riscv/binemit.rs index 8cc1ef17d1..120324d1be 100644 --- a/lib/cretonne/src/isa/riscv/binemit.rs +++ b/lib/cretonne/src/isa/riscv/binemit.rs @@ -1,8 +1,8 @@ //! Emitting binary RISC-V machine code. -use binemit::{CodeSink, Reloc, bad_encoding}; +use binemit::{bad_encoding, CodeSink, Reloc}; use ir::{Function, Inst, InstructionData}; -use isa::{RegUnit, StackRef, StackBaseMask}; +use isa::{RegUnit, StackBaseMask, StackRef}; use predicates::is_signed_int; use regalloc::RegDiversions; use std::u32; diff --git a/lib/cretonne/src/isa/riscv/mod.rs b/lib/cretonne/src/isa/riscv/mod.rs index 6fc976686b..63a3c01088 100644 --- a/lib/cretonne/src/isa/riscv/mod.rs +++ b/lib/cretonne/src/isa/riscv/mod.rs @@ -7,10 +7,10 @@ mod enc_tables; mod registers; use super::super::settings as shared_settings; -use binemit::{CodeSink, MemoryCodeSink, emit_function}; +use binemit::{emit_function, CodeSink, MemoryCodeSink}; use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings}; use isa::Builder as IsaBuilder; -use isa::{TargetIsa, RegInfo, RegClass, EncInfo}; +use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; use ir; use regalloc; use std::fmt; @@ -116,7 +116,7 @@ mod tests { use settings::{self, Configurable}; use isa; use ir::{DataFlowGraph, InstructionData, Opcode}; - use ir::{types, immediates}; + use ir::{immediates, types}; use std::string::{String, ToString}; fn encstr(isa: &isa::TargetIsa, enc: Result) -> String { diff --git a/lib/cretonne/src/isa/riscv/registers.rs b/lib/cretonne/src/isa/riscv/registers.rs index e2073899b6..d6254fe38e 100644 --- a/lib/cretonne/src/isa/riscv/registers.rs +++ b/lib/cretonne/src/isa/riscv/registers.rs @@ -6,7 +6,7 @@ include!(concat!(env!("OUT_DIR"), "/registers-riscv.rs")); #[cfg(test)] mod tests { - use super::{INFO, GPR, FPR}; + use super::{FPR, GPR, INFO}; use isa::RegUnit; use std::string::{String, ToString}; diff --git a/lib/cretonne/src/isa/riscv/settings.rs b/lib/cretonne/src/isa/riscv/settings.rs index 2f0f6822a9..27cba43f2f 100644 --- a/lib/cretonne/src/isa/riscv/settings.rs +++ b/lib/cretonne/src/isa/riscv/settings.rs @@ -22,12 +22,12 @@ mod tests { assert_eq!( f.to_string(), "[riscv]\n\ - supports_m = false\n\ - supports_a = false\n\ - supports_f = false\n\ - supports_d = false\n\ - enable_m = true\n\ - enable_e = false\n" + supports_m = false\n\ + supports_a = false\n\ + supports_f = false\n\ + supports_d = false\n\ + enable_m = true\n\ + enable_e = false\n" ); // Predicates are not part of the Display output. assert_eq!(f.full_float(), false); diff --git a/lib/cretonne/src/isa/stack.rs b/lib/cretonne/src/isa/stack.rs index 9e09a52808..7eac43b62c 100644 --- a/lib/cretonne/src/isa/stack.rs +++ b/lib/cretonne/src/isa/stack.rs @@ -4,7 +4,7 @@ //! defined in this module expresses the low-level details of accessing a stack slot from an //! encoded instruction. -use ir::stackslot::{StackSlots, StackOffset, StackSlotKind}; +use ir::stackslot::{StackOffset, StackSlotKind, StackSlots}; use ir::StackSlot; /// A method for referencing a stack slot in the current stack frame. diff --git a/lib/cretonne/src/legalizer/boundary.rs b/lib/cretonne/src/legalizer/boundary.rs index e1e4a17956..6cad2775e5 100644 --- a/lib/cretonne/src/legalizer/boundary.rs +++ b/lib/cretonne/src/legalizer/boundary.rs @@ -20,8 +20,8 @@ use abi::{legalize_abi_value, ValueConversion}; use cursor::{Cursor, FuncCursor}; use flowgraph::ControlFlowGraph; -use ir::{Function, DataFlowGraph, Inst, InstBuilder, Ebb, Type, Value, Signature, SigRef, - AbiParam, ArgumentPurpose, ArgumentLoc, ValueLoc}; +use ir::{AbiParam, ArgumentLoc, ArgumentPurpose, DataFlowGraph, Ebb, Function, Inst, InstBuilder, + SigRef, Signature, Type, Value, ValueLoc}; use ir::instructions::CallInfo; use isa::TargetIsa; use legalizer::split::{isplit, vsplit}; diff --git a/lib/cretonne/src/legalizer/mod.rs b/lib/cretonne/src/legalizer/mod.rs index 68f24ee0da..d434d6b6e5 100644 --- a/lib/cretonne/src/legalizer/mod.rs +++ b/lib/cretonne/src/legalizer/mod.rs @@ -235,7 +235,6 @@ fn expand_select( cfg.recompute_ebb(pos.func, old_ebb); } - /// Expand illegal `f32const` and `f64const` instructions. fn expand_fconst( inst: ir::Inst, diff --git a/lib/cretonne/src/legalizer/split.rs b/lib/cretonne/src/legalizer/split.rs index cdc60974e0..8f82166db8 100644 --- a/lib/cretonne/src/legalizer/split.rs +++ b/lib/cretonne/src/legalizer/split.rs @@ -66,7 +66,7 @@ use cursor::{Cursor, CursorPosition, FuncCursor}; use flowgraph::ControlFlowGraph; -use ir::{self, Ebb, Inst, Value, Type, Opcode, ValueDef, InstructionData, InstBuilder}; +use ir::{self, Ebb, Inst, InstBuilder, InstructionData, Opcode, Type, Value, ValueDef}; use std::iter; use std::vec::Vec; @@ -229,7 +229,6 @@ fn split_value( let hi = pos.func.dfg.append_ebb_param(ebb, split_type); reuse = Some((lo, hi)); - // Now the original value is dangling. Insert a concatenation instruction that can // compute it from the two new parameters. This also serves as a record of what we // did so a future call to this function doesn't have to redo the work. diff --git a/lib/cretonne/src/lib.rs b/lib/cretonne/src/lib.rs index cde427df9f..99246defe3 100644 --- a/lib/cretonne/src/lib.rs +++ b/lib/cretonne/src/lib.rs @@ -1,12 +1,7 @@ //! Cretonne code generation library. -#![deny(missing_docs, - trivial_numeric_casts, - unused_extern_crates)] - -#![cfg_attr(feature="clippy", - plugin(clippy(conf_file="../../clippy.toml")))] - +#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] #![cfg_attr(feature="cargo-clippy", allow( // Rustfmt 0.9.0 is at odds with this lint: block_in_if_condition_stmt, diff --git a/lib/cretonne/src/licm.rs b/lib/cretonne/src/licm.rs index f0327296a1..546fc01bd8 100644 --- a/lib/cretonne/src/licm.rs +++ b/lib/cretonne/src/licm.rs @@ -1,7 +1,7 @@ //! A Loop Invariant Code Motion optimization pass use cursor::{Cursor, FuncCursor}; -use ir::{Function, Ebb, Inst, Value, Type, InstBuilder, Layout, Opcode, DataFlowGraph}; +use ir::{DataFlowGraph, Ebb, Function, Inst, InstBuilder, Layout, Opcode, Type, Value}; use flowgraph::ControlFlowGraph; use std::collections::HashSet; use dominator_tree::DominatorTree; @@ -121,7 +121,6 @@ fn has_pre_header( result } - // Change the destination of a jump or branch instruction. Does nothing if called with a non-jump // or non-branch instruction. fn change_branch_jump_destination(inst: Inst, new_ebb: Ebb, func: &mut Function) { diff --git a/lib/cretonne/src/loop_analysis.rs b/lib/cretonne/src/loop_analysis.rs index 431496b6e4..89d2939ac9 100644 --- a/lib/cretonne/src/loop_analysis.rs +++ b/lib/cretonne/src/loop_analysis.rs @@ -2,10 +2,10 @@ //! and parent in the loop tree. use dominator_tree::DominatorTree; -use entity::{PrimaryMap, Keys}; +use entity::{Keys, PrimaryMap}; use entity::EntityMap; use flowgraph::ControlFlowGraph; -use ir::{Function, Ebb, Layout}; +use ir::{Ebb, Function, Layout}; use packed_option::PackedOption; use timing; use std::vec::Vec; @@ -218,7 +218,6 @@ impl LoopAnalysis { } } } - } } } @@ -227,7 +226,7 @@ impl LoopAnalysis { mod test { use cursor::{Cursor, FuncCursor}; - use ir::{Function, InstBuilder, types}; + use ir::{types, Function, InstBuilder}; use loop_analysis::{Loop, LoopAnalysis}; use flowgraph::ControlFlowGraph; use dominator_tree::DominatorTree; @@ -257,7 +256,6 @@ mod test { cur.insert_ebb(ebb3); cur.ins().brnz(cond, ebb0, &[]); - } let mut loop_analysis = LoopAnalysis::new(); @@ -317,7 +315,6 @@ mod test { cur.insert_ebb(ebb5); cur.ins().brnz(cond, ebb0, &[]); - } let mut loop_analysis = LoopAnalysis::new(); diff --git a/lib/cretonne/src/postopt.rs b/lib/cretonne/src/postopt.rs index a95baefd3a..efe85d40d7 100644 --- a/lib/cretonne/src/postopt.rs +++ b/lib/cretonne/src/postopt.rs @@ -4,8 +4,8 @@ use cursor::{Cursor, EncCursor}; use ir::dfg::ValueDef; -use ir::{Function, InstructionData, Value, InstBuilder, Ebb, Inst}; -use ir::condcodes::{CondCode, IntCC, FloatCC}; +use ir::{Ebb, Function, Inst, InstBuilder, InstructionData, Value}; +use ir::condcodes::{CondCode, FloatCC, IntCC}; use ir::instructions::{Opcode, ValueList}; use ir::immediates::Imm64; use isa::TargetIsa; @@ -67,54 +67,48 @@ fn optimize_cpu_flags( cond, args: cmp_args, .. - } => { - CmpBrInfo { - br_inst: inst, - cmp_inst: cond_inst, - destination, - args: args.clone(), - cmp_arg: cmp_args[0], - invert_branch_cond, - kind: CmpBrKind::Icmp { - cond, - arg: cmp_args[1], - }, - } - } + } => CmpBrInfo { + br_inst: inst, + cmp_inst: cond_inst, + destination, + args: args.clone(), + cmp_arg: cmp_args[0], + invert_branch_cond, + kind: CmpBrKind::Icmp { + cond, + arg: cmp_args[1], + }, + }, InstructionData::IntCompareImm { cond, arg: cmp_arg, imm: cmp_imm, .. - } => { - CmpBrInfo { - br_inst: inst, - cmp_inst: cond_inst, - destination, - args: args.clone(), - cmp_arg, - invert_branch_cond, - kind: CmpBrKind::IcmpImm { cond, imm: cmp_imm }, - } - } + } => CmpBrInfo { + br_inst: inst, + cmp_inst: cond_inst, + destination, + args: args.clone(), + cmp_arg, + invert_branch_cond, + kind: CmpBrKind::IcmpImm { cond, imm: cmp_imm }, + }, InstructionData::FloatCompare { cond, args: cmp_args, .. - } => { - CmpBrInfo { - br_inst: inst, - cmp_inst: cond_inst, - destination, - args: args.clone(), - cmp_arg: cmp_args[0], - invert_branch_cond, - kind: CmpBrKind::Fcmp { - cond, - arg: cmp_args[1], - }, - } - } + } => CmpBrInfo { + br_inst: inst, + cmp_inst: cond_inst, + destination, + args: args.clone(), + cmp_arg: cmp_args[0], + invert_branch_cond, + kind: CmpBrKind::Fcmp { + cond, + arg: cmp_args[1], + }, + }, _ => return, } } else { @@ -179,7 +173,6 @@ fn optimize_cpu_flags( pos.func.update_encoding(info.br_inst, isa).is_ok(); } - //---------------------------------------------------------------------- // // The main post-opt pass. @@ -204,7 +197,6 @@ pub fn do_postopt(func: &mut Function, isa: &TargetIsa) { last_flags_clobber = Some(inst) } } - } } } diff --git a/lib/cretonne/src/preopt.rs b/lib/cretonne/src/preopt.rs index 34dab71c4a..81e798e987 100644 --- a/lib/cretonne/src/preopt.rs +++ b/lib/cretonne/src/preopt.rs @@ -4,15 +4,14 @@ use cursor::{Cursor, FuncCursor}; use ir::dfg::ValueDef; -use ir::{Function, InstructionData, Value, DataFlowGraph, InstBuilder, Type}; +use ir::{DataFlowGraph, Function, InstBuilder, InstructionData, Type, Value}; use ir::Inst; use ir::types::{I32, I64}; use ir::instructions::Opcode; -use divconst_magic_numbers::{MU32, MU64, MS32, MS64}; -use divconst_magic_numbers::{magicU32, magicU64, magicS32, magicS64}; +use divconst_magic_numbers::{MS32, MS64, MU32, MU64}; +use divconst_magic_numbers::{magicS32, magicS64, magicU32, magicU64}; use timing; - //---------------------------------------------------------------------- // // Pattern-match helpers and transformation for div and rem by constants. @@ -149,7 +148,6 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso }; match *divrem_info { - // -------------------- U32 -------------------- // U32 div, rem by zero: ignore @@ -447,7 +445,6 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso } } } - } } @@ -554,13 +551,11 @@ fn simplify(pos: &mut FuncCursor, inst: Inst) { } } - /// The main pre-opt pass. pub fn do_preopt(func: &mut Function) { let _tt = timing::preopt(); let mut pos = FuncCursor::new(func); while let Some(_ebb) = pos.next_ebb() { - while let Some(inst) = pos.next_inst() { // Apply basic simplifications. simplify(&mut pos, inst); diff --git a/lib/cretonne/src/regalloc/affinity.rs b/lib/cretonne/src/regalloc/affinity.rs index 7d85ae8721..0e49ac5f0b 100644 --- a/lib/cretonne/src/regalloc/affinity.rs +++ b/lib/cretonne/src/regalloc/affinity.rs @@ -10,7 +10,7 @@ use std::fmt; use ir::{AbiParam, ArgumentLoc}; -use isa::{TargetIsa, RegInfo, RegClassIndex, OperandConstraint, ConstraintKind}; +use isa::{ConstraintKind, OperandConstraint, RegClassIndex, RegInfo, TargetIsa}; /// Preferred register allocation for an SSA value. #[derive(Clone, Copy, Debug)] diff --git a/lib/cretonne/src/regalloc/allocatable_set.rs b/lib/cretonne/src/regalloc/allocatable_set.rs index 8c40809310..63b7a297d7 100644 --- a/lib/cretonne/src/regalloc/allocatable_set.rs +++ b/lib/cretonne/src/regalloc/allocatable_set.rs @@ -5,7 +5,7 @@ //! "register unit" abstraction. Every register contains one or more register units. Registers that //! share a register unit can't be in use at the same time. -use isa::registers::{RegInfo, RegUnit, RegUnitMask, RegClass}; +use isa::registers::{RegClass, RegInfo, RegUnit, RegUnitMask}; use std::char; use std::fmt; use std::iter::ExactSizeIterator; diff --git a/lib/cretonne/src/regalloc/coalescing.rs b/lib/cretonne/src/regalloc/coalescing.rs index f23d55433e..b8a7270d59 100644 --- a/lib/cretonne/src/regalloc/coalescing.rs +++ b/lib/cretonne/src/regalloc/coalescing.rs @@ -10,7 +10,7 @@ use dbg::DisplayList; use dominator_tree::{DominatorTree, DominatorTreePreorder}; use flowgraph::ControlFlowGraph; use ir::{self, InstBuilder, ProgramOrder}; -use ir::{Function, Ebb, Inst, Value, ExpandedProgramPoint}; +use ir::{Ebb, ExpandedProgramPoint, Function, Inst, Value}; use regalloc::affinity::Affinity; use regalloc::liveness::Liveness; use regalloc::virtregs::{VirtReg, VirtRegs}; @@ -19,7 +19,7 @@ use std::iter; use std::fmt; use std::slice; use std::vec::Vec; -use isa::{TargetIsa, EncInfo}; +use isa::{EncInfo, TargetIsa}; use timing; // # Implementation @@ -92,7 +92,6 @@ impl Coalescing { predecessors: Vec::new(), backedges: Vec::new(), } - } /// Clear all data structures in this coalescing pass. diff --git a/lib/cretonne/src/regalloc/coloring.rs b/lib/cretonne/src/regalloc/coloring.rs index d7ab5dd0f3..ad5952885d 100644 --- a/lib/cretonne/src/regalloc/coloring.rs +++ b/lib/cretonne/src/regalloc/coloring.rs @@ -44,10 +44,10 @@ use cursor::{Cursor, EncCursor}; use dominator_tree::DominatorTree; -use ir::{Ebb, Inst, Value, Function, Layout, ValueLoc, SigRef}; -use ir::{InstBuilder, AbiParam, ArgumentLoc, ValueDef}; -use isa::{RegUnit, RegClass, RegInfo, regs_overlap}; -use isa::{TargetIsa, EncInfo, RecipeConstraints, OperandConstraint, ConstraintKind}; +use ir::{Ebb, Function, Inst, Layout, SigRef, Value, ValueLoc}; +use ir::{AbiParam, ArgumentLoc, InstBuilder, ValueDef}; +use isa::{regs_overlap, RegClass, RegInfo, RegUnit}; +use isa::{ConstraintKind, EncInfo, OperandConstraint, RecipeConstraints, TargetIsa}; use packed_option::PackedOption; use regalloc::RegDiversions; use regalloc::affinity::Affinity; @@ -59,7 +59,6 @@ use regalloc::solver::{Solver, SolverError}; use std::mem; use timing; - /// Data structures for the coloring pass. /// /// These are scratch space data structures that can be reused between invocations. @@ -268,7 +267,6 @@ impl<'a> Context<'a> { abi.display(&self.reginfo) ); } - } // The spiller will have assigned an incoming stack slot already. Affinity::Stack => debug_assert!(abi.location.is_stack()), @@ -426,7 +424,6 @@ impl<'a> Context<'a> { self.iterate_solution(throughs, ®s.global, &mut replace_global_defines) }); - // The solution and/or fixed input constraints may require us to shuffle the set of live // registers around. self.shuffle_inputs(&mut regs.input); @@ -722,7 +719,6 @@ impl<'a> Context<'a> { ConstraintKind::Reg | ConstraintKind::Tied(_) | ConstraintKind::Stack => {} - } } } @@ -869,7 +865,6 @@ impl<'a> Context<'a> { self.solver.clear_all_global_flags(); } }; - } } diff --git a/lib/cretonne/src/regalloc/context.rs b/lib/cretonne/src/regalloc/context.rs index a8284a9579..cb29963e89 100644 --- a/lib/cretonne/src/regalloc/context.rs +++ b/lib/cretonne/src/regalloc/context.rs @@ -18,7 +18,7 @@ use regalloc::virtregs::VirtRegs; use result::CtonResult; use timing; use topo_order::TopoOrder; -use verifier::{verify_context, verify_liveness, verify_cssa, verify_locations}; +use verifier::{verify_context, verify_cssa, verify_liveness, verify_locations}; /// Persistent memory allocations for register allocation. pub struct Context { @@ -106,7 +106,6 @@ impl Context { verify_cssa(func, cfg, domtree, &self.liveness, &self.virtregs)?; } - // Pass: Spilling. self.spilling.run( isa, diff --git a/lib/cretonne/src/regalloc/diversion.rs b/lib/cretonne/src/regalloc/diversion.rs index 68fd04754e..d0b7e4db91 100644 --- a/lib/cretonne/src/regalloc/diversion.rs +++ b/lib/cretonne/src/regalloc/diversion.rs @@ -7,9 +7,9 @@ //! These register diversions are local to an EBB. No values can be diverted when entering a new //! EBB. -use ir::{Value, ValueLoc, ValueLocations, StackSlot}; +use ir::{StackSlot, Value, ValueLoc, ValueLocations}; use ir::{InstructionData, Opcode}; -use isa::{RegUnit, RegInfo}; +use isa::{RegInfo, RegUnit}; use std::fmt; use std::vec::Vec; diff --git a/lib/cretonne/src/regalloc/live_value_tracker.rs b/lib/cretonne/src/regalloc/live_value_tracker.rs index ee1f58944b..27a76deb5c 100644 --- a/lib/cretonne/src/regalloc/live_value_tracker.rs +++ b/lib/cretonne/src/regalloc/live_value_tracker.rs @@ -6,7 +6,7 @@ use dominator_tree::DominatorTree; use entity::{EntityList, ListPool}; -use ir::{Inst, Ebb, Value, DataFlowGraph, Layout, ExpandedProgramPoint}; +use ir::{DataFlowGraph, Ebb, ExpandedProgramPoint, Inst, Layout, Value}; use partition_slice::partition_slice; use regalloc::affinity::Affinity; use regalloc::liveness::Liveness; diff --git a/lib/cretonne/src/regalloc/liveness.rs b/lib/cretonne/src/regalloc/liveness.rs index 9a76cb5899..1b82d98bf8 100644 --- a/lib/cretonne/src/regalloc/liveness.rs +++ b/lib/cretonne/src/regalloc/liveness.rs @@ -178,10 +178,10 @@ use entity::SparseMap; use flowgraph::ControlFlowGraph; use ir::dfg::ValueDef; -use ir::{Function, Value, Inst, Ebb, Layout, ProgramPoint}; -use isa::{TargetIsa, EncInfo}; +use ir::{Ebb, Function, Inst, Layout, ProgramPoint, Value}; +use isa::{EncInfo, TargetIsa}; use regalloc::affinity::Affinity; -use regalloc::liverange::{LiveRange, LiveRangeForest, LiveRangeContext}; +use regalloc::liverange::{LiveRange, LiveRangeContext, LiveRangeForest}; use std::mem; use std::ops::Index; use std::vec::Vec; @@ -378,7 +378,6 @@ impl Liveness { mem::replace(&mut lr.affinity, Affinity::Stack) } - /// Compute the live ranges of all SSA values used in `func`. /// This clears out any existing analysis stored in this data structure. pub fn compute(&mut self, isa: &TargetIsa, func: &mut Function, cfg: &ControlFlowGraph) { diff --git a/lib/cretonne/src/regalloc/liverange.rs b/lib/cretonne/src/regalloc/liverange.rs index 2d66b010f7..79526c613d 100644 --- a/lib/cretonne/src/regalloc/liverange.rs +++ b/lib/cretonne/src/regalloc/liverange.rs @@ -109,7 +109,7 @@ use bforest; use entity::SparseMapValue; -use ir::{Inst, Ebb, Value, Layout, ProgramPoint, ExpandedProgramPoint, ProgramOrder}; +use ir::{Ebb, ExpandedProgramPoint, Inst, Layout, ProgramOrder, ProgramPoint, Value}; use regalloc::affinity::Affinity; use std::cmp::Ordering; @@ -457,9 +457,9 @@ impl SparseMapValue for GenLiveRange { mod tests { use super::{GenLiveRange, LiveRangeContext}; use bforest; - use ir::{Inst, Ebb, Value}; + use ir::{Ebb, Inst, Value}; use entity::EntityRef; - use ir::{ProgramOrder, ExpandedProgramPoint}; + use ir::{ExpandedProgramPoint, ProgramOrder}; use std::cmp::Ordering; use std::vec::Vec; @@ -543,7 +543,6 @@ mod tests { // Save for next round. prev_end = Some(end); } - } } diff --git a/lib/cretonne/src/regalloc/pressure.rs b/lib/cretonne/src/regalloc/pressure.rs index 67e0e99b70..6bbe2b75a5 100644 --- a/lib/cretonne/src/regalloc/pressure.rs +++ b/lib/cretonne/src/regalloc/pressure.rs @@ -36,7 +36,7 @@ // Remove once we're using the pressure tracker. #![allow(dead_code)] -use isa::registers::{RegInfo, MAX_TRACKED_TOPRCS, RegClass, RegClassMask}; +use isa::registers::{RegClass, RegClassMask, RegInfo, MAX_TRACKED_TOPRCS}; use regalloc::AllocatableSet; use std::cmp::min; use std::fmt; @@ -135,7 +135,7 @@ impl Pressure { /// `can_take()` to check again. fn check_avail(&self, rc: RegClass) -> RegClassMask { let entry = match self.toprc.get(rc.toprc as usize) { - None => return 0, // Not a pressure tracked bank. + None => return 0, // Not a pressure tracked bank. Some(e) => e, }; let mask = 1 << rc.toprc; @@ -269,7 +269,7 @@ impl fmt::Display for Pressure { #[cfg(test)] #[cfg(build_arm32)] mod tests { - use isa::{TargetIsa, RegClass}; + use isa::{RegClass, TargetIsa}; use regalloc::AllocatableSet; use std::borrow::Borrow; use super::Pressure; diff --git a/lib/cretonne/src/regalloc/reload.rs b/lib/cretonne/src/regalloc/reload.rs index 106830bc19..2ce9a04f75 100644 --- a/lib/cretonne/src/regalloc/reload.rs +++ b/lib/cretonne/src/regalloc/reload.rs @@ -12,10 +12,10 @@ use cursor::{Cursor, EncCursor}; use dominator_tree::DominatorTree; use entity::{SparseMap, SparseMapValue}; -use ir::{Ebb, Inst, Value, Function}; -use ir::{InstBuilder, AbiParam, ArgumentLoc}; +use ir::{Ebb, Function, Inst, Value}; +use ir::{AbiParam, ArgumentLoc, InstBuilder}; use isa::RegClass; -use isa::{TargetIsa, Encoding, EncInfo, RecipeConstraints, ConstraintKind}; +use isa::{ConstraintKind, EncInfo, Encoding, RecipeConstraints, TargetIsa}; use regalloc::affinity::Affinity; use regalloc::live_value_tracker::{LiveValue, LiveValueTracker}; use regalloc::liveness::Liveness; diff --git a/lib/cretonne/src/regalloc/solver.rs b/lib/cretonne/src/regalloc/solver.rs index 3559623ae4..92b7a62679 100644 --- a/lib/cretonne/src/regalloc/solver.rs +++ b/lib/cretonne/src/regalloc/solver.rs @@ -350,7 +350,6 @@ impl Move { } } - /// Get the value being moved. fn value(&self) -> Value { match *self { @@ -1161,9 +1160,9 @@ impl fmt::Display for Solver { mod tests { use entity::EntityRef; use ir::Value; - use isa::{TargetIsa, RegClass, RegUnit, RegInfo}; + use isa::{RegClass, RegInfo, RegUnit, TargetIsa}; use regalloc::AllocatableSet; - use super::{Solver, Move}; + use super::{Move, Solver}; use std::boxed::Box; // Make an arm32 `TargetIsa`, if possible. @@ -1396,7 +1395,7 @@ mod tests { mov(v15, gpr, r5, r3), mov(v14, gpr, r4, r5), mov(v13, gpr, r1, r4), - fill(v10, gpr, 0, r1), // Finally complete cycle 1. + fill(v10, gpr, 0, r1) // Finally complete cycle 1. ] ); } diff --git a/lib/cretonne/src/regalloc/spilling.rs b/lib/cretonne/src/regalloc/spilling.rs index f616ea3b74..5a695eeb8b 100644 --- a/lib/cretonne/src/regalloc/spilling.rs +++ b/lib/cretonne/src/regalloc/spilling.rs @@ -17,9 +17,9 @@ use cursor::{Cursor, EncCursor}; use dominator_tree::DominatorTree; -use ir::{InstBuilder, Function, Ebb, Inst, Value, ValueLoc, SigRef}; -use isa::registers::{RegClassMask, RegClassIndex}; -use isa::{TargetIsa, RegInfo, EncInfo, RecipeConstraints, ConstraintKind}; +use ir::{Ebb, Function, Inst, InstBuilder, SigRef, Value, ValueLoc}; +use isa::registers::{RegClassIndex, RegClassMask}; +use isa::{ConstraintKind, EncInfo, RecipeConstraints, RegInfo, TargetIsa}; use regalloc::affinity::Affinity; use regalloc::live_value_tracker::{LiveValue, LiveValueTracker}; use regalloc::liveness::Liveness; @@ -359,12 +359,10 @@ impl<'a> Context<'a> { if abi.location.is_reg() { let (rci, spilled) = match self.liveness[arg].affinity { Affinity::Reg(rci) => (rci, false), - Affinity::Stack => { - ( - self.cur.isa.regclass_for_abi_type(abi.value_type).into(), - true, - ) - } + Affinity::Stack => ( + self.cur.isa.regclass_for_abi_type(abi.value_type).into(), + true, + ), Affinity::None => panic!("Missing affinity for {}", arg), }; let mut reguse = RegUse::new(arg, fixed_args + idx, rci); diff --git a/lib/cretonne/src/regalloc/virtregs.rs b/lib/cretonne/src/regalloc/virtregs.rs index 8069a0b69b..4583effe4f 100644 --- a/lib/cretonne/src/regalloc/virtregs.rs +++ b/lib/cretonne/src/regalloc/virtregs.rs @@ -14,9 +14,9 @@ use dbg::DisplayList; use dominator_tree::DominatorTreePreorder; use entity::{EntityList, ListPool}; -use entity::{PrimaryMap, EntityMap, Keys}; +use entity::{EntityMap, Keys, PrimaryMap}; use entity::EntityRef; -use ir::{Value, Function}; +use ir::{Function, Value}; use packed_option::PackedOption; use ref_slice::ref_slice; use std::cmp::Ordering; diff --git a/lib/cretonne/src/scoped_hash_map.rs b/lib/cretonne/src/scoped_hash_map.rs index ded42672ab..4acc7087f0 100644 --- a/lib/cretonne/src/scoped_hash_map.rs +++ b/lib/cretonne/src/scoped_hash_map.rs @@ -4,7 +4,7 @@ //! container that has a concept of scopes that can be entered and exited, such that //! values inserted while inside a scope aren't visible outside the scope. -use std::collections::{HashMap, hash_map}; +use std::collections::{hash_map, HashMap}; use std::hash::Hash; use std::mem; diff --git a/lib/cretonne/src/settings.rs b/lib/cretonne/src/settings.rs index 20ba99e0d9..ed1d8cd168 100644 --- a/lib/cretonne/src/settings.rs +++ b/lib/cretonne/src/settings.rs @@ -357,18 +357,18 @@ mod tests { assert_eq!( f.to_string(), "[shared]\n\ - opt_level = \"default\"\n\ - enable_verifier = true\n\ - is_64bit = false\n\ - is_pic = false\n\ - return_at_end = false\n\ - avoid_div_traps = false\n\ - is_compressed = false\n\ - enable_float = true\n\ - enable_simd = true\n\ - enable_atomics = true\n\ - spiderwasm_prologue_words = 0\n\ - allones_funcaddrs = false\n" + opt_level = \"default\"\n\ + enable_verifier = true\n\ + is_64bit = false\n\ + is_pic = false\n\ + return_at_end = false\n\ + avoid_div_traps = false\n\ + is_compressed = false\n\ + enable_float = true\n\ + enable_simd = true\n\ + enable_atomics = true\n\ + spiderwasm_prologue_words = 0\n\ + allones_funcaddrs = false\n" ); assert_eq!(f.opt_level(), super::OptLevel::Default); assert_eq!(f.enable_simd(), true); diff --git a/lib/cretonne/src/simple_gvn.rs b/lib/cretonne/src/simple_gvn.rs index 1cd82e4b2c..073101cd9c 100644 --- a/lib/cretonne/src/simple_gvn.rs +++ b/lib/cretonne/src/simple_gvn.rs @@ -2,7 +2,7 @@ use cursor::{Cursor, FuncCursor}; use dominator_tree::DominatorTree; -use ir::{InstructionData, Function, Inst, Opcode, Type}; +use ir::{Function, Inst, InstructionData, Opcode, Type}; use scoped_hash_map::ScopedHashMap; use timing; use std::vec::Vec; diff --git a/lib/cretonne/src/stack_layout.rs b/lib/cretonne/src/stack_layout.rs index 0cf6e77527..9d723791d7 100644 --- a/lib/cretonne/src/stack_layout.rs +++ b/lib/cretonne/src/stack_layout.rs @@ -1,9 +1,9 @@ //! Computing stack layout. use ir::StackSlots; -use ir::stackslot::{StackSize, StackOffset, StackSlotKind}; +use ir::stackslot::{StackOffset, StackSize, StackSlotKind}; use result::CtonError; -use std::cmp::{min, max}; +use std::cmp::{max, min}; /// Compute the stack frame layout. /// @@ -110,7 +110,7 @@ pub fn layout_stack(frame: &mut StackSlots, alignment: StackSize) -> Result Verifier<'a> { } fn ebb_integrity(&self, ebb: Ebb, inst: Inst) -> Result { - let is_terminator = self.func.dfg[inst].opcode().is_terminator(); let is_last_inst = self.func.layout.last_inst(ebb) == Some(inst); @@ -1155,7 +1154,7 @@ impl<'a> Verifier<'a> { #[cfg(test)] mod tests { - use super::{Verifier, Error}; + use super::{Error, Verifier}; use ir::Function; use ir::instructions::{InstructionData, Opcode}; use entity::EntityList; diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index 87316c8ca4..dee3ab0346 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -3,9 +3,9 @@ //! The `write` module provides the `write_function` function which converts an IR `Function` to an //! equivalent textual form. This textual form can be read back by the `cretonne-reader` crate. -use ir::{Function, DataFlowGraph, Ebb, Inst, Value, ValueDef, Type, SigRef}; -use isa::{TargetIsa, RegInfo}; -use std::fmt::{self, Result, Error, Write}; +use ir::{DataFlowGraph, Ebb, Function, Inst, SigRef, Type, Value, ValueDef}; +use isa::{RegInfo, TargetIsa}; +use std::fmt::{self, Error, Result, Write}; use std::result; use packed_option::ReservedValue; use std::string::String; @@ -146,7 +146,6 @@ pub fn write_ebb(w: &mut Write, func: &Function, isa: Option<&TargetIsa>, ebb: E Ok(()) } - //---------------------------------------------------------------------- // // Instructions @@ -452,7 +451,7 @@ impl<'a> fmt::Display for DisplayValues<'a> { #[cfg(test)] mod tests { - use ir::{Function, ExternalName, StackSlotData, StackSlotKind}; + use ir::{ExternalName, Function, StackSlotData, StackSlotKind}; use ir::types; use std::string::ToString; diff --git a/lib/filetests/src/concurrent.rs b/lib/filetests/src/concurrent.rs index 1db5aa6832..a93d39cddf 100644 --- a/lib/filetests/src/concurrent.rs +++ b/lib/filetests/src/concurrent.rs @@ -6,12 +6,12 @@ use cretonne::timing; use std::panic::catch_unwind; use std::path::{Path, PathBuf}; -use std::sync::mpsc::{channel, Sender, Receiver}; +use std::sync::mpsc::{channel, Receiver, Sender}; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; use num_cpus; -use {TestResult, runone}; +use {runone, TestResult}; /// Request sent to worker threads contains jobid and path. struct Request(usize, PathBuf); diff --git a/lib/filetests/src/runner.rs b/lib/filetests/src/runner.rs index d2d2db55c7..f9e8fb3638 100644 --- a/lib/filetests/src/runner.rs +++ b/lib/filetests/src/runner.rs @@ -8,7 +8,7 @@ use std::fmt::{self, Display}; use std::ffi::OsStr; use std::path::{Path, PathBuf}; use std::time; -use {TestResult, runone}; +use {runone, TestResult}; use concurrent::{ConcurrentRunner, Reply}; /// Timeout in seconds when we're not making progress. @@ -302,7 +302,6 @@ impl TestRunner { // Inter-quartile range. let iqr = q3 - q1; - // Cut-off for what we consider a 'slow' test: 3 IQR from the 75% quartile. // // Q3 + 1.5 IQR are the data points that would be plotted as outliers outside a box plot, @@ -319,7 +318,6 @@ impl TestRunner { { println!("slow: {}", t) } - } /// Scan pushed directories for tests and run them. diff --git a/lib/filetests/src/runone.rs b/lib/filetests/src/runone.rs index dab44ff920..4b3033ea2e 100644 --- a/lib/filetests/src/runone.rs +++ b/lib/filetests/src/runone.rs @@ -13,8 +13,8 @@ use cretonne::verify_function; use cretonne::print_errors::pretty_verifier_error; use cton_reader::parse_test; use cton_reader::IsaSpec; -use {TestResult, new_subtest}; -use subtest::{SubTest, Context, Result}; +use {new_subtest, TestResult}; +use subtest::{Context, Result, SubTest}; /// Read an entire file into a string. fn read_to_string>(path: P) -> io::Result { @@ -82,7 +82,6 @@ pub fn run(path: &Path) -> TestResult { run_one_test(last_tuple, Cow::Owned(func), &mut context)?; } - Ok(started.elapsed()) } diff --git a/lib/filetests/src/subtest.rs b/lib/filetests/src/subtest.rs index 39812ed228..4395780021 100644 --- a/lib/filetests/src/subtest.rs +++ b/lib/filetests/src/subtest.rs @@ -5,8 +5,8 @@ use std::borrow::Cow; use cretonne::ir::Function; use cretonne::isa::TargetIsa; use cretonne::settings::{Flags, FlagsOrIsa}; -use cton_reader::{Details, Comment}; -use filecheck::{CheckerBuilder, Checker, NO_VARIABLES}; +use cton_reader::{Comment, Details}; +use filecheck::{Checker, CheckerBuilder, NO_VARIABLES}; pub type Result = result::Result; diff --git a/lib/filetests/src/test_binemit.rs b/lib/filetests/src/test_binemit.rs index 81e48f84fe..db3d9be634 100644 --- a/lib/filetests/src/test_binemit.rs +++ b/lib/filetests/src/test_binemit.rs @@ -13,7 +13,7 @@ use cretonne::ir::entities::AnyEntity; use cretonne::binemit::RegDiversions; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{SubTest, Context, Result}; +use subtest::{Context, Result, SubTest}; use match_directive::match_directive; struct TestBinEmit; @@ -43,8 +43,6 @@ impl TextSink { } } - - impl binemit::CodeSink for TextSink { fn offset(&self) -> binemit::CodeOffset { self.offset @@ -80,23 +78,11 @@ impl binemit::CodeSink for TextSink { name: &ir::ExternalName, addend: binemit::Addend, ) { - write!( - self.text, - "{}({}", - reloc, - name, - ).unwrap(); + write!(self.text, "{}({}", reloc, name,).unwrap(); if addend != 0 { - write!( - self.text, - "{:+}", - addend, - ).unwrap(); + write!(self.text, "{:+}", addend,).unwrap(); } - write!( - self.text, - ") ", - ).unwrap(); + write!(self.text, ") ",).unwrap(); } fn reloc_jt(&mut self, reloc: binemit::Reloc, jt: ir::JumpTable) { @@ -278,10 +264,10 @@ impl SubTest for TestBinEmit { )); } return Err(format!( - "No matching encodings for {} in {}", - func.dfg.display_inst(inst, isa), - DisplayList(&encodings), - )); + "No matching encodings for {} in {}", + func.dfg.display_inst(inst, isa), + DisplayList(&encodings), + )); } let have = sink.text.trim(); if have != want { diff --git a/lib/filetests/src/test_cat.rs b/lib/filetests/src/test_cat.rs index fbbcbd034b..42b18b3625 100644 --- a/lib/filetests/src/test_cat.rs +++ b/lib/filetests/src/test_cat.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use cretonne::ir::Function; use cton_reader::TestCommand; -use subtest::{self, SubTest, Context, Result as STResult}; +use subtest::{self, Context, Result as STResult, SubTest}; /// Object implementing the `test cat` sub-test. /// diff --git a/lib/filetests/src/test_compile.rs b/lib/filetests/src/test_compile.rs index af2343f765..5217f7ebb6 100644 --- a/lib/filetests/src/test_compile.rs +++ b/lib/filetests/src/test_compile.rs @@ -7,7 +7,7 @@ use cretonne::ir; use cretonne; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; diff --git a/lib/filetests/src/test_dce.rs b/lib/filetests/src/test_dce.rs index 5a57d83e3e..4e826c9abc 100644 --- a/lib/filetests/src/test_dce.rs +++ b/lib/filetests/src/test_dce.rs @@ -9,7 +9,7 @@ use cretonne::ir::Function; use cretonne; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; diff --git a/lib/filetests/src/test_domtree.rs b/lib/filetests/src/test_domtree.rs index 6eae539644..fed38d9d50 100644 --- a/lib/filetests/src/test_domtree.rs +++ b/lib/filetests/src/test_domtree.rs @@ -17,7 +17,7 @@ use cretonne::flowgraph::ControlFlowGraph; use cretonne::ir::Function; use cretonne::ir::entities::AnyEntity; use cton_reader::TestCommand; -use subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::{Borrow, Cow}; use std::collections::HashMap; use std::fmt::{self, Write}; @@ -76,7 +76,7 @@ impl SubTest for TestDomtree { Some(got_inst) if got_inst != inst => { return Err(format!( "mismatching idoms for {}:\n\ - want: {}, got: {}", + want: {}, got: {}", src_ebb, inst, got_inst @@ -85,7 +85,7 @@ impl SubTest for TestDomtree { None => { return Err(format!( "mismatching idoms for {}:\n\ - want: {}, got: unreachable", + want: {}, got: unreachable", src_ebb, inst )); @@ -105,7 +105,7 @@ impl SubTest for TestDomtree { if let Some(got_inst) = domtree.idom(ebb) { return Err(format!( "mismatching idoms for renumbered {}:\n\ - want: unrechable, got: {}", + want: unrechable, got: {}", ebb, got_inst )); diff --git a/lib/filetests/src/test_legalizer.rs b/lib/filetests/src/test_legalizer.rs index 08f6c53ae4..76bd9f491b 100644 --- a/lib/filetests/src/test_legalizer.rs +++ b/lib/filetests/src/test_legalizer.rs @@ -8,7 +8,7 @@ use cretonne; use cretonne::ir::Function; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{run_filecheck, Context, Result, SubTest}; use std::fmt::Write; struct TestLegalizer; diff --git a/lib/filetests/src/test_licm.rs b/lib/filetests/src/test_licm.rs index f7d4397b5a..bed36b44c2 100644 --- a/lib/filetests/src/test_licm.rs +++ b/lib/filetests/src/test_licm.rs @@ -9,7 +9,7 @@ use cretonne::ir::Function; use cretonne; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; diff --git a/lib/filetests/src/test_postopt.rs b/lib/filetests/src/test_postopt.rs index 34ffb3f462..ad26a06c30 100644 --- a/lib/filetests/src/test_postopt.rs +++ b/lib/filetests/src/test_postopt.rs @@ -6,7 +6,7 @@ use cretonne::ir::Function; use cretonne; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; diff --git a/lib/filetests/src/test_preopt.rs b/lib/filetests/src/test_preopt.rs index c141d28480..8a30f0feb3 100644 --- a/lib/filetests/src/test_preopt.rs +++ b/lib/filetests/src/test_preopt.rs @@ -6,7 +6,7 @@ use cretonne::ir::Function; use cretonne; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; diff --git a/lib/filetests/src/test_print_cfg.rs b/lib/filetests/src/test_print_cfg.rs index b043dc58b2..4c0b3250d2 100644 --- a/lib/filetests/src/test_print_cfg.rs +++ b/lib/filetests/src/test_print_cfg.rs @@ -8,7 +8,7 @@ use std::borrow::Cow; use cretonne::ir::Function; use cretonne::cfg_printer::CFGPrinter; use cton_reader::TestCommand; -use subtest::{self, SubTest, Context, Result as STResult}; +use subtest::{self, Context, Result as STResult, SubTest}; /// Object implementing the `test print-cfg` sub-test. struct TestPrintCfg; diff --git a/lib/filetests/src/test_regalloc.rs b/lib/filetests/src/test_regalloc.rs index 7cd0788928..e94a142dcc 100644 --- a/lib/filetests/src/test_regalloc.rs +++ b/lib/filetests/src/test_regalloc.rs @@ -9,7 +9,7 @@ use cretonne::ir::Function; use cretonne; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; diff --git a/lib/filetests/src/test_simple_gvn.rs b/lib/filetests/src/test_simple_gvn.rs index f967c3fa91..04fcb078dd 100644 --- a/lib/filetests/src/test_simple_gvn.rs +++ b/lib/filetests/src/test_simple_gvn.rs @@ -9,7 +9,7 @@ use cretonne::ir::Function; use cretonne; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{SubTest, Context, Result, run_filecheck}; +use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; diff --git a/lib/filetests/src/test_verifier.rs b/lib/filetests/src/test_verifier.rs index 6db9c681ce..906b279408 100644 --- a/lib/filetests/src/test_verifier.rs +++ b/lib/filetests/src/test_verifier.rs @@ -13,7 +13,7 @@ use std::borrow::{Borrow, Cow}; use cretonne::verify_function; use cretonne::ir::Function; use cton_reader::TestCommand; -use subtest::{SubTest, Context, Result}; +use subtest::{Context, Result, SubTest}; use match_directive::match_directive; struct TestVerifier; diff --git a/lib/frontend/src/frontend.rs b/lib/frontend/src/frontend.rs index 37d2fe0206..00e5de53f1 100644 --- a/lib/frontend/src/frontend.rs +++ b/lib/frontend/src/frontend.rs @@ -1,13 +1,13 @@ //! A frontend for building Cretonne IR from other languages. use cretonne::cursor::{Cursor, FuncCursor}; use cretonne::ir; -use cretonne::ir::{Ebb, Type, Value, Function, Inst, JumpTable, StackSlot, JumpTableData, - StackSlotData, DataFlowGraph, InstructionData, ExtFuncData, FuncRef, SigRef, - Signature, InstBuilderBase, GlobalVarData, GlobalVar, HeapData, Heap}; +use cretonne::ir::{DataFlowGraph, Ebb, ExtFuncData, FuncRef, Function, GlobalVar, GlobalVarData, + Heap, HeapData, Inst, InstBuilderBase, InstructionData, JumpTable, + JumpTableData, SigRef, Signature, StackSlot, StackSlotData, Type, Value}; use cretonne::ir::function::DisplayFunction; use cretonne::isa::TargetIsa; -use ssa::{SSABuilder, SideEffects, Block}; -use cretonne::entity::{EntityRef, EntityMap, EntitySet}; +use ssa::{Block, SSABuilder, SideEffects}; +use cretonne::entity::{EntityMap, EntityRef, EntitySet}; use cretonne::packed_option::PackedOption; /// Structure used for translating a series of functions into Cretonne IR. @@ -28,7 +28,6 @@ where types: EntityMap, } - /// Temporary object used to build a single Cretonne IR `Function`. pub struct FunctionBuilder<'a, Variable: 'a> where @@ -125,7 +124,8 @@ where } impl<'short, 'long, Variable> InstBuilderBase<'short> for FuncInstBuilder<'short, 'long, Variable> - where Variable: EntityRef +where + Variable: EntityRef, { fn data_flow_graph(&self) -> &DataFlowGraph { &self.builder.func.dfg @@ -165,13 +165,14 @@ impl<'short, 'long, Variable> InstBuilderBase<'short> for FuncInstBuilder<'short // multiple times, so we must deduplicate. let mut unique = EntitySet::::new(); for dest_ebb in self.builder - .func - .jump_tables - .get(table) - .expect("you are referencing an undeclared jump table") - .entries() - .map(|(_, ebb)| ebb) - .filter(|dest_ebb| unique.insert(*dest_ebb)) { + .func + .jump_tables + .get(table) + .expect("you are referencing an undeclared jump table") + .entries() + .map(|(_, ebb)| ebb) + .filter(|dest_ebb| unique.insert(*dest_ebb)) + { self.builder.func_ctx.ssa.declare_ebb_predecessor( dest_ebb, self.builder.position.basic_block.unwrap(), @@ -592,9 +593,9 @@ where mod tests { use cretonne::entity::EntityRef; - use cretonne::ir::{ExternalName, Function, CallConv, Signature, AbiParam, InstBuilder}; + use cretonne::ir::{AbiParam, CallConv, ExternalName, Function, InstBuilder, Signature}; use cretonne::ir::types::*; - use frontend::{FunctionBuilderContext, FunctionBuilder}; + use frontend::{FunctionBuilder, FunctionBuilderContext}; use cretonne::verifier::verify_function; use cretonne::settings; use Variable; diff --git a/lib/frontend/src/lib.rs b/lib/frontend/src/lib.rs index 628195428a..329b6afb50 100644 --- a/lib/frontend/src/lib.rs +++ b/lib/frontend/src/lib.rs @@ -127,16 +127,12 @@ //! } //! ``` -#![deny(missing_docs, - trivial_numeric_casts, - unused_extern_crates)] - -#![cfg_attr(feature="cargo-clippy", - allow(new_without_default, redundant_field_names))] +#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![cfg_attr(feature = "cargo-clippy", allow(new_without_default, redundant_field_names))] extern crate cretonne; -pub use frontend::{FunctionBuilderContext, FunctionBuilder}; +pub use frontend::{FunctionBuilder, FunctionBuilderContext}; pub use variable::Variable; mod frontend; diff --git a/lib/frontend/src/ssa.rs b/lib/frontend/src/ssa.rs index 6fa59e784d..96085c38f8 100644 --- a/lib/frontend/src/ssa.rs +++ b/lib/frontend/src/ssa.rs @@ -6,9 +6,9 @@ //! Lecture Notes in Computer Science, vol 7791. Springer, Berlin, Heidelberg use cretonne::cursor::{Cursor, FuncCursor}; -use cretonne::ir::{Ebb, Value, Inst, Type, Function, InstBuilder}; +use cretonne::ir::{Ebb, Function, Inst, InstBuilder, Type, Value}; use cretonne::ir::instructions::BranchInfo; -use cretonne::entity::{EntityRef, PrimaryMap, EntityMap}; +use cretonne::entity::{EntityMap, EntityRef, PrimaryMap}; use cretonne::packed_option::PackedOption; use cretonne::packed_option::ReservedValue; use std::u32; @@ -715,7 +715,7 @@ where mod tests { use cretonne::cursor::{Cursor, FuncCursor}; use cretonne::entity::EntityRef; - use cretonne::ir::{Function, InstBuilder, Inst, JumpTableData, Opcode}; + use cretonne::ir::{Function, Inst, InstBuilder, JumpTableData, Opcode}; use cretonne::ir::types::*; use cretonne::verify_function; use cretonne::ir::instructions::BranchInfo; @@ -960,7 +960,6 @@ mod tests { assert_eq!(func.dfg.ebb_params(ebb1)[0], z2); assert_eq!(func.dfg.ebb_params(ebb1)[1], y3); assert_eq!(func.dfg.resolve_aliases(x3), x1); - } #[test] diff --git a/lib/native/src/lib.rs b/lib/native/src/lib.rs index ea828ea252..15f3e69350 100644 --- a/lib/native/src/lib.rs +++ b/lib/native/src/lib.rs @@ -1,9 +1,7 @@ //! Performs autodetection of the host for the purposes of running //! Cretonne to generate code to run on the same machine. -#![deny(missing_docs, - trivial_numeric_casts, - unused_extern_crates)] +#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] extern crate cretonne; diff --git a/lib/reader/src/isaspec.rs b/lib/reader/src/isaspec.rs index 2b1e8fae6d..6cc29a81a1 100644 --- a/lib/reader/src/isaspec.rs +++ b/lib/reader/src/isaspec.rs @@ -6,9 +6,9 @@ //! If a test case file contains `isa` commands, the tests will only be run against the specified //! ISAs. If the file contains no `isa` commands, the tests will be run against all supported ISAs. -use cretonne::settings::{Flags, Configurable, Error as SetError}; +use cretonne::settings::{Configurable, Error as SetError, Flags}; use cretonne::isa::TargetIsa; -use error::{Result, Location}; +use error::{Location, Result}; use testcommand::TestOption; /// The ISA specifications in a `.cton` file. diff --git a/lib/reader/src/lexer.rs b/lib/reader/src/lexer.rs index 4b1a952d1b..c55bbf1dd4 100644 --- a/lib/reader/src/lexer.rs +++ b/lib/reader/src/lexer.rs @@ -5,7 +5,7 @@ use std::u16; #[allow(unused_imports)] use std::ascii::AsciiExt; use cretonne::ir::types; -use cretonne::ir::{Value, Ebb}; +use cretonne::ir::{Ebb, Value}; use error::Location; /// A Token returned from the `Lexer`. @@ -458,7 +458,7 @@ mod tests { use super::trailing_digits; use super::*; use cretonne::ir::types; - use cretonne::ir::{Value, Ebb}; + use cretonne::ir::{Ebb, Value}; use error::Location; #[test] @@ -556,7 +556,7 @@ mod tests { fn lex_identifiers() { let mut lex = Lexer::new( "v0 v00 vx01 ebb1234567890 ebb5234567890 v1x vx1 vxvx4 \ - function0 function b1 i32x4 f32x5 \ + function0 function b1 i32x4 f32x5 \ iflags fflags iflagss", ); assert_eq!( diff --git a/lib/reader/src/lib.rs b/lib/reader/src/lib.rs index d6c23cfa81..58fe21b5ce 100644 --- a/lib/reader/src/lib.rs +++ b/lib/reader/src/lib.rs @@ -3,17 +3,15 @@ //! The `cton_reader` library supports reading .cton files. This functionality is needed for testing //! Cretonne, but is not essential for a JIT compiler. -#![deny(missing_docs, - trivial_numeric_casts, - unused_extern_crates)] +#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] extern crate cretonne; -pub use error::{Location, Result, Error}; +pub use error::{Error, Location, Result}; pub use parser::{parse_functions, parse_test}; pub use testcommand::{TestCommand, TestOption}; -pub use testfile::{TestFile, Details, Comment}; -pub use isaspec::{IsaSpec, parse_options}; +pub use testfile::{Comment, Details, TestFile}; +pub use isaspec::{parse_options, IsaSpec}; pub use sourcemap::SourceMap; mod error; diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index c9da49d9ee..48e2e2745b 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -3,22 +3,21 @@ use std::str::FromStr; use std::{u16, u32}; use std::mem; -use cretonne::ir::{Function, Ebb, Opcode, Value, Type, ExternalName, CallConv, StackSlotData, - StackSlotKind, JumpTable, JumpTableData, Signature, AbiParam, - ArgumentExtension, ExtFuncData, SigRef, FuncRef, StackSlot, ValueLoc, - ArgumentLoc, MemFlags, GlobalVar, GlobalVarData, Heap, HeapData, HeapStyle, - HeapBase}; +use cretonne::ir::{AbiParam, ArgumentExtension, ArgumentLoc, CallConv, Ebb, ExtFuncData, + ExternalName, FuncRef, Function, GlobalVar, GlobalVarData, Heap, HeapBase, + HeapData, HeapStyle, JumpTable, JumpTableData, MemFlags, Opcode, SigRef, + Signature, StackSlot, StackSlotData, StackSlotKind, Type, Value, ValueLoc}; use cretonne::ir; use cretonne::ir::types::VOID; -use cretonne::ir::immediates::{Imm64, Uimm32, Offset32, Ieee32, Ieee64}; +use cretonne::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm32}; use cretonne::ir::entities::AnyEntity; -use cretonne::ir::instructions::{InstructionFormat, InstructionData, VariableArgs}; -use cretonne::isa::{self, TargetIsa, Encoding, RegUnit}; +use cretonne::ir::instructions::{InstructionData, InstructionFormat, VariableArgs}; +use cretonne::isa::{self, Encoding, RegUnit, TargetIsa}; use cretonne::{settings, timing}; use cretonne::entity::EntityRef; use cretonne::packed_option::ReservedValue; -use testfile::{TestFile, Details, Comment}; -use error::{Location, Error, Result}; +use testfile::{Comment, Details, TestFile}; +use error::{Error, Location, Result}; use lexer::{self, Lexer, Token}; use testcommand::TestCommand; use isaspec; @@ -1189,12 +1188,12 @@ impl<'a> Parser<'a> { } "bound" => { data.style = match style_name { - "dynamic" => { - HeapStyle::Dynamic { bound_gv: self.match_gv("expected gv bound")? } - } - "static" => { - HeapStyle::Static { bound: self.match_imm64("expected integer bound")? } - } + "dynamic" => HeapStyle::Dynamic { + bound_gv: self.match_gv("expected gv bound")?, + }, + "static" => HeapStyle::Static { + bound: self.match_imm64("expected integer bound")?, + }, t => return err!(self.loc, "unknown heap style '{}'", t), }; } @@ -1736,7 +1735,7 @@ impl<'a> Parser<'a> { return err!( self.loc, "instruction produces {} result values, but {} locations were \ - specified", + specified", results.len(), result_locations.len() ); @@ -1791,7 +1790,7 @@ impl<'a> Parser<'a> { return err!( self.loc, "type variable required for polymorphic opcode, e.g. '{}.{}'; \ - can't infer from {} which is not yet defined", + can't infer from {} which is not yet defined", opcode, constraints.ctrl_typeset().unwrap().example(), ctrl_src_value @@ -1801,7 +1800,7 @@ impl<'a> Parser<'a> { return err!( self.loc, "type variable required for polymorphic opcode, e.g. '{}.{}'; \ - can't infer from {} which is not yet resolved", + can't infer from {} which is not yet resolved", opcode, constraints.ctrl_typeset().unwrap().example(), ctrl_src_value @@ -1890,36 +1889,26 @@ impl<'a> Parser<'a> { opcode: Opcode, ) -> Result { let idata = match opcode.format() { - InstructionFormat::Unary => { - InstructionData::Unary { - opcode, - arg: self.match_value("expected SSA value operand")?, - } - } - InstructionFormat::UnaryImm => { - InstructionData::UnaryImm { - opcode, - imm: self.match_imm64("expected immediate integer operand")?, - } - } - InstructionFormat::UnaryIeee32 => { - InstructionData::UnaryIeee32 { - opcode, - imm: self.match_ieee32("expected immediate 32-bit float operand")?, - } - } - InstructionFormat::UnaryIeee64 => { - InstructionData::UnaryIeee64 { - opcode, - imm: self.match_ieee64("expected immediate 64-bit float operand")?, - } - } - InstructionFormat::UnaryBool => { - InstructionData::UnaryBool { - opcode, - imm: self.match_bool("expected immediate boolean operand")?, - } - } + InstructionFormat::Unary => InstructionData::Unary { + opcode, + arg: self.match_value("expected SSA value operand")?, + }, + InstructionFormat::UnaryImm => InstructionData::UnaryImm { + opcode, + imm: self.match_imm64("expected immediate integer operand")?, + }, + InstructionFormat::UnaryIeee32 => InstructionData::UnaryIeee32 { + opcode, + imm: self.match_ieee32("expected immediate 32-bit float operand")?, + }, + InstructionFormat::UnaryIeee64 => InstructionData::UnaryIeee64 { + opcode, + imm: self.match_ieee64("expected immediate 64-bit float operand")?, + }, + InstructionFormat::UnaryBool => InstructionData::UnaryBool { + opcode, + imm: self.match_bool("expected immediate boolean operand")?, + }, InstructionFormat::UnaryGlobalVar => { let gv = self.match_gv("expected global variable")?; ctx.check_gv(gv, &self.loc)?; @@ -2406,11 +2395,11 @@ impl<'a> Parser<'a> { #[cfg(test)] mod tests { use super::*; - use cretonne::ir::{CallConv, ArgumentExtension, ArgumentPurpose}; + use cretonne::ir::{ArgumentExtension, ArgumentPurpose, CallConv}; use cretonne::ir::types; use cretonne::ir::StackSlotKind; use cretonne::ir::entities::AnyEntity; - use testfile::{Details, Comment}; + use testfile::{Comment, Details}; use isaspec::IsaSpec; use error::Error; diff --git a/lib/reader/src/sourcemap.rs b/lib/reader/src/sourcemap.rs index 36fb954fd9..b30b172768 100644 --- a/lib/reader/src/sourcemap.rs +++ b/lib/reader/src/sourcemap.rs @@ -7,8 +7,8 @@ //! to parser clients. use cretonne::ir::entities::AnyEntity; -use cretonne::ir::{StackSlot, GlobalVar, Heap, JumpTable, Ebb, Value, SigRef, FuncRef}; -use error::{Result, Location}; +use cretonne::ir::{Ebb, FuncRef, GlobalVar, Heap, JumpTable, SigRef, StackSlot, Value}; +use error::{Location, Result}; use lexer::split_entity_name; use std::collections::HashMap; diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index 97f67d6c48..82fec54e5b 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -22,16 +22,16 @@ //! //! That is why `translate_function_body` takes an object having the `WasmRuntime` trait as //! argument. -use cretonne::ir::{self, InstBuilder, MemFlags, JumpTableData}; +use cretonne::ir::{self, InstBuilder, JumpTableData, MemFlags}; use cretonne::ir::types::*; -use cretonne::ir::condcodes::{IntCC, FloatCC}; +use cretonne::ir::condcodes::{FloatCC, IntCC}; use cretonne::packed_option::ReservedValue; use cton_frontend::{FunctionBuilder, Variable}; -use wasmparser::{Operator, MemoryImmediate}; -use translation_utils::{f32_translation, f64_translation, type_to_type, num_return_values}; -use translation_utils::{TableIndex, SignatureIndex, FunctionIndex, MemoryIndex}; -use state::{TranslationState, ControlStackFrame}; -use std::collections::{HashMap, hash_map}; +use wasmparser::{MemoryImmediate, Operator}; +use translation_utils::{num_return_values, type_to_type, f32_translation, f64_translation}; +use translation_utils::{FunctionIndex, MemoryIndex, SignatureIndex, TableIndex}; +use state::{ControlStackFrame, TranslationState}; +use std::collections::{hash_map, HashMap}; use environ::{FuncEnvironment, GlobalValue}; use std::{i32, u32}; use std::vec::Vec; diff --git a/lib/wasm/src/environ/dummy.rs b/lib/wasm/src/environ/dummy.rs index bb21b7536a..b24499bde0 100644 --- a/lib/wasm/src/environ/dummy.rs +++ b/lib/wasm/src/environ/dummy.rs @@ -1,8 +1,8 @@ //! "Dummy" environment for testing wasm translation. use environ::{FuncEnvironment, GlobalValue, ModuleEnvironment}; -use translation_utils::{Global, Memory, Table, GlobalIndex, TableIndex, SignatureIndex, - FunctionIndex, MemoryIndex}; +use translation_utils::{FunctionIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, + Table, TableIndex}; use func_translator::FuncTranslator; use cretonne::ir::{self, InstBuilder}; use cretonne::ir::types::*; diff --git a/lib/wasm/src/environ/mod.rs b/lib/wasm/src/environ/mod.rs index f45dbd3161..57c9f593b2 100644 --- a/lib/wasm/src/environ/mod.rs +++ b/lib/wasm/src/environ/mod.rs @@ -3,5 +3,5 @@ mod spec; mod dummy; -pub use environ::spec::{ModuleEnvironment, FuncEnvironment, GlobalValue}; +pub use environ::spec::{FuncEnvironment, GlobalValue, ModuleEnvironment}; pub use environ::dummy::DummyEnvironment; diff --git a/lib/wasm/src/environ/spec.rs b/lib/wasm/src/environ/spec.rs index 233188364a..882ca1a30f 100644 --- a/lib/wasm/src/environ/spec.rs +++ b/lib/wasm/src/environ/spec.rs @@ -3,8 +3,8 @@ use cretonne::ir::{self, InstBuilder}; use cretonne::cursor::FuncCursor; use cretonne::settings::Flags; -use translation_utils::{SignatureIndex, FunctionIndex, TableIndex, GlobalIndex, MemoryIndex, - Global, Table, Memory}; +use translation_utils::{FunctionIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, + Table, TableIndex}; use std::vec::Vec; use std::string::String; diff --git a/lib/wasm/src/func_translator.rs b/lib/wasm/src/func_translator.rs index dbb1fc9bcc..159d8120d1 100644 --- a/lib/wasm/src/func_translator.rs +++ b/lib/wasm/src/func_translator.rs @@ -6,10 +6,10 @@ use code_translator::translate_operator; use cretonne::entity::EntityRef; -use cretonne::ir::{self, InstBuilder, Ebb}; -use cretonne::result::{CtonResult, CtonError}; +use cretonne::ir::{self, Ebb, InstBuilder}; +use cretonne::result::{CtonError, CtonResult}; use cretonne::timing; -use cton_frontend::{FunctionBuilderContext, FunctionBuilder, Variable}; +use cton_frontend::{FunctionBuilder, FunctionBuilderContext, Variable}; use environ::FuncEnvironment; use state::TranslationState; use wasmparser::{self, BinaryReader}; diff --git a/lib/wasm/src/lib.rs b/lib/wasm/src/lib.rs index cc35a19fbc..6f0ed8fd70 100644 --- a/lib/wasm/src/lib.rs +++ b/lib/wasm/src/lib.rs @@ -9,18 +9,14 @@ //! //! The main function of this module is [`translate_module`](fn.translate_module.html). -#![deny(missing_docs, - trivial_numeric_casts, - unused_extern_crates)] -#![cfg_attr(feature="clippy", - plugin(clippy(conf_file="../../clippy.toml")))] -#![cfg_attr(feature="cargo-clippy", - allow(new_without_default, redundant_field_names))] +#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] +#![cfg_attr(feature = "cargo-clippy", allow(new_without_default, redundant_field_names))] -extern crate wasmparser; -extern crate cton_frontend; #[macro_use(dbg)] extern crate cretonne; +extern crate cton_frontend; +extern crate wasmparser; mod code_translator; mod func_translator; @@ -32,6 +28,6 @@ mod translation_utils; pub use func_translator::FuncTranslator; pub use module_translator::translate_module; -pub use environ::{FuncEnvironment, ModuleEnvironment, DummyEnvironment, GlobalValue}; -pub use translation_utils::{FunctionIndex, GlobalIndex, TableIndex, MemoryIndex, SignatureIndex, - Global, GlobalInit, Table, Memory}; +pub use environ::{DummyEnvironment, FuncEnvironment, GlobalValue, ModuleEnvironment}; +pub use translation_utils::{FunctionIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, + SignatureIndex, Table, TableIndex}; diff --git a/lib/wasm/src/module_translator.rs b/lib/wasm/src/module_translator.rs index 171f720e12..e345e5ef3c 100644 --- a/lib/wasm/src/module_translator.rs +++ b/lib/wasm/src/module_translator.rs @@ -1,11 +1,11 @@ //! Translation skeleton that traverses the whole WebAssembly module and call helper functions //! to deal with each part of it. use cretonne::timing; -use wasmparser::{ParserState, SectionCode, ParserInput, Parser, WasmDecoder, BinaryReaderError}; -use sections_translator::{SectionParsingError, parse_function_signatures, parse_import_section, - parse_function_section, parse_export_section, parse_start_section, - parse_memory_section, parse_global_section, parse_table_section, - parse_elements_section, parse_data_section}; +use wasmparser::{BinaryReaderError, Parser, ParserInput, ParserState, SectionCode, WasmDecoder}; +use sections_translator::{parse_data_section, parse_elements_section, parse_export_section, + parse_function_section, parse_function_signatures, parse_global_section, + parse_import_section, parse_memory_section, parse_start_section, + parse_table_section, SectionParsingError}; use environ::ModuleEnvironment; use std::string::String; diff --git a/lib/wasm/src/sections_translator.rs b/lib/wasm/src/sections_translator.rs index 05f655ba82..4792c3f450 100644 --- a/lib/wasm/src/sections_translator.rs +++ b/lib/wasm/src/sections_translator.rs @@ -7,12 +7,12 @@ //! The special case of the initialize expressions for table elements offsets or global variables //! is handled, according to the semantics of WebAssembly, to only specific expressions that are //! interpreted on the fly. -use translation_utils::{type_to_type, TableIndex, FunctionIndex, GlobalIndex, SignatureIndex, - MemoryIndex, Global, GlobalInit, Table, TableElementType, Memory}; -use cretonne::ir::{Signature, AbiParam, CallConv}; +use translation_utils::{type_to_type, FunctionIndex, Global, GlobalIndex, GlobalInit, Memory, + MemoryIndex, SignatureIndex, Table, TableElementType, TableIndex}; +use cretonne::ir::{AbiParam, CallConv, Signature}; use cretonne; -use wasmparser::{Parser, ParserState, FuncType, ImportSectionEntryType, ExternalKind, WasmDecoder, - MemoryType, Operator}; +use wasmparser::{ExternalKind, FuncType, ImportSectionEntryType, MemoryType, Operator, Parser, + ParserState, WasmDecoder}; use wasmparser; use std::str::from_utf8; use environ::ModuleEnvironment; diff --git a/lib/wasm/src/state.rs b/lib/wasm/src/state.rs index 5ced6d6056..8d1d86fe80 100644 --- a/lib/wasm/src/state.rs +++ b/lib/wasm/src/state.rs @@ -6,7 +6,7 @@ use cretonne::ir::{self, Ebb, Inst, Value}; use environ::{FuncEnvironment, GlobalValue}; use std::collections::HashMap; -use translation_utils::{GlobalIndex, MemoryIndex, SignatureIndex, FunctionIndex}; +use translation_utils::{FunctionIndex, GlobalIndex, MemoryIndex, SignatureIndex}; use std::vec::Vec; /// A control stack frame can be an `if`, a `block` or a `loop`, each one having the following diff --git a/lib/wasm/tests/wasm_testsuite.rs b/lib/wasm/tests/wasm_testsuite.rs index 5d969c9cc2..1bd6ecf3f9 100644 --- a/lib/wasm/tests/wasm_testsuite.rs +++ b/lib/wasm/tests/wasm_testsuite.rs @@ -1,5 +1,5 @@ -extern crate cton_wasm; extern crate cretonne; +extern crate cton_wasm; extern crate tempdir; use cton_wasm::{translate_module, DummyEnvironment}; From c50675deb8125f2bf4fea187765443c5e8f88885 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 30 Mar 2018 13:24:58 -0700 Subject: [PATCH 71/72] Format with nightly rustfmt-preview, then with rustfmt-0.9 again. --- cranelift/src/cat.rs | 2 +- cranelift/src/compile.rs | 6 ++-- cranelift/src/cton-util.rs | 4 +-- cranelift/src/rsfilecheck.rs | 2 +- cranelift/src/utils.rs | 2 +- cranelift/src/wasm.rs | 8 ++--- lib/cretonne/src/abi.rs | 2 +- lib/cretonne/src/bforest/map.rs | 6 ++-- lib/cretonne/src/bforest/node.rs | 4 +-- lib/cretonne/src/bforest/path.rs | 8 ++--- lib/cretonne/src/bforest/pool.rs | 6 ++-- lib/cretonne/src/bforest/set.rs | 6 ++-- lib/cretonne/src/binemit/memorysink.rs | 2 +- lib/cretonne/src/binemit/mod.rs | 6 ++-- lib/cretonne/src/bitset.rs | 2 +- lib/cretonne/src/context.rs | 14 ++++---- lib/cretonne/src/dbg.rs | 1 - lib/cretonne/src/dce.rs | 4 +-- lib/cretonne/src/divconst_magic_numbers.rs | 2 +- lib/cretonne/src/dominator_tree.rs | 8 ++--- lib/cretonne/src/entity/list.rs | 2 +- lib/cretonne/src/entity/map.rs | 2 +- lib/cretonne/src/entity/mod.rs | 8 ++--- lib/cretonne/src/entity/primary.rs | 2 +- lib/cretonne/src/flowgraph.rs | 4 +-- lib/cretonne/src/ir/builder.rs | 4 +-- lib/cretonne/src/ir/dfg.rs | 4 +-- lib/cretonne/src/ir/entities.rs | 4 +-- lib/cretonne/src/ir/function.rs | 2 +- lib/cretonne/src/ir/globalvar.rs | 2 +- lib/cretonne/src/ir/heap.rs | 2 +- lib/cretonne/src/ir/immediates.rs | 4 +-- lib/cretonne/src/ir/instructions.rs | 6 ++-- lib/cretonne/src/ir/jumptable.rs | 8 ++--- lib/cretonne/src/ir/layout.rs | 4 +-- lib/cretonne/src/ir/mod.rs | 20 ++++++------ lib/cretonne/src/ir/progpoint.rs | 2 +- lib/cretonne/src/ir/stackslot.rs | 4 +-- lib/cretonne/src/ir/valueloc.rs | 2 +- lib/cretonne/src/isa/arm32/abi.rs | 2 +- lib/cretonne/src/isa/arm32/mod.rs | 12 +++---- lib/cretonne/src/isa/arm64/abi.rs | 2 +- lib/cretonne/src/isa/arm64/mod.rs | 12 +++---- lib/cretonne/src/isa/constraints.rs | 2 +- lib/cretonne/src/isa/intel/abi.rs | 16 ++++----- lib/cretonne/src/isa/intel/binemit.rs | 4 +-- lib/cretonne/src/isa/intel/enc_tables.rs | 6 ++-- lib/cretonne/src/isa/intel/mod.rs | 14 ++++---- lib/cretonne/src/isa/mod.rs | 38 ++++++++++------------ lib/cretonne/src/isa/riscv/abi.rs | 4 +-- lib/cretonne/src/isa/riscv/enc_tables.rs | 2 +- lib/cretonne/src/isa/riscv/mod.rs | 14 ++++---- lib/cretonne/src/isa/stack.rs | 2 +- lib/cretonne/src/legalizer/boundary.rs | 2 +- lib/cretonne/src/legalizer/heap.rs | 2 +- lib/cretonne/src/legalizer/mod.rs | 2 +- lib/cretonne/src/licm.rs | 8 ++--- lib/cretonne/src/loop_analysis.rs | 8 ++--- lib/cretonne/src/postopt.rs | 6 ++-- lib/cretonne/src/preopt.rs | 10 +++--- lib/cretonne/src/print_errors.rs | 4 +-- lib/cretonne/src/regalloc/affinity.rs | 2 +- lib/cretonne/src/regalloc/coalescing.rs | 4 +-- lib/cretonne/src/regalloc/coloring.rs | 4 +-- lib/cretonne/src/regalloc/diversion.rs | 4 +-- lib/cretonne/src/regalloc/liverange.rs | 2 +- lib/cretonne/src/regalloc/mod.rs | 6 ++-- lib/cretonne/src/regalloc/pressure.rs | 4 +-- lib/cretonne/src/regalloc/reload.rs | 4 +-- lib/cretonne/src/regalloc/solver.rs | 6 ++-- lib/cretonne/src/regalloc/virtregs.rs | 2 +- lib/cretonne/src/result.rs | 2 +- lib/cretonne/src/settings.rs | 6 ++-- lib/cretonne/src/simple_gvn.rs | 2 +- lib/cretonne/src/stack_layout.rs | 4 +-- lib/cretonne/src/topo_order.rs | 6 ++-- lib/cretonne/src/verifier/flags.rs | 4 +-- lib/cretonne/src/verifier/liveness.rs | 4 +-- lib/cretonne/src/verifier/locations.rs | 2 +- lib/cretonne/src/verifier/mod.rs | 21 +++++++----- lib/cretonne/src/write.rs | 4 +-- lib/filetests/src/concurrent.rs | 2 +- lib/filetests/src/lib.rs | 6 ++-- lib/filetests/src/runner.rs | 4 +-- lib/filetests/src/runone.rs | 16 ++++----- lib/filetests/src/subtest.rs | 4 +-- lib/filetests/src/test_binemit.rs | 10 +++--- lib/filetests/src/test_cat.rs | 2 +- lib/filetests/src/test_compile.rs | 4 +-- lib/filetests/src/test_dce.rs | 4 +-- lib/filetests/src/test_domtree.rs | 4 +-- lib/filetests/src/test_legalizer.rs | 4 +-- lib/filetests/src/test_licm.rs | 4 +-- lib/filetests/src/test_postopt.rs | 4 +-- lib/filetests/src/test_preopt.rs | 4 +-- lib/filetests/src/test_print_cfg.rs | 2 +- lib/filetests/src/test_regalloc.rs | 4 +-- lib/filetests/src/test_simple_gvn.rs | 4 +-- lib/filetests/src/test_verifier.rs | 6 ++-- lib/frontend/src/frontend.rs | 18 +++++----- lib/frontend/src/ssa.rs | 18 +++++----- lib/reader/src/isaspec.rs | 2 +- lib/reader/src/lexer.rs | 8 ++--- lib/reader/src/lib.rs | 10 +++--- lib/reader/src/parser.rs | 34 +++++++++---------- lib/reader/src/testfile.rs | 4 +-- lib/wasm/src/code_translator.rs | 14 ++++---- lib/wasm/src/environ/dummy.rs | 16 ++++----- lib/wasm/src/environ/mod.rs | 4 +-- lib/wasm/src/environ/spec.rs | 6 ++-- lib/wasm/src/func_translator.rs | 6 ++-- lib/wasm/src/lib.rs | 4 +-- lib/wasm/src/module_translator.rs | 4 +-- lib/wasm/src/sections_translator.rs | 14 ++++---- lib/wasm/src/state.rs | 2 +- lib/wasm/src/translation_utils.rs | 2 +- lib/wasm/tests/wasm_testsuite.rs | 20 ++++++------ 117 files changed, 360 insertions(+), 360 deletions(-) diff --git a/cranelift/src/cat.rs b/cranelift/src/cat.rs index 0fc5541db9..e82af42624 100644 --- a/cranelift/src/cat.rs +++ b/cranelift/src/cat.rs @@ -3,8 +3,8 @@ //! Read a sequence of Cretonne IR files and print them again to stdout. This has the effect of //! normalizing formatting and removing comments. -use cton_reader::parse_functions; use CommandResult; +use cton_reader::parse_functions; use utils::read_to_string; pub fn run(files: &[String]) -> CommandResult { diff --git a/cranelift/src/compile.rs b/cranelift/src/compile.rs index f2272494cf..6bab77e0d2 100644 --- a/cranelift/src/compile.rs +++ b/cranelift/src/compile.rs @@ -1,12 +1,12 @@ //! CLI tool to read Cretonne IR files and compile them into native code. -use cton_reader::parse_test; -use std::path::PathBuf; use cretonne::Context; +use cretonne::print_errors::pretty_error; use cretonne::settings::FlagsOrIsa; use cretonne::{binemit, ir}; -use cretonne::print_errors::pretty_error; +use cton_reader::parse_test; use std::path::Path; +use std::path::PathBuf; use utils::{parse_sets_and_isa, read_to_string}; struct PrintRelocs { diff --git a/cranelift/src/cton-util.rs b/cranelift/src/cton-util.rs index 42887640df..3968030709 100644 --- a/cranelift/src/cton-util.rs +++ b/cranelift/src/cton-util.rs @@ -14,12 +14,12 @@ use docopt::Docopt; use std::io::{self, Write}; use std::process; -mod utils; mod cat; +mod compile; mod print_cfg; mod rsfilecheck; +mod utils; mod wasm; -mod compile; const USAGE: &str = " Cretonne code generator utility diff --git a/cranelift/src/rsfilecheck.rs b/cranelift/src/rsfilecheck.rs index f71571b513..6269ed226b 100644 --- a/cranelift/src/rsfilecheck.rs +++ b/cranelift/src/rsfilecheck.rs @@ -3,9 +3,9 @@ //! This file is named to avoid a name collision with the filecheck crate. use CommandResult; -use utils::read_to_string; use filecheck::{Checker, CheckerBuilder, NO_VARIABLES}; use std::io::{self, Read}; +use utils::read_to_string; pub fn run(files: &[String], verbose: bool) -> CommandResult { if files.is_empty() { diff --git a/cranelift/src/utils.rs b/cranelift/src/utils.rs index dc4f501893..8a2994a7ab 100644 --- a/cranelift/src/utils.rs +++ b/cranelift/src/utils.rs @@ -1,8 +1,8 @@ //! Utility functions. +use cretonne::isa; use cretonne::isa::TargetIsa; use cretonne::settings::{self, FlagsOrIsa}; -use cretonne::isa; use cton_reader::{parse_options, Location}; use std::fs::File; use std::io::{self, Read}; diff --git a/cranelift/src/wasm.rs b/cranelift/src/wasm.rs index 918deffd5a..029c7ad5c0 100644 --- a/cranelift/src/wasm.rs +++ b/cranelift/src/wasm.rs @@ -3,15 +3,15 @@ //! Reads Wasm binary files, translates the functions' code to Cretonne IR. #![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments, cyclomatic_complexity))] -use cton_wasm::{translate_module, DummyEnvironment, ModuleEnvironment}; -use std::path::PathBuf; use cretonne::Context; -use cretonne::settings::FlagsOrIsa; use cretonne::print_errors::{pretty_error, pretty_verifier_error}; -use std::fs::File; +use cretonne::settings::FlagsOrIsa; +use cton_wasm::{translate_module, DummyEnvironment, ModuleEnvironment}; use std::error::Error; +use std::fs::File; use std::io; use std::path::Path; +use std::path::PathBuf; use std::process::Command; use tempdir::TempDir; use term; diff --git a/lib/cretonne/src/abi.rs b/lib/cretonne/src/abi.rs index 2ba3f7b7a1..88a8a424a6 100644 --- a/lib/cretonne/src/abi.rs +++ b/lib/cretonne/src/abi.rs @@ -186,8 +186,8 @@ pub fn legalize_abi_value(have: Type, arg: &AbiParam) -> ValueConversion { #[cfg(test)] mod tests { use super::*; - use ir::types; use ir::AbiParam; + use ir::types; #[test] fn legalize() { diff --git a/lib/cretonne/src/bforest/map.rs b/lib/cretonne/src/bforest/map.rs index 23b4625555..6f8bedc225 100644 --- a/lib/cretonne/src/bforest/map.rs +++ b/lib/cretonne/src/bforest/map.rs @@ -1,8 +1,8 @@ //! Forest of maps. +use super::{Comparator, Forest, Node, NodeData, NodePool, Path, INNER_SIZE}; use packed_option::PackedOption; use std::marker::PhantomData; -use super::{Comparator, Forest, Node, NodeData, NodePool, Path, INNER_SIZE}; /// Tag type defining forest types for a map. struct MapTypes(PhantomData<(K, V, C)>); @@ -422,10 +422,10 @@ where #[cfg(test)] mod test { + use super::super::NodeData; + use super::*; use std::mem; use std::vec::Vec; - use super::*; - use super::super::NodeData; #[test] fn node_size() { diff --git a/lib/cretonne/src/bforest/node.rs b/lib/cretonne/src/bforest/node.rs index 61fb6e994d..f4a85613b5 100644 --- a/lib/cretonne/src/bforest/node.rs +++ b/lib/cretonne/src/bforest/node.rs @@ -1,8 +1,8 @@ //! B+-tree nodes. +use super::{slice_insert, slice_shift, Forest, Node, SetValue, INNER_SIZE}; use std::borrow::{Borrow, BorrowMut}; use std::fmt; -use super::{slice_insert, slice_shift, Forest, Node, SetValue, INNER_SIZE}; /// B+-tree node. /// @@ -579,9 +579,9 @@ where #[cfg(test)] mod test { + use super::*; use std::mem; use std::string::ToString; - use super::*; // Forest impl for a set implementation. struct TF(); diff --git a/lib/cretonne/src/bforest/path.rs b/lib/cretonne/src/bforest/path.rs index a2d15173a3..d011455571 100644 --- a/lib/cretonne/src/bforest/path.rs +++ b/lib/cretonne/src/bforest/path.rs @@ -1,9 +1,9 @@ //! A path from the root of a B+-tree to a leaf node. +use super::node::Removed; +use super::{slice_insert, slice_shift, Comparator, Forest, Node, NodeData, NodePool, MAX_PATH}; use std::borrow::Borrow; use std::marker::PhantomData; -use super::{slice_insert, slice_shift, Comparator, Forest, Node, NodeData, NodePool, MAX_PATH}; -use super::node::Removed; #[cfg(test)] use std::fmt; @@ -699,9 +699,9 @@ impl fmt::Display for Path { #[cfg(test)] mod test { - use std::cmp::Ordering; - use super::*; use super::super::{Forest, NodeData, NodePool}; + use super::*; + use std::cmp::Ordering; struct TC(); diff --git a/lib/cretonne/src/bforest/pool.rs b/lib/cretonne/src/bforest/pool.rs index 54a1f81cef..0e312f9380 100644 --- a/lib/cretonne/src/bforest/pool.rs +++ b/lib/cretonne/src/bforest/pool.rs @@ -1,8 +1,8 @@ //! B+-tree node pool. +use super::{Forest, Node, NodeData}; use entity::PrimaryMap; use std::ops::{Index, IndexMut}; -use super::{Forest, Node, NodeData}; /// A pool of nodes, including a free list. pub(super) struct NodePool { @@ -77,11 +77,11 @@ impl NodePool { NodeData: ::std::fmt::Display, F::Key: ::std::fmt::Display, { + use super::Comparator; + use entity::SparseSet; use std::borrow::Borrow; use std::cmp::Ordering; use std::vec::Vec; - use super::Comparator; - use entity::SparseSet; // The root node can't be an inner node with just a single sub-tree. It should have been // pruned. diff --git a/lib/cretonne/src/bforest/set.rs b/lib/cretonne/src/bforest/set.rs index 374c26ad2b..fbd0dbfca1 100644 --- a/lib/cretonne/src/bforest/set.rs +++ b/lib/cretonne/src/bforest/set.rs @@ -1,8 +1,8 @@ //! Forest of sets. +use super::{Comparator, Forest, Node, NodeData, NodePool, Path, SetValue, INNER_SIZE}; use packed_option::PackedOption; use std::marker::PhantomData; -use super::{Comparator, Forest, Node, NodeData, NodePool, Path, SetValue, INNER_SIZE}; /// Tag type defining forest types for a set. struct SetTypes(PhantomData<(K, C)>); @@ -350,10 +350,10 @@ where #[cfg(test)] mod test { + use super::super::NodeData; + use super::*; use std::mem; use std::vec::Vec; - use super::*; - use super::super::NodeData; #[test] fn node_size() { diff --git a/lib/cretonne/src/binemit/memorysink.rs b/lib/cretonne/src/binemit/memorysink.rs index 5a9fa8a298..bed34cd1ac 100644 --- a/lib/cretonne/src/binemit/memorysink.rs +++ b/lib/cretonne/src/binemit/memorysink.rs @@ -14,8 +14,8 @@ //! relocations to a `RelocSink` trait object. Relocations are less frequent than the //! `CodeSink::put*` methods, so the performance impact of the virtual callbacks is less severe. -use ir::{ExternalName, JumpTable, SourceLoc, TrapCode}; use super::{Addend, CodeOffset, CodeSink, Reloc}; +use ir::{ExternalName, JumpTable, SourceLoc, TrapCode}; use std::ptr::write_unaligned; /// A `CodeSink` that writes binary machine code directly into memory. diff --git a/lib/cretonne/src/binemit/mod.rs b/lib/cretonne/src/binemit/mod.rs index 20ff429756..ea31abaae5 100644 --- a/lib/cretonne/src/binemit/mod.rs +++ b/lib/cretonne/src/binemit/mod.rs @@ -3,12 +3,12 @@ //! The `binemit` module contains code for translating Cretonne's intermediate representation into //! binary machine code. -mod relaxation; mod memorysink; +mod relaxation; -pub use regalloc::RegDiversions; -pub use self::relaxation::relax_branches; pub use self::memorysink::{MemoryCodeSink, RelocSink, TrapSink}; +pub use self::relaxation::relax_branches; +pub use regalloc::RegDiversions; use ir::{ExternalName, Function, Inst, JumpTable, SourceLoc, TrapCode}; use std::fmt; diff --git a/lib/cretonne/src/bitset.rs b/lib/cretonne/src/bitset.rs index f0a7271957..160c1c3e09 100644 --- a/lib/cretonne/src/bitset.rs +++ b/lib/cretonne/src/bitset.rs @@ -5,9 +5,9 @@ //! //! If you would like to add support for larger bitsets in the future, you need to change the trait //! bound Into and the u32 in the implementation of `max_bits()`. +use std::convert::{From, Into}; use std::mem::size_of; use std::ops::{Add, BitOr, Shl, Sub}; -use std::convert::{From, Into}; /// A small bitset built on a single primitive integer type #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/lib/cretonne/src/context.rs b/lib/cretonne/src/context.rs index c7841f9366..ad31e9025b 100644 --- a/lib/cretonne/src/context.rs +++ b/lib/cretonne/src/context.rs @@ -10,23 +10,23 @@ //! single ISA instance. use binemit::{relax_branches, CodeOffset, MemoryCodeSink, RelocSink, TrapSink}; +use dce::do_dce; use dominator_tree::DominatorTree; use flowgraph::ControlFlowGraph; use ir::Function; -use loop_analysis::LoopAnalysis; use isa::TargetIsa; use legalize_function; +use licm::do_licm; +use loop_analysis::LoopAnalysis; +use postopt::do_postopt; +use preopt::do_preopt; use regalloc; use result::{CtonError, CtonResult}; use settings::{FlagsOrIsa, OptLevel}; +use simple_gvn::do_simple_gvn; +use timing; use unreachable_code::eliminate_unreachable_code; use verifier; -use dce::do_dce; -use simple_gvn::do_simple_gvn; -use licm::do_licm; -use preopt::do_preopt; -use postopt::do_postopt; -use timing; /// Persistent data structures and compilation pipeline. pub struct Context { diff --git a/lib/cretonne/src/dbg.rs b/lib/cretonne/src/dbg.rs index 5acadd2098..0d9f77b76d 100644 --- a/lib/cretonne/src/dbg.rs +++ b/lib/cretonne/src/dbg.rs @@ -8,7 +8,6 @@ /// /// The output will appear in files named `cretonne.dbg.*`, where the suffix is named after the /// thread doing the logging. - use std::cell::RefCell; use std::env; use std::ffi::OsStr; diff --git a/lib/cretonne/src/dce.rs b/lib/cretonne/src/dce.rs index b78d260ecb..895b922dd7 100644 --- a/lib/cretonne/src/dce.rs +++ b/lib/cretonne/src/dce.rs @@ -6,10 +6,10 @@ use cursor::{Cursor, FuncCursor}; use dominator_tree::DominatorTree; use entity::EntityRef; -use ir::{DataFlowGraph, Function, Inst, Opcode}; use ir::instructions::InstructionData; -use timing; +use ir::{DataFlowGraph, Function, Inst, Opcode}; use std::vec::Vec; +use timing; /// Test whether the given opcode is unsafe to even consider for DCE. fn trivially_unsafe_for_dce(opcode: Opcode) -> bool { diff --git a/lib/cretonne/src/divconst_magic_numbers.rs b/lib/cretonne/src/divconst_magic_numbers.rs index 80a59aed8b..8a848711a4 100644 --- a/lib/cretonne/src/divconst_magic_numbers.rs +++ b/lib/cretonne/src/divconst_magic_numbers.rs @@ -220,8 +220,8 @@ pub fn magicS64(d: i64) -> MS64 { #[cfg(test)] mod tests { - use super::{magicS32, magicS64, magicU32, magicU64}; use super::{MS32, MS64, MU32, MU64}; + use super::{magicS32, magicS64, magicU32, magicU64}; fn mkMU32(mulBy: u32, doAdd: bool, shiftBy: i32) -> MU32 { MU32 { diff --git a/lib/cretonne/src/dominator_tree.rs b/lib/cretonne/src/dominator_tree.rs index 574697c1ba..60ef1e6e42 100644 --- a/lib/cretonne/src/dominator_tree.rs +++ b/lib/cretonne/src/dominator_tree.rs @@ -2,14 +2,14 @@ use entity::EntityMap; use flowgraph::{BasicBlock, ControlFlowGraph}; -use ir::{Ebb, ExpandedProgramPoint, Function, Inst, Layout, ProgramOrder, Value}; use ir::instructions::BranchInfo; +use ir::{Ebb, ExpandedProgramPoint, Function, Inst, Layout, ProgramOrder, Value}; use packed_option::PackedOption; use std::cmp; -use std::mem; -use timing; use std::cmp::Ordering; +use std::mem; use std::vec::Vec; +use timing; /// RPO numbers are not first assigned in a contiguous way but as multiples of STRIDE, to leave /// room for modifications of the dominator tree. @@ -666,12 +666,12 @@ impl DominatorTreePreorder { #[cfg(test)] mod test { + use super::*; use cursor::{Cursor, FuncCursor}; use flowgraph::ControlFlowGraph; use ir::types::*; use ir::{Function, InstBuilder, TrapCode}; use settings; - use super::*; use verifier::verify_context; #[test] diff --git a/lib/cretonne/src/entity/list.rs b/lib/cretonne/src/entity/list.rs index 2c743e169b..545b1e146b 100644 --- a/lib/cretonne/src/entity/list.rs +++ b/lib/cretonne/src/entity/list.rs @@ -481,8 +481,8 @@ impl EntityList { mod tests { use super::*; use super::{sclass_for_length, sclass_size}; - use ir::Inst; use entity::EntityRef; + use ir::Inst; #[test] fn size_classes() { diff --git a/lib/cretonne/src/entity/map.rs b/lib/cretonne/src/entity/map.rs index 88b355585b..ff402b104f 100644 --- a/lib/cretonne/src/entity/map.rs +++ b/lib/cretonne/src/entity/map.rs @@ -3,8 +3,8 @@ use entity::{EntityRef, Iter, IterMut, Keys}; use std::marker::PhantomData; use std::ops::{Index, IndexMut}; -use std::vec::Vec; use std::slice; +use std::vec::Vec; /// A mapping `K -> V` for densely indexed entity references. /// diff --git a/lib/cretonne/src/entity/mod.rs b/lib/cretonne/src/entity/mod.rs index 9aeab1449d..88c0977cf2 100644 --- a/lib/cretonne/src/entity/mod.rs +++ b/lib/cretonne/src/entity/mod.rs @@ -29,16 +29,16 @@ //! references allocated from an associated memory pool. It has a much smaller footprint than //! `Vec`. -mod keys; mod iter; +mod keys; mod list; mod map; mod primary; -mod sparse; mod set; +mod sparse; -pub use self::keys::Keys; pub use self::iter::{Iter, IterMut}; +pub use self::keys::Keys; pub use self::list::{EntityList, ListPool}; pub use self::map::EntityMap; pub use self::primary::PrimaryMap; @@ -95,5 +95,5 @@ macro_rules! entity_impl { (self as &::std::fmt::Display).fmt(f) } } - } + }; } diff --git a/lib/cretonne/src/entity/primary.rs b/lib/cretonne/src/entity/primary.rs index a442928d77..5d690a7553 100644 --- a/lib/cretonne/src/entity/primary.rs +++ b/lib/cretonne/src/entity/primary.rs @@ -2,8 +2,8 @@ use entity::{EntityRef, Iter, IterMut, Keys}; use std::marker::PhantomData; use std::ops::{Index, IndexMut}; -use std::vec::Vec; use std::slice; +use std::vec::Vec; /// A primary mapping `K -> V` allocating dense entity references. /// diff --git a/lib/cretonne/src/flowgraph.rs b/lib/cretonne/src/flowgraph.rs index 3ed295d6f0..66f377ce35 100644 --- a/lib/cretonne/src/flowgraph.rs +++ b/lib/cretonne/src/flowgraph.rs @@ -24,9 +24,9 @@ //! and `(Ebb0, jmp Ebb2)` respectively. use bforest; -use ir::{Ebb, Function, Inst}; -use ir::instructions::BranchInfo; use entity::EntityMap; +use ir::instructions::BranchInfo; +use ir::{Ebb, Function, Inst}; use std::mem; use timing; diff --git a/lib/cretonne/src/ir/builder.rs b/lib/cretonne/src/ir/builder.rs index 6308f3e1bd..34f56b9439 100644 --- a/lib/cretonne/src/ir/builder.rs +++ b/lib/cretonne/src/ir/builder.rs @@ -216,9 +216,9 @@ impl<'f> InstBuilderBase<'f> for ReplaceBuilder<'f> { #[cfg(test)] mod tests { use cursor::{Cursor, FuncCursor}; - use ir::{Function, InstBuilder, ValueDef}; - use ir::types::*; use ir::condcodes::*; + use ir::types::*; + use ir::{Function, InstBuilder, ValueDef}; #[test] fn types() { diff --git a/lib/cretonne/src/ir/dfg.rs b/lib/cretonne/src/ir/dfg.rs index 48faf3b5ac..24f18ff332 100644 --- a/lib/cretonne/src/ir/dfg.rs +++ b/lib/cretonne/src/ir/dfg.rs @@ -1,20 +1,20 @@ //! Data flow graph tracking Instructions, Values, and EBBs. use entity::{EntityMap, PrimaryMap}; -use isa::{Encoding, Legalize, TargetIsa}; use ir; use ir::builder::ReplaceBuilder; use ir::extfunc::ExtFuncData; use ir::instructions::{BranchInfo, CallInfo, InstructionData}; use ir::types; use ir::{Ebb, FuncRef, Inst, SigRef, Signature, Type, Value, ValueList, ValueListPool}; +use isa::{Encoding, Legalize, TargetIsa}; use packed_option::ReservedValue; -use write::write_operands; use std::fmt; use std::iter; use std::mem; use std::ops::{Index, IndexMut}; use std::u16; +use write::write_operands; /// A data flow graph defines all instructions and extended basic blocks in a function as well as /// the data flow dependencies between them. The DFG also tracks values which can be either diff --git a/lib/cretonne/src/ir/entities.rs b/lib/cretonne/src/ir/entities.rs index 0727721d6a..d0c627952b 100644 --- a/lib/cretonne/src/ir/entities.rs +++ b/lib/cretonne/src/ir/entities.rs @@ -261,8 +261,8 @@ impl From for AnyEntity { #[cfg(test)] mod tests { use super::*; - use std::u32; use std::string::ToString; + use std::u32; #[test] fn value_with_number() { @@ -275,8 +275,8 @@ mod tests { #[test] fn memory() { - use std::mem; use packed_option::PackedOption; + use std::mem; // This is the whole point of `PackedOption`. assert_eq!( mem::size_of::(), diff --git a/lib/cretonne/src/ir/function.rs b/lib/cretonne/src/ir/function.rs index 5010e0caae..19baa16b2b 100644 --- a/lib/cretonne/src/ir/function.rs +++ b/lib/cretonne/src/ir/function.rs @@ -7,9 +7,9 @@ use binemit::CodeOffset; use entity::{EntityMap, PrimaryMap}; use ir; use ir::{CallConv, DataFlowGraph, ExternalName, Layout, Signature}; -use ir::{EbbOffsets, InstEncodings, JumpTables, SourceLocs, StackSlots, ValueLocations}; use ir::{Ebb, ExtFuncData, FuncRef, GlobalVar, GlobalVarData, Heap, HeapData, JumpTable, JumpTableData, SigRef, StackSlot, StackSlotData}; +use ir::{EbbOffsets, InstEncodings, JumpTables, SourceLocs, StackSlots, ValueLocations}; use isa::{EncInfo, Legalize, TargetIsa}; use std::fmt; use write::write_function; diff --git a/lib/cretonne/src/ir/globalvar.rs b/lib/cretonne/src/ir/globalvar.rs index c8fc3b8ce1..228f691d84 100644 --- a/lib/cretonne/src/ir/globalvar.rs +++ b/lib/cretonne/src/ir/globalvar.rs @@ -1,7 +1,7 @@ //! Global variables. -use ir::{ExternalName, GlobalVar}; use ir::immediates::Offset32; +use ir::{ExternalName, GlobalVar}; use std::fmt; /// Information about a global variable declaration. diff --git a/lib/cretonne/src/ir/heap.rs b/lib/cretonne/src/ir/heap.rs index b41565b25b..01beb15b35 100644 --- a/lib/cretonne/src/ir/heap.rs +++ b/lib/cretonne/src/ir/heap.rs @@ -1,7 +1,7 @@ //! Heaps. -use ir::immediates::Imm64; use ir::GlobalVar; +use ir::immediates::Imm64; use std::fmt; /// Information about a heap declaration. diff --git a/lib/cretonne/src/ir/immediates.rs b/lib/cretonne/src/ir/immediates.rs index 3dd09bd0bd..d56e963bb1 100644 --- a/lib/cretonne/src/ir/immediates.rs +++ b/lib/cretonne/src/ir/immediates.rs @@ -651,10 +651,10 @@ impl FromStr for Ieee64 { #[cfg(test)] mod tests { use super::*; - use std::{f32, f64}; - use std::str::FromStr; use std::fmt::Display; + use std::str::FromStr; use std::string::ToString; + use std::{f32, f64}; #[test] fn format_imm64() { diff --git a/lib/cretonne/src/ir/instructions.rs b/lib/cretonne/src/ir/instructions.rs index 94293b517b..aa6a35df3f 100644 --- a/lib/cretonne/src/ir/instructions.rs +++ b/lib/cretonne/src/ir/instructions.rs @@ -7,17 +7,17 @@ //! directory. use std::fmt::{self, Display, Formatter}; -use std::str::FromStr; use std::ops::{Deref, DerefMut}; +use std::str::FromStr; use std::vec::Vec; use ir; -use ir::{Ebb, FuncRef, JumpTable, SigRef, Type, Value}; use ir::types; +use ir::{Ebb, FuncRef, JumpTable, SigRef, Type, Value}; use isa; -use entity; use bitset::BitSet; +use entity; use ref_slice::{ref_slice, ref_slice_mut}; /// Some instructions use an external list of argument values because there is not enough space in diff --git a/lib/cretonne/src/ir/jumptable.rs b/lib/cretonne/src/ir/jumptable.rs index 1c7bf79157..90b18b1bfe 100644 --- a/lib/cretonne/src/ir/jumptable.rs +++ b/lib/cretonne/src/ir/jumptable.rs @@ -3,11 +3,11 @@ //! Jump tables are declared in the preamble and assigned an `ir::entities::JumpTable` reference. //! The actual table of destinations is stored in a `JumpTableData` struct defined in this module. -use packed_option::PackedOption; use ir::entities::Ebb; +use packed_option::PackedOption; +use std::fmt::{self, Display, Formatter}; use std::iter; use std::slice; -use std::fmt::{self, Display, Formatter}; use std::vec::Vec; /// Contents of a jump table. @@ -140,10 +140,10 @@ impl Display for JumpTableData { #[cfg(test)] mod tests { use super::JumpTableData; - use ir::Ebb; use entity::EntityRef; - use std::vec::Vec; + use ir::Ebb; use std::string::ToString; + use std::vec::Vec; #[test] fn empty() { diff --git a/lib/cretonne/src/ir/layout.rs b/lib/cretonne/src/ir/layout.rs index 78db62530b..2e3ac89903 100644 --- a/lib/cretonne/src/ir/layout.rs +++ b/lib/cretonne/src/ir/layout.rs @@ -4,8 +4,8 @@ //! determined by the `Layout` data structure defined in this module. use entity::EntityMap; -use ir::{Ebb, Inst}; use ir::progpoint::{ExpandedProgramPoint, ProgramOrder}; +use ir::{Ebb, Inst}; use packed_option::PackedOption; use std::cmp; use std::iter::{IntoIterator, Iterator}; @@ -736,8 +736,8 @@ impl<'f> DoubleEndedIterator for Insts<'f> { #[cfg(test)] mod tests { - use cursor::{Cursor, CursorPosition}; use super::Layout; + use cursor::{Cursor, CursorPosition}; use entity::EntityRef; use ir::{Ebb, Inst, ProgramOrder, SourceLoc}; use std::cmp::Ordering; diff --git a/lib/cretonne/src/ir/mod.rs b/lib/cretonne/src/ir/mod.rs index 0d805cb3de..ed9771ccad 100644 --- a/lib/cretonne/src/ir/mod.rs +++ b/lib/cretonne/src/ir/mod.rs @@ -1,25 +1,25 @@ //! Representation of Cretonne IR functions. -pub mod types; -pub mod entities; -pub mod condcodes; -pub mod immediates; -pub mod instructions; -pub mod stackslot; -pub mod jumptable; -pub mod dfg; -pub mod layout; -pub mod function; mod builder; +pub mod condcodes; +pub mod dfg; +pub mod entities; mod extfunc; mod extname; +pub mod function; mod globalvar; mod heap; +pub mod immediates; +pub mod instructions; +pub mod jumptable; +pub mod layout; mod libcall; mod memflags; mod progpoint; mod sourceloc; +pub mod stackslot; mod trapcode; +pub mod types; mod valueloc; pub use ir::builder::{InsertBuilder, InstBuilder, InstBuilderBase, InstInserterBase}; diff --git a/lib/cretonne/src/ir/progpoint.rs b/lib/cretonne/src/ir/progpoint.rs index 6eab7ec743..4a0785aef4 100644 --- a/lib/cretonne/src/ir/progpoint.rs +++ b/lib/cretonne/src/ir/progpoint.rs @@ -2,9 +2,9 @@ use entity::EntityRef; use ir::{Ebb, Inst, ValueDef}; +use std::cmp; use std::fmt; use std::u32; -use std::cmp; /// A `ProgramPoint` represents a position in a function where the live range of an SSA value can /// begin or end. It can be either: diff --git a/lib/cretonne/src/ir/stackslot.rs b/lib/cretonne/src/ir/stackslot.rs index fd484915fd..9dfcfa7d21 100644 --- a/lib/cretonne/src/ir/stackslot.rs +++ b/lib/cretonne/src/ir/stackslot.rs @@ -8,8 +8,8 @@ use ir::{StackSlot, Type}; use packed_option::PackedOption; use std::cmp; use std::fmt; -use std::slice; use std::ops::{Index, IndexMut}; +use std::slice; use std::str::FromStr; use std::vec::Vec; @@ -338,9 +338,9 @@ impl StackSlots { #[cfg(test)] mod tests { + use super::*; use ir::Function; use ir::types; - use super::*; use std::string::ToString; #[test] diff --git a/lib/cretonne/src/ir/valueloc.rs b/lib/cretonne/src/ir/valueloc.rs index 1e3cf20f87..aecf23d0bb 100644 --- a/lib/cretonne/src/ir/valueloc.rs +++ b/lib/cretonne/src/ir/valueloc.rs @@ -3,8 +3,8 @@ //! The register allocator assigns every SSA value to either a register or a stack slot. This //! assignment is represented by a `ValueLoc` object. -use isa::{RegInfo, RegUnit}; use ir::StackSlot; +use isa::{RegInfo, RegUnit}; use std::fmt; /// Value location. diff --git a/lib/cretonne/src/isa/arm32/abi.rs b/lib/cretonne/src/isa/arm32/abi.rs index 020a525ac5..528a396570 100644 --- a/lib/cretonne/src/isa/arm32/abi.rs +++ b/lib/cretonne/src/isa/arm32/abi.rs @@ -1,10 +1,10 @@ //! ARM ABI implementation. +use super::registers::{D, GPR, Q, S}; use ir; use isa::RegClass; use regalloc::AllocatableSet; use settings as shared_settings; -use super::registers::{D, GPR, Q, S}; /// Legalize `sig`. pub fn legalize_signature( diff --git a/lib/cretonne/src/isa/arm32/mod.rs b/lib/cretonne/src/isa/arm32/mod.rs index 11271fe3d9..350764a436 100644 --- a/lib/cretonne/src/isa/arm32/mod.rs +++ b/lib/cretonne/src/isa/arm32/mod.rs @@ -1,20 +1,20 @@ //! ARM 32-bit Instruction Set Architecture. -pub mod settings; mod abi; mod binemit; mod enc_tables; mod registers; +pub mod settings; -use binemit::{emit_function, CodeSink, MemoryCodeSink}; use super::super::settings as shared_settings; -use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings}; -use isa::Builder as IsaBuilder; -use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; +use binemit::{emit_function, CodeSink, MemoryCodeSink}; use ir; +use isa::Builder as IsaBuilder; +use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings}; +use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; use regalloc; -use std::fmt; use std::boxed::Box; +use std::fmt; #[allow(dead_code)] struct Isa { diff --git a/lib/cretonne/src/isa/arm64/abi.rs b/lib/cretonne/src/isa/arm64/abi.rs index 9dba70c42f..0540746afa 100644 --- a/lib/cretonne/src/isa/arm64/abi.rs +++ b/lib/cretonne/src/isa/arm64/abi.rs @@ -1,10 +1,10 @@ //! ARM 64 ABI implementation. +use super::registers::{FPR, GPR}; use ir; use isa::RegClass; use regalloc::AllocatableSet; use settings as shared_settings; -use super::registers::{FPR, GPR}; /// Legalize `sig`. pub fn legalize_signature( diff --git a/lib/cretonne/src/isa/arm64/mod.rs b/lib/cretonne/src/isa/arm64/mod.rs index 485b008574..3b63d56d54 100644 --- a/lib/cretonne/src/isa/arm64/mod.rs +++ b/lib/cretonne/src/isa/arm64/mod.rs @@ -1,20 +1,20 @@ //! ARM 64-bit Instruction Set Architecture. -pub mod settings; mod abi; mod binemit; mod enc_tables; mod registers; +pub mod settings; -use binemit::{emit_function, CodeSink, MemoryCodeSink}; use super::super::settings as shared_settings; -use isa::enc_tables::{lookup_enclist, Encodings}; -use isa::Builder as IsaBuilder; -use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; +use binemit::{emit_function, CodeSink, MemoryCodeSink}; use ir; +use isa::Builder as IsaBuilder; +use isa::enc_tables::{lookup_enclist, Encodings}; +use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; use regalloc; -use std::fmt; use std::boxed::Box; +use std::fmt; #[allow(dead_code)] struct Isa { diff --git a/lib/cretonne/src/isa/constraints.rs b/lib/cretonne/src/isa/constraints.rs index 4ab22a6026..b08f635ba4 100644 --- a/lib/cretonne/src/isa/constraints.rs +++ b/lib/cretonne/src/isa/constraints.rs @@ -8,8 +8,8 @@ //! are satisfied. use binemit::CodeOffset; -use isa::{RegClass, RegUnit}; use ir::{Function, Inst, ValueLoc}; +use isa::{RegClass, RegUnit}; use regalloc::RegDiversions; /// Register constraint for a single value operand or instruction result. diff --git a/lib/cretonne/src/isa/intel/abi.rs b/lib/cretonne/src/isa/intel/abi.rs index 46ad7679e6..e9019291ef 100644 --- a/lib/cretonne/src/isa/intel/abi.rs +++ b/lib/cretonne/src/isa/intel/abi.rs @@ -1,18 +1,18 @@ //! Intel ABI implementation. -use ir; -use isa::{RegClass, RegUnit, TargetIsa}; -use regalloc::AllocatableSet; -use settings as shared_settings; use super::registers::{FPR, GPR, RU}; use abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion}; -use ir::{AbiParam, ArgumentExtension, ArgumentLoc, ArgumentPurpose, CallConv, InstBuilder}; -use ir::stackslot::{StackOffset, StackSize}; +use cursor::{Cursor, CursorPosition, EncCursor}; +use ir; use ir::immediates::Imm64; +use ir::stackslot::{StackOffset, StackSize}; +use ir::{AbiParam, ArgumentExtension, ArgumentLoc, ArgumentPurpose, CallConv, InstBuilder}; +use isa::{RegClass, RegUnit, TargetIsa}; +use regalloc::AllocatableSet; +use result; +use settings as shared_settings; use stack_layout::layout_stack; use std::i32; -use cursor::{Cursor, CursorPosition, EncCursor}; -use result; /// Argument registers for x86-64 static ARG_GPRS: [RU; 6] = [RU::rdi, RU::rsi, RU::rdx, RU::rcx, RU::r8, RU::r9]; diff --git a/lib/cretonne/src/isa/intel/binemit.rs b/lib/cretonne/src/isa/intel/binemit.rs index 5ec1d7175f..da14f80d29 100644 --- a/lib/cretonne/src/isa/intel/binemit.rs +++ b/lib/cretonne/src/isa/intel/binemit.rs @@ -1,11 +1,11 @@ //! Emitting binary Intel machine code. +use super::registers::RU; use binemit::{bad_encoding, CodeSink, Reloc}; -use ir::{Ebb, Function, Inst, InstructionData, Opcode, TrapCode}; use ir::condcodes::{CondCode, FloatCC, IntCC}; +use ir::{Ebb, Function, Inst, InstructionData, Opcode, TrapCode}; use isa::{RegUnit, StackBase, StackBaseMask, StackRef}; use regalloc::RegDiversions; -use super::registers::RU; include!(concat!(env!("OUT_DIR"), "/binemit-intel.rs")); diff --git a/lib/cretonne/src/isa/intel/enc_tables.rs b/lib/cretonne/src/isa/intel/enc_tables.rs index b8461c0008..d847eb6d53 100644 --- a/lib/cretonne/src/isa/intel/enc_tables.rs +++ b/lib/cretonne/src/isa/intel/enc_tables.rs @@ -1,16 +1,16 @@ //! Encoding tables for Intel ISAs. +use super::registers::*; use bitset::BitSet; use cursor::{Cursor, FuncCursor}; use flowgraph::ControlFlowGraph; -use ir::{self, InstBuilder}; use ir::condcodes::IntCC; +use ir::{self, InstBuilder}; +use isa; use isa::constraints::*; use isa::enc_tables::*; use isa::encoding::RecipeSizing; -use isa; use predicates; -use super::registers::*; include!(concat!(env!("OUT_DIR"), "/encoding-intel.rs")); include!(concat!(env!("OUT_DIR"), "/legalize-intel.rs")); diff --git a/lib/cretonne/src/isa/intel/mod.rs b/lib/cretonne/src/isa/intel/mod.rs index aa6f2a0a01..91d8325a6b 100644 --- a/lib/cretonne/src/isa/intel/mod.rs +++ b/lib/cretonne/src/isa/intel/mod.rs @@ -1,22 +1,22 @@ //! Intel Instruction Set Architectures. -pub mod settings; mod abi; mod binemit; mod enc_tables; mod registers; +pub mod settings; -use binemit::{emit_function, CodeSink, MemoryCodeSink}; use super::super::settings as shared_settings; -use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings}; -use isa::Builder as IsaBuilder; -use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; +use binemit::{emit_function, CodeSink, MemoryCodeSink}; use ir; +use isa::Builder as IsaBuilder; +use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings}; +use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; use regalloc; use result; -use timing; -use std::fmt; use std::boxed::Box; +use std::fmt; +use timing; #[allow(dead_code)] struct Isa { diff --git a/lib/cretonne/src/isa/mod.rs b/lib/cretonne/src/isa/mod.rs index 8c141126af..39d7d4eb60 100644 --- a/lib/cretonne/src/isa/mod.rs +++ b/lib/cretonne/src/isa/mod.rs @@ -47,14 +47,14 @@ pub use isa::stack::{StackBase, StackBaseMask, StackRef}; use binemit; use flowgraph; -use settings; use ir; +use isa::enc_tables::Encodings; use regalloc; use result; -use timing; -use isa::enc_tables::Encodings; -use std::fmt; +use settings; use std::boxed::Box; +use std::fmt; +use timing; #[cfg(build_riscv)] mod riscv; @@ -68,28 +68,26 @@ mod arm32; #[cfg(build_arm64)] mod arm64; -pub mod registers; -mod encoding; -mod enc_tables; mod constraints; +mod enc_tables; +mod encoding; +pub mod registers; mod stack; /// Returns a builder that can create a corresponding `TargetIsa` /// or `Err(LookupError::Unsupported)` if not enabled. macro_rules! isa_builder { - ($module:ident, $name:ident) => { - { - #[cfg($name)] - fn $name() -> Result { - Ok($module::isa_builder()) - }; - #[cfg(not($name))] - fn $name() -> Result { - Err(LookupError::Unsupported) - } - $name() + ($module:ident, $name:ident) => {{ + #[cfg($name)] + fn $name() -> Result { + Ok($module::isa_builder()) + }; + #[cfg(not($name))] + fn $name() -> Result { + Err(LookupError::Unsupported) } - }; + $name() + }}; } /// Look for a supported ISA with the given `name`. @@ -248,8 +246,8 @@ pub trait TargetIsa: fmt::Display { fn prologue_epilogue(&self, func: &mut ir::Function) -> result::CtonResult { let _tt = timing::prologue_epilogue(); // This default implementation is unlikely to be good enough. - use stack_layout::layout_stack; use ir::stackslot::{StackOffset, StackSize}; + use stack_layout::layout_stack; let word_size = if self.flags().is_64bit() { 8 } else { 4 }; diff --git a/lib/cretonne/src/isa/riscv/abi.rs b/lib/cretonne/src/isa/riscv/abi.rs index 4eff90c954..0782fa5e53 100644 --- a/lib/cretonne/src/isa/riscv/abi.rs +++ b/lib/cretonne/src/isa/riscv/abi.rs @@ -5,13 +5,13 @@ //! //! This doesn't support the soft-float ABI at the moment. +use super::registers::{FPR, GPR}; +use super::settings; use abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion}; use ir::{self, AbiParam, ArgumentExtension, ArgumentLoc, ArgumentPurpose, Type}; use isa::RegClass; use regalloc::AllocatableSet; use settings as shared_settings; -use super::registers::{FPR, GPR}; -use super::settings; use std::i32; struct Args { diff --git a/lib/cretonne/src/isa/riscv/enc_tables.rs b/lib/cretonne/src/isa/riscv/enc_tables.rs index 1f0f2e132d..46b2458b49 100644 --- a/lib/cretonne/src/isa/riscv/enc_tables.rs +++ b/lib/cretonne/src/isa/riscv/enc_tables.rs @@ -1,12 +1,12 @@ //! Encoding tables for RISC-V. +use super::registers::*; use ir; use isa; use isa::constraints::*; use isa::enc_tables::*; use isa::encoding::RecipeSizing; use predicates; -use super::registers::*; // Include the generated encoding tables: // - `LEVEL1_RV32` diff --git a/lib/cretonne/src/isa/riscv/mod.rs b/lib/cretonne/src/isa/riscv/mod.rs index 63a3c01088..9c3a498d5e 100644 --- a/lib/cretonne/src/isa/riscv/mod.rs +++ b/lib/cretonne/src/isa/riscv/mod.rs @@ -1,20 +1,20 @@ //! RISC-V Instruction Set Architecture. -pub mod settings; mod abi; mod binemit; mod enc_tables; mod registers; +pub mod settings; use super::super::settings as shared_settings; use binemit::{emit_function, CodeSink, MemoryCodeSink}; -use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings}; -use isa::Builder as IsaBuilder; -use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; use ir; +use isa::Builder as IsaBuilder; +use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings}; +use isa::{EncInfo, RegClass, RegInfo, TargetIsa}; use regalloc; -use std::fmt; use std::boxed::Box; +use std::fmt; #[allow(dead_code)] struct Isa { @@ -113,10 +113,10 @@ impl TargetIsa for Isa { #[cfg(test)] mod tests { - use settings::{self, Configurable}; - use isa; use ir::{DataFlowGraph, InstructionData, Opcode}; use ir::{immediates, types}; + use isa; + use settings::{self, Configurable}; use std::string::{String, ToString}; fn encstr(isa: &isa::TargetIsa, enc: Result) -> String { diff --git a/lib/cretonne/src/isa/stack.rs b/lib/cretonne/src/isa/stack.rs index 7eac43b62c..0db6279d3f 100644 --- a/lib/cretonne/src/isa/stack.rs +++ b/lib/cretonne/src/isa/stack.rs @@ -4,8 +4,8 @@ //! defined in this module expresses the low-level details of accessing a stack slot from an //! encoded instruction. -use ir::stackslot::{StackOffset, StackSlotKind, StackSlots}; use ir::StackSlot; +use ir::stackslot::{StackOffset, StackSlotKind, StackSlots}; /// A method for referencing a stack slot in the current stack frame. /// diff --git a/lib/cretonne/src/legalizer/boundary.rs b/lib/cretonne/src/legalizer/boundary.rs index 6cad2775e5..61f07884ca 100644 --- a/lib/cretonne/src/legalizer/boundary.rs +++ b/lib/cretonne/src/legalizer/boundary.rs @@ -20,9 +20,9 @@ use abi::{legalize_abi_value, ValueConversion}; use cursor::{Cursor, FuncCursor}; use flowgraph::ControlFlowGraph; +use ir::instructions::CallInfo; use ir::{AbiParam, ArgumentLoc, ArgumentPurpose, DataFlowGraph, Ebb, Function, Inst, InstBuilder, SigRef, Signature, Type, Value, ValueLoc}; -use ir::instructions::CallInfo; use isa::TargetIsa; use legalizer::split::{isplit, vsplit}; use std::vec::Vec; diff --git a/lib/cretonne/src/legalizer/heap.rs b/lib/cretonne/src/legalizer/heap.rs index 0d6e7d385b..b3a595833f 100644 --- a/lib/cretonne/src/legalizer/heap.rs +++ b/lib/cretonne/src/legalizer/heap.rs @@ -5,8 +5,8 @@ use cursor::{Cursor, FuncCursor}; use flowgraph::ControlFlowGraph; -use ir::{self, InstBuilder, MemFlags}; use ir::condcodes::IntCC; +use ir::{self, InstBuilder, MemFlags}; use isa::TargetIsa; /// Expand a `heap_addr` instruction according to the definition of the heap. diff --git a/lib/cretonne/src/legalizer/mod.rs b/lib/cretonne/src/legalizer/mod.rs index d434d6b6e5..23b3f56c89 100644 --- a/lib/cretonne/src/legalizer/mod.rs +++ b/lib/cretonne/src/legalizer/mod.rs @@ -13,11 +13,11 @@ //! The legalizer does not deal with register allocation constraints. These constraints are derived //! from the encoding recipes, and solved later by the register allocator. +use bitset::BitSet; use cursor::{Cursor, FuncCursor}; use flowgraph::ControlFlowGraph; use ir::{self, InstBuilder}; use isa::TargetIsa; -use bitset::BitSet; use timing; mod boundary; diff --git a/lib/cretonne/src/licm.rs b/lib/cretonne/src/licm.rs index 546fc01bd8..b5a8f5ed68 100644 --- a/lib/cretonne/src/licm.rs +++ b/lib/cretonne/src/licm.rs @@ -1,14 +1,14 @@ //! A Loop Invariant Code Motion optimization pass use cursor::{Cursor, FuncCursor}; -use ir::{DataFlowGraph, Ebb, Function, Inst, InstBuilder, Layout, Opcode, Type, Value}; -use flowgraph::ControlFlowGraph; -use std::collections::HashSet; use dominator_tree::DominatorTree; use entity::{EntityList, ListPool}; +use flowgraph::ControlFlowGraph; +use ir::{DataFlowGraph, Ebb, Function, Inst, InstBuilder, Layout, Opcode, Type, Value}; use loop_analysis::{Loop, LoopAnalysis}; -use timing; +use std::collections::HashSet; use std::vec::Vec; +use timing; /// Performs the LICM pass by detecting loops within the CFG and moving /// loop-invariant instructions out of them. diff --git a/lib/cretonne/src/loop_analysis.rs b/lib/cretonne/src/loop_analysis.rs index 89d2939ac9..e75f5f26fe 100644 --- a/lib/cretonne/src/loop_analysis.rs +++ b/lib/cretonne/src/loop_analysis.rs @@ -2,13 +2,13 @@ //! and parent in the loop tree. use dominator_tree::DominatorTree; -use entity::{Keys, PrimaryMap}; use entity::EntityMap; +use entity::{Keys, PrimaryMap}; use flowgraph::ControlFlowGraph; use ir::{Ebb, Function, Layout}; use packed_option::PackedOption; -use timing; use std::vec::Vec; +use timing; /// A opaque reference to a code loop. #[derive(Copy, Clone, PartialEq, Eq, Hash)] @@ -226,10 +226,10 @@ impl LoopAnalysis { mod test { use cursor::{Cursor, FuncCursor}; + use dominator_tree::DominatorTree; + use flowgraph::ControlFlowGraph; use ir::{types, Function, InstBuilder}; use loop_analysis::{Loop, LoopAnalysis}; - use flowgraph::ControlFlowGraph; - use dominator_tree::DominatorTree; use std::vec::Vec; #[test] diff --git a/lib/cretonne/src/postopt.rs b/lib/cretonne/src/postopt.rs index efe85d40d7..18f467a68a 100644 --- a/lib/cretonne/src/postopt.rs +++ b/lib/cretonne/src/postopt.rs @@ -3,11 +3,11 @@ #![allow(non_snake_case)] use cursor::{Cursor, EncCursor}; -use ir::dfg::ValueDef; -use ir::{Ebb, Function, Inst, InstBuilder, InstructionData, Value}; use ir::condcodes::{CondCode, FloatCC, IntCC}; -use ir::instructions::{Opcode, ValueList}; +use ir::dfg::ValueDef; use ir::immediates::Imm64; +use ir::instructions::{Opcode, ValueList}; +use ir::{Ebb, Function, Inst, InstBuilder, InstructionData, Value}; use isa::TargetIsa; use timing; diff --git a/lib/cretonne/src/preopt.rs b/lib/cretonne/src/preopt.rs index 81e798e987..bdd1c445eb 100644 --- a/lib/cretonne/src/preopt.rs +++ b/lib/cretonne/src/preopt.rs @@ -3,13 +3,13 @@ #![allow(non_snake_case)] use cursor::{Cursor, FuncCursor}; -use ir::dfg::ValueDef; -use ir::{DataFlowGraph, Function, InstBuilder, InstructionData, Type, Value}; -use ir::Inst; -use ir::types::{I32, I64}; -use ir::instructions::Opcode; use divconst_magic_numbers::{MS32, MS64, MU32, MU64}; use divconst_magic_numbers::{magicS32, magicS64, magicU32, magicU64}; +use ir::Inst; +use ir::dfg::ValueDef; +use ir::instructions::Opcode; +use ir::types::{I32, I64}; +use ir::{DataFlowGraph, Function, InstBuilder, InstructionData, Type, Value}; use timing; //---------------------------------------------------------------------- diff --git a/lib/cretonne/src/print_errors.rs b/lib/cretonne/src/print_errors.rs index 1bc61cfb59..917f860ce9 100644 --- a/lib/cretonne/src/print_errors.rs +++ b/lib/cretonne/src/print_errors.rs @@ -1,10 +1,10 @@ //! Utility routines for pretty-printing error messages. use ir; -use verifier; -use result::CtonError; use isa::TargetIsa; +use result::CtonError; use std::fmt::Write; +use verifier; /// Pretty-print a verifier error. pub fn pretty_verifier_error( diff --git a/lib/cretonne/src/regalloc/affinity.rs b/lib/cretonne/src/regalloc/affinity.rs index 0e49ac5f0b..e0078579a7 100644 --- a/lib/cretonne/src/regalloc/affinity.rs +++ b/lib/cretonne/src/regalloc/affinity.rs @@ -8,9 +8,9 @@ //! subclass. This is just a hint, and the register allocator is allowed to pick a register from a //! larger register class instead. -use std::fmt; use ir::{AbiParam, ArgumentLoc}; use isa::{ConstraintKind, OperandConstraint, RegClassIndex, RegInfo, TargetIsa}; +use std::fmt; /// Preferred register allocation for an SSA value. #[derive(Clone, Copy, Debug)] diff --git a/lib/cretonne/src/regalloc/coalescing.rs b/lib/cretonne/src/regalloc/coalescing.rs index b8a7270d59..b77488fec7 100644 --- a/lib/cretonne/src/regalloc/coalescing.rs +++ b/lib/cretonne/src/regalloc/coalescing.rs @@ -11,15 +11,15 @@ use dominator_tree::{DominatorTree, DominatorTreePreorder}; use flowgraph::ControlFlowGraph; use ir::{self, InstBuilder, ProgramOrder}; use ir::{Ebb, ExpandedProgramPoint, Function, Inst, Value}; +use isa::{EncInfo, TargetIsa}; use regalloc::affinity::Affinity; use regalloc::liveness::Liveness; use regalloc::virtregs::{VirtReg, VirtRegs}; use std::cmp; -use std::iter; use std::fmt; +use std::iter; use std::slice; use std::vec::Vec; -use isa::{EncInfo, TargetIsa}; use timing; // # Implementation diff --git a/lib/cretonne/src/regalloc/coloring.rs b/lib/cretonne/src/regalloc/coloring.rs index ad5952885d..b9b1512220 100644 --- a/lib/cretonne/src/regalloc/coloring.rs +++ b/lib/cretonne/src/regalloc/coloring.rs @@ -44,10 +44,10 @@ use cursor::{Cursor, EncCursor}; use dominator_tree::DominatorTree; -use ir::{Ebb, Function, Inst, Layout, SigRef, Value, ValueLoc}; use ir::{AbiParam, ArgumentLoc, InstBuilder, ValueDef}; -use isa::{regs_overlap, RegClass, RegInfo, RegUnit}; +use ir::{Ebb, Function, Inst, Layout, SigRef, Value, ValueLoc}; use isa::{ConstraintKind, EncInfo, OperandConstraint, RecipeConstraints, TargetIsa}; +use isa::{regs_overlap, RegClass, RegInfo, RegUnit}; use packed_option::PackedOption; use regalloc::RegDiversions; use regalloc::affinity::Affinity; diff --git a/lib/cretonne/src/regalloc/diversion.rs b/lib/cretonne/src/regalloc/diversion.rs index d0b7e4db91..b848a879c9 100644 --- a/lib/cretonne/src/regalloc/diversion.rs +++ b/lib/cretonne/src/regalloc/diversion.rs @@ -7,8 +7,8 @@ //! These register diversions are local to an EBB. No values can be diverted when entering a new //! EBB. -use ir::{StackSlot, Value, ValueLoc, ValueLocations}; use ir::{InstructionData, Opcode}; +use ir::{StackSlot, Value, ValueLoc, ValueLocations}; use isa::{RegInfo, RegUnit}; use std::fmt; use std::vec::Vec; @@ -187,8 +187,8 @@ impl<'a> fmt::Display for DisplayDiversions<'a> { #[cfg(test)] mod tests { use super::*; - use ir::Value; use entity::EntityRef; + use ir::Value; #[test] fn inserts() { diff --git a/lib/cretonne/src/regalloc/liverange.rs b/lib/cretonne/src/regalloc/liverange.rs index 79526c613d..18118e706d 100644 --- a/lib/cretonne/src/regalloc/liverange.rs +++ b/lib/cretonne/src/regalloc/liverange.rs @@ -457,8 +457,8 @@ impl SparseMapValue for GenLiveRange { mod tests { use super::{GenLiveRange, LiveRangeContext}; use bforest; - use ir::{Ebb, Inst, Value}; use entity::EntityRef; + use ir::{Ebb, Inst, Value}; use ir::{ExpandedProgramPoint, ProgramOrder}; use std::cmp::Ordering; use std::vec::Vec; diff --git a/lib/cretonne/src/regalloc/mod.rs b/lib/cretonne/src/regalloc/mod.rs index 6ae93c67b6..6868c0a235 100644 --- a/lib/cretonne/src/regalloc/mod.rs +++ b/lib/cretonne/src/regalloc/mod.rs @@ -2,11 +2,11 @@ //! //! This module contains data structures and algorithms used for register allocation. -pub mod liverange; -pub mod liveness; pub mod allocatable_set; -pub mod live_value_tracker; pub mod coloring; +pub mod live_value_tracker; +pub mod liveness; +pub mod liverange; pub mod virtregs; mod affinity; diff --git a/lib/cretonne/src/regalloc/pressure.rs b/lib/cretonne/src/regalloc/pressure.rs index 6bbe2b75a5..14978f48b8 100644 --- a/lib/cretonne/src/regalloc/pressure.rs +++ b/lib/cretonne/src/regalloc/pressure.rs @@ -269,16 +269,16 @@ impl fmt::Display for Pressure { #[cfg(test)] #[cfg(build_arm32)] mod tests { + use super::Pressure; use isa::{RegClass, TargetIsa}; use regalloc::AllocatableSet; use std::borrow::Borrow; - use super::Pressure; use std::boxed::Box; // Make an arm32 `TargetIsa`, if possible. fn arm32() -> Option> { - use settings; use isa; + use settings; let shared_builder = settings::builder(); let shared_flags = settings::Flags::new(&shared_builder); diff --git a/lib/cretonne/src/regalloc/reload.rs b/lib/cretonne/src/regalloc/reload.rs index 2ce9a04f75..df527fdbca 100644 --- a/lib/cretonne/src/regalloc/reload.rs +++ b/lib/cretonne/src/regalloc/reload.rs @@ -12,16 +12,16 @@ use cursor::{Cursor, EncCursor}; use dominator_tree::DominatorTree; use entity::{SparseMap, SparseMapValue}; -use ir::{Ebb, Function, Inst, Value}; use ir::{AbiParam, ArgumentLoc, InstBuilder}; +use ir::{Ebb, Function, Inst, Value}; use isa::RegClass; use isa::{ConstraintKind, EncInfo, Encoding, RecipeConstraints, TargetIsa}; use regalloc::affinity::Affinity; use regalloc::live_value_tracker::{LiveValue, LiveValueTracker}; use regalloc::liveness::Liveness; +use std::vec::Vec; use timing; use topo_order::TopoOrder; -use std::vec::Vec; /// Reusable data structures for the reload pass. pub struct Reload { diff --git a/lib/cretonne/src/regalloc/solver.rs b/lib/cretonne/src/regalloc/solver.rs index 92b7a62679..4bac41aa99 100644 --- a/lib/cretonne/src/regalloc/solver.rs +++ b/lib/cretonne/src/regalloc/solver.rs @@ -98,6 +98,7 @@ //! appropriate candidate among the set of live register values, add it as a variable and start //! over. +use super::AllocatableSet; use dbg::DisplayList; use entity::{SparseMap, SparseMapValue}; use ir::Value; @@ -106,7 +107,6 @@ use regalloc::allocatable_set::RegSetIter; use std::cmp; use std::fmt; use std::mem; -use super::AllocatableSet; use std::u16; use std::vec::Vec; @@ -1158,17 +1158,17 @@ impl fmt::Display for Solver { #[cfg(test)] #[cfg(build_arm32)] mod tests { + use super::{Move, Solver}; use entity::EntityRef; use ir::Value; use isa::{RegClass, RegInfo, RegUnit, TargetIsa}; use regalloc::AllocatableSet; - use super::{Move, Solver}; use std::boxed::Box; // Make an arm32 `TargetIsa`, if possible. fn arm32() -> Option> { - use settings; use isa; + use settings; let shared_builder = settings::builder(); let shared_flags = settings::Flags::new(&shared_builder); diff --git a/lib/cretonne/src/regalloc/virtregs.rs b/lib/cretonne/src/regalloc/virtregs.rs index 4583effe4f..215e5efac2 100644 --- a/lib/cretonne/src/regalloc/virtregs.rs +++ b/lib/cretonne/src/regalloc/virtregs.rs @@ -13,9 +13,9 @@ use dbg::DisplayList; use dominator_tree::DominatorTreePreorder; +use entity::EntityRef; use entity::{EntityList, ListPool}; use entity::{EntityMap, Keys, PrimaryMap}; -use entity::EntityRef; use ir::{Function, Value}; use packed_option::PackedOption; use ref_slice::ref_slice; diff --git a/lib/cretonne/src/result.rs b/lib/cretonne/src/result.rs index bd2ae5a101..04e248dcbb 100644 --- a/lib/cretonne/src/result.rs +++ b/lib/cretonne/src/result.rs @@ -1,8 +1,8 @@ //! Result and error types representing the outcome of compiling a function. -use verifier; use std::error::Error as StdError; use std::fmt; +use verifier; /// A compilation error. /// diff --git a/lib/cretonne/src/settings.rs b/lib/cretonne/src/settings.rs index ed1d8cd168..aee441f3ca 100644 --- a/lib/cretonne/src/settings.rs +++ b/lib/cretonne/src/settings.rs @@ -190,8 +190,8 @@ impl<'a> PredicateView<'a> { /// This module holds definitions that need to be public so the can be instantiated by generated /// code in other modules. pub mod detail { - use std::fmt; use constant_hash; + use std::fmt; /// An instruction group template. pub struct Template { @@ -345,9 +345,9 @@ impl<'a> From<&'a TargetIsa> for FlagsOrIsa<'a> { #[cfg(test)] mod tests { - use super::{builder, Flags}; - use super::Error::*; use super::Configurable; + use super::Error::*; + use super::{builder, Flags}; use std::string::ToString; #[test] diff --git a/lib/cretonne/src/simple_gvn.rs b/lib/cretonne/src/simple_gvn.rs index 073101cd9c..ae8dd387d6 100644 --- a/lib/cretonne/src/simple_gvn.rs +++ b/lib/cretonne/src/simple_gvn.rs @@ -4,8 +4,8 @@ use cursor::{Cursor, FuncCursor}; use dominator_tree::DominatorTree; use ir::{Function, Inst, InstructionData, Opcode, Type}; use scoped_hash_map::ScopedHashMap; -use timing; use std::vec::Vec; +use timing; /// Test whether the given opcode is unsafe to even consider for GVN. fn trivially_unsafe_for_gvn(opcode: Opcode) -> bool { diff --git a/lib/cretonne/src/stack_layout.rs b/lib/cretonne/src/stack_layout.rs index 9d723791d7..3b07ee154a 100644 --- a/lib/cretonne/src/stack_layout.rs +++ b/lib/cretonne/src/stack_layout.rs @@ -110,10 +110,10 @@ pub fn layout_stack(frame: &mut StackSlots, alignment: StackSize) -> Result Verifier<'a> { #[cfg(test)] mod tests { use super::{Error, Verifier}; + use entity::EntityList; use ir::Function; use ir::instructions::{InstructionData, Opcode}; - use entity::EntityList; use settings; macro_rules! assert_err_with_msg { - ($e:expr, $msg:expr) => ( + ($e:expr, $msg:expr) => { match $e { - Ok(_) => { panic!("Expected an error!") }, - Err(Error { message, .. } ) => { + Ok(_) => panic!("Expected an error!"), + Err(Error { message, .. }) => { if !message.contains($msg) { - panic!(format!("'{}' did not contain the substring '{}'", message, $msg)); + panic!(format!( + "'{}' did not contain the substring '{}'", + message, $msg + )); } } } - ) + }; } #[test] diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index dee3ab0346..2ed8da87e9 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -5,9 +5,9 @@ use ir::{DataFlowGraph, Ebb, Function, Inst, SigRef, Type, Value, ValueDef}; use isa::{RegInfo, TargetIsa}; +use packed_option::ReservedValue; use std::fmt::{self, Error, Result, Write}; use std::result; -use packed_option::ReservedValue; use std::string::String; /// Write `func` to `w` as equivalent text. @@ -451,8 +451,8 @@ impl<'a> fmt::Display for DisplayValues<'a> { #[cfg(test)] mod tests { - use ir::{ExternalName, Function, StackSlotData, StackSlotKind}; use ir::types; + use ir::{ExternalName, Function, StackSlotData, StackSlotKind}; use std::string::ToString; #[test] diff --git a/lib/filetests/src/concurrent.rs b/lib/filetests/src/concurrent.rs index a93d39cddf..7ca4b01d89 100644 --- a/lib/filetests/src/concurrent.rs +++ b/lib/filetests/src/concurrent.rs @@ -4,13 +4,13 @@ //! concurrently. use cretonne::timing; +use num_cpus; use std::panic::catch_unwind; use std::path::{Path, PathBuf}; use std::sync::mpsc::{channel, Receiver, Sender}; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; -use num_cpus; use {runone, TestResult}; /// Request sent to worker threads contains jobid and path. diff --git a/lib/filetests/src/lib.rs b/lib/filetests/src/lib.rs index 66bb7023ec..718502eb53 100644 --- a/lib/filetests/src/lib.rs +++ b/lib/filetests/src/lib.rs @@ -14,16 +14,16 @@ extern crate cton_reader; extern crate filecheck; extern crate num_cpus; -use std::path::Path; -use std::time; use cton_reader::TestCommand; use runner::TestRunner; +use std::path::Path; +use std::time; mod concurrent; +mod match_directive; mod runner; mod runone; mod subtest; -mod match_directive; mod test_binemit; mod test_cat; diff --git a/lib/filetests/src/runner.rs b/lib/filetests/src/runner.rs index f9e8fb3638..d4865b92e9 100644 --- a/lib/filetests/src/runner.rs +++ b/lib/filetests/src/runner.rs @@ -3,13 +3,13 @@ //! This module implements the `TestRunner` struct which manages executing tests as well as //! scanning directories for tests. +use concurrent::{ConcurrentRunner, Reply}; use std::error::Error; -use std::fmt::{self, Display}; use std::ffi::OsStr; +use std::fmt::{self, Display}; use std::path::{Path, PathBuf}; use std::time; use {runone, TestResult}; -use concurrent::{ConcurrentRunner, Reply}; /// Timeout in seconds when we're not making progress. const TIMEOUT_PANIC: usize = 10; diff --git a/lib/filetests/src/runone.rs b/lib/filetests/src/runone.rs index 4b3033ea2e..8cdec2d626 100644 --- a/lib/filetests/src/runone.rs +++ b/lib/filetests/src/runone.rs @@ -1,20 +1,20 @@ //! Run the tests in a single test file. -use std::borrow::Cow; -use std::path::Path; -use std::time; -use std::io::{self, Read}; -use std::fs; use cretonne::ir::Function; use cretonne::isa::TargetIsa; +use cretonne::print_errors::pretty_verifier_error; use cretonne::settings::Flags; use cretonne::timing; use cretonne::verify_function; -use cretonne::print_errors::pretty_verifier_error; -use cton_reader::parse_test; use cton_reader::IsaSpec; -use {new_subtest, TestResult}; +use cton_reader::parse_test; +use std::borrow::Cow; +use std::fs; +use std::io::{self, Read}; +use std::path::Path; +use std::time; use subtest::{Context, Result, SubTest}; +use {new_subtest, TestResult}; /// Read an entire file into a string. fn read_to_string>(path: P) -> io::Result { diff --git a/lib/filetests/src/subtest.rs b/lib/filetests/src/subtest.rs index 4395780021..ba94f87e78 100644 --- a/lib/filetests/src/subtest.rs +++ b/lib/filetests/src/subtest.rs @@ -1,12 +1,12 @@ //! `SubTest` trait. -use std::result; -use std::borrow::Cow; use cretonne::ir::Function; use cretonne::isa::TargetIsa; use cretonne::settings::{Flags, FlagsOrIsa}; use cton_reader::{Comment, Details}; use filecheck::{Checker, CheckerBuilder, NO_VARIABLES}; +use std::borrow::Cow; +use std::result; pub type Result = result::Result; diff --git a/lib/filetests/src/test_binemit.rs b/lib/filetests/src/test_binemit.rs index db3d9be634..775e014600 100644 --- a/lib/filetests/src/test_binemit.rs +++ b/lib/filetests/src/test_binemit.rs @@ -3,18 +3,18 @@ //! The `binemit` test command generates binary machine code for every instruction in the input //! functions and compares the results to the expected output. -use std::borrow::Cow; -use std::collections::HashMap; -use std::fmt::Write; use cretonne::binemit; +use cretonne::binemit::RegDiversions; use cretonne::dbg::DisplayList; use cretonne::ir; use cretonne::ir::entities::AnyEntity; -use cretonne::binemit::RegDiversions; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{Context, Result, SubTest}; use match_directive::match_directive; +use std::borrow::Cow; +use std::collections::HashMap; +use std::fmt::Write; +use subtest::{Context, Result, SubTest}; struct TestBinEmit; diff --git a/lib/filetests/src/test_cat.rs b/lib/filetests/src/test_cat.rs index 42b18b3625..f8f145834c 100644 --- a/lib/filetests/src/test_cat.rs +++ b/lib/filetests/src/test_cat.rs @@ -1,8 +1,8 @@ //! The `cat` subtest. -use std::borrow::Cow; use cretonne::ir::Function; use cton_reader::TestCommand; +use std::borrow::Cow; use subtest::{self, Context, Result as STResult, SubTest}; /// Object implementing the `test cat` sub-test. diff --git a/lib/filetests/src/test_compile.rs b/lib/filetests/src/test_compile.rs index 5217f7ebb6..a924eee799 100644 --- a/lib/filetests/src/test_compile.rs +++ b/lib/filetests/src/test_compile.rs @@ -2,14 +2,14 @@ //! //! The `compile` test command runs each function through the full code generator pipeline +use cretonne; use cretonne::binemit; use cretonne::ir; -use cretonne; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; +use subtest::{run_filecheck, Context, Result, SubTest}; struct TestCompile; diff --git a/lib/filetests/src/test_dce.rs b/lib/filetests/src/test_dce.rs index 4e826c9abc..d96214182b 100644 --- a/lib/filetests/src/test_dce.rs +++ b/lib/filetests/src/test_dce.rs @@ -5,13 +5,13 @@ //! //! The resulting function is sent to `filecheck`. -use cretonne::ir::Function; use cretonne; +use cretonne::ir::Function; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; +use subtest::{run_filecheck, Context, Result, SubTest}; struct TestDCE; diff --git a/lib/filetests/src/test_domtree.rs b/lib/filetests/src/test_domtree.rs index fed38d9d50..da5a926f3d 100644 --- a/lib/filetests/src/test_domtree.rs +++ b/lib/filetests/src/test_domtree.rs @@ -17,12 +17,12 @@ use cretonne::flowgraph::ControlFlowGraph; use cretonne::ir::Function; use cretonne::ir::entities::AnyEntity; use cton_reader::TestCommand; -use subtest::{run_filecheck, Context, Result, SubTest}; +use match_directive::match_directive; use std::borrow::{Borrow, Cow}; use std::collections::HashMap; use std::fmt::{self, Write}; use std::result; -use match_directive::match_directive; +use subtest::{run_filecheck, Context, Result, SubTest}; struct TestDomtree; diff --git a/lib/filetests/src/test_legalizer.rs b/lib/filetests/src/test_legalizer.rs index 76bd9f491b..0794081e51 100644 --- a/lib/filetests/src/test_legalizer.rs +++ b/lib/filetests/src/test_legalizer.rs @@ -3,13 +3,13 @@ //! The `test legalizer` test command runs each function through `legalize_function()` and sends //! the result to filecheck. -use std::borrow::Cow; use cretonne; use cretonne::ir::Function; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{run_filecheck, Context, Result, SubTest}; +use std::borrow::Cow; use std::fmt::Write; +use subtest::{run_filecheck, Context, Result, SubTest}; struct TestLegalizer; diff --git a/lib/filetests/src/test_licm.rs b/lib/filetests/src/test_licm.rs index bed36b44c2..c59dee1cba 100644 --- a/lib/filetests/src/test_licm.rs +++ b/lib/filetests/src/test_licm.rs @@ -5,13 +5,13 @@ //! //! The resulting function is sent to `filecheck`. -use cretonne::ir::Function; use cretonne; +use cretonne::ir::Function; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; +use subtest::{run_filecheck, Context, Result, SubTest}; struct TestLICM; diff --git a/lib/filetests/src/test_postopt.rs b/lib/filetests/src/test_postopt.rs index ad26a06c30..c89fb33ea5 100644 --- a/lib/filetests/src/test_postopt.rs +++ b/lib/filetests/src/test_postopt.rs @@ -2,13 +2,13 @@ //! //! The resulting function is sent to `filecheck`. -use cretonne::ir::Function; use cretonne; +use cretonne::ir::Function; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; +use subtest::{run_filecheck, Context, Result, SubTest}; struct TestPostopt; diff --git a/lib/filetests/src/test_preopt.rs b/lib/filetests/src/test_preopt.rs index 8a30f0feb3..e2fc9819c9 100644 --- a/lib/filetests/src/test_preopt.rs +++ b/lib/filetests/src/test_preopt.rs @@ -2,13 +2,13 @@ //! //! The resulting function is sent to `filecheck`. -use cretonne::ir::Function; use cretonne; +use cretonne::ir::Function; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; +use subtest::{run_filecheck, Context, Result, SubTest}; struct TestPreopt; diff --git a/lib/filetests/src/test_print_cfg.rs b/lib/filetests/src/test_print_cfg.rs index 4c0b3250d2..7092126cd7 100644 --- a/lib/filetests/src/test_print_cfg.rs +++ b/lib/filetests/src/test_print_cfg.rs @@ -5,8 +5,8 @@ use std::borrow::Cow; -use cretonne::ir::Function; use cretonne::cfg_printer::CFGPrinter; +use cretonne::ir::Function; use cton_reader::TestCommand; use subtest::{self, Context, Result as STResult, SubTest}; diff --git a/lib/filetests/src/test_regalloc.rs b/lib/filetests/src/test_regalloc.rs index e94a142dcc..b2ab98c3a4 100644 --- a/lib/filetests/src/test_regalloc.rs +++ b/lib/filetests/src/test_regalloc.rs @@ -5,13 +5,13 @@ //! //! The resulting function is sent to `filecheck`. -use cretonne::ir::Function; use cretonne; +use cretonne::ir::Function; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; +use subtest::{run_filecheck, Context, Result, SubTest}; struct TestRegalloc; diff --git a/lib/filetests/src/test_simple_gvn.rs b/lib/filetests/src/test_simple_gvn.rs index 04fcb078dd..62f5a2adae 100644 --- a/lib/filetests/src/test_simple_gvn.rs +++ b/lib/filetests/src/test_simple_gvn.rs @@ -5,13 +5,13 @@ //! //! The resulting function is sent to `filecheck`. -use cretonne::ir::Function; use cretonne; +use cretonne::ir::Function; use cretonne::print_errors::pretty_error; use cton_reader::TestCommand; -use subtest::{run_filecheck, Context, Result, SubTest}; use std::borrow::Cow; use std::fmt::Write; +use subtest::{run_filecheck, Context, Result, SubTest}; struct TestSimpleGVN; diff --git a/lib/filetests/src/test_verifier.rs b/lib/filetests/src/test_verifier.rs index 906b279408..a4ec799ee3 100644 --- a/lib/filetests/src/test_verifier.rs +++ b/lib/filetests/src/test_verifier.rs @@ -9,12 +9,12 @@ //! This annotation means that the verifier is expected to given an error for the jump instruction //! containing the substring "jump to non-existent EBB". -use std::borrow::{Borrow, Cow}; -use cretonne::verify_function; use cretonne::ir::Function; +use cretonne::verify_function; use cton_reader::TestCommand; -use subtest::{Context, Result, SubTest}; use match_directive::match_directive; +use std::borrow::{Borrow, Cow}; +use subtest::{Context, Result, SubTest}; struct TestVerifier; diff --git a/lib/frontend/src/frontend.rs b/lib/frontend/src/frontend.rs index 00e5de53f1..4396c4edac 100644 --- a/lib/frontend/src/frontend.rs +++ b/lib/frontend/src/frontend.rs @@ -1,14 +1,14 @@ //! A frontend for building Cretonne IR from other languages. use cretonne::cursor::{Cursor, FuncCursor}; +use cretonne::entity::{EntityMap, EntityRef, EntitySet}; use cretonne::ir; +use cretonne::ir::function::DisplayFunction; use cretonne::ir::{DataFlowGraph, Ebb, ExtFuncData, FuncRef, Function, GlobalVar, GlobalVarData, Heap, HeapData, Inst, InstBuilderBase, InstructionData, JumpTable, JumpTableData, SigRef, Signature, StackSlot, StackSlotData, Type, Value}; -use cretonne::ir::function::DisplayFunction; use cretonne::isa::TargetIsa; -use ssa::{Block, SSABuilder, SideEffects}; -use cretonne::entity::{EntityMap, EntityRef, EntitySet}; use cretonne::packed_option::PackedOption; +use ssa::{Block, SSABuilder, SideEffects}; /// Structure used for translating a series of functions into Cretonne IR. /// @@ -592,13 +592,13 @@ where #[cfg(test)] mod tests { - use cretonne::entity::EntityRef; - use cretonne::ir::{AbiParam, CallConv, ExternalName, Function, InstBuilder, Signature}; - use cretonne::ir::types::*; - use frontend::{FunctionBuilder, FunctionBuilderContext}; - use cretonne::verifier::verify_function; - use cretonne::settings; use Variable; + use cretonne::entity::EntityRef; + use cretonne::ir::types::*; + use cretonne::ir::{AbiParam, CallConv, ExternalName, Function, InstBuilder, Signature}; + use cretonne::settings; + use cretonne::verifier::verify_function; + use frontend::{FunctionBuilder, FunctionBuilderContext}; fn sample_function(lazy_seal: bool) { let mut sig = Signature::new(CallConv::SystemV); diff --git a/lib/frontend/src/ssa.rs b/lib/frontend/src/ssa.rs index 96085c38f8..82e9242b4f 100644 --- a/lib/frontend/src/ssa.rs +++ b/lib/frontend/src/ssa.rs @@ -6,15 +6,15 @@ //! Lecture Notes in Computer Science, vol 7791. Springer, Berlin, Heidelberg use cretonne::cursor::{Cursor, FuncCursor}; -use cretonne::ir::{Ebb, Function, Inst, InstBuilder, Type, Value}; -use cretonne::ir::instructions::BranchInfo; use cretonne::entity::{EntityMap, EntityRef, PrimaryMap}; +use cretonne::ir::immediates::{Ieee32, Ieee64}; +use cretonne::ir::instructions::BranchInfo; +use cretonne::ir::types::{F32, F64}; +use cretonne::ir::{Ebb, Function, Inst, InstBuilder, Type, Value}; use cretonne::packed_option::PackedOption; use cretonne::packed_option::ReservedValue; -use std::u32; -use cretonne::ir::types::{F32, F64}; -use cretonne::ir::immediates::{Ieee32, Ieee64}; use std::mem; +use std::u32; use std::vec::Vec; /// Structure containing the data relevant the construction of SSA for a given function. @@ -713,15 +713,15 @@ where #[cfg(test)] mod tests { + use Variable; use cretonne::cursor::{Cursor, FuncCursor}; use cretonne::entity::EntityRef; - use cretonne::ir::{Function, Inst, InstBuilder, JumpTableData, Opcode}; - use cretonne::ir::types::*; - use cretonne::verify_function; use cretonne::ir::instructions::BranchInfo; + use cretonne::ir::types::*; + use cretonne::ir::{Function, Inst, InstBuilder, JumpTableData, Opcode}; use cretonne::settings; + use cretonne::verify_function; use ssa::SSABuilder; - use Variable; #[test] fn simple_block() { diff --git a/lib/reader/src/isaspec.rs b/lib/reader/src/isaspec.rs index 6cc29a81a1..e87b2b6771 100644 --- a/lib/reader/src/isaspec.rs +++ b/lib/reader/src/isaspec.rs @@ -6,8 +6,8 @@ //! If a test case file contains `isa` commands, the tests will only be run against the specified //! ISAs. If the file contains no `isa` commands, the tests will be run against all supported ISAs. -use cretonne::settings::{Configurable, Error as SetError, Flags}; use cretonne::isa::TargetIsa; +use cretonne::settings::{Configurable, Error as SetError, Flags}; use error::{Location, Result}; use testcommand::TestOption; diff --git a/lib/reader/src/lexer.rs b/lib/reader/src/lexer.rs index c55bbf1dd4..a2fde86b5a 100644 --- a/lib/reader/src/lexer.rs +++ b/lib/reader/src/lexer.rs @@ -1,12 +1,12 @@ //! Lexical analysis for .cton files. -use std::str::CharIndices; -use std::u16; -#[allow(unused_imports)] -use std::ascii::AsciiExt; use cretonne::ir::types; use cretonne::ir::{Ebb, Value}; use error::Location; +#[allow(unused_imports)] +use std::ascii::AsciiExt; +use std::str::CharIndices; +use std::u16; /// A Token returned from the `Lexer`. /// diff --git a/lib/reader/src/lib.rs b/lib/reader/src/lib.rs index 58fe21b5ce..e012876c1c 100644 --- a/lib/reader/src/lib.rs +++ b/lib/reader/src/lib.rs @@ -8,16 +8,16 @@ extern crate cretonne; pub use error::{Error, Location, Result}; +pub use isaspec::{parse_options, IsaSpec}; pub use parser::{parse_functions, parse_test}; +pub use sourcemap::SourceMap; pub use testcommand::{TestCommand, TestOption}; pub use testfile::{Comment, Details, TestFile}; -pub use isaspec::{parse_options, IsaSpec}; -pub use sourcemap::SourceMap; mod error; +mod isaspec; mod lexer; mod parser; -mod testcommand; -mod isaspec; -mod testfile; mod sourcemap; +mod testcommand; +mod testfile; diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index 48e2e2745b..f23f644a0e 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -1,27 +1,27 @@ //! Parser for .cton files. -use std::str::FromStr; -use std::{u16, u32}; -use std::mem; +use cretonne::entity::EntityRef; +use cretonne::ir; +use cretonne::ir::entities::AnyEntity; +use cretonne::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm32}; +use cretonne::ir::instructions::{InstructionData, InstructionFormat, VariableArgs}; +use cretonne::ir::types::VOID; use cretonne::ir::{AbiParam, ArgumentExtension, ArgumentLoc, CallConv, Ebb, ExtFuncData, ExternalName, FuncRef, Function, GlobalVar, GlobalVarData, Heap, HeapBase, HeapData, HeapStyle, JumpTable, JumpTableData, MemFlags, Opcode, SigRef, Signature, StackSlot, StackSlotData, StackSlotKind, Type, Value, ValueLoc}; -use cretonne::ir; -use cretonne::ir::types::VOID; -use cretonne::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm32}; -use cretonne::ir::entities::AnyEntity; -use cretonne::ir::instructions::{InstructionData, InstructionFormat, VariableArgs}; use cretonne::isa::{self, Encoding, RegUnit, TargetIsa}; -use cretonne::{settings, timing}; -use cretonne::entity::EntityRef; use cretonne::packed_option::ReservedValue; -use testfile::{Comment, Details, TestFile}; +use cretonne::{settings, timing}; use error::{Error, Location, Result}; -use lexer::{self, Lexer, Token}; -use testcommand::TestCommand; use isaspec; +use lexer::{self, Lexer, Token}; use sourcemap::SourceMap; +use std::mem; +use std::str::FromStr; +use std::{u16, u32}; +use testcommand::TestCommand; +use testfile::{Comment, Details, TestFile}; /// Parse the entire `text` into a list of functions. /// @@ -2395,13 +2395,13 @@ impl<'a> Parser<'a> { #[cfg(test)] mod tests { use super::*; - use cretonne::ir::{ArgumentExtension, ArgumentPurpose, CallConv}; - use cretonne::ir::types; use cretonne::ir::StackSlotKind; use cretonne::ir::entities::AnyEntity; - use testfile::{Comment, Details}; - use isaspec::IsaSpec; + use cretonne::ir::types; + use cretonne::ir::{ArgumentExtension, ArgumentPurpose, CallConv}; use error::Error; + use isaspec::IsaSpec; + use testfile::{Comment, Details}; #[test] fn argument_type() { diff --git a/lib/reader/src/testfile.rs b/lib/reader/src/testfile.rs index 8ec5271a07..7218f8cb72 100644 --- a/lib/reader/src/testfile.rs +++ b/lib/reader/src/testfile.rs @@ -6,10 +6,10 @@ use cretonne::ir::Function; use cretonne::ir::entities::AnyEntity; -use testcommand::TestCommand; +use error::Location; use isaspec::IsaSpec; use sourcemap::SourceMap; -use error::Location; +use testcommand::TestCommand; /// A parsed test case. /// diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index 82fec54e5b..9dbace8556 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -22,19 +22,19 @@ //! //! That is why `translate_function_body` takes an object having the `WasmRuntime` trait as //! argument. -use cretonne::ir::{self, InstBuilder, JumpTableData, MemFlags}; -use cretonne::ir::types::*; use cretonne::ir::condcodes::{FloatCC, IntCC}; +use cretonne::ir::types::*; +use cretonne::ir::{self, InstBuilder, JumpTableData, MemFlags}; use cretonne::packed_option::ReservedValue; use cton_frontend::{FunctionBuilder, Variable}; -use wasmparser::{MemoryImmediate, Operator}; -use translation_utils::{num_return_values, type_to_type, f32_translation, f64_translation}; -use translation_utils::{FunctionIndex, MemoryIndex, SignatureIndex, TableIndex}; +use environ::{FuncEnvironment, GlobalValue}; use state::{ControlStackFrame, TranslationState}; use std::collections::{hash_map, HashMap}; -use environ::{FuncEnvironment, GlobalValue}; -use std::{i32, u32}; use std::vec::Vec; +use std::{i32, u32}; +use translation_utils::{FunctionIndex, MemoryIndex, SignatureIndex, TableIndex}; +use translation_utils::{num_return_values, type_to_type, f32_translation, f64_translation}; +use wasmparser::{MemoryImmediate, Operator}; // Clippy warns about "flags: _" but its important to document that the flags field is ignored #[cfg_attr(feature = "cargo-clippy", allow(unneeded_field_pattern))] diff --git a/lib/wasm/src/environ/dummy.rs b/lib/wasm/src/environ/dummy.rs index b24499bde0..a71dddda3d 100644 --- a/lib/wasm/src/environ/dummy.rs +++ b/lib/wasm/src/environ/dummy.rs @@ -1,17 +1,17 @@ //! "Dummy" environment for testing wasm translation. +use cretonne::cursor::FuncCursor; +use cretonne::ir::types::*; +use cretonne::ir::{self, InstBuilder}; +use cretonne::settings; use environ::{FuncEnvironment, GlobalValue, ModuleEnvironment}; +use func_translator::FuncTranslator; +use std::error::Error; +use std::string::String; +use std::vec::Vec; use translation_utils::{FunctionIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex}; -use func_translator::FuncTranslator; -use cretonne::ir::{self, InstBuilder}; -use cretonne::ir::types::*; -use cretonne::cursor::FuncCursor; -use cretonne::settings; use wasmparser; -use std::error::Error; -use std::vec::Vec; -use std::string::String; /// Compute a `ir::ExternalName` for a given wasm function index. fn get_func_name(func_index: FunctionIndex) -> ir::ExternalName { diff --git a/lib/wasm/src/environ/mod.rs b/lib/wasm/src/environ/mod.rs index 57c9f593b2..e89995d8f8 100644 --- a/lib/wasm/src/environ/mod.rs +++ b/lib/wasm/src/environ/mod.rs @@ -1,7 +1,7 @@ //! Support for configurable wasm translation. -mod spec; mod dummy; +mod spec; -pub use environ::spec::{FuncEnvironment, GlobalValue, ModuleEnvironment}; pub use environ::dummy::DummyEnvironment; +pub use environ::spec::{FuncEnvironment, GlobalValue, ModuleEnvironment}; diff --git a/lib/wasm/src/environ/spec.rs b/lib/wasm/src/environ/spec.rs index 882ca1a30f..8c313f0ef3 100644 --- a/lib/wasm/src/environ/spec.rs +++ b/lib/wasm/src/environ/spec.rs @@ -1,12 +1,12 @@ //! All the runtime support necessary for the wasm to cretonne translation is formalized by the //! traits `FunctionEnvironment` and `ModuleEnvironment`. -use cretonne::ir::{self, InstBuilder}; use cretonne::cursor::FuncCursor; +use cretonne::ir::{self, InstBuilder}; use cretonne::settings::Flags; +use std::string::String; +use std::vec::Vec; use translation_utils::{FunctionIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex}; -use std::vec::Vec; -use std::string::String; /// The value of a WebAssembly global variable. #[derive(Clone, Copy)] diff --git a/lib/wasm/src/func_translator.rs b/lib/wasm/src/func_translator.rs index 159d8120d1..c89fa21266 100644 --- a/lib/wasm/src/func_translator.rs +++ b/lib/wasm/src/func_translator.rs @@ -232,10 +232,10 @@ fn cur_srcloc(reader: &BinaryReader) -> ir::SourceLoc { #[cfg(test)] mod tests { - use cretonne::{ir, Context}; - use cretonne::ir::types::I32; - use environ::{DummyEnvironment, FuncEnvironment}; use super::FuncTranslator; + use cretonne::ir::types::I32; + use cretonne::{ir, Context}; + use environ::{DummyEnvironment, FuncEnvironment}; #[test] fn small1() { diff --git a/lib/wasm/src/lib.rs b/lib/wasm/src/lib.rs index 6f0ed8fd70..6ed76be8e3 100644 --- a/lib/wasm/src/lib.rs +++ b/lib/wasm/src/lib.rs @@ -19,15 +19,15 @@ extern crate cton_frontend; extern crate wasmparser; mod code_translator; +mod environ; mod func_translator; mod module_translator; -mod environ; mod sections_translator; mod state; mod translation_utils; +pub use environ::{DummyEnvironment, FuncEnvironment, GlobalValue, ModuleEnvironment}; pub use func_translator::FuncTranslator; pub use module_translator::translate_module; -pub use environ::{DummyEnvironment, FuncEnvironment, GlobalValue, ModuleEnvironment}; pub use translation_utils::{FunctionIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex, Table, TableIndex}; diff --git a/lib/wasm/src/module_translator.rs b/lib/wasm/src/module_translator.rs index e345e5ef3c..e41712a6d6 100644 --- a/lib/wasm/src/module_translator.rs +++ b/lib/wasm/src/module_translator.rs @@ -1,12 +1,12 @@ //! Translation skeleton that traverses the whole WebAssembly module and call helper functions //! to deal with each part of it. use cretonne::timing; -use wasmparser::{BinaryReaderError, Parser, ParserInput, ParserState, SectionCode, WasmDecoder}; +use environ::ModuleEnvironment; use sections_translator::{parse_data_section, parse_elements_section, parse_export_section, parse_function_section, parse_function_signatures, parse_global_section, parse_import_section, parse_memory_section, parse_start_section, parse_table_section, SectionParsingError}; -use environ::ModuleEnvironment; +use wasmparser::{BinaryReaderError, Parser, ParserInput, ParserState, SectionCode, WasmDecoder}; use std::string::String; diff --git a/lib/wasm/src/sections_translator.rs b/lib/wasm/src/sections_translator.rs index 4792c3f450..ce5ed05995 100644 --- a/lib/wasm/src/sections_translator.rs +++ b/lib/wasm/src/sections_translator.rs @@ -7,17 +7,17 @@ //! The special case of the initialize expressions for table elements offsets or global variables //! is handled, according to the semantics of WebAssembly, to only specific expressions that are //! interpreted on the fly. +use cretonne; +use cretonne::ir::{AbiParam, CallConv, Signature}; +use environ::ModuleEnvironment; +use std::str::from_utf8; +use std::string::String; +use std::vec::Vec; use translation_utils::{type_to_type, FunctionIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex, Table, TableElementType, TableIndex}; -use cretonne::ir::{AbiParam, CallConv, Signature}; -use cretonne; +use wasmparser; use wasmparser::{ExternalKind, FuncType, ImportSectionEntryType, MemoryType, Operator, Parser, ParserState, WasmDecoder}; -use wasmparser; -use std::str::from_utf8; -use environ::ModuleEnvironment; -use std::vec::Vec; -use std::string::String; pub enum SectionParsingError { WrongSectionContent(String), diff --git a/lib/wasm/src/state.rs b/lib/wasm/src/state.rs index 8d1d86fe80..f95619d52b 100644 --- a/lib/wasm/src/state.rs +++ b/lib/wasm/src/state.rs @@ -6,8 +6,8 @@ use cretonne::ir::{self, Ebb, Inst, Value}; use environ::{FuncEnvironment, GlobalValue}; use std::collections::HashMap; -use translation_utils::{FunctionIndex, GlobalIndex, MemoryIndex, SignatureIndex}; use std::vec::Vec; +use translation_utils::{FunctionIndex, GlobalIndex, MemoryIndex, SignatureIndex}; /// A control stack frame can be an `if`, a `block` or a `loop`, each one having the following /// fields: diff --git a/lib/wasm/src/translation_utils.rs b/lib/wasm/src/translation_utils.rs index 44c03fb6dd..bac50be7a6 100644 --- a/lib/wasm/src/translation_utils.rs +++ b/lib/wasm/src/translation_utils.rs @@ -1,7 +1,7 @@ //! Helper functions and structures for the translation. -use wasmparser; use cretonne; use std::u32; +use wasmparser; /// Index of a function (imported or defined) inside the WebAssembly module. pub type FunctionIndex = usize; diff --git a/lib/wasm/tests/wasm_testsuite.rs b/lib/wasm/tests/wasm_testsuite.rs index 1bd6ecf3f9..273818f470 100644 --- a/lib/wasm/tests/wasm_testsuite.rs +++ b/lib/wasm/tests/wasm_testsuite.rs @@ -2,18 +2,18 @@ extern crate cretonne; extern crate cton_wasm; extern crate tempdir; -use cton_wasm::{translate_module, DummyEnvironment}; -use std::path::PathBuf; -use std::fs::File; -use std::error::Error; -use std::io; -use std::str; -use std::io::prelude::*; -use std::process::Command; -use std::fs; +use cretonne::print_errors::pretty_verifier_error; use cretonne::settings::{self, Configurable, Flags}; use cretonne::verifier; -use cretonne::print_errors::pretty_verifier_error; +use cton_wasm::{translate_module, DummyEnvironment}; +use std::error::Error; +use std::fs; +use std::fs::File; +use std::io; +use std::io::prelude::*; +use std::path::PathBuf; +use std::process::Command; +use std::str; use tempdir::TempDir; #[test] From b523b69c1675dc918931763aea0dc9713aff468d Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 30 Mar 2018 13:38:30 -0700 Subject: [PATCH 72/72] Make bash function syntax consistent with other scripts in the repo. --- lib/cretonne/meta/check.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cretonne/meta/check.sh b/lib/cretonne/meta/check.sh index aa0e88ce1e..fa86bf0804 100755 --- a/lib/cretonne/meta/check.sh +++ b/lib/cretonne/meta/check.sh @@ -2,7 +2,7 @@ set -euo pipefail cd $(dirname "$0") -runif() { +function runif() { if command -v "$1" > /dev/null; then echo " === $1 ===" "$@"