ffi_gen/
abi.rs

1use crate::parser::{Interface, Type};
2
3pub mod export;
4pub mod import;
5
6#[derive(Clone, Copy, Debug)]
7pub enum NumType {
8    U8,
9    U16,
10    U32,
11    U64,
12    I8,
13    I16,
14    I32,
15    I64,
16    F32,
17    F64,
18}
19
20#[derive(Clone, Debug)]
21pub enum AbiType {
22    Num(NumType),
23    Usize,
24    Isize,
25    Bool,
26    RefStr,
27    String,
28    RefSlice(NumType),
29    Vec(NumType),
30    RefObject(String),
31    Object(String),
32    Option(Box<AbiType>),
33    Result(Box<AbiType>),
34    RefIter(Box<AbiType>),
35    Iter(Box<AbiType>),
36    RefFuture(Box<AbiType>),
37    Future(Box<AbiType>),
38    RefStream(Box<AbiType>),
39    Stream(Box<AbiType>),
40    Tuple(Vec<AbiType>),
41}
42
43impl AbiType {
44    pub fn num(&self) -> NumType {
45        if let Self::Num(num) = self {
46            *num
47        } else {
48            panic!()
49        }
50    }
51}
52
53#[derive(Clone, Debug)]
54pub enum FunctionType {
55    Constructor(String),
56    Method(String),
57    Function,
58    NextIter(String, AbiType),
59    PollFuture(String, AbiType),
60    PollStream(String, AbiType),
61}
62
63#[derive(Clone, Debug)]
64pub struct AbiFunction {
65    pub doc: Vec<String>,
66    pub ty: FunctionType,
67    pub name: String,
68    pub args: Vec<(String, AbiType)>,
69    pub ret: Option<AbiType>,
70}
71
72impl AbiFunction {
73    pub fn symbol(&self) -> String {
74        match &self.ty {
75            FunctionType::Constructor(object) | FunctionType::Method(object) => {
76                format!("__{}_{}", object, &self.name)
77            }
78            FunctionType::Function => format!("__{}", &self.name),
79            FunctionType::NextIter(symbol, _) => format!("{}_iter_{}", symbol, &self.name),
80            FunctionType::PollFuture(symbol, _) => format!("{}_future_{}", symbol, &self.name),
81            FunctionType::PollStream(symbol, _) => format!("{}_stream_{}", symbol, &self.name),
82        }
83    }
84
85    pub fn ret(&self, rets: Vec<Var>) -> Return {
86        match rets.len() {
87            0 => Return::Void,
88            1 => Return::Num(rets[0].clone()),
89            _ => Return::Struct(rets, format!("{}Return", self.symbol())),
90        }
91    }
92}
93
94#[derive(Clone, Debug)]
95pub struct AbiObject {
96    pub doc: Vec<String>,
97    pub name: String,
98    pub methods: Vec<AbiFunction>,
99    pub destructor: String,
100}
101
102#[derive(Clone, Debug)]
103pub struct AbiIter {
104    pub ty: AbiType,
105    pub symbol: String,
106}
107
108impl AbiIter {
109    pub fn next(&self) -> AbiFunction {
110        AbiFunction {
111            ty: FunctionType::NextIter(self.symbol.clone(), self.ty.clone()),
112            doc: vec![],
113            name: "next".to_string(),
114            args: vec![],
115            ret: Some(AbiType::Option(Box::new(self.ty.clone()))),
116        }
117    }
118}
119
120#[derive(Clone, Debug)]
121pub struct AbiFuture {
122    pub ty: AbiType,
123    pub symbol: String,
124}
125
126impl AbiFuture {
127    pub fn poll(&self) -> AbiFunction {
128        AbiFunction {
129            ty: FunctionType::PollFuture(self.symbol.clone(), self.ty.clone()),
130            doc: vec![],
131            name: "poll".to_string(),
132            args: vec![
133                ("post_cobject".to_string(), AbiType::Isize),
134                ("port".to_string(), AbiType::Num(NumType::I64)),
135            ],
136            ret: Some(AbiType::Option(Box::new(self.ty.clone()))),
137        }
138    }
139}
140
141#[derive(Clone, Debug)]
142pub struct AbiStream {
143    pub ty: AbiType,
144    pub symbol: String,
145}
146
147impl AbiStream {
148    pub fn poll(&self) -> AbiFunction {
149        AbiFunction {
150            ty: FunctionType::PollStream(self.symbol.clone(), self.ty.clone()),
151            doc: vec![],
152            name: "poll".to_string(),
153            args: vec![
154                ("post_cobject".to_string(), AbiType::Isize),
155                ("port".to_string(), AbiType::Num(NumType::I64)),
156                ("done".to_string(), AbiType::Num(NumType::I64)),
157            ],
158            ret: Some(AbiType::Option(Box::new(self.ty.clone()))),
159        }
160    }
161}
162
163#[derive(Clone, Debug)]
164pub enum Return {
165    Void,
166    Num(Var),
167    Struct(Vec<Var>, String),
168}
169
170#[derive(Default)]
171struct VarGen {
172    counter: u32,
173}
174
175impl VarGen {
176    pub fn new() -> Self {
177        Self::default()
178    }
179
180    pub fn gen_num(&mut self, num: NumType) -> Var {
181        self.gen(AbiType::Num(num))
182    }
183
184    pub fn gen(&mut self, ty: AbiType) -> Var {
185        let binding = self.counter;
186        self.counter += 1;
187        Var { binding, ty }
188    }
189}
190
191#[derive(Clone, Debug)]
192pub struct Var {
193    pub binding: u32,
194    pub ty: AbiType,
195}
196
197/// Abi type.
198#[derive(Clone, Copy, Debug, Eq, PartialEq)]
199pub enum Abi {
200    /// Native 32bit
201    Native32,
202    /// Native 64bit
203    Native64,
204    /// Wasm 32bit
205    Wasm32,
206    /// Wasm 64bit
207    Wasm64,
208}
209
210impl Abi {
211    pub(crate) fn native() -> Self {
212        #[cfg(target_pointer_width = "32")]
213        return Abi::Native32;
214        #[cfg(target_pointer_width = "64")]
215        return Abi::Native64;
216    }
217
218    pub(crate) fn uptr(self) -> NumType {
219        match self {
220            Self::Native32 | Self::Wasm32 => NumType::U32,
221            Self::Native64 | Self::Wasm64 => NumType::U64,
222        }
223    }
224
225    pub(crate) fn iptr(self) -> NumType {
226        match self {
227            Self::Native32 | Self::Wasm32 => NumType::I32,
228            Self::Native64 | Self::Wasm64 => NumType::I64,
229        }
230    }
231
232    /// Returns the size and alignment of a primitive type.
233    pub(crate) fn layout(self, ty: NumType) -> (usize, usize) {
234        let size = match ty {
235            NumType::U8 | NumType::I8 => 1,
236            NumType::U16 | NumType::I16 => 2,
237            NumType::U32 | NumType::I32 | NumType::F32 => 4,
238            NumType::U64 | NumType::I64 | NumType::F64 => 8,
239        };
240        let size = match self {
241            Self::Native32 | Self::Native64 => size,
242            Self::Wasm32 | Self::Wasm64 => core::cmp::max(4, size),
243        };
244        (size, size)
245    }
246}
247
248impl Interface {
249    pub fn objects(&self) -> Vec<AbiObject> {
250        let mut objs = vec![];
251        for object in &self.objects {
252            let mut methods = vec![];
253            for method in &object.methods {
254                let obj = object.ident.clone();
255                let func = AbiFunction {
256                    doc: method.doc.clone(),
257                    name: method.ident.clone(),
258                    ty: if method.is_static {
259                        FunctionType::Constructor(obj)
260                    } else {
261                        FunctionType::Method(obj)
262                    },
263                    args: method
264                        .args
265                        .iter()
266                        .map(|(n, ty)| (n.clone(), self.to_type(ty)))
267                        .collect(),
268                    ret: method.ret.as_ref().map(|ty| self.to_type(ty)),
269                };
270                methods.push(func);
271            }
272            objs.push(AbiObject {
273                doc: object.doc.clone(),
274                name: object.ident.clone(),
275                methods,
276                destructor: format!("drop_box_{}", &object.ident),
277            });
278        }
279        objs
280    }
281
282    pub fn functions(&self) -> Vec<AbiFunction> {
283        let mut funcs = vec![];
284        for func in &self.functions {
285            assert!(!func.is_static);
286            let args = func
287                .args
288                .iter()
289                .map(|(n, ty)| (n.clone(), self.to_type(ty)))
290                .collect();
291            let ret = func.ret.as_ref().map(|ty| self.to_type(ty));
292            let func = AbiFunction {
293                doc: func.doc.clone(),
294                name: func.ident.clone(),
295                ty: FunctionType::Function,
296                args,
297                ret,
298            };
299            funcs.push(func);
300        }
301        funcs
302    }
303
304    pub fn iterators(&self) -> Vec<AbiIter> {
305        let mut iterators = vec![];
306        let mut functions = self.functions();
307        for obj in self.objects() {
308            functions.extend(obj.methods);
309        }
310        for func in functions {
311            if let Some(ty) = func.ret.as_ref() {
312                let mut p = ty;
313                let mut symbol = func.symbol();
314                loop {
315                    match p {
316                        AbiType::Option(ty) | AbiType::Result(ty) => p = &**ty,
317                        AbiType::Future(ty) => {
318                            symbol.push_str("_future_poll");
319                            p = &**ty
320                        }
321                        AbiType::Stream(ty) => {
322                            symbol.push_str("_stream_poll");
323                            p = &**ty
324                        }
325                        AbiType::Iter(ty) => {
326                            iterators.push(AbiIter {
327                                ty: (&**ty).clone(),
328                                symbol,
329                            });
330                            break;
331                        }
332                        _ => break,
333                    }
334                }
335            }
336        }
337        iterators
338    }
339
340    pub fn futures(&self) -> Vec<AbiFuture> {
341        let mut futures = vec![];
342        let mut functions = self.functions();
343        for obj in self.objects() {
344            functions.extend(obj.methods);
345        }
346        for func in functions {
347            if let Some(ty) = func.ret.as_ref() {
348                let mut p = ty;
349                loop {
350                    match p {
351                        AbiType::Option(ty) | AbiType::Result(ty) => p = &**ty,
352                        AbiType::Future(ty) => {
353                            let symbol = func.symbol();
354                            futures.push(AbiFuture {
355                                ty: (&**ty).clone(),
356                                symbol,
357                            });
358                            break;
359                        }
360                        _ => break,
361                    }
362                }
363            }
364        }
365        futures
366    }
367
368    pub fn streams(&self) -> Vec<AbiStream> {
369        let mut streams = vec![];
370        let mut functions = self.functions();
371        for obj in self.objects() {
372            functions.extend(obj.methods);
373        }
374        for func in functions {
375            if let Some(ty) = func.ret.as_ref() {
376                let mut p = ty;
377                loop {
378                    match p {
379                        AbiType::Option(ty) | AbiType::Result(ty) => p = &**ty,
380                        AbiType::Stream(ty) => {
381                            let symbol = func.symbol();
382                            streams.push(AbiStream {
383                                ty: (&**ty).clone(),
384                                symbol,
385                            });
386                            break;
387                        }
388                        _ => break,
389                    }
390                }
391            }
392        }
393        streams
394    }
395
396    pub fn imports(&self, abi: &Abi) -> Vec<import::Import> {
397        let mut imports = vec![];
398        for function in self.functions() {
399            imports.push(abi.import(&function));
400        }
401        for obj in self.objects() {
402            for method in &obj.methods {
403                imports.push(abi.import(method));
404            }
405        }
406        for iter in self.iterators() {
407            imports.push(abi.import(&iter.next()));
408        }
409        for fut in self.futures() {
410            imports.push(abi.import(&fut.poll()));
411        }
412        for stream in self.streams() {
413            imports.push(abi.import(&stream.poll()));
414        }
415        imports
416    }
417
418    pub fn to_type(&self, ty: &Type) -> AbiType {
419        match ty {
420            Type::U8 => AbiType::Num(NumType::U8),
421            Type::U16 => AbiType::Num(NumType::U16),
422            Type::U32 => AbiType::Num(NumType::U32),
423            Type::U64 => AbiType::Num(NumType::U64),
424            Type::Usize => AbiType::Usize,
425            Type::I8 => AbiType::Num(NumType::I8),
426            Type::I16 => AbiType::Num(NumType::I16),
427            Type::I32 => AbiType::Num(NumType::I32),
428            Type::I64 => AbiType::Num(NumType::I64),
429            Type::Isize => AbiType::Isize,
430            Type::F32 => AbiType::Num(NumType::F32),
431            Type::F64 => AbiType::Num(NumType::F64),
432            Type::Bool => AbiType::Bool,
433            Type::Ref(inner) => match &**inner {
434                Type::String => AbiType::RefStr,
435                Type::Slice(inner) => match self.to_type(inner) {
436                    AbiType::Num(ty) => AbiType::RefSlice(ty),
437                    ty => unimplemented!("&{:?}", ty),
438                },
439                Type::Ident(ident) => {
440                    if !self.is_object(ident) {
441                        panic!("unknown identifier {}", ident);
442                    }
443                    AbiType::RefObject(ident.clone())
444                }
445                ty => unimplemented!("&{:?}", ty),
446            },
447            Type::String => AbiType::String,
448            Type::Slice(_) => panic!("slice needs to be passed by reference"),
449            Type::Vec(inner) => match self.to_type(inner) {
450                AbiType::Num(ty) => AbiType::Vec(ty),
451                ty => unimplemented!("Vec<{:?}>", ty),
452            },
453            Type::Ident(ident) => {
454                if !self.is_object(ident) {
455                    panic!("unknown identifier {}", ident);
456                }
457                AbiType::Object(ident.clone())
458            }
459            Type::Option(ty) => {
460                let inner = self.to_type(ty);
461                if let AbiType::Option(_) = inner {
462                    panic!("nested options are not supported");
463                }
464                AbiType::Option(Box::new(inner))
465            }
466            Type::Result(ty) => AbiType::Result(Box::new(self.to_type(ty))),
467            Type::Iter(ty) => AbiType::Iter(Box::new(self.to_type(ty))),
468            Type::Future(ty) => AbiType::Future(Box::new(self.to_type(ty))),
469            Type::Stream(ty) => AbiType::Stream(Box::new(self.to_type(ty))),
470            Type::Tuple(ty) => AbiType::Tuple(ty.iter().map(|ty| self.to_type(ty)).collect()),
471        }
472    }
473}