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}