swasm_utils/
build.rs

1use std;
2use super::{
3	optimize,
4	pack_instance,
5	ununderscore_funcs,
6	externalize_mem,
7	shrink_unknown_stack,
8	inject_runtime_type,
9	PackingError,
10	OptimizerError,
11	TargetRuntime,
12};
13use swasm;
14use swasm::elements;
15
16#[derive(Debug)]
17pub enum Error {
18	Encoding(elements::Error),
19	Packing(PackingError),
20	Optimizer,
21}
22
23impl From<OptimizerError> for Error {
24	fn from(_err: OptimizerError) -> Self {
25		Error::Optimizer
26	}
27}
28
29impl From<PackingError> for Error {
30	fn from(err: PackingError) -> Self {
31		Error::Packing(err)
32	}
33}
34
35#[derive(Debug, Clone, Copy)]
36pub enum SourceTarget {
37	Emscripten,
38	Unknown,
39}
40
41impl std::fmt::Display for Error {
42	fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
43		use self::Error::*;
44		match *self {
45			Encoding(ref err) => write!(f, "Encoding error ({})", err),
46			Optimizer => write!(f, "Optimization error due to missing export section. Pointed wrong file?"),
47			Packing(ref e) => write!(f, "Packing failed due to module structure error: {}. Sure used correct libraries for building contracts?", e),
48		}
49	}
50}
51
52fn has_ctor(module: &elements::Module, target_runtime: &TargetRuntime) -> bool {
53	if let Some(ref section) = module.export_section() {
54		section.entries().iter().any(|e| target_runtime.create_symbol == e.field())
55	} else {
56		false
57	}
58}
59
60pub fn build(
61	mut module: elements::Module,
62	source_target: SourceTarget,
63	runtime_type_version: Option<([u8; 4], u32)>,
64	public_api_entries: &[&str],
65	enforce_stack_adjustment: bool,
66	stack_size: u32,
67	skip_optimization: bool,
68	target_runtime: &TargetRuntime,
69) -> Result<(elements::Module, Option<elements::Module>), Error> {
70
71	if let SourceTarget::Emscripten = source_target {
72		module = ununderscore_funcs(module);
73	}
74
75	if let SourceTarget::Unknown = source_target {
76		// 49152 is 48kb!
77		if enforce_stack_adjustment {
78			assert!(stack_size <= 1024*1024);
79			let (new_module, new_stack_top) = shrink_unknown_stack(module, 1024 * 1024 - stack_size);
80			module = new_module;
81			let mut stack_top_page = new_stack_top / 65536;
82			if new_stack_top % 65536 > 0 { stack_top_page += 1 };
83			module = externalize_mem(module, Some(stack_top_page), 16);
84		} else {
85			module = externalize_mem(module, None, 16);
86		}
87	}
88
89	if let Some(runtime_type_version) = runtime_type_version {
90		let (runtime_type, runtime_version) = runtime_type_version;
91		module = inject_runtime_type(module, runtime_type, runtime_version);
92	}
93
94	let mut ctor_module = module.clone();
95
96	let mut public_api_entries = public_api_entries.to_vec();
97	public_api_entries.push(target_runtime.call_symbol);
98	if !skip_optimization {
99		optimize(
100			&mut module,
101			public_api_entries,
102		)?;
103	}
104
105	if has_ctor(&ctor_module, target_runtime) {
106		if !skip_optimization {
107			optimize(&mut ctor_module, vec![target_runtime.create_symbol])?;
108		}
109		let ctor_module = pack_instance(
110			swasm::serialize(module.clone()).map_err(Error::Encoding)?,
111			ctor_module.clone(),
112			target_runtime,
113		)?;
114		Ok((module, Some(ctor_module)))
115	} else {
116		Ok((module, None))
117	}
118}