waffle/
ir.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//! Intermediate representation for Wasm.

use crate::{declare_entity, entity::EntityRef};

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
/// Types in waffle's IR.
///
/// These types correspond to (a subset of) the primitive Wasm value
/// types: integers, floats, SIMD vectors, and function references
/// (optionally typed).
///
/// Every SSA value in a function body has a `Type`, unless it is a
/// tuple (multi-value or zero-value result).

pub enum Type {
    /// A 32-bit integer. Signedness is unspecified: individual
    /// operators specify how they handle sign.
    I32,
    /// A 64-bit integer. Signedness is unspecified: individual
    /// operators specify how they handle sign.
    I64,
    /// A 32-bit IEEE 754 floating point value. Semantics around NaNs
    /// are defined by individual operators; from the point of view of
    /// IR scaffolding, floating-point values are bags of bits.
    F32,
    /// A 64-bit IEEE 754 floating point value. Semantics around NaNs
    /// are defined by individual operators; from the point of view of
    /// IR scaffolding, floating-point values are bags of bits.
    F64,
    /// A 128-bit SIMD vector value. Lanes and lane types are
    /// specified by individual operators; from the point of view of
    /// IR scaffolding, SIMD vector values are bags of bits.
    V128,
    /// A function reference.
    FuncRef,
    ExternRef,
    TypedFuncRef {
        nullable: bool,
        sig_index: Signature,
    },
}
impl From<wasmparser::ValType> for Type {
    fn from(ty: wasmparser::ValType) -> Self {
        match ty {
            wasmparser::ValType::I32 => Type::I32,
            wasmparser::ValType::I64 => Type::I64,
            wasmparser::ValType::F32 => Type::F32,
            wasmparser::ValType::F64 => Type::F64,
            wasmparser::ValType::V128 => Type::V128,
            wasmparser::ValType::Ref(r) => r.into(),
        }
    }
}
impl From<wasmparser::RefType> for Type {
    fn from(ty: wasmparser::RefType) -> Self {
        if ty.is_extern_ref() {
            return Type::ExternRef;
        }
        match ty.type_index() {
            Some(idx) => {
                let nullable = ty.is_nullable();
                Type::TypedFuncRef {
                    nullable: nullable,
                    sig_index: Signature::new(idx.as_module_index().unwrap() as usize),
                }
            }
            None => Type::FuncRef,
        }
    }
}

impl std::fmt::Display for Type {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            Type::I32 => write!(f, "i32"),
            Type::I64 => write!(f, "i64"),
            Type::F32 => write!(f, "f32"),
            Type::F64 => write!(f, "f64"),
            Type::V128 => write!(f, "v128"),
            Type::FuncRef => write!(f, "funcref"),
            Type::ExternRef => write!(f, "externref"),
            Type::TypedFuncRef {
                nullable,
                sig_index,
            } => write!(
                f,
                "funcref({}, {})",
                if *nullable { "null" } else { "not_null" },
                sig_index
            ),
        }
    }
}

impl From<Type> for wasm_encoder::ValType {
    fn from(ty: Type) -> wasm_encoder::ValType {
        match ty {
            Type::I32 => wasm_encoder::ValType::I32,
            Type::I64 => wasm_encoder::ValType::I64,
            Type::F32 => wasm_encoder::ValType::F32,
            Type::F64 => wasm_encoder::ValType::F64,
            Type::V128 => wasm_encoder::ValType::V128,
            Type::FuncRef | Type::TypedFuncRef { .. } | Type::ExternRef => {
                wasm_encoder::ValType::Ref(ty.into())
            }
        }
    }
}

impl From<Type> for wasm_encoder::RefType {
    fn from(ty: Type) -> wasm_encoder::RefType {
        match ty {
            Type::ExternRef => wasm_encoder::RefType::EXTERNREF,
            Type::FuncRef => wasm_encoder::RefType::FUNCREF,
            Type::TypedFuncRef{nullable,sig_index} => wasm_encoder::RefType {
                nullable,
                heap_type: wasm_encoder::HeapType::Concrete(sig_index.0),
            },
            _ => panic!("Cannot convert {:?} into reftype", ty),
        }
    }
}

// Per-module index spaces:

// A signature (list of parameter types and list of return types) in
// the module.
declare_entity!(Signature, "sig");
// A function in the module.
declare_entity!(Func, "func");
// A global variable in the module.
declare_entity!(Global, "global");
// A table in the module.
declare_entity!(Table, "table");
// A memory in the module.
declare_entity!(Memory, "memory");

// Per-function index spaces:

// A basic block in one function body.
declare_entity!(Block, "block");
// A local variable (storage slot) in one function body.
declare_entity!(Local, "local");
// An SSA value in one function body.
declare_entity!(Value, "v");

mod module;
pub use module::*;
mod func;
pub use func::*;
mod value;
pub use value::*;
mod display;
pub use display::*;
mod debug;
pub use debug::*;