wasmtime_environ/fact/
transcode.rs

1use crate::component::Transcode;
2use crate::fact::core_types::CoreTypes;
3use crate::prelude::*;
4use crate::MemoryIndex;
5use wasm_encoder::{EntityType, ValType};
6
7#[derive(Copy, Clone, Hash, Eq, PartialEq)]
8pub struct Transcoder {
9    pub from_memory: MemoryIndex,
10    pub from_memory64: bool,
11    pub to_memory: MemoryIndex,
12    pub to_memory64: bool,
13    pub op: Transcode,
14}
15
16impl Transcoder {
17    pub fn name(&self) -> String {
18        format!(
19            "{} (mem{} => mem{})",
20            self.op.desc(),
21            self.from_memory.as_u32(),
22            self.to_memory.as_u32(),
23        )
24    }
25
26    pub fn ty(&self, types: &mut CoreTypes) -> EntityType {
27        let from_ptr = if self.from_memory64 {
28            ValType::I64
29        } else {
30            ValType::I32
31        };
32        let to_ptr = if self.to_memory64 {
33            ValType::I64
34        } else {
35            ValType::I32
36        };
37
38        let ty = match self.op {
39            // These direct transcodings take the source pointer, the source
40            // code units, and the destination pointer.
41            //
42            // The memories being copied between are part of each intrinsic and
43            // the destination code units are the same as the source.
44            // Note that the pointers are dynamically guaranteed to be aligned
45            // and in-bounds for the code units length as defined by the string
46            // encoding.
47            Transcode::Copy(_) | Transcode::Latin1ToUtf16 => {
48                types.function(&[from_ptr, from_ptr, to_ptr], &[])
49            }
50
51            // Transcoding from utf8 to utf16 takes the from ptr/len as well as
52            // a destination. The destination is valid for len*2 bytes. The
53            // return value is how many code units were written to the
54            // destination.
55            Transcode::Utf8ToUtf16 => types.function(&[from_ptr, from_ptr, to_ptr], &[to_ptr]),
56
57            // Transcoding to utf8 as a smaller format takes all the parameters
58            // and returns the amount of space consumed in the src/destination
59            Transcode::Utf16ToUtf8 | Transcode::Latin1ToUtf8 => {
60                types.function(&[from_ptr, from_ptr, to_ptr, to_ptr], &[from_ptr, to_ptr])
61            }
62
63            // The return type is a tagged length which indicates which was
64            // used
65            Transcode::Utf16ToCompactProbablyUtf16 => {
66                types.function(&[from_ptr, from_ptr, to_ptr], &[to_ptr])
67            }
68
69            // The initial step of transcoding from a fixed format to a compact
70            // format. Takes the ptr/len of the source the destination
71            // pointer. The destination length is implicitly the same. Returns
72            // how many code units were consumed in the source, which is also
73            // how many bytes were written to the destination.
74            Transcode::Utf8ToLatin1 | Transcode::Utf16ToLatin1 => {
75                types.function(&[from_ptr, from_ptr, to_ptr], &[from_ptr, to_ptr])
76            }
77
78            // The final step of transcoding to a compact format when the fixed
79            // transcode has failed. This takes the ptr/len of the source that's
80            // remaining to transcode. Then this takes the destination ptr/len
81            // as well as the destination bytes written so far with latin1.
82            // Finally this returns the number of code units written to the
83            // destination.
84            Transcode::Utf8ToCompactUtf16 | Transcode::Utf16ToCompactUtf16 => {
85                types.function(&[from_ptr, from_ptr, to_ptr, to_ptr, to_ptr], &[to_ptr])
86            }
87        };
88        EntityType::Function(ty)
89    }
90}