wasmer_cli/c_gen/
staticlib_header.rs

1//! Generate a header file for the static object file produced.
2
3use wasmer_compiler::types::symbols::{Symbol, SymbolRegistry};
4use wasmer_types::ModuleInfo;
5
6use super::{CStatement, CType, generate_c};
7
8/// Helper functions to simplify the usage of the static artifact.
9fn gen_helper_functions(atom_name: &str, module_name: &str) -> String {
10    format!("
11    wasm_module_t* wasmer_object_module_new_{atom_name}(wasm_store_t* store, const char* wasm_name) {{
12            // wasm_name intentionally unused for now: will be used in the future.
13            wasm_byte_vec_t module_byte_vec = {{
14                .size = module_bytes_len_{atom_name},
15                .data = (char*)&{module_name}[0],
16            }};
17            wasm_module_t* module = wasm_module_deserialize(store, &module_byte_vec);
18
19            return module;
20    }}
21    ")
22}
23
24/// Generate the header file that goes with the generated object file.
25pub fn generate_header_file(
26    atom_name: &str,
27    module_info: &ModuleInfo,
28    symbol_registry: &dyn SymbolRegistry,
29    metadata_length: usize,
30) -> String {
31    let mut c_statements = vec![
32        CStatement::LiteralConstant {
33            value: "#include \"wasmer.h\"\n#include <stdlib.h>\n#include <string.h>\n\n"
34                .to_string(),
35        },
36        CStatement::LiteralConstant {
37            value: "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n".to_string(),
38        },
39        CStatement::Declaration {
40            name: format!("module_bytes_len_{atom_name}"),
41            is_extern: false,
42            is_const: true,
43            ctype: CType::U32,
44            definition: Some(Box::new(CStatement::LiteralConstant {
45                value: metadata_length.to_string(),
46            })),
47        },
48        CStatement::Declaration {
49            name: symbol_registry.symbol_to_name(Symbol::Metadata),
50            is_extern: true,
51            is_const: true,
52            ctype: CType::Array {
53                inner: Box::new(CType::U8),
54            },
55            definition: None,
56        },
57    ];
58    let function_declarations = module_info
59        .functions
60        .iter()
61        .filter_map(|(f_index, sig_index)| {
62            Some((module_info.local_func_index(f_index)?, sig_index))
63        })
64        .map(|(function_local_index, _sig_index)| {
65            let function_name =
66                symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index));
67            // TODO: figure out the signature here too
68            CStatement::Declaration {
69                name: function_name,
70                is_extern: true,
71                is_const: false,
72                ctype: CType::Function {
73                    arguments: vec![CType::Void],
74                    return_value: None,
75                },
76                definition: None,
77            }
78        });
79    c_statements.push(CStatement::LiteralConstant {
80        value: r#"
81// Compiled Wasm function pointers ordered by function index: the order they
82// appeared in in the Wasm module.
83"#
84        .to_string(),
85    });
86    c_statements.extend(function_declarations);
87
88    let func_trampoline_declarations =
89        module_info
90            .signatures
91            .iter()
92            .map(|(sig_index, _func_type)| {
93                let function_name =
94                    symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index));
95
96                CStatement::Declaration {
97                    name: function_name,
98                    is_extern: true,
99                    is_const: false,
100                    ctype: CType::Function {
101                        arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()],
102                        return_value: None,
103                    },
104                    definition: None,
105                }
106            });
107    c_statements.push(CStatement::LiteralConstant {
108        value: r#"
109// Trampolines (functions by which we can call into Wasm) ordered by signature.
110// There is 1 trampoline per function signature in the order they appear in
111// the Wasm module.
112"#
113        .to_string(),
114    });
115    c_statements.extend(func_trampoline_declarations);
116
117    let dyn_func_declarations = module_info
118        .functions
119        .keys()
120        .take(module_info.num_imported_functions)
121        .map(|func_index| {
122            let function_name =
123                symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index));
124            // TODO: figure out the signature here
125            CStatement::Declaration {
126                name: function_name,
127                is_extern: true,
128                is_const: false,
129                ctype: CType::Function {
130                    arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()],
131                    return_value: None,
132                },
133                definition: None,
134            }
135        });
136    c_statements.push(CStatement::LiteralConstant {
137        value: r#"
138// Dynamic trampolines are per-function and are used for each function where
139// the type signature is not known statically. In this case, this corresponds to
140// the imported functions.
141"#
142        .to_string(),
143    });
144    c_statements.extend(dyn_func_declarations);
145
146    c_statements.push(CStatement::TypeDef {
147        source_type: CType::Function {
148            arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()],
149            return_value: None,
150        },
151        new_name: "dyn_func_trampoline_t".to_string(),
152    });
153
154    c_statements.push(CStatement::LiteralConstant {
155        value: gen_helper_functions(atom_name, &symbol_registry.symbol_to_name(Symbol::Metadata)),
156    });
157
158    c_statements.push(CStatement::LiteralConstant {
159        value: "\n#ifdef __cplusplus\n}\n#endif\n\n".to_string(),
160    });
161
162    generate_c(&c_statements)
163}