diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index 9c4c1608ff..021440c024 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cretonne-tools" authors = ["The Cretonne Project Developers"] -version = "0.5.0" +version = "0.5.1" description = "Binaries for testing the Cretonne libraries" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" @@ -13,16 +13,16 @@ name = "cton-util" path = "src/cton-util.rs" [dependencies] -cretonne-codegen = { path = "lib/codegen", version = "0.5.0" } -cretonne-reader = { path = "lib/reader", version = "0.5.0" } -cretonne-frontend = { path = "lib/frontend", version = "0.5.0" } -cretonne-wasm = { path = "lib/wasm", version = "0.5.0" } -cretonne-native = { path = "lib/native", version = "0.5.0" } -cretonne-filetests = { path = "lib/filetests", version = "0.5.0" } -cretonne-module = { path = "lib/module", version = "0.5.0" } -cretonne-faerie = { path = "lib/faerie", version = "0.5.0" } -cretonne-simplejit = { path = "lib/simplejit", version = "0.5.0" } -cretonne = { path = "lib/umbrella", version = "0.5.0" } +cretonne-codegen = { path = "lib/codegen", version = "0.5.1" } +cretonne-reader = { path = "lib/reader", version = "0.5.1" } +cretonne-frontend = { path = "lib/frontend", version = "0.5.1" } +cretonne-wasm = { path = "lib/wasm", version = "0.5.1" } +cretonne-native = { path = "lib/native", version = "0.5.1" } +cretonne-filetests = { path = "lib/filetests", version = "0.5.1" } +cretonne-module = { path = "lib/module", version = "0.5.1" } +cretonne-faerie = { path = "lib/faerie", version = "0.5.1" } +cretonne-simplejit = { path = "lib/simplejit", version = "0.5.1" } +cretonne = { path = "lib/umbrella", version = "0.5.1" } filecheck = "0.2.1" docopt = "0.8.0" serde = "1.0.8" diff --git a/cranelift/docs/index.rst b/cranelift/docs/index.rst index c2e5b6d5ef..60b153e2a1 100644 --- a/cranelift/docs/index.rst +++ b/cranelift/docs/index.rst @@ -34,6 +34,19 @@ Rust Crate Documentation This crate translates from Cretonne IR's text format into Cretonne IR in in-memory data structures. +`cretonne-module `_ + This crate manages compiling multiple functions and data objects + together. + +`cretonne-faerie `_ + This crate provides a faerie-based backend for `cretonne-module`, which + emits native object files using the + `faerie `_ library. + +`cretonne-simplejit `_ + This crate provides a simple JIT backend for `cretonne-module`, which + emits code and data into memory. + Indices and tables ================== diff --git a/cranelift/filetests/isa/x86/binary64.cton b/cranelift/filetests/isa/x86/binary64.cton index faf4fe99ac..2a945ee17c 100644 --- a/cranelift/filetests/isa/x86/binary64.cton +++ b/cranelift/filetests/isa/x86/binary64.cton @@ -477,7 +477,7 @@ ebb0: ; Colocated functions. ; asm: call bar - ; call fn1() ; bin: e8 PCRel4(%bar-4) 00000000 + call fn1() ; bin: e8 PCRel4(%bar-4) 00000000 ; asm: lea 0x0(%rip), %rcx [-,%rcx] v400 = func_addr.i64 fn1 ; bin: 48 8d 0d PCRel4(%bar-4) 00000000 diff --git a/cranelift/filetests/isa/x86/legalize-call.cton b/cranelift/filetests/isa/x86/legalize-call.cton new file mode 100644 index 0000000000..adcb6a6ad1 --- /dev/null +++ b/cranelift/filetests/isa/x86/legalize-call.cton @@ -0,0 +1,15 @@ +; Test legalization of a non-colocated call in 64-bit non-PIC mode. +test legalizer +set is_64bit +set is_compressed +isa x86 haswell + +function %call() { + fn0 = %foo() +ebb0: + call fn0() + return +} + +; check: v0 = func_addr.i64 fn0 +; nextln: call_indirect sig0, v0() diff --git a/cranelift/publish-all.sh b/cranelift/publish-all.sh index ba539f2f26..06aaab658a 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.5.0" +version="0.5.1" # Update all of the Cargo.toml files. # diff --git a/cranelift/src/compile.rs b/cranelift/src/compile.rs index ae8cd1e30c..4b9f77494d 100644 --- a/cranelift/src/compile.rs +++ b/cranelift/src/compile.rs @@ -96,19 +96,18 @@ fn handle_module( for (func, _) in test_file.functions { let mut context = Context::new(); context.func = func; - let size = context.compile(isa).map_err(|err| { - pretty_error(&context.func, Some(isa), err) - })?; - if flag_print { - println!("{}", context.func.display(isa)); - } - // Encode the result as machine code. + // Compile and encode the result to 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, &mut traps, &*isa); + context + .compile_and_emit(isa, &mut mem, &mut relocs, &mut traps) + .map_err(|err| pretty_error(&context.func, Some(isa), err))?; + + if flag_print { + println!("{}", context.func.display(isa)); + } if flag_print { print!(".byte "); diff --git a/cranelift/src/cton-util.rs b/cranelift/src/cton-util.rs index 20743d923b..d69c561c44 100644 --- a/cranelift/src/cton-util.rs +++ b/cranelift/src/cton-util.rs @@ -1,3 +1,15 @@ +#![deny(trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces, unstable_features)] +#![cfg_attr(feature="cargo-clippy", warn( + float_arithmetic, + mut_mut, + nonminimal_bool, + option_map_unwrap_or, + option_map_unwrap_or_else, + unicode_not_nfc, + use_self, + ))] + extern crate cretonne_codegen; extern crate cretonne_filetests; extern crate cretonne_reader; diff --git a/lib/codegen/Cargo.toml b/lib/codegen/Cargo.toml index d362e0ee4e..2a7854f6c1 100644 --- a/lib/codegen/Cargo.toml +++ b/lib/codegen/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cretonne Project Developers"] name = "cretonne-codegen" -version = "0.5.0" +version = "0.5.1" description = "Low-level code generator library" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" @@ -11,7 +11,7 @@ keywords = ["compile", "compiler", "jit"] build = "build.rs" [dependencies] -cretonne-entity = { path = "../entity", version = "0.5.0", default-features = false } +cretonne-entity = { path = "../entity", version = "0.5.1", default-features = false } # It is a goal of the cretonne-codegen crate to have minimal external dependencies. # 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 diff --git a/lib/codegen/meta/cdsl/isa.py b/lib/codegen/meta/cdsl/isa.py index 77b071636a..bcff050b1b 100644 --- a/lib/codegen/meta/cdsl/isa.py +++ b/lib/codegen/meta/cdsl/isa.py @@ -54,7 +54,7 @@ class TargetISA(object): self._predicates = dict() # type: Dict[PredKey, PredNode] assert InstructionGroup._current is None,\ - "InstructionGroup {} is still open!"\ + "InstructionGroup {} is still open"\ .format(InstructionGroup._current.name) def __str__(self): diff --git a/lib/codegen/meta/cdsl/typevar.py b/lib/codegen/meta/cdsl/typevar.py index 8cda58785e..d58381529f 100644 --- a/lib/codegen/meta/cdsl/typevar.py +++ b/lib/codegen/meta/cdsl/typevar.py @@ -231,7 +231,7 @@ class TypeSet(object): def __hash__(self): # type: () -> int h = hash(self.typeset_key()) - assert h == getattr(self, 'prev_hash', h), "TypeSet changed!" + assert h == getattr(self, 'prev_hash', h), "TypeSet changed" self.prev_hash = h return h diff --git a/lib/codegen/meta/gen_instr.py b/lib/codegen/meta/gen_instr.py index 4e0bc6cb78..0b25cc1835 100644 --- a/lib/codegen/meta/gen_instr.py +++ b/lib/codegen/meta/gen_instr.py @@ -47,7 +47,7 @@ def gen_formats(fmt): with fmt.indented( "impl<'a> From<&'a InstructionData> for InstructionFormat {", '}'): with fmt.indented( - "fn from(inst: &'a InstructionData) -> InstructionFormat {", + "fn from(inst: &'a InstructionData) -> Self {", '}'): m = srcgen.Match('*inst') for f in InstructionFormat.all_formats: diff --git a/lib/codegen/meta/gen_settings.py b/lib/codegen/meta/gen_settings.py index 373c9cb1a9..f111c6c415 100644 --- a/lib/codegen/meta/gen_settings.py +++ b/lib/codegen/meta/gen_settings.py @@ -29,7 +29,7 @@ def gen_enum_types(sgrp, fmt): continue ty = camel_case(setting.name) fmt.doc_comment('Values for `{}`.'.format(setting)) - fmt.line('#[derive(Debug, PartialEq, Eq)]') + fmt.line('#[derive(Debug, Copy, Clone, PartialEq, Eq)]') with fmt.indented('pub enum {} {{'.format(ty), '}'): for v in setting.values: fmt.doc_comment('`{}`.'.format(v)) @@ -223,7 +223,7 @@ def gen_display(sgrp, fmt): fmt.line( 'TEMPLATE.format_toml_value(d.detail,' + 'self.bytes[d.offset as usize], f)?;') - fmt.line('writeln!(f, "")?;') + fmt.line('writeln!(f)?;') fmt.line('Ok(())') @@ -241,7 +241,7 @@ def gen_constructor(sgrp, parent, fmt): fmt.doc_comment('Create flags {} settings group.'.format(sgrp.name)) fmt.line('#[allow(unused_variables)]') with fmt.indented( - 'pub fn new({}) -> Flags {{'.format(args), '}'): + 'pub fn new({}) -> Self {{'.format(args), '}'): fmt.line('let bvec = builder.state_for("{}");'.format(sgrp.name)) fmt.line('let mut bytes = [0; {}];'.format(sgrp.byte_size())) fmt.line( @@ -252,12 +252,12 @@ def gen_constructor(sgrp, parent, fmt): # Stop here without predicates. if len(sgrp.predicate_number) == sgrp.boolean_settings: - fmt.line('Flags { bytes: bytes }') + fmt.line('Self { bytes }') return # Now compute the predicates. fmt.line( - 'let mut {} = Flags {{ bytes: bytes }};' + 'let mut {} = Self {{ bytes }};' .format(sgrp.name)) for pred, number in sgrp.predicate_number.items(): diff --git a/lib/codegen/meta/isa/x86/recipes.py b/lib/codegen/meta/isa/x86/recipes.py index ea0da832b7..0f9a79d6a7 100644 --- a/lib/codegen/meta/isa/x86/recipes.py +++ b/lib/codegen/meta/isa/x86/recipes.py @@ -530,7 +530,7 @@ puid_bool = TailRecipe( // 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 }; + let imm: u32 = if imm { 1 } else { 0 }; sink.put4(imm); ''') diff --git a/lib/codegen/src/abi.rs b/lib/codegen/src/abi.rs index 88a8a424a6..5f1452159b 100644 --- a/lib/codegen/src/abi.rs +++ b/lib/codegen/src/abi.rs @@ -25,13 +25,13 @@ pub enum ArgAction { } impl From for ArgAction { - fn from(x: ArgumentLoc) -> ArgAction { + fn from(x: ArgumentLoc) -> Self { ArgAction::Assign(x) } } impl From for ArgAction { - fn from(x: ValueConversion) -> ArgAction { + fn from(x: ValueConversion) -> Self { ArgAction::Convert(x) } } diff --git a/lib/codegen/src/bforest/map.rs b/lib/codegen/src/bforest/map.rs index b8b4980b3f..b6a62ef419 100644 --- a/lib/codegen/src/bforest/map.rs +++ b/lib/codegen/src/bforest/map.rs @@ -45,8 +45,8 @@ where C: Comparator, { /// Create a new empty forest. - pub fn new() -> MapForest { - MapForest { nodes: NodePool::new() } + pub fn new() -> Self { + Self { nodes: NodePool::new() } } /// Clear all maps in the forest. @@ -83,8 +83,8 @@ where C: Comparator, { /// Make an empty map. - pub fn new() -> Map { - Map { + pub fn new() -> Self { + Self { root: None.into(), unused: PhantomData, } diff --git a/lib/codegen/src/bforest/node.rs b/lib/codegen/src/bforest/node.rs index f4a85613b5..d47a16283b 100644 --- a/lib/codegen/src/bforest/node.rs +++ b/lib/codegen/src/bforest/node.rs @@ -73,7 +73,7 @@ impl NodeData { } /// Create an inner node with a single key and two sub-trees. - pub fn inner(left: Node, key: F::Key, right: Node) -> NodeData { + pub fn inner(left: Node, key: F::Key, right: Node) -> Self { // Splat the key and right node to the whole array. // Saves us from inventing a default/reserved value. let mut tree = [right; INNER_SIZE]; @@ -86,7 +86,7 @@ impl NodeData { } /// Create a leaf node with a single key-value pair. - pub fn leaf(key: F::Key, value: F::Value) -> NodeData { + pub fn leaf(key: F::Key, value: F::Value) -> Self { NodeData::Leaf { size: 1, keys: F::splat_key(key), @@ -360,7 +360,7 @@ impl NodeData { /// /// In the first case, `None` is returned. In the second case, the new critical key for the /// right sibling node is returned. - pub fn balance(&mut self, crit_key: F::Key, rhs: &mut NodeData) -> Option { + pub fn balance(&mut self, crit_key: F::Key, rhs: &mut Self) -> Option { match (self, rhs) { (&mut NodeData::Inner { size: ref mut l_size, @@ -514,7 +514,7 @@ pub(super) enum Removed { impl Removed { /// Create a `Removed` status from a size and capacity. - fn new(removed: usize, new_size: usize, capacity: usize) -> Removed { + fn new(removed: usize, new_size: usize, capacity: usize) -> Self { if 2 * new_size >= capacity { if removed == new_size { Removed::Rightmost diff --git a/lib/codegen/src/bforest/path.rs b/lib/codegen/src/bforest/path.rs index d011455571..3ed91ee09a 100644 --- a/lib/codegen/src/bforest/path.rs +++ b/lib/codegen/src/bforest/path.rs @@ -22,8 +22,8 @@ pub(super) struct Path { } impl Default for Path { - fn default() -> Path { - Path { + fn default() -> Self { + Self { size: 0, node: [Node(0); MAX_PATH], entry: [0; MAX_PATH], diff --git a/lib/codegen/src/bforest/pool.rs b/lib/codegen/src/bforest/pool.rs index 0e312f9380..eed9402c84 100644 --- a/lib/codegen/src/bforest/pool.rs +++ b/lib/codegen/src/bforest/pool.rs @@ -12,8 +12,8 @@ pub(super) struct NodePool { impl NodePool { /// Allocate a new empty pool of nodes. - pub fn new() -> NodePool { - NodePool { + pub fn new() -> Self { + Self { nodes: PrimaryMap::new(), freelist: None, } diff --git a/lib/codegen/src/bforest/set.rs b/lib/codegen/src/bforest/set.rs index e1434df39c..3c479dd876 100644 --- a/lib/codegen/src/bforest/set.rs +++ b/lib/codegen/src/bforest/set.rs @@ -42,8 +42,8 @@ where C: Comparator, { /// Create a new empty forest. - pub fn new() -> SetForest { - SetForest { nodes: NodePool::new() } + pub fn new() -> Self { + Self { nodes: NodePool::new() } } /// Clear all sets in the forest. @@ -78,8 +78,8 @@ where C: Comparator, { /// Make an empty set. - pub fn new() -> Set { - Set { + pub fn new() -> Self { + Self { root: None.into(), unused: PhantomData, } diff --git a/lib/codegen/src/binemit/memorysink.rs b/lib/codegen/src/binemit/memorysink.rs index 34380d2464..6871dc0942 100644 --- a/lib/codegen/src/binemit/memorysink.rs +++ b/lib/codegen/src/binemit/memorysink.rs @@ -38,7 +38,10 @@ pub struct MemoryCodeSink<'a> { impl<'a> MemoryCodeSink<'a> { /// Create a new memory code sink that writes a function to the memory pointed to by `data`. - pub fn new<'sink>( + /// + /// This function is unsafe since `MemoryCodeSink` does not perform bounds checking on the + /// memory buffer, and it can't guarantee that the `data` pointer is valid. + pub unsafe fn new<'sink>( data: *mut u8, relocs: &'sink mut RelocSink, traps: &'sink mut TrapSink, @@ -84,6 +87,7 @@ impl<'a> CodeSink for MemoryCodeSink<'a> { fn put2(&mut self, x: u16) { unsafe { + #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))] write_unaligned(self.data.offset(self.offset) as *mut u16, x); } self.offset += 2; @@ -91,6 +95,7 @@ impl<'a> CodeSink for MemoryCodeSink<'a> { fn put4(&mut self, x: u32) { unsafe { + #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))] write_unaligned(self.data.offset(self.offset) as *mut u32, x); } self.offset += 4; @@ -98,6 +103,7 @@ impl<'a> CodeSink for MemoryCodeSink<'a> { fn put8(&mut self, x: u64) { unsafe { + #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))] write_unaligned(self.data.offset(self.offset) as *mut u64, x); } self.offset += 8; diff --git a/lib/codegen/src/binemit/mod.rs b/lib/codegen/src/binemit/mod.rs index fbe88cc61f..9752901ce9 100644 --- a/lib/codegen/src/binemit/mod.rs +++ b/lib/codegen/src/binemit/mod.rs @@ -48,12 +48,12 @@ impl fmt::Display for Reloc { /// already unambigious, e.g. cton syntax with isa specified. In other contexts, use Debug. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Reloc::Abs4 => write!(f, "{}", "Abs4"), - Reloc::Abs8 => write!(f, "{}", "Abs8"), - Reloc::X86PCRel4 => write!(f, "{}", "PCRel4"), - Reloc::X86GOTPCRel4 => write!(f, "{}", "GOTPCRel4"), - Reloc::X86PLTRel4 => write!(f, "{}", "PLTRel4"), - Reloc::Arm32Call | Reloc::Arm64Call | Reloc::RiscvCall => write!(f, "{}", "Call"), + Reloc::Abs4 => write!(f, "Abs4"), + Reloc::Abs8 => write!(f, "Abs8"), + Reloc::X86PCRel4 => write!(f, "PCRel4"), + Reloc::X86GOTPCRel4 => write!(f, "GOTPCRel4"), + Reloc::X86PLTRel4 => write!(f, "PLTRel4"), + Reloc::Arm32Call | Reloc::Arm64Call | Reloc::RiscvCall => write!(f, "Call"), } } } diff --git a/lib/codegen/src/context.rs b/lib/codegen/src/context.rs index ad31e9025b..95e78ff128 100644 --- a/lib/codegen/src/context.rs +++ b/lib/codegen/src/context.rs @@ -52,7 +52,7 @@ impl Context { /// The returned instance should be reused for compiling multiple functions in order to avoid /// needless allocator thrashing. pub fn new() -> Self { - Context::for_function(Function::new()) + Self::for_function(Function::new()) } /// Allocate a new compilation context with an existing Function. @@ -61,7 +61,7 @@ impl Context { /// needless allocator thrashing. pub fn for_function(func: Function) -> Self { Self { - func: func, + func, cfg: ControlFlowGraph::new(), domtree: DominatorTree::new(), regalloc: regalloc::Context::new(), @@ -78,6 +78,36 @@ impl Context { self.loop_analysis.clear(); } + /// Compile the function, and emit machine code into a `Vec`. + /// + /// Run the function through all the passes necessary to generate code for the target ISA + /// represented by `isa`, as well as the final step of emitting machine code into a + /// `Vec`. The machine code is not relocated. Instead, any relocations are emitted + /// into `relocs`. + /// + /// This function calls `compile` and `emit_to_memory`, taking care to resize `mem` as + /// needed, so it provides a safe interface. + pub fn compile_and_emit( + &mut self, + isa: &TargetIsa, + mem: &mut Vec, + relocs: &mut RelocSink, + traps: &mut TrapSink, + ) -> CtonResult { + let code_size = self.compile(isa)?; + let old_len = mem.len(); + mem.resize(old_len + code_size as usize, 0); + unsafe { + self.emit_to_memory( + isa, + mem.as_mut_ptr().offset(old_len as isize), + relocs, + traps, + ) + }; + Ok(()) + } + /// Compile the function. /// /// Run the function through all the passes necessary to generate code for the target ISA @@ -119,12 +149,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( + /// + /// This function is unsafe since it does not perform bounds checking on the memory buffer, + /// and it can't guarantee that the `mem` pointer is valid. + pub unsafe fn emit_to_memory( &self, + isa: &TargetIsa, 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, traps)); diff --git a/lib/codegen/src/dominator_tree.rs b/lib/codegen/src/dominator_tree.rs index 60ef1e6e42..b717d524e3 100644 --- a/lib/codegen/src/dominator_tree.rs +++ b/lib/codegen/src/dominator_tree.rs @@ -528,8 +528,8 @@ struct ExtraNode { /// Creating and computing the dominator tree pre-order. impl DominatorTreePreorder { /// Create a new blank `DominatorTreePreorder`. - pub fn new() -> DominatorTreePreorder { - DominatorTreePreorder { + pub fn new() -> Self { + Self { nodes: EntityMap::new(), stack: Vec::new(), } diff --git a/lib/codegen/src/ir/entities.rs b/lib/codegen/src/ir/entities.rs index d0c627952b..30c7cd3fb4 100644 --- a/lib/codegen/src/ir/entities.rs +++ b/lib/codegen/src/ir/entities.rs @@ -31,7 +31,7 @@ impl Ebb { /// Create a new EBB reference from its number. This corresponds to the `ebbNN` representation. /// /// This method is for use by the parser. - pub fn with_number(n: u32) -> Option { + pub fn with_number(n: u32) -> Option { if n < u32::MAX { Some(Ebb(n)) } else { None } } } @@ -46,7 +46,7 @@ impl Value { /// This is the number in the `vNN` notation. /// /// This method is for use by the parser. - pub fn with_number(n: u32) -> Option { + pub fn with_number(n: u32) -> Option { if n < u32::MAX / 2 { Some(Value(n)) } else { @@ -69,7 +69,7 @@ impl StackSlot { /// Create a new stack slot reference from its number. /// /// This method is for use by the parser. - pub fn with_number(n: u32) -> Option { + pub fn with_number(n: u32) -> Option { if n < u32::MAX { Some(StackSlot(n)) } else { @@ -87,7 +87,7 @@ impl GlobalVar { /// Create a new global variable reference from its number. /// /// This method is for use by the parser. - pub fn with_number(n: u32) -> Option { + pub fn with_number(n: u32) -> Option { if n < u32::MAX { Some(GlobalVar(n)) } else { @@ -105,7 +105,7 @@ impl JumpTable { /// Create a new jump table reference from its number. /// /// This method is for use by the parser. - pub fn with_number(n: u32) -> Option { + pub fn with_number(n: u32) -> Option { if n < u32::MAX { Some(JumpTable(n)) } else { @@ -123,7 +123,7 @@ impl FuncRef { /// Create a new external function reference from its number. /// /// This method is for use by the parser. - pub fn with_number(n: u32) -> Option { + pub fn with_number(n: u32) -> Option { if n < u32::MAX { Some(FuncRef(n)) } else { None } } } @@ -137,7 +137,7 @@ impl SigRef { /// Create a new function signature reference from its number. /// /// This method is for use by the parser. - pub fn with_number(n: u32) -> Option { + pub fn with_number(n: u32) -> Option { if n < u32::MAX { Some(SigRef(n)) } else { None } } } @@ -151,7 +151,7 @@ impl Heap { /// Create a new heap reference from its number. /// /// This method is for use by the parser. - pub fn with_number(n: u32) -> Option { + pub fn with_number(n: u32) -> Option { if n < u32::MAX { Some(Heap(n)) } else { None } } } @@ -205,55 +205,55 @@ impl fmt::Debug for AnyEntity { } impl From for AnyEntity { - fn from(r: Ebb) -> AnyEntity { + fn from(r: Ebb) -> Self { AnyEntity::Ebb(r) } } impl From for AnyEntity { - fn from(r: Inst) -> AnyEntity { + fn from(r: Inst) -> Self { AnyEntity::Inst(r) } } impl From for AnyEntity { - fn from(r: Value) -> AnyEntity { + fn from(r: Value) -> Self { AnyEntity::Value(r) } } impl From for AnyEntity { - fn from(r: StackSlot) -> AnyEntity { + fn from(r: StackSlot) -> Self { AnyEntity::StackSlot(r) } } impl From for AnyEntity { - fn from(r: GlobalVar) -> AnyEntity { + fn from(r: GlobalVar) -> Self { AnyEntity::GlobalVar(r) } } impl From for AnyEntity { - fn from(r: JumpTable) -> AnyEntity { + fn from(r: JumpTable) -> Self { AnyEntity::JumpTable(r) } } impl From for AnyEntity { - fn from(r: FuncRef) -> AnyEntity { + fn from(r: FuncRef) -> Self { AnyEntity::FuncRef(r) } } impl From for AnyEntity { - fn from(r: SigRef) -> AnyEntity { + fn from(r: SigRef) -> Self { AnyEntity::SigRef(r) } } impl From for AnyEntity { - fn from(r: Heap) -> AnyEntity { + fn from(r: Heap) -> Self { AnyEntity::Heap(r) } } diff --git a/lib/codegen/src/ir/extfunc.rs b/lib/codegen/src/ir/extfunc.rs index afb32fee81..01008946e6 100644 --- a/lib/codegen/src/ir/extfunc.rs +++ b/lib/codegen/src/ir/extfunc.rs @@ -304,7 +304,7 @@ impl fmt::Display for ArgumentPurpose { impl FromStr for ArgumentPurpose { type Err = (); - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> Result { match s { "normal" => Ok(ArgumentPurpose::Normal), "sret" => Ok(ArgumentPurpose::StructReturn), diff --git a/lib/codegen/src/ir/extname.rs b/lib/codegen/src/ir/extname.rs index f3a69f7e7a..dcb3666703 100644 --- a/lib/codegen/src/ir/extname.rs +++ b/lib/codegen/src/ir/extname.rs @@ -56,7 +56,7 @@ impl ExternalName { /// let name = ExternalName::testcase("hello"); /// assert_eq!(name.to_string(), "%hello"); /// ``` - pub fn testcase>(v: T) -> ExternalName { + pub fn testcase>(v: T) -> Self { let vec = v.as_ref(); let len = cmp::min(vec.len(), TESTCASE_NAME_LENGTH); let mut bytes = [0u8; TESTCASE_NAME_LENGTH]; @@ -77,17 +77,14 @@ impl ExternalName { /// let name = ExternalName::user(123, 456); /// assert_eq!(name.to_string(), "u123:456"); /// ``` - pub fn user(namespace: u32, index: u32) -> ExternalName { - ExternalName::User { - namespace: namespace, - index: index, - } + pub fn user(namespace: u32, index: u32) -> Self { + ExternalName::User { namespace, index } } } impl Default for ExternalName { - fn default() -> ExternalName { - ExternalName::user(0, 0) + fn default() -> Self { + Self::user(0, 0) } } diff --git a/lib/codegen/src/ir/immediates.rs b/lib/codegen/src/ir/immediates.rs index d56e963bb1..32b64dabf8 100644 --- a/lib/codegen/src/ir/immediates.rs +++ b/lib/codegen/src/ir/immediates.rs @@ -18,12 +18,12 @@ pub struct Imm64(i64); impl Imm64 { /// Create a new `Imm64` representing the signed number `x`. - pub fn new(x: i64) -> Imm64 { + pub fn new(x: i64) -> Self { Imm64(x) } /// Return self negated. - pub fn wrapping_neg(self) -> Imm64 { + pub fn wrapping_neg(self) -> Self { Imm64(self.0.wrapping_neg()) } } @@ -143,8 +143,8 @@ impl FromStr for Imm64 { type Err = &'static str; // Parse a decimal or hexadecimal `Imm64`, formatted as above. - fn from_str(s: &str) -> Result { - parse_i64(s).map(Imm64::new) + fn from_str(s: &str) -> Result { + parse_i64(s).map(Self::new) } } @@ -191,7 +191,7 @@ impl FromStr for Uimm32 { type Err = &'static str; // Parse a decimal or hexadecimal `Uimm32`, formatted as above. - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> Result { parse_i64(s).and_then(|x| if 0 <= x && x <= i64::from(u32::MAX) { Ok(Uimm32(x as u32)) } else { @@ -209,7 +209,7 @@ pub struct Offset32(i32); impl Offset32 { /// Create a new `Offset32` representing the signed number `x`. - pub fn new(x: i32) -> Offset32 { + pub fn new(x: i32) -> Self { Offset32(x) } } @@ -255,14 +255,14 @@ impl FromStr for Offset32 { type Err = &'static str; // Parse a decimal or hexadecimal `Offset32`, formatted as above. - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> Result { if !(s.starts_with('-') || s.starts_with('+')) { return Err("Offset must begin with sign"); } parse_i64(s).and_then(|x| if i64::from(i32::MIN) <= x && x <= i64::from(i32::MAX) { - Ok(Offset32::new(x as i32)) + Ok(Self::new(x as i32)) } else { Err("Offset out of range") }) @@ -524,12 +524,12 @@ fn parse_float(s: &str, w: u8, t: u8) -> Result { impl Ieee32 { /// Create a new `Ieee32` containing the bits of `x`. - pub fn with_bits(x: u32) -> Ieee32 { + pub fn with_bits(x: u32) -> Self { Ieee32(x) } /// Create an `Ieee32` number representing `2.0^n`. - pub fn pow2>(n: I) -> Ieee32 { + pub fn pow2>(n: I) -> Self { let n = n.into(); let w = 8; let t = 23; @@ -542,7 +542,7 @@ impl Ieee32 { /// Create an `Ieee32` number representing the greatest negative value /// not convertable from f32 to a signed integer with width n. - pub fn fcvt_to_sint_negative_overflow>(n: I) -> Ieee32 { + pub fn fcvt_to_sint_negative_overflow>(n: I) -> Self { let n = n.into(); debug_assert!(n < 32); debug_assert!(23 + 1 - n < 32); @@ -552,12 +552,12 @@ impl Ieee32 { } /// Return self negated. - pub fn neg(self) -> Ieee32 { + pub fn neg(self) -> Self { Ieee32(self.0 ^ (1 << 31)) } /// Create a new `Ieee32` representing the number `x`. - pub fn with_float(x: f32) -> Ieee32 { + pub fn with_float(x: f32) -> Self { Ieee32(unsafe { mem::transmute(x) }) } @@ -577,7 +577,7 @@ impl Display for Ieee32 { impl FromStr for Ieee32 { type Err = &'static str; - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> Result { match parse_float(s, 8, 23) { Ok(b) => Ok(Ieee32(b as u32)), Err(s) => Err(s), @@ -587,12 +587,12 @@ impl FromStr for Ieee32 { impl Ieee64 { /// Create a new `Ieee64` containing the bits of `x`. - pub fn with_bits(x: u64) -> Ieee64 { + pub fn with_bits(x: u64) -> Self { Ieee64(x) } /// Create an `Ieee64` number representing `2.0^n`. - pub fn pow2>(n: I) -> Ieee64 { + pub fn pow2>(n: I) -> Self { let n = n.into(); let w = 11; let t = 52; @@ -605,7 +605,7 @@ impl Ieee64 { /// Create an `Ieee64` number representing the greatest negative value /// not convertable from f64 to a signed integer with width n. - pub fn fcvt_to_sint_negative_overflow>(n: I) -> Ieee64 { + pub fn fcvt_to_sint_negative_overflow>(n: I) -> Self { let n = n.into(); debug_assert!(n < 64); debug_assert!(52 + 1 - n < 64); @@ -615,12 +615,12 @@ impl Ieee64 { } /// Return self negated. - pub fn neg(self) -> Ieee64 { + pub fn neg(self) -> Self { Ieee64(self.0 ^ (1 << 63)) } /// Create a new `Ieee64` representing the number `x`. - pub fn with_float(x: f64) -> Ieee64 { + pub fn with_float(x: f64) -> Self { Ieee64(unsafe { mem::transmute(x) }) } @@ -640,7 +640,7 @@ impl Display for Ieee64 { impl FromStr for Ieee64 { type Err = &'static str; - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> Result { match parse_float(s, 11, 52) { Ok(b) => Ok(Ieee64(b)), Err(s) => Err(s), diff --git a/lib/codegen/src/ir/instructions.rs b/lib/codegen/src/ir/instructions.rs index d4ca4a1396..e1db66099b 100644 --- a/lib/codegen/src/ir/instructions.rs +++ b/lib/codegen/src/ir/instructions.rs @@ -72,7 +72,7 @@ impl FromStr for Opcode { type Err = &'static str; /// Parse an Opcode name from a string. - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> Result { use constant_hash::{probe, simple_hash, Table}; impl<'a> Table<&'a str> for [Option] { @@ -85,7 +85,7 @@ impl FromStr for Opcode { } } - match probe::<&str, [Option]>(&OPCODE_HASH_TABLE, s, simple_hash(s)) { + match probe::<&str, [Option]>(&OPCODE_HASH_TABLE, s, simple_hash(s)) { Err(_) => Err("Unknown opcode"), // We unwrap here because probe() should have ensured that the entry // at this index is not None. diff --git a/lib/codegen/src/ir/libcall.rs b/lib/codegen/src/ir/libcall.rs index 6434197247..12216522ae 100644 --- a/lib/codegen/src/ir/libcall.rs +++ b/lib/codegen/src/ir/libcall.rs @@ -72,7 +72,7 @@ impl LibCall { /// given opcode and controlling type variable. /// /// Returns `None` if no well-known library routine name exists for that instruction. - pub fn for_inst(opcode: Opcode, ctrl_type: Type) -> Option { + pub fn for_inst(opcode: Opcode, ctrl_type: Type) -> Option { Some(match ctrl_type { types::F32 => { match opcode { diff --git a/lib/codegen/src/ir/progpoint.rs b/lib/codegen/src/ir/progpoint.rs index 4a0785aef4..86c0e591e4 100644 --- a/lib/codegen/src/ir/progpoint.rs +++ b/lib/codegen/src/ir/progpoint.rs @@ -17,7 +17,7 @@ use std::u32; pub struct ProgramPoint(u32); impl From for ProgramPoint { - fn from(inst: Inst) -> ProgramPoint { + fn from(inst: Inst) -> Self { let idx = inst.index(); debug_assert!(idx < (u32::MAX / 2) as usize); ProgramPoint((idx * 2) as u32) @@ -25,7 +25,7 @@ impl From for ProgramPoint { } impl From for ProgramPoint { - fn from(ebb: Ebb) -> ProgramPoint { + fn from(ebb: Ebb) -> Self { let idx = ebb.index(); debug_assert!(idx < (u32::MAX / 2) as usize); ProgramPoint((idx * 2 + 1) as u32) @@ -33,7 +33,7 @@ impl From for ProgramPoint { } impl From for ProgramPoint { - fn from(def: ValueDef) -> ProgramPoint { + fn from(def: ValueDef) -> Self { match def { ValueDef::Result(inst, _) => inst.into(), ValueDef::Param(ebb, _) => ebb.into(), @@ -62,19 +62,19 @@ impl ExpandedProgramPoint { } impl From for ExpandedProgramPoint { - fn from(inst: Inst) -> ExpandedProgramPoint { + fn from(inst: Inst) -> Self { ExpandedProgramPoint::Inst(inst) } } impl From for ExpandedProgramPoint { - fn from(ebb: Ebb) -> ExpandedProgramPoint { + fn from(ebb: Ebb) -> Self { ExpandedProgramPoint::Ebb(ebb) } } impl From for ExpandedProgramPoint { - fn from(def: ValueDef) -> ExpandedProgramPoint { + fn from(def: ValueDef) -> Self { match def { ValueDef::Result(inst, _) => inst.into(), ValueDef::Param(ebb, _) => ebb.into(), @@ -83,7 +83,7 @@ impl From for ExpandedProgramPoint { } impl From for ExpandedProgramPoint { - fn from(pp: ProgramPoint) -> ExpandedProgramPoint { + fn from(pp: ProgramPoint) -> Self { if pp.0 & 1 == 0 { ExpandedProgramPoint::Inst(Inst::new((pp.0 / 2) as usize)) } else { diff --git a/lib/codegen/src/ir/sourceloc.rs b/lib/codegen/src/ir/sourceloc.rs index 768bbf99d5..6de2206c8a 100644 --- a/lib/codegen/src/ir/sourceloc.rs +++ b/lib/codegen/src/ir/sourceloc.rs @@ -17,7 +17,7 @@ pub struct SourceLoc(u32); impl SourceLoc { /// Create a new source location with the given bits. - pub fn new(bits: u32) -> SourceLoc { + pub fn new(bits: u32) -> Self { SourceLoc(bits) } diff --git a/lib/codegen/src/ir/stackslot.rs b/lib/codegen/src/ir/stackslot.rs index bdf2c95825..aecf8abc8f 100644 --- a/lib/codegen/src/ir/stackslot.rs +++ b/lib/codegen/src/ir/stackslot.rs @@ -70,7 +70,7 @@ pub enum StackSlotKind { impl FromStr for StackSlotKind { type Err = (); - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> Result { use self::StackSlotKind::*; match s { "explicit_slot" => Ok(ExplicitSlot), @@ -117,8 +117,8 @@ pub struct StackSlotData { impl StackSlotData { /// Create a stack slot with the specified byte size. - pub fn new(kind: StackSlotKind, size: StackSize) -> StackSlotData { - StackSlotData { + pub fn new(kind: StackSlotKind, size: StackSize) -> Self { + Self { kind, size, offset: None, diff --git a/lib/codegen/src/ir/types.rs b/lib/codegen/src/ir/types.rs index 3dc71454de..c4dd5ad724 100644 --- a/lib/codegen/src/ir/types.rs +++ b/lib/codegen/src/ir/types.rs @@ -39,7 +39,7 @@ impl Type { /// Get the lane type of this SIMD vector type. /// /// A lane type is the same as a SIMD vector type with one lane, so it returns itself. - pub fn lane_type(self) -> Type { + pub fn lane_type(self) -> Self { if self.0 < VECTOR_BASE { self } else { @@ -72,7 +72,7 @@ impl Type { } /// Get an integer type with the requested number of bits. - pub fn int(bits: u16) -> Option { + pub fn int(bits: u16) -> Option { match bits { 8 => Some(I8), 16 => Some(I16), @@ -83,7 +83,7 @@ impl Type { } /// Get a type with the same number of lanes as `self`, but using `lane` as the lane type. - fn replace_lanes(self, lane: Type) -> Type { + fn replace_lanes(self, lane: Self) -> Self { debug_assert!(lane.is_lane() && !self.is_special()); Type((lane.0 & 0x0f) | (self.0 & 0xf0)) } @@ -93,7 +93,7 @@ impl Type { /// /// Scalar types are treated as vectors with one lane, so they are converted to the multi-bit /// boolean types. - pub fn as_bool_pedantic(self) -> Type { + pub fn as_bool_pedantic(self) -> Self { // Replace the low 4 bits with the boolean version, preserve the high 4 bits. self.replace_lanes(match self.lane_type() { B8 | I8 => B8, @@ -108,7 +108,7 @@ impl Type { /// booleans of the same size. /// /// Scalar types are all converted to `b1` which is usually what you want. - pub fn as_bool(self) -> Type { + pub fn as_bool(self) -> Self { if !self.is_vector() { B1 } else { @@ -118,7 +118,7 @@ impl Type { /// Get a type with the same number of lanes as this type, but with lanes that are half the /// number of bits. - pub fn half_width(self) -> Option { + pub fn half_width(self) -> Option { Some(self.replace_lanes(match self.lane_type() { I16 => I8, I32 => I16, @@ -133,7 +133,7 @@ impl Type { /// Get a type with the same number of lanes as this type, but with lanes that are twice the /// number of bits. - pub fn double_width(self) -> Option { + pub fn double_width(self) -> Option { Some(self.replace_lanes(match self.lane_type() { I8 => I16, I16 => I32, @@ -235,7 +235,7 @@ impl Type { /// /// If this is already a SIMD vector type, this produces a SIMD vector type with `n * /// self.lane_count()` lanes. - pub fn by(self, n: u16) -> Option { + pub fn by(self, n: u16) -> Option { if self.lane_bits() == 0 || !n.is_power_of_two() { return None; } @@ -251,7 +251,7 @@ impl Type { /// Get a SIMD vector with half the number of lanes. /// /// There is no `double_vector()` method. Use `t.by(2)` instead. - pub fn half_vector(self) -> Option { + pub fn half_vector(self) -> Option { if self.is_vector() { Some(Type(self.0 - 0x10)) } else { @@ -268,7 +268,7 @@ impl Type { /// /// 1. `self.lane_count() == other.lane_count()` and /// 2. `self.lane_bits() >= other.lane_bits()` - pub fn wider_or_equal(self, other: Type) -> bool { + pub fn wider_or_equal(self, other: Self) -> bool { self.lane_count() == other.lane_count() && self.lane_bits() >= other.lane_bits() } } diff --git a/lib/codegen/src/isa/encoding.rs b/lib/codegen/src/isa/encoding.rs index 1b850d5c64..c13c4de40d 100644 --- a/lib/codegen/src/isa/encoding.rs +++ b/lib/codegen/src/isa/encoding.rs @@ -18,8 +18,8 @@ pub struct Encoding { impl Encoding { /// Create a new `Encoding` containing `(recipe, bits)`. - pub fn new(recipe: u16, bits: u16) -> Encoding { - Encoding { recipe, bits } + pub fn new(recipe: u16, bits: u16) -> Self { + Self { recipe, bits } } /// Get the recipe number in this encoding. @@ -122,10 +122,10 @@ impl EncInfo { /// /// Returns 0 for illegal encodings. pub fn bytes(&self, enc: Encoding) -> CodeOffset { - self.sizing - .get(enc.recipe()) - .map(|s| CodeOffset::from(s.bytes)) - .unwrap_or(0) + self.sizing.get(enc.recipe()).map_or( + 0, + |s| CodeOffset::from(s.bytes), + ) } /// Get the branch range that is supported by `enc`, if any. diff --git a/lib/codegen/src/isa/riscv/abi.rs b/lib/codegen/src/isa/riscv/abi.rs index 96e532e827..ebc4a67fab 100644 --- a/lib/codegen/src/isa/riscv/abi.rs +++ b/lib/codegen/src/isa/riscv/abi.rs @@ -24,8 +24,8 @@ struct Args { } impl Args { - fn new(bits: u16, enable_e: bool) -> Args { - Args { + fn new(bits: u16, enable_e: bool) -> Self { + Self { pointer_bits: bits, pointer_bytes: u32::from(bits) / 8, pointer_type: Type::int(bits).unwrap(), diff --git a/lib/codegen/src/isa/stack.rs b/lib/codegen/src/isa/stack.rs index 0db6279d3f..91df090cb4 100644 --- a/lib/codegen/src/isa/stack.rs +++ b/lib/codegen/src/isa/stack.rs @@ -23,10 +23,10 @@ pub struct StackRef { impl StackRef { /// Get a reference to the stack slot `ss` using one of the base pointers in `mask`. - pub fn masked(ss: StackSlot, mask: StackBaseMask, frame: &StackSlots) -> Option { + pub fn masked(ss: StackSlot, mask: StackBaseMask, frame: &StackSlots) -> Option { // Try an SP-relative reference. if mask.contains(StackBase::SP) { - return Some(StackRef::sp(ss, frame)); + return Some(Self::sp(ss, frame)); } // No reference possible with this mask. @@ -34,7 +34,7 @@ impl StackRef { } /// Get a reference to `ss` using the stack pointer as a base. - pub fn sp(ss: StackSlot, frame: &StackSlots) -> StackRef { + pub fn sp(ss: StackSlot, frame: &StackSlots) -> Self { let size = frame.frame_size.expect( "Stack layout must be computed before referencing stack slots", ); @@ -48,7 +48,7 @@ impl StackRef { let sp_offset = -(size as StackOffset); slot.offset.unwrap() - sp_offset }; - StackRef { + Self { base: StackBase::SP, offset, } diff --git a/lib/codegen/src/isa/x86/abi.rs b/lib/codegen/src/isa/x86/abi.rs index 16cea926b8..fe64aed5b1 100644 --- a/lib/codegen/src/isa/x86/abi.rs +++ b/lib/codegen/src/isa/x86/abi.rs @@ -34,8 +34,8 @@ struct Args { } impl Args { - fn new(bits: u16, gpr: &'static [RU], fpr_limit: usize, call_conv: CallConv) -> Args { - Args { + fn new(bits: u16, gpr: &'static [RU], fpr_limit: usize, call_conv: CallConv) -> Self { + Self { pointer_bytes: u32::from(bits) / 8, pointer_bits: bits, pointer_type: ir::Type::int(bits).unwrap(), @@ -44,7 +44,7 @@ impl Args { fpr_limit, fpr_used: 0, offset: 0, - call_conv: call_conv, + call_conv, } } } @@ -205,7 +205,7 @@ fn callee_saved_gprs_used(flags: &shared_settings::Flags, func: &ir::Function) - } used.intersect(&all_callee_saved); - return used; + used } pub fn prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> result::CtonResult { diff --git a/lib/codegen/src/lib.rs b/lib/codegen/src/lib.rs index 87a86559f9..8f60d23ebe 100644 --- a/lib/codegen/src/lib.rs +++ b/lib/codegen/src/lib.rs @@ -1,6 +1,7 @@ //! Cretonne code generation library. #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces, unstable_features)] #![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: @@ -29,6 +30,16 @@ redundant_field_names, useless_let_if_seq, len_without_is_empty))] +#![cfg_attr(feature="cargo-clippy", warn( + float_arithmetic, + mut_mut, + nonminimal_bool, + option_map_unwrap_or, + option_map_unwrap_or_else, + print_stdout, + unicode_not_nfc, + use_self, + ))] // Turns on no_std and alloc features if std is not available. #![cfg_attr(not(feature = "std"), no_std)] diff --git a/lib/codegen/src/licm.rs b/lib/codegen/src/licm.rs index b5a8f5ed68..154b222df2 100644 --- a/lib/codegen/src/licm.rs +++ b/lib/codegen/src/licm.rs @@ -150,7 +150,7 @@ fn is_loop_invariant(inst: Inst, dfg: &DataFlowGraph, loop_values: &HashSet) -> LoopData { - LoopData { - header: header, + pub fn new(header: Ebb, parent: Option) -> Self { + Self { + header, parent: parent.into(), } } diff --git a/lib/codegen/src/regalloc/affinity.rs b/lib/codegen/src/regalloc/affinity.rs index e0078579a7..a8fa423049 100644 --- a/lib/codegen/src/regalloc/affinity.rs +++ b/lib/codegen/src/regalloc/affinity.rs @@ -19,7 +19,7 @@ pub enum Affinity { /// /// This indicates a value that is not defined or used by any real instructions. It is a ghost /// value that won't appear in the final program. - None, + Unassigned, /// This value should be placed in a spill slot on the stack. Stack, @@ -30,16 +30,16 @@ pub enum Affinity { impl Default for Affinity { fn default() -> Self { - Affinity::None + Affinity::Unassigned } } impl Affinity { /// Create an affinity that satisfies a single constraint. /// - /// This will never create an `Affinity::None`. + /// This will never create an `Affinity::Unassigned`. /// Use the `Default` implementation for that. - pub fn new(constraint: &OperandConstraint) -> Affinity { + pub fn new(constraint: &OperandConstraint) -> Self { if constraint.kind == ConstraintKind::Stack { Affinity::Stack } else { @@ -48,18 +48,18 @@ impl Affinity { } /// Create an affinity that matches an ABI argument for `isa`. - pub fn abi(arg: &AbiParam, isa: &TargetIsa) -> Affinity { + pub fn abi(arg: &AbiParam, isa: &TargetIsa) -> Self { match arg.location { - ArgumentLoc::Unassigned => Affinity::None, + ArgumentLoc::Unassigned => Affinity::Unassigned, ArgumentLoc::Reg(_) => Affinity::Reg(isa.regclass_for_abi_type(arg.value_type).into()), ArgumentLoc::Stack(_) => Affinity::Stack, } } - /// Is this the `None` affinity? - pub fn is_none(self) -> bool { + /// Is this the `Unassigned` affinity? + pub fn is_unassigned(self) -> bool { match self { - Affinity::None => true, + Affinity::Unassigned => true, _ => false, } } @@ -84,18 +84,18 @@ impl Affinity { /// /// Note that this does not guarantee that the register allocator will pick a register that /// satisfies the constraint. - pub fn merge(&mut self, constraint: &OperandConstraint, reg_info: &RegInfo) { + pub fn merge(&mut self, constraint: &OperandConstraint, reginfo: &RegInfo) { match *self { - Affinity::None => *self = Affinity::new(constraint), + Affinity::Unassigned => *self = Self::new(constraint), Affinity::Reg(rc) => { // If the preferred register class is a subclass of the constraint, there's no need // to change anything. if constraint.kind != ConstraintKind::Stack && !constraint.regclass.has_subclass(rc) { - // If the register classes don't overlap, `intersect` returns `None`, and we - // just keep our previous affinity. - if let Some(subclass) = constraint.regclass.intersect_index(reg_info.rc(rc)) { + // If the register classes don't overlap, `intersect` returns `Unassigned`, and + // we just keep our previous affinity. + if let Some(subclass) = constraint.regclass.intersect_index(reginfo.rc(rc)) { // This constraint shrinks our preferred register class. *self = Affinity::Reg(subclass); } @@ -118,7 +118,7 @@ pub struct DisplayAffinity<'a>(Affinity, Option<&'a RegInfo>); impl<'a> fmt::Display for DisplayAffinity<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { - Affinity::None => write!(f, "none"), + Affinity::Unassigned => write!(f, "unassigned"), Affinity::Stack => write!(f, "stack"), Affinity::Reg(rci) => { match self.1 { diff --git a/lib/codegen/src/regalloc/coalescing.rs b/lib/codegen/src/regalloc/coalescing.rs index b77488fec7..096c8546bc 100644 --- a/lib/codegen/src/regalloc/coalescing.rs +++ b/lib/codegen/src/regalloc/coalescing.rs @@ -704,10 +704,10 @@ struct Node { impl Node { /// Create a node representing `value`. - pub fn value(value: Value, set_id: u8, func: &Function) -> Node { + pub fn value(value: Value, set_id: u8, func: &Function) -> Self { let def = func.dfg.value_def(value).pp(); let ebb = func.layout.pp_ebb(def); - Node { + Self { def, ebb, is_vcopy: false, @@ -717,10 +717,10 @@ impl Node { } /// Create a node representing a virtual copy. - pub fn vcopy(branch: Inst, value: Value, set_id: u8, func: &Function) -> Node { + pub fn vcopy(branch: Inst, value: Value, set_id: u8, func: &Function) -> Self { let def = branch.into(); let ebb = func.layout.pp_ebb(def); - Node { + Self { def, ebb, is_vcopy: true, @@ -891,8 +891,8 @@ struct VirtualCopies { impl VirtualCopies { /// Create an empty VirtualCopies struct. - pub fn new() -> VirtualCopies { - VirtualCopies { + pub fn new() -> Self { + Self { params: Vec::new(), branches: Vec::new(), filter: Vec::new(), diff --git a/lib/codegen/src/regalloc/coloring.rs b/lib/codegen/src/regalloc/coloring.rs index 4ddda53e16..e6281920d2 100644 --- a/lib/codegen/src/regalloc/coloring.rs +++ b/lib/codegen/src/regalloc/coloring.rs @@ -272,7 +272,7 @@ impl<'a> Context<'a> { Affinity::Stack => debug_assert!(abi.location.is_stack()), // This is a ghost value, unused in the function. Don't assign it to a location // either. - Affinity::None => {} + Affinity::Unassigned => {} } } @@ -1126,8 +1126,8 @@ struct AvailableRegs { impl AvailableRegs { /// Initialize both the input and global sets from `regs`. - pub fn new(regs: &RegisterSet) -> AvailableRegs { - AvailableRegs { + pub fn new(regs: &RegisterSet) -> Self { + Self { input: regs.clone(), global: regs.clone(), } diff --git a/lib/codegen/src/regalloc/diversion.rs b/lib/codegen/src/regalloc/diversion.rs index b848a879c9..1a747fc7e6 100644 --- a/lib/codegen/src/regalloc/diversion.rs +++ b/lib/codegen/src/regalloc/diversion.rs @@ -32,9 +32,9 @@ pub struct Diversion { impl Diversion { /// Make a new diversion. - pub fn new(value: Value, from: ValueLoc, to: ValueLoc) -> Diversion { + pub fn new(value: Value, from: ValueLoc, to: ValueLoc) -> Self { debug_assert!(from.is_assigned() && to.is_assigned()); - Diversion { value, from, to } + Self { value, from, to } } } diff --git a/lib/codegen/src/regalloc/liveness.rs b/lib/codegen/src/regalloc/liveness.rs index 1b82d98bf8..faf35f6a1f 100644 --- a/lib/codegen/src/regalloc/liveness.rs +++ b/lib/codegen/src/regalloc/liveness.rs @@ -179,7 +179,7 @@ use entity::SparseMap; use flowgraph::ControlFlowGraph; use ir::dfg::ValueDef; use ir::{Ebb, Function, Inst, Layout, ProgramPoint, Value}; -use isa::{EncInfo, TargetIsa}; +use isa::{EncInfo, TargetIsa, OperandConstraint}; use regalloc::affinity::Affinity; use regalloc::liverange::{LiveRange, LiveRangeContext, LiveRangeForest}; use std::mem; @@ -197,7 +197,7 @@ fn get_or_create<'a>( value: Value, isa: &TargetIsa, func: &Function, - enc_info: &EncInfo, + encinfo: &EncInfo, ) -> &'a mut LiveRange { // It would be better to use `get_mut()` here, but that leads to borrow checker fighting // which can probably only be resolved by non-lexical lifetimes. @@ -211,7 +211,7 @@ fn get_or_create<'a>( def = inst.into(); // Initialize the affinity from the defining instruction's result constraints. // Don't do this for call return values which are always tied to a single register. - affinity = enc_info + affinity = encinfo .operand_constraints(func.encodings[inst]) .and_then(|rc| rc.outs.get(rnum)) .map(Affinity::new) @@ -385,8 +385,8 @@ impl Liveness { self.ranges.clear(); // Get ISA data structures used for computing live range affinities. - let enc_info = isa.encoding_info(); - let reg_info = isa.register_info(); + let encinfo = isa.encoding_info(); + let reginfo = isa.register_info(); // The liveness computation needs to visit all uses, but the order doesn't matter. // TODO: Perhaps this traversal of the function could be combined with a dead code @@ -397,7 +397,7 @@ impl Liveness { // TODO: If these parameters are really dead, we could remove them, except for the // entry block which must match the function signature. for &arg in func.dfg.ebb_params(ebb) { - get_or_create(&mut self.ranges, arg, isa, func, &enc_info); + get_or_create(&mut self.ranges, arg, isa, func, &encinfo); } for inst in func.layout.ebb_insts(ebb) { @@ -408,20 +408,18 @@ impl Liveness { // TODO: When we implement DCE, we can use the absence of a live range to indicate // an unused value. for &def in func.dfg.inst_results(inst) { - get_or_create(&mut self.ranges, def, isa, func, &enc_info); + get_or_create(&mut self.ranges, def, isa, func, &encinfo); } // Iterator of constraints, one per value operand. let encoding = func.encodings[inst]; - let mut operand_constraints = enc_info - .operand_constraints(encoding) - .map(|c| c.ins) - .unwrap_or(&[]) - .iter(); + let operand_constraint_slice: &[OperandConstraint] = + encinfo.operand_constraints(encoding).map_or(&[], |c| c.ins); + let mut operand_constraints = operand_constraint_slice.iter(); for &arg in func.dfg.inst_args(inst) { // Get the live range, create it as a dead range if necessary. - let lr = get_or_create(&mut self.ranges, arg, isa, func, &enc_info); + let lr = get_or_create(&mut self.ranges, arg, isa, func, &encinfo); // Extend the live range to reach this use. extend_to_use( @@ -438,7 +436,7 @@ impl Liveness { // operands described by `operand_constraints`. Variable arguments are either // EBB arguments or call/return ABI arguments. if let Some(constraint) = operand_constraints.next() { - lr.affinity.merge(constraint, ®_info); + lr.affinity.merge(constraint, ®info); } } } diff --git a/lib/codegen/src/regalloc/liverange.rs b/lib/codegen/src/regalloc/liverange.rs index 18118e706d..d9ccc4fac5 100644 --- a/lib/codegen/src/regalloc/liverange.rs +++ b/lib/codegen/src/regalloc/liverange.rs @@ -217,8 +217,8 @@ impl GenLiveRange { /// Create a new live range for `value` defined at `def`. /// /// The live range will be created as dead, but it can be extended with `extend_in_ebb()`. - pub fn new(value: Value, def: ProgramPoint, affinity: Affinity) -> GenLiveRange { - GenLiveRange { + pub fn new(value: Value, def: ProgramPoint, affinity: Affinity) -> Self { + Self { value, affinity, def_begin: def, diff --git a/lib/codegen/src/regalloc/pressure.rs b/lib/codegen/src/regalloc/pressure.rs index 9f7d64365d..2c86050c59 100644 --- a/lib/codegen/src/regalloc/pressure.rs +++ b/lib/codegen/src/regalloc/pressure.rs @@ -81,8 +81,8 @@ pub struct Pressure { impl Pressure { /// Create a new register pressure tracker. - pub fn new(reginfo: &RegInfo, usable: &RegisterSet) -> Pressure { - let mut p = Pressure { + pub fn new(reginfo: &RegInfo, usable: &RegisterSet) -> Self { + let mut p = Self { aliased: 0, toprc: Default::default(), }; diff --git a/lib/codegen/src/regalloc/register_set.rs b/lib/codegen/src/regalloc/register_set.rs index 65414dbd9b..59f312150e 100644 --- a/lib/codegen/src/regalloc/register_set.rs +++ b/lib/codegen/src/regalloc/register_set.rs @@ -103,7 +103,7 @@ impl RegisterSet { /// of `other`. /// /// This assumes that unused bits are 1. - pub fn interferes_with(&self, other: &RegisterSet) -> bool { + pub fn interferes_with(&self, other: &Self) -> bool { self.avail.iter().zip(&other.avail).any( |(&x, &y)| (x | y) != !0, ) @@ -111,7 +111,7 @@ impl RegisterSet { /// Intersect this set of registers with `other`. This has the effect of removing any register /// units from this set that are not in `other`. - pub fn intersect(&mut self, other: &RegisterSet) { + pub fn intersect(&mut self, other: &Self) { for (x, &y) in self.avail.iter_mut().zip(&other.avail) { *x &= y; } diff --git a/lib/codegen/src/regalloc/reload.rs b/lib/codegen/src/regalloc/reload.rs index df527fdbca..9397d1a606 100644 --- a/lib/codegen/src/regalloc/reload.rs +++ b/lib/codegen/src/regalloc/reload.rs @@ -219,7 +219,7 @@ impl<'a> Context<'a> { self.reloads.insert(ReloadedValue { stack: cand.value, - reg: reg, + reg, }); cand.value = reg; diff --git a/lib/codegen/src/regalloc/solver.rs b/lib/codegen/src/regalloc/solver.rs index 218f0a2600..f3c14c9d81 100644 --- a/lib/codegen/src/regalloc/solver.rs +++ b/lib/codegen/src/regalloc/solver.rs @@ -151,8 +151,8 @@ pub struct Variable { } impl Variable { - fn new_live(value: Value, constraint: RegClass, from: RegUnit, is_output: bool) -> Variable { - Variable { + fn new_live(value: Value, constraint: RegClass, from: RegUnit, is_output: bool) -> Self { + Self { value, constraint, from: Some(from), @@ -164,8 +164,8 @@ impl Variable { } } - fn new_def(value: Value, constraint: RegClass, is_global: bool) -> Variable { - Variable { + fn new_def(value: Value, constraint: RegClass, is_global: bool) -> Self { + Self { value, constraint, from: None, @@ -280,7 +280,7 @@ pub enum Move { impl Move { /// Create a register move from an assignment, but not for identity assignments. - fn with_assignment(a: &Assignment) -> Option { + fn with_assignment(a: &Assignment) -> Option { if a.from != a.to { Some(Move::Reg { value: a.value, diff --git a/lib/codegen/src/regalloc/spilling.rs b/lib/codegen/src/regalloc/spilling.rs index 5a695eeb8b..34eb48a031 100644 --- a/lib/codegen/src/regalloc/spilling.rs +++ b/lib/codegen/src/regalloc/spilling.rs @@ -363,7 +363,7 @@ impl<'a> Context<'a> { self.cur.isa.regclass_for_abi_type(abi.value_type).into(), true, ), - Affinity::None => panic!("Missing affinity for {}", arg), + Affinity::Unassigned => panic!("Missing affinity for {}", arg), }; let mut reguse = RegUse::new(arg, fixed_args + idx, rci); reguse.fixed = true; @@ -393,10 +393,9 @@ impl<'a> Context<'a> { } else if ru.fixed { // This is a fixed register use which doesn't necessarily require a copy. // Make a copy only if this is not the first use of the value. - self.reg_uses - .get(i.wrapping_sub(1)) - .map(|ru2| ru2.value == ru.value) - .unwrap_or(false) + self.reg_uses.get(i.wrapping_sub(1)).map_or(false, |ru2| { + ru2.value == ru.value + }) } else { false }; @@ -567,8 +566,8 @@ struct RegUse { } impl RegUse { - fn new(value: Value, idx: usize, rci: RegClassIndex) -> RegUse { - RegUse { + fn new(value: Value, idx: usize, rci: RegClassIndex) -> Self { + Self { value, opidx: idx as u16, rci, diff --git a/lib/codegen/src/regalloc/virtregs.rs b/lib/codegen/src/regalloc/virtregs.rs index 215e5efac2..58c7c380de 100644 --- a/lib/codegen/src/regalloc/virtregs.rs +++ b/lib/codegen/src/regalloc/virtregs.rs @@ -101,10 +101,9 @@ impl VirtRegs { where 'a: 'b, { - self.get(*value).map(|vr| self.values(vr)).unwrap_or_else( - || { - ref_slice(value) - }, + self.get(*value).map_or_else( + || ref_slice(value), + |vr| self.values(vr), ) } @@ -257,7 +256,7 @@ enum UFEntry { /// A singleton set is the same as a set with rank 0. It contains only the leader value. impl UFEntry { /// Decode a table entry. - fn decode(x: i32) -> UFEntry { + fn decode(x: i32) -> Self { if x < 0 { UFEntry::Link(Value::new((!x) as usize)) } else { diff --git a/lib/codegen/src/result.rs b/lib/codegen/src/result.rs index 2807202013..47047e2f4e 100644 --- a/lib/codegen/src/result.rs +++ b/lib/codegen/src/result.rs @@ -45,7 +45,7 @@ pub enum CtonError { pub type CtonResult = Result<(), CtonError>; impl From for CtonError { - fn from(e: verifier::Error) -> CtonError { + fn from(e: verifier::Error) -> Self { CtonError::Verifier(e) } } diff --git a/lib/codegen/src/settings.rs b/lib/codegen/src/settings.rs index 6db7ef402e..f4edfc73cf 100644 --- a/lib/codegen/src/settings.rs +++ b/lib/codegen/src/settings.rs @@ -50,8 +50,8 @@ pub struct Builder { impl Builder { /// Create a new builder with defaults and names from the given template. - pub fn new(tmpl: &'static detail::Template) -> Builder { - Builder { + pub fn new(tmpl: &'static detail::Template) -> Self { + Self { template: tmpl, bytes: tmpl.defaults.into(), } diff --git a/lib/codegen/src/verifier/flags.rs b/lib/codegen/src/verifier/flags.rs index 286c169517..582ae525b8 100644 --- a/lib/codegen/src/verifier/flags.rs +++ b/lib/codegen/src/verifier/flags.rs @@ -102,8 +102,7 @@ impl<'a> FlagsVerifier<'a> { if self.encinfo .as_ref() .and_then(|ei| ei.operand_constraints(self.func.encodings[inst])) - .map(|c| c.clobbers_flags) - .unwrap_or(false) && live_val.is_some() + .map_or(false, |c| c.clobbers_flags) && live_val.is_some() { return err!(inst, "encoding clobbers live CPU flags in {}", live); } diff --git a/lib/codegen/src/verifier/liveness.rs b/lib/codegen/src/verifier/liveness.rs index cb57de9a4f..eeb041c88a 100644 --- a/lib/codegen/src/verifier/liveness.rs +++ b/lib/codegen/src/verifier/liveness.rs @@ -78,7 +78,7 @@ impl<'a> LivenessVerifier<'a> { if encoding.is_legal() { // A legal instruction is not allowed to define ghost values. - if lr.affinity.is_none() { + if lr.affinity.is_unassigned() { return err!( inst, "{} is a ghost value defined by a real [{}] instruction", @@ -86,7 +86,7 @@ impl<'a> LivenessVerifier<'a> { self.isa.encoding_info().display(encoding) ); } - } else if !lr.affinity.is_none() { + } else if !lr.affinity.is_unassigned() { // A non-encoded instruction can only define ghost values. return err!( inst, @@ -108,7 +108,7 @@ impl<'a> LivenessVerifier<'a> { } // A legal instruction is not allowed to depend on ghost values. - if encoding.is_legal() && lr.affinity.is_none() { + if encoding.is_legal() && lr.affinity.is_unassigned() { return err!( inst, "{} is a ghost value used by a real [{}] instruction", diff --git a/lib/codegen/src/verifier/mod.rs b/lib/codegen/src/verifier/mod.rs index a5d3a8f2cc..6408b61977 100644 --- a/lib/codegen/src/verifier/mod.rs +++ b/lib/codegen/src/verifier/mod.rs @@ -200,7 +200,7 @@ impl<'a> Verifier<'a> { ); } if is_last_inst && !is_terminator { - return err!(ebb, "block does not end in a terminator instruction!"); + return err!(ebb, "block does not end in a terminator instruction"); } // Instructions belong to the correct ebb. @@ -237,9 +237,9 @@ impl<'a> Verifier<'a> { let fixed_results = inst_data.opcode().constraints().fixed_results(); // var_results is 0 if we aren't a call instruction - let var_results = dfg.call_signature(inst) - .map(|sig| dfg.signatures[sig].returns.len()) - .unwrap_or(0); + let var_results = dfg.call_signature(inst).map_or(0, |sig| { + dfg.signatures[sig].returns.len() + }); let total_results = fixed_results + var_results; // All result values for multi-valued instructions are created @@ -1156,7 +1156,7 @@ mod tests { macro_rules! assert_err_with_msg { ($e:expr, $msg:expr) => { match $e { - Ok(_) => panic!("Expected an error!"), + Ok(_) => panic!("Expected an error"), Err(Error { message, .. }) => { if !message.contains($msg) { #[cfg(feature = "std")] diff --git a/lib/codegen/src/write.rs b/lib/codegen/src/write.rs index 073ae22f11..a8f12d024f 100644 --- a/lib/codegen/src/write.rs +++ b/lib/codegen/src/write.rs @@ -22,7 +22,7 @@ pub fn write_function(w: &mut Write, func: &Function, isa: Option<&TargetIsa>) - let mut any = write_preamble(w, func, regs)?; for ebb in &func.layout { if any { - writeln!(w, "")?; + writeln!(w)?; } write_ebb(w, func, isa, ebb)?; any = true; @@ -258,7 +258,7 @@ fn write_instruction( } write_operands(w, &func.dfg, isa, inst)?; - writeln!(w, "") + writeln!(w) } /// Write the operands of `inst` to `w` with a prepended space. diff --git a/lib/entity/Cargo.toml b/lib/entity/Cargo.toml index c7c6b0dde0..c5f1b88c03 100644 --- a/lib/entity/Cargo.toml +++ b/lib/entity/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cretonne Project Developers"] name = "cretonne-entity" -version = "0.5.0" +version = "0.5.1" description = "Data structures using entity references as mapping keys" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" diff --git a/lib/entity/src/lib.rs b/lib/entity/src/lib.rs index 00b6412c0d..7936495568 100644 --- a/lib/entity/src/lib.rs +++ b/lib/entity/src/lib.rs @@ -30,9 +30,20 @@ //! `Vec`. #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces, unstable_features)] #![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] #![cfg_attr(feature = "cargo-clippy", - allow(new_without_default, new_without_default_derive, redundant_field_names))] + allow(new_without_default, new_without_default_derive))] +#![cfg_attr(feature="cargo-clippy", warn( + float_arithmetic, + mut_mut, + nonminimal_bool, + option_map_unwrap_or, + option_map_unwrap_or_else, + print_stdout, + unicode_not_nfc, + use_self, + ))] // Turns on no_std and alloc features if std is not available. #![cfg_attr(not(feature = "std"), no_std)] @@ -91,7 +102,7 @@ macro_rules! entity_impl { impl $crate::__core::fmt::Display for $entity { fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result { - write!(f, "{}{}", $display_prefix, self.0) + write!(f, concat!($display_prefix, "{}"), self.0) } } diff --git a/lib/entity/src/map.rs b/lib/entity/src/map.rs index 8256ba9c90..8c09cd6486 100644 --- a/lib/entity/src/map.rs +++ b/lib/entity/src/map.rs @@ -49,7 +49,7 @@ where pub fn with_default(default: V) -> Self { Self { elems: Vec::new(), - default: default, + default, unused: PhantomData, } } diff --git a/lib/entity/src/packed_option.rs b/lib/entity/src/packed_option.rs index f92e821f72..869c57bb0d 100644 --- a/lib/entity/src/packed_option.rs +++ b/lib/entity/src/packed_option.rs @@ -28,7 +28,7 @@ impl PackedOption { /// Returns `true` if the packed option is a `Some` value. pub fn is_some(&self) -> bool { - !self.is_none() + self.0 != T::reserved_value() } /// Expand the packed option into a normal `Option`. @@ -62,14 +62,14 @@ impl PackedOption { impl Default for PackedOption { /// Create a default packed option representing `None`. - fn default() -> PackedOption { + fn default() -> Self { PackedOption(T::reserved_value()) } } impl From for PackedOption { /// Convert `t` into a packed `Some(x)`. - fn from(t: T) -> PackedOption { + fn from(t: T) -> Self { debug_assert!( t != T::reserved_value(), "Can't make a PackedOption from the reserved value." @@ -80,7 +80,7 @@ impl From for PackedOption { impl From> for PackedOption { /// Convert an option into its packed equivalent. - fn from(opt: Option) -> PackedOption { + fn from(opt: Option) -> Self { match opt { None => Self::default(), Some(t) => t.into(), diff --git a/lib/faerie/Cargo.toml b/lib/faerie/Cargo.toml index a0e1effeea..77477b8f98 100644 --- a/lib/faerie/Cargo.toml +++ b/lib/faerie/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cretonne-faerie" -version = "0.5.0" +version = "0.5.1" authors = ["The Cretonne Project Developers"] description = "Emit Cretonne output to native object files with Faerie" repository = "https://github.com/Cretonne/cretonne" @@ -9,8 +9,8 @@ license = "Apache-2.0" readme = "README.md" [dependencies] -cretonne-codegen = { path = "../codegen", version = "0.5.0" } -cretonne-module = { path = "../module", version = "0.5.0" } +cretonne-codegen = { path = "../codegen", version = "0.5.1" } +cretonne-module = { path = "../module", version = "0.5.1" } faerie = "0.1.0" goblin = "0.0.14" failure = "0.1.1" diff --git a/lib/faerie/src/backend.rs b/lib/faerie/src/backend.rs index e33fe5e420..37e94e29e0 100644 --- a/lib/faerie/src/backend.rs +++ b/lib/faerie/src/backend.rs @@ -107,12 +107,14 @@ impl Backend for FaerieBackend { // that traps. let mut trap_sink = NullTrapSink {}; - ctx.emit_to_memory( - code.as_mut_ptr(), - &mut reloc_sink, - &mut trap_sink, - &*self.isa, - ); + unsafe { + ctx.emit_to_memory( + &*self.isa, + code.as_mut_ptr(), + &mut reloc_sink, + &mut trap_sink, + ) + }; } self.artifact.define(name, code).expect( @@ -270,7 +272,7 @@ impl<'a> RelocSink for FaerieRelocSink<'a> { &self.namespace.get_data_decl(name).name }; let addend_i32 = addend as i32; - debug_assert!(addend_i32 as i64 == addend); + debug_assert!(i64::from(addend_i32) == addend); let raw_reloc = container::raw_relocation(reloc, self.format); self.artifact .link_with( diff --git a/lib/faerie/src/lib.rs b/lib/faerie/src/lib.rs index dc1dd5a0c3..3cf007357c 100644 --- a/lib/faerie/src/lib.rs +++ b/lib/faerie/src/lib.rs @@ -3,6 +3,20 @@ //! Users of this module should not have to depend on faerie directly. #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces, unstable_features)] +#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] +#![cfg_attr(feature = "cargo-clippy", + allow(new_without_default, new_without_default_derive))] +#![cfg_attr(feature="cargo-clippy", warn( + float_arithmetic, + mut_mut, + nonminimal_bool, + option_map_unwrap_or, + option_map_unwrap_or_else, + print_stdout, + unicode_not_nfc, + use_self, + ))] extern crate cretonne_codegen; extern crate cretonne_module; diff --git a/lib/filetests/Cargo.toml b/lib/filetests/Cargo.toml index 2ab50d0ebd..4e80bfc17e 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.5.0" +version = "0.5.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" @@ -9,7 +9,7 @@ repository = "https://github.com/cretonne/cretonne" publish = false [dependencies] -cretonne-codegen = { path = "../codegen", version = "0.5.0" } -cretonne-reader = { path = "../reader", version = "0.5.0" } +cretonne-codegen = { path = "../codegen", version = "0.5.1" } +cretonne-reader = { path = "../reader", version = "0.5.1" } filecheck = "0.3.0" num_cpus = "1.8.0" diff --git a/lib/filetests/src/lib.rs b/lib/filetests/src/lib.rs index df7be54fa6..30a2edc68c 100644 --- a/lib/filetests/src/lib.rs +++ b/lib/filetests/src/lib.rs @@ -3,10 +3,20 @@ //! This crate contains the main test driver as well as implementations of the //! available filetest commands. +#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces, unstable_features)] #![cfg_attr(feature="cargo-clippy", allow( type_complexity, // Rustfmt 0.9.0 is at odds with this lint: block_in_if_condition_stmt))] +#![cfg_attr(feature="cargo-clippy", warn( + mut_mut, + nonminimal_bool, + option_map_unwrap_or, + option_map_unwrap_or_else, + unicode_not_nfc, + use_self, + ))] #[macro_use(dbg)] extern crate cretonne_codegen; diff --git a/lib/filetests/src/runone.rs b/lib/filetests/src/runone.rs index 6d80afffad..5389cfdb95 100644 --- a/lib/filetests/src/runone.rs +++ b/lib/filetests/src/runone.rs @@ -122,7 +122,7 @@ fn run_one_test<'a>( ) -> Result<()> { let (test, flags, isa) = tuple; let name = format!("{}({})", test.name(), func.name); - dbg!("Test: {} {}", name, isa.map(TargetIsa::name).unwrap_or("-")); + dbg!("Test: {} {}", name, isa.map_or("-", TargetIsa::name)); context.flags = flags; context.isa = isa; diff --git a/lib/filetests/src/test_domtree.rs b/lib/filetests/src/test_domtree.rs index 9803a67d4e..8bf4a36cfe 100644 --- a/lib/filetests/src/test_domtree.rs +++ b/lib/filetests/src/test_domtree.rs @@ -125,7 +125,7 @@ fn filecheck_text(func: &Function, domtree: &DominatorTree) -> result::Result result::Result FunctionBuilder<'a, Variable> { debug_assert!(func_ctx.is_empty()); FunctionBuilder { - func: func, + func, srcloc: Default::default(), - func_ctx: func_ctx, + func_ctx, position: Position::default(), } } diff --git a/lib/frontend/src/lib.rs b/lib/frontend/src/lib.rs index 5a3d4d9b66..494fecb414 100644 --- a/lib/frontend/src/lib.rs +++ b/lib/frontend/src/lib.rs @@ -128,7 +128,18 @@ //! ``` #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] -#![cfg_attr(feature = "cargo-clippy", allow(new_without_default, redundant_field_names))] +#![warn(unused_import_braces, unstable_features)] +#![cfg_attr(feature = "cargo-clippy", allow(new_without_default))] +#![cfg_attr(feature="cargo-clippy", warn( + float_arithmetic, + mut_mut, + nonminimal_bool, + option_map_unwrap_or, + option_map_unwrap_or_else, + print_stdout, + unicode_not_nfc, + use_self, + ))] #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] diff --git a/lib/frontend/src/ssa.rs b/lib/frontend/src/ssa.rs index 138dfe3933..9c07730de9 100644 --- a/lib/frontend/src/ssa.rs +++ b/lib/frontend/src/ssa.rs @@ -361,7 +361,7 @@ where let block = self.blocks.push(BlockData::EbbHeader(EbbHeaderBlockData { predecessors: Vec::new(), sealed: false, - ebb: ebb, + ebb, undef_variables: Vec::new(), })); self.ebb_headers[ebb] = block.into(); diff --git a/lib/module/Cargo.toml b/lib/module/Cargo.toml index f43fde30a7..42dc6ee916 100644 --- a/lib/module/Cargo.toml +++ b/lib/module/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cretonne-module" -version = "0.5.0" +version = "0.5.1" authors = ["The Cretonne Project Developers"] description = "Support for linking functions and data with Cretonne" repository = "https://github.com/Cretonne/cretonne" @@ -9,8 +9,8 @@ license = "Apache-2.0" readme = "README.md" [dependencies] -cretonne-codegen = { path = "../codegen", version = "0.5.0" } -cretonne-entity = { path = "../entity", version = "0.5.0" } +cretonne-codegen = { path = "../codegen", version = "0.5.1" } +cretonne-entity = { path = "../entity", version = "0.5.1" } [badges] maintenance = { status = "experimental" } diff --git a/lib/module/src/lib.rs b/lib/module/src/lib.rs index ebc44420cc..3835f2f0ce 100644 --- a/lib/module/src/lib.rs +++ b/lib/module/src/lib.rs @@ -1,6 +1,20 @@ //! Top-level lib.rs for `cretonne_module`. #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces, unstable_features)] +#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] +#![cfg_attr(feature = "cargo-clippy", + allow(new_without_default, new_without_default_derive))] +#![cfg_attr(feature="cargo-clippy", warn( + float_arithmetic, + mut_mut, + nonminimal_bool, + option_map_unwrap_or, + option_map_unwrap_or_else, + print_stdout, + unicode_not_nfc, + use_self, + ))] extern crate cretonne_codegen; #[macro_use] diff --git a/lib/module/src/module.rs b/lib/module/src/module.rs index 69e9d7432f..79ef29eba3 100644 --- a/lib/module/src/module.rs +++ b/lib/module/src/module.rs @@ -36,7 +36,7 @@ pub enum Linkage { } impl Linkage { - fn merge(a: Linkage, b: Linkage) -> Linkage { + fn merge(a: Self, b: Self) -> Self { match a { Linkage::Export => Linkage::Export, Linkage::Preemptible => { diff --git a/lib/native/Cargo.toml b/lib/native/Cargo.toml index d01a72ddde..f043542cc7 100644 --- a/lib/native/Cargo.toml +++ b/lib/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cretonne-native" -version = "0.5.0" +version = "0.5.1" authors = ["The Cretonne Project Developers"] description = "Support for targeting the host with Cretonne" repository = "https://github.com/cretonne/cretonne" @@ -8,7 +8,7 @@ license = "Apache-2.0" readme = "README.md" [dependencies] -cretonne-codegen = { path = "../codegen", version = "0.5.0", default-features = false } +cretonne-codegen = { path = "../codegen", version = "0.5.1", default-features = false } [target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies] raw-cpuid = "3.0.0" diff --git a/lib/native/src/lib.rs b/lib/native/src/lib.rs index 601a9bfc28..e84be550e2 100644 --- a/lib/native/src/lib.rs +++ b/lib/native/src/lib.rs @@ -2,6 +2,20 @@ //! Cretonne to generate code to run on the same machine. #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces, unstable_features)] +#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] +#![cfg_attr(feature = "cargo-clippy", + allow(new_without_default, new_without_default_derive))] +#![cfg_attr(feature="cargo-clippy", warn( + float_arithmetic, + mut_mut, + nonminimal_bool, + option_map_unwrap_or, + option_map_unwrap_or_else, + print_stdout, + unicode_not_nfc, + use_self, + ))] #![cfg_attr(not(feature = "std"), no_std)] extern crate cretonne_codegen; diff --git a/lib/reader/Cargo.toml b/lib/reader/Cargo.toml index 0b984515d9..c97cc3a113 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.5.0" +version = "0.5.1" description = "Cretonne textual IR reader" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" @@ -9,7 +9,7 @@ repository = "https://github.com/cretonne/cretonne" readme = "README.md" [dependencies] -cretonne-codegen = { path = "../codegen", version = "0.5.0" } +cretonne-codegen = { path = "../codegen", version = "0.5.1" } [badges] maintenance = { status = "experimental" } diff --git a/lib/reader/src/lib.rs b/lib/reader/src/lib.rs index 5a51d4199d..3527bbf587 100644 --- a/lib/reader/src/lib.rs +++ b/lib/reader/src/lib.rs @@ -4,6 +4,20 @@ //! testing Cretonne, but is not essential for a JIT compiler. #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces, unstable_features)] +#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] +#![cfg_attr(feature = "cargo-clippy", + allow(new_without_default, new_without_default_derive))] +#![cfg_attr(feature="cargo-clippy", warn( + float_arithmetic, + mut_mut, + nonminimal_bool, + option_map_unwrap_or, + option_map_unwrap_or_else, + print_stdout, + unicode_not_nfc, + use_self, + ))] extern crate cretonne_codegen; diff --git a/lib/reader/src/testcommand.rs b/lib/reader/src/testcommand.rs index 2b848a9348..32220e006e 100644 --- a/lib/reader/src/testcommand.rs +++ b/lib/reader/src/testcommand.rs @@ -54,7 +54,7 @@ impl<'a> Display for TestCommand<'a> { for opt in &self.options { write!(f, " {}", opt)?; } - writeln!(f, "") + writeln!(f) } } diff --git a/lib/simplejit/Cargo.toml b/lib/simplejit/Cargo.toml index 699212afc0..0fdc16da32 100644 --- a/lib/simplejit/Cargo.toml +++ b/lib/simplejit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cretonne-simplejit" -version = "0.5.0" +version = "0.5.1" authors = ["The Cretonne Project Developers"] description = "A simple JIT library backed by Cretonne" repository = "https://github.com/Cretonne/cretonne" @@ -9,9 +9,9 @@ license = "Apache-2.0" readme = "README.md" [dependencies] -cretonne-codegen = { path = "../codegen", version = "0.5.0" } -cretonne-module = { path = "../module", version = "0.5.0" } -cretonne-native = { path = "../native", version = "0.5.0" } +cretonne-codegen = { path = "../codegen", version = "0.5.1" } +cretonne-module = { path = "../module", version = "0.5.1" } +cretonne-native = { path = "../native", version = "0.5.1" } region = "0.2.0" libc = "0.2.40" errno = "0.2.3" diff --git a/lib/simplejit/src/backend.rs b/lib/simplejit/src/backend.rs index 497ac1bb15..15e6892e19 100644 --- a/lib/simplejit/src/backend.rs +++ b/lib/simplejit/src/backend.rs @@ -103,7 +103,7 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend { // Ignore traps for now. For now, frontends should just avoid generating code // that traps. let mut trap_sink = NullTrapSink {}; - ctx.emit_to_memory(ptr, &mut reloc_sink, &mut trap_sink, &*self.isa); + unsafe { ctx.emit_to_memory(&*self.isa, ptr, &mut reloc_sink, &mut trap_sink) }; Ok(Self::CompiledFunction { code: ptr, @@ -238,14 +238,17 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend { match reloc { Reloc::Abs4 => { // TODO: Handle overflow. + #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))] unsafe { write_unaligned(at as *mut u32, what as u32) }; } Reloc::Abs8 => { + #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))] unsafe { write_unaligned(at as *mut u64, what as u64) }; } Reloc::X86PCRel4 => { // TODO: Handle overflow. let pcrel = ((what as isize) - (at as isize)) as i32; + #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))] unsafe { write_unaligned(at as *mut i32, pcrel) }; } Reloc::X86GOTPCRel4 | @@ -295,9 +298,11 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend { match reloc { Reloc::Abs4 => { // TODO: Handle overflow. + #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))] unsafe { write_unaligned(at as *mut u32, what as u32) }; } Reloc::Abs8 => { + #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))] unsafe { write_unaligned(at as *mut u64, what as u64) }; } Reloc::X86PCRel4 | diff --git a/lib/simplejit/src/lib.rs b/lib/simplejit/src/lib.rs index 0157466cac..1917a3db5e 100644 --- a/lib/simplejit/src/lib.rs +++ b/lib/simplejit/src/lib.rs @@ -1,6 +1,20 @@ //! Top-level lib.rs for `cretonne_simplejit`. #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces, unstable_features)] +#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] +#![cfg_attr(feature = "cargo-clippy", + allow(new_without_default, new_without_default_derive))] +#![cfg_attr(feature="cargo-clippy", warn( + float_arithmetic, + mut_mut, + nonminimal_bool, + option_map_unwrap_or, + option_map_unwrap_or_else, + print_stdout, + unicode_not_nfc, + use_self, + ))] extern crate cretonne_codegen; extern crate cretonne_module; diff --git a/lib/simplejit/src/memory.rs b/lib/simplejit/src/memory.rs index 235a3976d7..1ea654e924 100644 --- a/lib/simplejit/src/memory.rs +++ b/lib/simplejit/src/memory.rs @@ -25,7 +25,7 @@ impl PtrLen { let err = libc::posix_memalign(&mut ptr, page_size, alloc_size); if err == 0 { Ok(Self { - ptr: mem::transmute(ptr), + ptr: ptr as *mut u8, len: alloc_size, }) } else { diff --git a/lib/umbrella/Cargo.toml b/lib/umbrella/Cargo.toml index fc89536394..f7bdc002cd 100644 --- a/lib/umbrella/Cargo.toml +++ b/lib/umbrella/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cretonne Project Developers"] name = "cretonne" -version = "0.5.0" +version = "0.5.1" description = "Umbrella for commonly-used cretonne crates" license = "Apache-2.0" documentation = "https://cretonne.readthedocs.io/" @@ -10,8 +10,8 @@ readme = "README.md" keywords = ["compile", "compiler", "jit"] [dependencies] -cretonne-codegen = { path = "../codegen", version = "0.5.0" } -cretonne-frontend = { path = "../frontend", version = "0.5.0" } +cretonne-codegen = { path = "../codegen", version = "0.5.1" } +cretonne-frontend = { path = "../frontend", version = "0.5.1" } [badges] maintenance = { status = "experimental" } diff --git a/lib/umbrella/src/lib.rs b/lib/umbrella/src/lib.rs index a70a97e86f..179a33224a 100644 --- a/lib/umbrella/src/lib.rs +++ b/lib/umbrella/src/lib.rs @@ -1,7 +1,20 @@ //! Cretonne umbrella crate, providing a convenient one-line dependency. #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces, unstable_features)] #![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] +#![cfg_attr(feature = "cargo-clippy", + allow(new_without_default, new_without_default_derive))] +#![cfg_attr(feature="cargo-clippy", warn( + float_arithmetic, + mut_mut, + nonminimal_bool, + option_map_unwrap_or, + option_map_unwrap_or_else, + print_stdout, + unicode_not_nfc, + use_self, + ))] pub extern crate cretonne_codegen; pub extern crate cretonne_frontend; diff --git a/lib/wasm/Cargo.toml b/lib/wasm/Cargo.toml index b2ec94fa34..7c83cf9ed8 100644 --- a/lib/wasm/Cargo.toml +++ b/lib/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cretonne-wasm" -version = "0.5.0" +version = "0.5.1" authors = ["The Cretonne Project Developers"] description = "Translator from WebAssembly to Cretonne IR" repository = "https://github.com/cretonne/cretonne" @@ -9,9 +9,9 @@ readme = "README.md" keywords = ["webassembly", "wasm"] [dependencies] -wasmparser = { version = "0.16.0", default_features = false } -cretonne-codegen = { path = "../codegen", version = "0.5.0", default_features = false } -cretonne-frontend = { path = "../frontend", version = "0.5.0", default_features = false } +wasmparser = { version = "0.16.0", default-features = false } +cretonne-codegen = { path = "../codegen", version = "0.5.1", default-features = false } +cretonne-frontend = { path = "../frontend", version = "0.5.1", default-features = false } [dependencies.hashmap_core] version = "0.1.1" diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index 2b48cd50c0..aea622cc34 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -949,7 +949,7 @@ fn get_heap_addr( heap: ir::Heap, addr32: ir::Value, offset: u32, - addr_ty: ir::Type, + addr_ty: Type, builder: &mut FunctionBuilder, ) -> (ir::Value, i32) { use std::cmp::min; @@ -985,7 +985,7 @@ fn get_heap_addr( fn translate_load( offset: u32, opcode: ir::Opcode, - result_ty: ir::Type, + result_ty: Type, builder: &mut FunctionBuilder, state: &mut TranslationState, environ: &mut FE, diff --git a/lib/wasm/src/environ/dummy.rs b/lib/wasm/src/environ/dummy.rs index 3676ea23da..e04bd5f180 100644 --- a/lib/wasm/src/environ/dummy.rs +++ b/lib/wasm/src/environ/dummy.rs @@ -225,7 +225,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ args.push(vmctx, &mut pos.func.dfg.value_lists); pos.ins() - .CallIndirect(ir::Opcode::CallIndirect, ir::types::VOID, sig_ref, args) + .CallIndirect(ir::Opcode::CallIndirect, VOID, sig_ref, args) .0 } @@ -247,9 +247,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ args.extend(call_args.iter().cloned(), &mut pos.func.dfg.value_lists); args.push(vmctx, &mut pos.func.dfg.value_lists); - pos.ins() - .Call(ir::Opcode::Call, ir::types::VOID, callee, args) - .0 + pos.ins().Call(ir::Opcode::Call, VOID, callee, args).0 } fn translate_grow_memory( diff --git a/lib/wasm/src/lib.rs b/lib/wasm/src/lib.rs index f63eb26e14..b893e3b903 100644 --- a/lib/wasm/src/lib.rs +++ b/lib/wasm/src/lib.rs @@ -10,8 +10,20 @@ //! The main function of this module is [`translate_module`](fn.translate_module.html). #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces, unstable_features)] #![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] -#![cfg_attr(feature = "cargo-clippy", allow(new_without_default, redundant_field_names))] +#![cfg_attr(feature = "cargo-clippy", + allow(new_without_default, new_without_default_derive))] +#![cfg_attr(feature="cargo-clippy", warn( + float_arithmetic, + mut_mut, + nonminimal_bool, + option_map_unwrap_or, + option_map_unwrap_or_else, + print_stdout, + unicode_not_nfc, + use_self, + ))] #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] diff --git a/lib/wasm/src/sections_translator.rs b/lib/wasm/src/sections_translator.rs index b744c505e4..c243348d5a 100644 --- a/lib/wasm/src/sections_translator.rs +++ b/lib/wasm/src/sections_translator.rs @@ -241,8 +241,8 @@ pub fn parse_global_section( } let global = Global { ty: type_to_type(&content_type).unwrap(), - mutability: mutability, - initializer: initializer, + mutability, + initializer, }; environ.declare_global(global); match *parser.read() {