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 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}