Repository: bytecodealliance/wasmtime
Pull request #6235 (2023-04-18 21:35:33)

cranelift: Remove EBB references from docs
Remove some references in the docs to extended basic blocks, now that we've completely migrated away.
<!--
Please make sure you include the following information:

- If this work has been discussed elsewhere, please include a link to that
  conversation. If it was discussed in an issue, just mention "issue #...".

- Explain why this change is needed. If the details are in an issue already,
  this can be brief.

Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.html

Please ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->



Patch:
diff --git a/cranelift/docs/compare-llvm.md b/cranelift/docs/compare-llvm.md
index 8c928b4c5..bc9e2060f 100644
--- a/cranelift/docs/compare-llvm.md
+++ b/cranelift/docs/compare-llvm.md
@@ -125,20 +125,13 @@ the [cranelift-module](https://docs.rs/cranelift-module/) crate. It provides
 facilities for working with modules, which can contain multiple functions as
 well as data objects, and it links them together.
 
-An LLVM IR function is a graph of *basic blocks*. A Cranelift 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 Cranelift branch instruction
-only has a single target and falls through to the next instruction when its
-condition is false. The Cranelift representation is closer to how machine code
-works; LLVM's representation is more abstract.
-
-LLVM uses
-[phi instructions](https://llvm.org/docs/LangRef.html#phi-instruction)
-in its SSA representation. Cranelift passes arguments to EBBs instead. The two
-representations are equivalent, but the EBB arguments are better suited to
-handle EBBs that may contain multiple branches to the same destination block
-with different arguments. Passing arguments to an EBB looks a lot like passing
+Both LLVM and Cranelift use a graph of *basic blocks* as their IR for functions.
+However, LLVM uses
+[phi instructions](https://llvm.org/docs/LangRef.html#phi-instruction) in its
+SSA representation while Cranelift passes arguments to BBs instead. The two
+representations are equivalent, but the BB arguments are better suited to handle
+BBs that may contain multiple branches to the same destination block with
+different arguments. Passing arguments to a BB looks a lot like passing
 arguments to a function call, and the register allocator treats them very
 similarly. Arguments are assigned to registers or stack locations.
 
diff --git a/cranelift/docs/ir.md b/cranelift/docs/ir.md
index cd3907603..f2b48627f 100644
--- a/cranelift/docs/ir.md
+++ b/cranelift/docs/ir.md
@@ -86,10 +86,10 @@ Then follows the [function preamble] which declares a number of entities
 that can be referenced inside the function. In the example above, the preamble
 declares a single explicit stack slot, `ss0`.
 
-After the preamble follows the [function body] which consists of
-[extended basic block]s (EBBs), the first of which is the
-[entry block]. Every EBB ends with a [terminator instruction], so
-execution can never fall through to the next EBB without an explicit branch.
+After the preamble follows the [function body] which consists of [basic block]s
+(BBs), the first of which is the [entry block]. Every BB ends with a
+[terminator instruction], so execution can never fall through to the next BB
+without an explicit branch.
 
 A `.clif` file consists of a sequence of independent function definitions:
 
@@ -97,7 +97,7 @@ A `.clif` file consists of a sequence of independent function definitions:
 function_list : { function }
 function      : "function" function_name signature "{" preamble function_body "}"
 preamble      : { preamble_decl }
-function_body : { extended_basic_block }
+function_body : { basic_block }
 ```
 
 ### Static single assignment form
@@ -106,18 +106,18 @@ The instructions in the function body use and produce *values* in SSA form. This
 means that every value is defined exactly once, and every use of a value must be
 dominated by the definition.
 
-Cranelift does not have phi instructions but uses [EBB parameter]s
-instead. An EBB can be defined with a list of typed parameters. Whenever control
-is transferred to the EBB, argument values for the parameters must be provided.
+Cranelift does not have phi instructions but uses [BB parameter]s
+instead. A BB can be defined with a list of typed parameters. Whenever control
+is transferred to the BB, argument values for the parameters must be provided.
 When entering a function, the incoming function parameters are passed as
-arguments to the entry EBB's parameters.
+arguments to the entry BB's parameters.
 
 Instructions define zero, one, or more result values. All SSA values are either
-EBB parameters or instruction results.
+BB parameters or instruction results.
 
 In the example above, the loop induction variable `i` is represented
 as three SSA values: In `block2`, `v3` is the initial value. In the
-loop block `block3`, the EBB parameter `v4` represents the value of the
+loop block `block3`, the BB parameter `v4` represents the value of the
 induction variable during each iteration. Finally, `v11` is computed
 as the induction variable value for the next iteration.
 
@@ -248,7 +248,7 @@ Mem
     Any type that can be stored in memory: `Int` or `Float`.
 
 Testable
-    Either `b1` or `iN`.
+    `iN`
 
 ### Immediate operand types
 
@@ -321,24 +321,14 @@ Signaling NaNs
 
 ## Control flow
 
-Branches transfer control to a new EBB and provide values for the target EBB's
-arguments, if it has any. Conditional branches only take the branch if their
-condition is satisfied, otherwise execution continues at the following
-instruction in the EBB.
+Branches transfer control to a new BB and provide values for the target BB's
+arguments, if it has any. Conditional branches terminate a BB, and transfer to
+the first BB if the condition is satisfied, and the second otherwise.
 
-JT = jump_table [EBB0, EBB1, ..., EBBn]
-    Declare a jump table in the [function preamble].
-
-    This declares a jump table for use by the `br_table` indirect branch
-    instruction. Entries in the table are EBB names.
-
-    The EBBs listed must belong to the current function, and they can't have
-    any arguments.
-
-    :arg EBB0: Target EBB when `x = 0`.
-    :arg EBB1: Target EBB when `x = 1`.
-    :arg EBBn: Target EBB when `x = n`.
-    :result: A jump table identifier. (Not an SSA value).
+The `br_table v, BB(args), [BB1(args)...BBn(args)]` looks up the index `v` in
+the inline jump table given as the third argument, and jumps to that BB. If `v`
+is out of bounds for the jump table, the default BB (second argument) is used
+instead.
 
 Traps stop the program because something went wrong. The exact behavior depends
 on the target instruction set architecture and operating system. There are
@@ -711,10 +701,10 @@ implementation will panic.
 Number of instructions in a function
     At most :math:`2^{31} - 1`.
 
-Number of EBBs in a function
+Number of BBs in a function
     At most :math:`2^{31} - 1`.
 
-    Every EBB needs at least a terminator instruction anyway.
+    Every BB needs at least a terminator instruction anyway.
 
 Number of secondary values in a function
     At most :math:`2^{31} - 1`.
@@ -728,13 +718,13 @@ Other entities declared in the preamble
     This covers things like stack slots, jump tables, external functions, and
     function signatures, etc.
 
-Number of arguments to an EBB
+Number of arguments to a BB
     At most :math:`2^{16}`.
 
 Number of arguments to a function
     At most :math:`2^{16}`.
 
-    This follows from the limit on arguments to the entry EBB. Note that
+    This follows from the limit on arguments to the entry BB. Note that
     Cranelift may add a handful of ABI register arguments as function signatures
     are lowered. This is for representing things like the link register, the
     incoming frame pointer, and callee-saved registers that are saved in the
@@ -767,37 +757,21 @@ Size of function call arguments on the stack
         the last instruction.
 
     entry block
-        The [EBB] that is executed first in a function. Currently, a
+        The [BB] that is executed first in a function. Currently, a
         Cranelift function must have exactly one entry block which must be the
         first block in the function. The types of the entry block arguments must
         match the types of arguments in the function signature.
 
-    extended basic block
-    EBB
-        A maximal sequence of instructions that can only be entered from the
-        top, and that contains no [terminator instruction]s except for
-        the last one. An EBB can contain conditional branches that can fall
-        through to the following instructions in the block, but only the first
-        instruction in the EBB can be a branch target.
-
-        The last instruction in an EBB must be a [terminator instruction],
-        so execution cannot flow through to the next EBB in the function. (But
-        there may be a branch to the next EBB.)
-
-        Note that some textbooks define an EBB as a maximal *subtree* in the
-        control flow graph where only the root can be a join node. This
-        definition is not equivalent to Cranelift EBBs.
-
-    EBB parameter
-        A formal parameter for an EBB is an SSA value that dominates everything
-        in the EBB. For each parameter declared by an EBB, a corresponding
-        argument value must be passed when branching to the EBB. The function's
-        entry EBB has parameters that correspond to the function's parameters.
-
-    EBB argument
-        Similar to function arguments, EBB arguments must be provided when
-        branching to an EBB that declares formal parameters. When execution
-        begins at the top of an EBB, the formal parameters have the values of
+    BB parameter
+        A formal parameter for a BB is an SSA value that dominates everything
+        in the BB. For each parameter declared by a BB, a corresponding
+        argument value must be passed when branching to the BB. The function's
+        entry BB has parameters that correspond to the function's parameters.
+
+    BB argument
+        Similar to function arguments, BB arguments must be provided when
+        branching to a BB that declares formal parameters. When execution
+        begins at the top of a BB, the formal parameters have the values of
         the arguments passed in the branch.
 
     function signature
@@ -824,8 +798,8 @@ Size of function call arguments on the stack
         - Function flags and attributes that are not part of the signature.
 
     function body
-        The extended basic blocks which contain all the executable code in a
-        function. The function body follows the function preamble.
+        The basic blocks which contain all the executable code in a function.
+        The function body follows the function preamble.
 
     intermediate representation
     IR
diff --git a/crates/wasmtime/src/engine.rs b/crates/wasmtime/src/engine.rs
index a900a435f..2db8602fc 100644
--- a/crates/wasmtime/src/engine.rs
+++ b/crates/wasmtime/src/engine.rs
@@ -239,6 +239,18 @@ impl Engine {
         Ok(mmap.to_vec())
     }
 
+    /// Returns a [`std::hash::Hash`] that can be used to check precompiled WebAssembly compatibility.
+    ///
+    /// The outputs of [`Engine::precompile_module`] and [`Engine::precompile_component`]
+    /// are compatible with a different [`Engine`] instance only if the two engines use
+    /// compatible [`Config`]s. If this Hash matches between two [`Engine`]s then binaries
+    /// from one are guaranteed to deserialize in the other.
+    #[cfg(compiler)]
+    #[cfg_attr(nightlydoc, doc(cfg(feature = "cranelift")))] // see build.rs
+    pub fn precompile_compatibility_hash(&self) -> impl std::hash::Hash + '_ {
+        crate::module::HashedEngineCompileEnv(self)
+    }
+
     pub(crate) fn run_maybe_parallel<
         A: Send,
         B: Send,
@@ -628,6 +640,11 @@ impl Default for Engine {
 
 #[cfg(test)]
 mod tests {
+    use std::{
+        collections::hash_map::DefaultHasher,
+        hash::{Hash, Hasher},
+    };
+
     use crate::{Config, Engine, Module, OptLevel};
 
     use anyhow::Result;
@@ -693,4 +710,20 @@ mod tests {
 
         Ok(())
     }
+
+    #[test]
+    fn precompile_compatibility_key_accounts_for_opt_level() {
+        fn hash_for_config(cfg: &Config) -> u64 {
+            let engine = Engine::new(cfg).expect("Config should be valid");
+            let mut hasher = DefaultHasher::new();
+            engine.precompile_compatibility_hash().hash(&mut hasher);
+            hasher.finish()
+        }
+        let mut cfg = Config::new();
+        cfg.cranelift_opt_level(OptLevel::None);
+        let opt_none_hash = hash_for_config(&cfg);
+        cfg.cranelift_opt_level(OptLevel::Speed);
+        let opt_speed_hash = hash_for_config(&cfg);
+        assert_ne!(opt_none_hash, opt_speed_hash)
+    }
 }
diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs
index 3d72c7b27..8e366bf50 100644
--- a/crates/wasmtime/src/module.rs
+++ b/crates/wasmtime/src/module.rs
@@ -1144,10 +1144,10 @@ fn _assert_send_sync() {
 /// The hash computed for this structure is used to key the global wasmtime
 /// cache and dictates whether artifacts are reused. Consequently the contents
 /// of this hash dictate when artifacts are or aren't re-used.
-#[cfg(all(feature = "cache", compiler))]
-struct HashedEngineCompileEnv<'a>(&'a Engine);
+#[cfg(compiler)]
+pub(crate) struct HashedEngineCompileEnv<'a>(pub &'a Engine);
 
-#[cfg(all(feature = "cache", compiler))]
+#[cfg(compiler)]
 impl std::hash::Hash for HashedEngineCompileEnv<'_> {
     fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) {
         // Hash the compiler's state based on its target and configuration.


Test patch:
diff --git a/cranelift/docs/testing.md b/cranelift/docs/testing.md
index 1f1c32a49..b1c110b2c 100644
--- a/cranelift/docs/testing.md
+++ b/cranelift/docs/testing.md
@@ -205,7 +205,7 @@ Compute the dominator tree of each function and validate it against the
     }
 ```
 
-Every reachable extended basic block except for the entry block has an
+Every reachable basic block except for the entry block has an
 *immediate dominator* which is a jump or branch instruction. This test passes
 if the `dominates:` annotations on the immediate dominator instructions are
 both correct and complete.