瀏覽代碼

Merge pull request #16 from seanyoung/modules

Reorganise code into parse, resolve and emit modules
Sean Young 6 年之前
父節點
當前提交
cf7e078da5
共有 13 個文件被更改,包括 220 次插入210 次删除
  1. 1 1
      Cargo.toml
  2. 181 184
      src/emit/mod.rs
  3. 3 4
      src/main.rs
  4. 1 1
      src/output.rs
  5. 1 1
      src/parser/ast.rs
  6. 3 2
      src/parser/mod.rs
  7. 1 1
      src/parser/solidity.lalrpop
  8. 4 4
      src/parser/solidity.rs
  9. 1 1
      src/resolver/cfg.rs
  10. 3 2
      src/resolver/mod.rs
  11. 20 8
      src/test.rs
  12. 二進制
      stdlib/stdlib.bc
  13. 1 1
      stdlib/stdlib.c

+ 1 - 1
Cargo.toml

@@ -13,7 +13,7 @@ lalrpop = "0.17.0"
 [dependencies]
 lalrpop-util = "0.17.0"
 regex = "0.2.1"
-inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm8-0" }
+inkwell = { git = "https://github.com/seanyoung/inkwell", branch = "llvm8-0" }
 num-bigint = "0.2"
 num-traits = "0.2.6"
 parity-wasm = "0.35"

+ 181 - 184
src/emit.rs → src/emit/mod.rs

@@ -1,6 +1,7 @@
-use ast;
-use cfg;
+
+use parser::ast;
 use resolver;
+use resolver::cfg;
 use std::str;
 use std::path::Path;
 
@@ -30,25 +31,26 @@ lazy_static::lazy_static! {
 }
 
 #[derive(Clone)]
-struct Variable {
-    value: BasicValueEnum,
+struct Variable<'a> {
+    value: BasicValueEnum<'a>,
     stack: bool,
 }
 
 #[derive(Clone)]
-struct Function {
-    value_ref: FunctionValue,
+struct Function<'a> {
+    value_ref: FunctionValue<'a>,
     wasm_return: bool,
 }
 
 pub struct Contract<'a> {
     pub name: String,
-    pub module: Module,
+    pub module: Module<'a>,
+    builder: Builder<'a>,
+    context: &'a Context,
     target: Target,
-    context: Context,
     ns: &'a resolver::Contract,
-    functions: Vec<Function>,
-    externals: HashMap<String, FunctionValue>,
+    functions: Vec<Function<'a>>,
+    externals: HashMap<String, FunctionValue<'a>>,
 }
 
 impl<'a> Contract<'a> {
@@ -81,20 +83,23 @@ impl<'a> Contract<'a> {
         Ok(())
     }
 
-    pub fn new(contract: &'a resolver::Contract, filename: &str) -> Self {
+    pub fn new(context: &'a Context, contract: &'a resolver::Contract, filename: &'a str) -> Self {
         lazy_static::initialize(&LLVM_INIT);
 
         let target = Target::from_triple(WASMTRIPLE).unwrap();
-        let context = Context::create();
         let module = context.create_module(&contract.name);
+
         module.set_target(&target);
         module.set_source_file_name(filename);
 
-        let builder = context.create_builder();
+        // stdlib
+        let intr = load_stdlib(&context);
+        module.link_in_module(intr).unwrap();
 
         let mut e = Contract {
             name: contract.name.to_owned(),
             module: module,
+            builder: context.create_builder(),
             target: target,
             context: context,
             ns: contract,
@@ -102,21 +107,15 @@ impl<'a> Contract<'a> {
             externals: HashMap::new(),
         };
 
-        // stdlib
-        let intr = load_stdlib(&e.context);
-
-        e.module.link_in_module(intr).unwrap();
-
         // externals
         e.declare_externals();
 
         for func in &contract.functions {
-            let f = e.emit_func(func, &builder);
-            e.functions.push(f);
+            e.emit_func(func);
         }
 
-        e.emit_constructor_dispatch(contract, &builder);
-        e.emit_function_dispatch(contract, &builder);
+        e.emit_constructor_dispatch(contract);
+        e.emit_function_dispatch(contract);
 
         e
     }
@@ -139,10 +138,9 @@ impl<'a> Contract<'a> {
 
     fn expression(
         &self,
-        builder: &Builder,
         e: &cfg::Expression,
-        vartab: &Vec<Variable>,
-    ) -> IntValue {
+        vartab: &Vec<Variable<'a>>,
+    ) -> IntValue<'a> {
         match e {
             cfg::Expression::NumberLiteral(bits, n) => {
                 let ty = self.context.custom_width_int_type(*bits as _);
@@ -151,77 +149,77 @@ impl<'a> Contract<'a> {
                 ty.const_int_from_string(&s, StringRadix::Decimal).unwrap()
             }
             cfg::Expression::Add(l, r) => {
-                let left = self.expression(builder, l, vartab);
-                let right = self.expression(builder, r, vartab);
+                let left = self.expression(l, vartab);
+                let right = self.expression(r, vartab);
 
-                builder.build_int_add(left, right, "")
+                self.builder.build_int_add(left, right, "")
             }
             cfg::Expression::Subtract(l, r) => {
-                let left = self.expression(builder, l, vartab);
-                let right = self.expression(builder, r, vartab);
+                let left = self.expression(l, vartab);
+                let right = self.expression(r, vartab);
 
-                builder.build_int_sub(left, right, "")
+                self.builder.build_int_sub(left, right, "")
             }
             cfg::Expression::Multiply(l, r) => {
-                let left = self.expression(builder, l, vartab);
-                let right = self.expression(builder, r, vartab);
+                let left = self.expression(l, vartab);
+                let right = self.expression(r, vartab);
 
-                builder.build_int_mul(left, right, "")
+                self.builder.build_int_mul(left, right, "")
             }
             cfg::Expression::UDivide(l, r) => {
-                let left = self.expression(builder, l, vartab);
-                let right = self.expression(builder, r, vartab);
+                let left = self.expression(l, vartab);
+                let right = self.expression(r, vartab);
 
-                builder.build_int_unsigned_div(left, right, "")
+                self.builder.build_int_unsigned_div(left, right, "")
             }
             cfg::Expression::SDivide(l, r) => {
-                let left = self.expression(builder, l, vartab);
-                let right = self.expression(builder, r, vartab);
+                let left = self.expression(l, vartab);
+                let right = self.expression(r, vartab);
 
-                builder.build_int_signed_div(left, right, "")
+                self.builder.build_int_signed_div(left, right, "")
             }
             cfg::Expression::Equal(l, r) => {
-                let left = self.expression(builder, l, vartab);
-                let right = self.expression(builder, r, vartab);
+                let left = self.expression(l, vartab);
+                let right = self.expression(r, vartab);
 
-                builder.build_int_compare(IntPredicate::EQ, left, right, "")
+                self.builder.build_int_compare(IntPredicate::EQ, left, right, "")
             }
             cfg::Expression::More(l, r) => {
-                let left = self.expression(builder, l, vartab);
-                let right = self.expression(builder, r, vartab);
+                let left = self.expression(l, vartab);
+                let right = self.expression(r, vartab);
 
-                builder.build_int_compare(IntPredicate::SGT, left, right, "")
+                self.builder.build_int_compare(IntPredicate::SGT, left, right, "")
             }
             cfg::Expression::Less(l, r) => {
-                let left = self.expression(builder, l, vartab);
-                let right = self.expression(builder, r, vartab);
+                let left = self.expression(l, vartab);
+                let right = self.expression(r, vartab);
 
-                builder.build_int_compare(IntPredicate::SLT, left, right, "")
+                self.builder.build_int_compare(IntPredicate::SLT, left, right, "")
             }
             cfg::Expression::Variable(_, s) => {
                 if vartab[*s].stack {
-                    builder.build_load(vartab[*s].value.into_pointer_value(), "").into_int_value()
+                    self.builder.build_load(vartab[*s].value.into_pointer_value(), "").into_int_value()
                 } else {
                     vartab[*s].value.into_int_value()
                 }
             }
             cfg::Expression::ZeroExt(t, e) => {
-                let e = self.expression(builder, e, vartab);
+                let e = self.expression(e, vartab);
                 let ty = t.LLVMType(self.ns, &self.context);
 
-                builder.build_int_z_extend(e, ty, "")
+                self.builder.build_int_z_extend(e, ty, "")
             }
             cfg::Expression::SignExt(t, e) => {
-                let e = self.expression(builder, e, vartab);
+                let e = self.expression(e, vartab);
                 let ty = t.LLVMType(self.ns, &self.context);
 
-                builder.build_int_s_extend(e, ty, "")
+                self.builder.build_int_s_extend(e, ty, "")
             }
             cfg::Expression::Trunc(t, e) => {
-                let e = self.expression(builder, e, vartab);
+                let e = self.expression(e, vartab);
                 let ty = t.LLVMType(self.ns, &self.context);
 
-                builder.build_int_truncate(e, ty, "")
+                self.builder.build_int_truncate(e, ty, "")
             }
             _ => {
                 panic!("expression not implemented");
@@ -229,18 +227,18 @@ impl<'a> Contract<'a> {
         }
     }
 
-    fn emit_constructor_dispatch(&self, contract: &resolver::Contract, builder: &Builder) {
+    fn emit_constructor_dispatch(&self, contract: &resolver::Contract) {
         // create start function
         let ret = self.context.void_type();
         let ftype = ret.fn_type(&[self.context.i32_type().ptr_type(AddressSpace::Generic).into()], false);
         let function = self.module.add_function("constructor", ftype, None);
 
-        let entry = self.context.append_basic_block(&function, "entry");
+        let entry = self.context.append_basic_block(function, "entry");
 
-        builder.position_at_end(&entry);
+        self.builder.position_at_end(&entry);
 
         // init our heap
-        builder.build_call(
+        self.builder.build_call(
             self.module.get_function("__init_heap").unwrap(),
             &[],
             "");
@@ -249,84 +247,83 @@ impl<'a> Contract<'a> {
             let mut args = Vec::new();
 
             let arg = function.get_first_param().unwrap().into_pointer_value();
-            let length = builder.build_load(arg, "length");
+            let length = self.builder.build_load(arg, "length");
 
             // step over length
             let args_ptr = unsafe {
-                builder.build_gep(arg,
+                self.builder.build_gep(arg,
                     &[self.context.i32_type().const_int(1, false).into()],
                     "args_ptr")
             };
 
             // insert abi decode
             self.emit_abi_decode(
-                builder,
-                &function,
+                function,
                 &mut args,
                 args_ptr,
                 length.into_int_value(),
                 &contract.functions[n],
             );
 
-            builder.build_call(self.functions[n].value_ref, &args, "");
+            self.builder.build_call(self.functions[n].value_ref, &args, "");
         }
 
-        builder.build_return(None);
+        self.builder.build_return(None);
     }
 
-    fn emit_function_dispatch(&self, contract: &resolver::Contract, builder: &Builder) {
+    fn emit_function_dispatch(&self, contract: &resolver::Contract) {
         // create start function
         let ret = self.context.i32_type().ptr_type(AddressSpace::Generic);
         let ftype = ret.fn_type(&[self.context.i32_type().ptr_type(AddressSpace::Generic).into()], false);
         let function = self.module.add_function("function", ftype, None);
 
-        let entry = self.context.append_basic_block(&function, "entry");
-        let fallback = self.context.append_basic_block(&function, "fallback");
-        let switch = self.context.append_basic_block(&function, "switch");
+        let entry = self.context.append_basic_block(function, "entry");
+        let fallback = self.context.append_basic_block(function, "fallback");
+        let switch = self.context.append_basic_block(function, "switch");
 
-        builder.position_at_end(&entry);
+        self.builder.position_at_end(&entry);
 
         let arg = function.get_first_param().unwrap().into_pointer_value();
-        let length = builder.build_load(arg, "length").into_int_value();
+        let length = self.builder.build_load(arg, "length").into_int_value();
 
-        let not_fallback = builder.build_int_compare(
+        let not_fallback = self.builder.build_int_compare(
             IntPredicate::UGE,
             length,
             self.context.i32_type().const_int(4, false).into(),
             "");
 
-        builder.build_conditional_branch(not_fallback, &switch, &fallback);
+        self.builder.build_conditional_branch(not_fallback, &switch, &fallback);
 
-        builder.position_at_end(&switch);
+        self.builder.position_at_end(&switch);
 
         let fid_ptr = unsafe {
-            builder.build_gep(
+            self.builder.build_gep(
                 arg,
                 &[self.context.i32_type().const_int(1, false).into()],
                 "fid_ptr")
         };
 
-        let fid = builder.build_load(fid_ptr, "fid");
+        let fid = self.builder.build_load(fid_ptr, "fid");
 
         // pointer/size for abi decoding
         let args_ptr = unsafe {
-            builder.build_gep(
+            self.builder.build_gep(
                 arg,
                 &[self.context.i32_type().const_int(2, false).into()],
                 "fid_ptr")
         };
 
-        let args_len = builder.build_int_sub(
+        let args_len = self.builder.build_int_sub(
             length.into(),
             self.context.i32_type().const_int(4, false).into(),
             "args_len"
         );
 
-        let nomatch = self.context.append_basic_block(&function, "nomatch");
+        let nomatch = self.context.append_basic_block(function, "nomatch");
 
-        builder.position_at_end(&nomatch);
+        self.builder.position_at_end(&nomatch);
 
-        builder.build_unreachable();
+        self.builder.build_unreachable();
 
         let mut cases = Vec::new();
 
@@ -345,17 +342,17 @@ impl<'a> Contract<'a> {
 
             let res = keccak256(f.sig.as_bytes());
 
-            let bb = self.context.append_basic_block(&function, "");
+            let bb = self.context.append_basic_block(function, "");
             let id = u32::from_le_bytes([res[0], res[1], res[2], res[3]]);
 
-            builder.position_at_end(&bb);
+            self.builder.position_at_end(&bb);
 
             let mut args = Vec::new();
 
             // insert abi decode
-            self.emit_abi_decode(builder, &function, &mut args, args_ptr, args_len, f);
+            self.emit_abi_decode(function, &mut args, args_ptr, args_len, f);
 
-            let ret = builder.build_call(
+            let ret = self.builder.build_call(
                 self.functions[i].value_ref,
                 &args,
                 "").try_as_basic_value().left();
@@ -364,37 +361,37 @@ impl<'a> Contract<'a> {
                 // return ABI of length 0
 
                 // malloc 4 bytes
-                let dest = builder.build_call(
+                let dest = self.builder.build_call(
                     self.module.get_function("__malloc").unwrap(),
                     &[self.context.i32_type().const_int(4, false).into()],
                     ""
                 ).try_as_basic_value().left().unwrap().into_pointer_value();
 
-                builder.build_store(
-                    builder.build_pointer_cast(dest,
+                self.builder.build_store(
+                    self.builder.build_pointer_cast(dest,
                         self.context.i32_type().ptr_type(AddressSpace::Generic),
                         ""),
                     self.context.i32_type().const_zero());
 
-                builder.build_return(Some(&dest));
+                self.builder.build_return(Some(&dest));
             } else if self.functions[i].wasm_return {
                 // malloc 36 bytes
-                let dest = builder.build_call(
+                let dest = self.builder.build_call(
                     self.module.get_function("__malloc").unwrap(),
                     &[self.context.i32_type().const_int(36, false).into()],
                     ""
                 ).try_as_basic_value().left().unwrap().into_pointer_value();
 
                 // write length
-                builder.build_store(
-                    builder.build_pointer_cast(dest,
+                self.builder.build_store(
+                    self.builder.build_pointer_cast(dest,
                         self.context.i32_type().ptr_type(AddressSpace::Generic),
                         ""),
                     self.context.i32_type().const_int(32, false));
 
                 // malloc returns u8*
                 let abi_ptr = unsafe {
-                    builder.build_gep(
+                    self.builder.build_gep(
                         dest,
                         &[ self.context.i32_type().const_int(4, false).into()],
                         "abi_ptr")
@@ -407,9 +404,9 @@ impl<'a> Contract<'a> {
                     resolver::TypeName::Noreturn => unreachable!(),
                 };
 
-                self.emit_abi_encode_single_val(builder, &ty, abi_ptr, ret.unwrap().into_int_value());
+                self.emit_abi_encode_single_val(&ty, abi_ptr, ret.unwrap().into_int_value());
 
-                builder.build_return(Some(&dest));
+                self.builder.build_return(Some(&dest));
             } else {
                 // FIXME: abi encode all the arguments
             }
@@ -417,7 +414,7 @@ impl<'a> Contract<'a> {
             cases.push((self.context.i32_type().const_int(id as u64, false), bb));
         }
 
-        builder.position_at_end(&switch);
+        self.builder.position_at_end(&switch);
 
         let mut c = Vec::new();
 
@@ -427,33 +424,32 @@ impl<'a> Contract<'a> {
 
         //let c = cases.into_iter().map(|(id, bb)| (id, &bb)).collect();
 
-        builder.build_switch(
+        self.builder.build_switch(
             fid.into_int_value(), &nomatch,
             &c);
 
         // FIXME: emit code for public contract variables
 
         // emit fallback code
-        builder.position_at_end(&fallback);
+        self.builder.position_at_end(&fallback);
 
         match contract.fallback_function() {
             Some(n) => {
-                builder.build_call(
+                self.builder.build_call(
                     self.functions[n].value_ref,
                     &[],
                     "");
 
-                builder.build_return(None);
+                self.builder.build_return(None);
             }
             None => {
-                builder.build_unreachable();
+                self.builder.build_unreachable();
             },
         }
     }
 
     fn emit_abi_encode_single_val(
         &self,
-        builder: &Builder,
         ty: &ast::ElementaryTypeName,
         dest: PointerValue,
         val: IntValue,
@@ -461,36 +457,36 @@ impl<'a> Contract<'a> {
         match ty {
             ast::ElementaryTypeName::Bool => {
                 // first clear
-                let dest8 = builder.build_pointer_cast(dest,
+                let dest8 = self.builder.build_pointer_cast(dest,
                     self.context.i8_type().ptr_type(AddressSpace::Generic),
                     "destvoid");
 
-                builder.build_call(
+                self.builder.build_call(
                     self.module.get_function("__bzero8").unwrap(),
                     &[ dest8.into(),
                        self.context.i32_type().const_int(4, false).into() ],
                     "");
 
-                let value = builder.build_select(val,
+                let value = self.builder.build_select(val,
                     self.context.i8_type().const_int(1, false),
                     self.context.i8_type().const_zero(),
                     "bool_val");
 
                 let dest = unsafe {
-                    builder.build_gep(
+                    self.builder.build_gep(
                         dest8,
                         &[ self.context.i32_type().const_int(31, false).into() ],
                         "")
                 };
 
-                builder.build_store(dest, value);
+                self.builder.build_store(dest, value);
             }
             ast::ElementaryTypeName::Int(8) | ast::ElementaryTypeName::Uint(8) => {
                 let signval = if let ast::ElementaryTypeName::Int(8) = ty {
-                    let negative = builder.build_int_compare(IntPredicate::SLT,
+                    let negative = self.builder.build_int_compare(IntPredicate::SLT,
                             val, self.context.i8_type().const_zero(), "neg");
 
-                    builder.build_select(negative,
+                            self.builder.build_select(negative,
                         self.context.i64_type().const_zero(),
                         self.context.i64_type().const_int(std::u64::MAX, true),
                         "val").into_int_value()
@@ -498,33 +494,33 @@ impl<'a> Contract<'a> {
                     self.context.i64_type().const_zero()
                 };
 
-                let dest8 = builder.build_pointer_cast(dest,
+                let dest8 = self.builder.build_pointer_cast(dest,
                     self.context.i8_type().ptr_type(AddressSpace::Generic),
                     "destvoid");
 
-                builder.build_call(
+                    self.builder.build_call(
                     self.module.get_function("__memset8").unwrap(),
                     &[ dest8.into(), signval.into(),
                        self.context.i32_type().const_int(4, false).into() ],
                     "");
 
                 let dest = unsafe {
-                    builder.build_gep(
+                    self.builder.build_gep(
                         dest8,
                         &[ self.context.i32_type().const_int(31, false).into() ],
                         "")
                 };
 
-                builder.build_store(dest, val);
+                self.builder.build_store(dest, val);
             }
             ast::ElementaryTypeName::Uint(n) | ast::ElementaryTypeName::Int(n) => {
                 // first clear/set the upper bits
                 if *n < 256 {
                     let signval = if let ast::ElementaryTypeName::Int(8) = ty {
-                        let negative = builder.build_int_compare(IntPredicate::SLT,
+                        let negative = self.builder.build_int_compare(IntPredicate::SLT,
                                 val, self.context.i8_type().const_zero(), "neg");
 
-                        builder.build_select(negative,
+                        self.builder.build_select(negative,
                             self.context.i64_type().const_zero(),
                             self.context.i64_type().const_int(std::u64::MAX, true),
                             "val").into_int_value()
@@ -532,11 +528,11 @@ impl<'a> Contract<'a> {
                         self.context.i64_type().const_zero()
                     };
 
-                    let dest8 = builder.build_pointer_cast(dest,
+                    let dest8 = self.builder.build_pointer_cast(dest,
                         self.context.i8_type().ptr_type(AddressSpace::Generic),
                         "destvoid");
 
-                    builder.build_call(
+                    self.builder.build_call(
                         self.module.get_function("__memset8").unwrap(),
                         &[ dest8.into(), signval.into(),
                             self.context.i32_type().const_int(4, false).into() ],
@@ -548,19 +544,19 @@ impl<'a> Contract<'a> {
                 let int_type = self.context.custom_width_int_type(*n as u32);
                 let type_size = int_type.size_of();
 
-                let store = builder.build_alloca(int_type, "stack");
+                let store = self.builder.build_alloca(int_type, "stack");
 
-                builder.build_store(store, val);
+                self.builder.build_store(store, val);
 
-                builder.build_call(
+                self.builder.build_call(
                     self.module.get_function("__leNtobe32").unwrap(),
-                    &[ builder.build_pointer_cast(store,
+                    &[ self.builder.build_pointer_cast(store,
                             self.context.i8_type().ptr_type(AddressSpace::Generic),
                             "destvoid").into(),
-                       builder.build_pointer_cast(dest,
+                        self.builder.build_pointer_cast(dest,
                             self.context.i8_type().ptr_type(AddressSpace::Generic),
                             "destvoid").into(),
-                        builder.build_int_truncate(type_size,
+                        self.builder.build_int_truncate(type_size,
                             self.context.i32_type(), "").into()
                     ],
                     "");
@@ -571,10 +567,9 @@ impl<'a> Contract<'a> {
 
     fn emit_abi_decode(
         &self,
-        builder: &Builder,
-        function: &FunctionValue,
-        args: &mut Vec<BasicValueEnum>,
-        data: PointerValue,
+        function: FunctionValue,
+        args: &mut Vec<BasicValueEnum<'a>>,
+        data: PointerValue<'a>,
         length: IntValue,
         spec: &resolver::FunctionDecl,
     ) {
@@ -582,13 +577,13 @@ impl<'a> Contract<'a> {
         let decode_block = self.context.append_basic_block(function, "abi_decode");
         let wrong_length_block = self.context.append_basic_block(function, "wrong_abi_length");
 
-        let is_ok = builder.build_int_compare(IntPredicate::EQ, length,
+        let is_ok = self.builder.build_int_compare(IntPredicate::EQ, length,
             self.context.i32_type().const_int(32  * spec.params.len() as u64, false),
             "correct_length");
 
-        builder.build_conditional_branch(is_ok, &decode_block, &wrong_length_block);
+        self.builder.build_conditional_branch(is_ok, &decode_block, &wrong_length_block);
 
-        builder.position_at_end(&decode_block);
+        self.builder.position_at_end(&decode_block);
 
         for arg in &spec.params {
             let ty = match &arg.ty {
@@ -602,52 +597,52 @@ impl<'a> Contract<'a> {
                     // solidity checks all the 32 bytes for being non-zero; we will just look at the upper 8 bytes, else we would need four loads
                     // which is unneeded (hopefully)
                     // cast to 64 bit pointer
-                    let bool_ptr = builder.build_pointer_cast(data,
+                    let bool_ptr = self.builder.build_pointer_cast(data,
                         self.context.i64_type().ptr_type(AddressSpace::Generic), "");
 
                     let bool_ptr = unsafe {
-                        builder.build_gep(bool_ptr,
+                        self.builder.build_gep(bool_ptr,
                             &[ self.context.i32_type().const_int(3, false) ],
                             "bool_ptr")
                     };
 
-                    builder.build_int_compare(IntPredicate::EQ,
-                        builder.build_load(bool_ptr, "abi_bool").into_int_value(),
+                    self.builder.build_int_compare(IntPredicate::EQ,
+                        self.builder.build_load(bool_ptr, "abi_bool").into_int_value(),
                         self.context.i64_type().const_zero(), "bool").into()
                 }
                 ast::ElementaryTypeName::Uint(8) | ast::ElementaryTypeName::Int(8) => {
-                    let int8_ptr = builder.build_pointer_cast(data,
+                    let int8_ptr = self.builder.build_pointer_cast(data,
                         self.context.i8_type().ptr_type(AddressSpace::Generic), "");
 
                     let int8_ptr = unsafe {
-                        builder.build_gep(int8_ptr,
+                        self.builder.build_gep(int8_ptr,
                         &[ self.context.i32_type().const_int(31, false) ],
                         "bool_ptr")
                     };
 
-                    builder.build_load(int8_ptr, "abi_int8")
+                    self.builder.build_load(int8_ptr, "abi_int8")
                 }
                 ast::ElementaryTypeName::Uint(n) | ast::ElementaryTypeName::Int(n) => {
                     let int_type = self.context.custom_width_int_type(*n as u32);
                     let type_size = int_type.size_of();
 
-                    let store = builder.build_alloca(int_type, "stack");
+                    let store = self.builder.build_alloca(int_type, "stack");
 
-                    builder.build_call(
+                    self.builder.build_call(
                         self.module.get_function("__be32toleN").unwrap(),
                         &[
-                            builder.build_pointer_cast(data,
+                            self.builder.build_pointer_cast(data,
                                 self.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                            builder.build_pointer_cast(store,
+                            self.builder.build_pointer_cast(store,
                                 self.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                            builder.build_int_truncate(type_size,
+                            self.builder.build_int_truncate(type_size,
                                 self.context.i32_type(), "size").into()
                         ],
                         ""
                     );
 
                     if *n <= 64 {
-                        builder.build_load(store, &format!("abi_int{}", *n))
+                        self.builder.build_load(store, &format!("abi_int{}", *n))
                     } else {
                         store.into()
                     }
@@ -656,20 +651,20 @@ impl<'a> Contract<'a> {
             });
 
             data = unsafe {
-                builder.build_gep(data,
+                self.builder.build_gep(data,
                     &[ self.context.i32_type().const_int(8, false)],
                     "data_next")
             };
         }
 
         // FIXME: generate a call to revert/abort with some human readable error or error code
-        builder.position_at_end(&wrong_length_block);
-        builder.build_unreachable();
+        self.builder.position_at_end(&wrong_length_block);
+        self.builder.build_unreachable();
 
-        builder.position_at_end(&decode_block);
+        self.builder.position_at_end(&decode_block);
     }
 
-    fn emit_func(&self, f: &resolver::FunctionDecl, builder: &Builder) -> Function {
+    fn emit_func(&mut self, f: &resolver::FunctionDecl) {
         let mut args: Vec<BasicTypeEnum> = Vec::new();
         let mut wasm_return = false;
 
@@ -682,6 +677,8 @@ impl<'a> Contract<'a> {
             });
         }
 
+        // FIXME: Substrate can have multiple overloaded constructors
+        // FIXME: Solidity can have multiple overloaded functions by the same name
         let fname = if f.constructor {
             "sol::__constructor".to_string()
         } else if let Some(ref name) = f.name {
@@ -694,7 +691,7 @@ impl<'a> Contract<'a> {
             wasm_return = true;
             f.returns[0].ty.LLVMType(self.ns, &self.context).fn_type(&args, false)
         } else {
-            // add return
+            // add return values
             for p in &f.returns {
                 args.push(p.ty.LLVMType(self.ns, &self.context).ptr_type(AddressSpace::Generic).into());
             }
@@ -709,14 +706,14 @@ impl<'a> Contract<'a> {
         };
 
         // recurse through basic blocks
-        struct BasicBlock {
+        struct BasicBlock<'a> {
             bb: inkwell::basic_block::BasicBlock,
-            phis: HashMap<usize, PhiValue>,
+            phis: HashMap<usize, PhiValue<'a>>,
         }
 
-        struct Work {
+        struct Work<'b> {
             bb_no: usize,
-            vars: Vec<Variable>,
+            vars: Vec<Variable<'b>>,
         }
 
         let mut blocks: HashMap<usize, BasicBlock> = HashMap::new();
@@ -725,16 +722,16 @@ impl<'a> Contract<'a> {
             let cfg_bb: &cfg::BasicBlock = &cfg.bb[bb_no];
             let mut phis = HashMap::new();
 
-            let bb = self.context.append_basic_block(&function, &cfg_bb.name);
+            let bb = self.context.append_basic_block(function, &cfg_bb.name);
 
-            builder.position_at_end(&bb);
+            self.builder.position_at_end(&bb);
 
             if let Some(ref cfg_phis) = cfg_bb.phis {
                 for v in cfg_phis {
                     // FIXME: no phis needed for stack based vars
                     let ty = cfg.vars[*v].ty.LLVMType(self.ns, &self.context);
 
-                    phis.insert(*v, builder.build_phi(ty, &cfg.vars[*v].id.name).into());
+                    phis.insert(*v, self.builder.build_phi(ty, &cfg.vars[*v].id.name).into());
                 }
             }
 
@@ -758,7 +755,7 @@ impl<'a> Contract<'a> {
                 }
                 cfg::Storage::Local | cfg::Storage::Contract(_) => {
                     vars.push(Variable {
-                        value: builder.build_alloca(
+                        value: self.builder.build_alloca(
                             v.ty.LLVMType(self.ns, &self.context), &v.id.name).into(),
                         stack: true,
                     });
@@ -784,7 +781,7 @@ impl<'a> Contract<'a> {
             let ll_bb = {
                 let bb = blocks.get(&w.bb_no).unwrap();
 
-                builder.position_at_end(&bb.bb);
+                self.builder.position_at_end(&bb.bb);
 
                 for (v, phi) in bb.phis.iter() {
                     w.vars[*v].value = (*phi).as_basic_value();
@@ -799,26 +796,26 @@ impl<'a> Contract<'a> {
                         w.vars[*res].value = function.get_nth_param(*arg as u32).unwrap().into();
                     }
                     cfg::Instr::Return { value } if value.is_empty() => {
-                        builder.build_return(None);
+                        self.builder.build_return(None);
                     },
                     cfg::Instr::Return { value } if wasm_return => {
-                        let retval = self.expression(builder, &value[0], &w.vars);
-                        builder.build_return(Some(&retval));
+                        let retval = self.expression(&value[0], &w.vars);
+                        self.builder.build_return(Some(&retval));
                     }
                     cfg::Instr::Return { value } => {
                         let returns_offset = f.params.len();
                         for (i, val) in value.iter().enumerate() {
                             let arg = function.get_nth_param((returns_offset + i) as u32).unwrap();
-                            let retval = self.expression(builder, val, &w.vars);
+                            let retval = self.expression(val, &w.vars);
 
-                            builder.build_store(arg.into_pointer_value(), retval);
+                            self.builder.build_store(arg.into_pointer_value(), retval);
                         }
-                        builder.build_return(None);
+                        self.builder.build_return(None);
                     }
                     cfg::Instr::Set { res, expr } => {
-                        let value_ref = self.expression(builder, expr, &w.vars);
+                        let value_ref = self.expression(expr, &w.vars);
                         if w.vars[*res].stack {
-                            builder.build_store(w.vars[*res].value.into_pointer_value(), value_ref);
+                            self.builder.build_store(w.vars[*res].value.into_pointer_value(), value_ref);
                         } else {
                             w.vars[*res].value = value_ref.into();
                         }
@@ -838,15 +835,15 @@ impl<'a> Contract<'a> {
                             phi.add_incoming(&[ (&w.vars[*v].value, &ll_bb) ]);
                         }
 
-                        builder.position_at_end(&ll_bb);
-                        builder.build_unconditional_branch(&bb.bb);
+                        self.builder.position_at_end(&ll_bb);
+                        self.builder.build_unconditional_branch(&bb.bb);
                     }
                     cfg::Instr::BranchCond {
                         cond,
                         true_,
                         false_,
                     } => {
-                        let cond = self.expression(builder, cond, &w.vars);
+                        let cond = self.expression(cond, &w.vars);
 
                         let bb_true = {
                             if !blocks.contains_key(&true_) {
@@ -884,17 +881,17 @@ impl<'a> Contract<'a> {
                             bb.bb
                         };
 
-                        builder.position_at_end(&ll_bb);
-                        builder.build_conditional_branch(cond, &bb_true, &bb_false);
+                        self.builder.position_at_end(&ll_bb);
+                        self.builder.build_conditional_branch(cond, &bb_true, &bb_false);
                     }
                     cfg::Instr::GetStorage { local, storage } => {
                         let dest = w.vars[*local].value.into_pointer_value();
 
-                        builder.build_call(
+                        self.builder.build_call(
                             self.externals["get_storage32"],
                             &[
                                 self.context.i32_type().const_int(*storage as u64, false).into(),
-                                builder.build_pointer_cast(dest,
+                                self.builder.build_pointer_cast(dest,
                                     self.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
                                 dest.get_type().size_of().const_cast(
                                     self.context.i32_type(), false).into()
@@ -904,11 +901,11 @@ impl<'a> Contract<'a> {
                     cfg::Instr::SetStorage { local, storage } => {
                         let dest = w.vars[*local].value.into_pointer_value();
 
-                        builder.build_call(
+                        self.builder.build_call(
                             self.externals["set_storage32"],
                             &[
                                 self.context.i32_type().const_int(*storage as u64, false).into(),
-                                builder.build_pointer_cast(dest,
+                                self.builder.build_pointer_cast(dest,
                                     self.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
                                 dest.get_type().size_of().const_cast(
                                     self.context.i32_type(), false).into()
@@ -919,10 +916,10 @@ impl<'a> Contract<'a> {
                         let mut parms: Vec<BasicValueEnum> = Vec::new();
 
                         for a in args {
-                            parms.push(self.expression(builder, &a, &w.vars).into());
+                            parms.push(self.expression(&a, &w.vars).into());
                         }
 
-                        let ret = builder.build_call(
+                        let ret = self.builder.build_call(
                             self.functions[*func].value_ref,
                             &parms, "").try_as_basic_value().left().unwrap();
 
@@ -934,16 +931,16 @@ impl<'a> Contract<'a> {
             }
         }
 
-        Function {
+        self.functions.push(Function {
             value_ref: function,
             wasm_return,
-        }
+        });
     }
 }
 
 impl ast::ElementaryTypeName {
     #[allow(non_snake_case)]
-    fn LLVMType(&self, context: &Context) -> IntType {
+    fn LLVMType<'a>(&self, context: &'a Context) -> IntType<'a> {
         match self {
             ast::ElementaryTypeName::Bool => context.bool_type(),
             ast::ElementaryTypeName::Int(n) |
@@ -970,7 +967,7 @@ impl ast::ElementaryTypeName {
 
 impl resolver::TypeName {
     #[allow(non_snake_case)]
-    fn LLVMType(&self, ns: &resolver::Contract, context: &Context) -> IntType {
+    fn LLVMType<'a>(&self, ns: &resolver::Contract, context: &'a Context) -> IntType<'a> {
         match self {
             resolver::TypeName::Elementary(e) => e.LLVMType(context),
             resolver::TypeName::Enum(n) => ns.enums[*n].ty.LLVMType(context),
@@ -987,10 +984,10 @@ impl resolver::TypeName {
     }
 }
 
-static STDLIB_IR: &'static [u8] = include_bytes!("../stdlib/stdlib.bc");
+static STDLIB_IR: &'static [u8] = include_bytes!("../../stdlib/stdlib.bc");
 
 fn load_stdlib(context: &Context) -> Module {
     let memory = MemoryBuffer::create_from_memory_range(STDLIB_IR, "stdlib");
 
-    Module::parse_bitcode_from_buffer_in_context(&memory, context).unwrap()
+    Module::parse_bitcode_from_buffer(&memory, context).unwrap()
 }

+ 3 - 4
src/main.rs

@@ -14,14 +14,11 @@ extern crate wasmi;
 extern crate inkwell;
 
 use clap::{App, Arg};
-mod ast;
-mod cfg;
 mod emit;
 mod link;
 mod output;
 mod parser;
 mod resolver;
-mod solidity;
 mod test;
 
 use serde::Serialize;
@@ -104,6 +101,8 @@ fn main() {
             .join(format!("{}.{}", stem, ext))
     };
 
+    let context = inkwell::context::Context::create();
+
     for filename in matches.values_of("INPUT").unwrap() {
         let mut f = File::open(&filename).expect("file not found");
 
@@ -155,7 +154,7 @@ fn main() {
 
             let abi = contract.generate_abi();
 
-            let contract = emit::Contract::new(contract, &filename);
+            let contract = emit::Contract::new(&context, contract, &filename);
 
             if let Some("llvm") = matches.value_of("EMIT") {
                 contract.dump_llvm(&output_file(&contract.name, "ll")).unwrap();

+ 1 - 1
src/output.rs

@@ -1,4 +1,4 @@
-use ast;
+use parser::ast;
 use serde::Serialize;
 
 #[derive(Debug, PartialEq)]

+ 1 - 1
src/ast.rs → src/parser/ast.rs

@@ -378,7 +378,7 @@ impl Statement {
 #[cfg(test)]
 mod test {
     use super::*;
-    use solidity;
+    use parser::solidity;
 
     #[test]
     fn parse_test() {

+ 3 - 2
src/parser.rs → src/parser/mod.rs

@@ -1,7 +1,8 @@
-use ast;
+pub mod ast;
+pub mod solidity;
+
 use lalrpop_util::ParseError;
 use output::Output;
-use solidity;
 
 pub fn parse(src: &str) -> Result<ast::SourceUnit, Vec<Output>> {
     // parse phase

+ 1 - 1
src/solidity.lalrpop → src/parser/solidity.lalrpop

@@ -1,7 +1,7 @@
 
 use std::str::FromStr;
 use num_bigint::BigInt;
-use ast::*;
+use parser::ast::*;
 use parser::box_option;
 
 grammar;

+ 4 - 4
src/solidity.rs → src/parser/solidity.rs

@@ -1,8 +1,8 @@
 // auto-generated: "lalrpop 0.17.2"
-// sha256: 6a92124102d652ea5457ffc7778167a483e5faf6f31173b86d87c672a8e5d52
+// sha256: 3256a684bd7eca0e6bbe52cc37391c66fda8cdcf19a55c4b75d50c43e1d17f6
 use std::str::FromStr;
 use num_bigint::BigInt;
-use ast::*;
+use parser::ast::*;
 use parser::box_option;
 #[allow(unused_extern_crates)]
 extern crate lalrpop_util as __lalrpop_util;
@@ -15,7 +15,7 @@ mod __parse__SourceUnit {
 
     use std::str::FromStr;
     use num_bigint::BigInt;
-    use ast::*;
+    use parser::ast::*;
     use parser::box_option;
     #[allow(unused_extern_crates)]
     extern crate lalrpop_util as __lalrpop_util;
@@ -15237,7 +15237,7 @@ mod __intern_token {
     #![allow(unused_imports)]
     use std::str::FromStr;
     use num_bigint::BigInt;
-    use ast::*;
+    use parser::ast::*;
     use parser::box_option;
     #[allow(unused_extern_crates)]
     extern crate lalrpop_util as __lalrpop_util;

+ 1 - 1
src/cfg.rs → src/resolver/cfg.rs

@@ -7,7 +7,7 @@ use std::collections::HashSet;
 use std::collections::LinkedList;
 use unescape::unescape;
 
-use ast;
+use parser::ast;
 use hex;
 use output;
 use output::Output;

+ 3 - 2
src/resolver/mod.rs

@@ -1,10 +1,11 @@
 
-use ast;
-use cfg;
+use parser::ast;
 use output::{Note, Output};
 use serde::Serialize;
 use std::collections::HashMap;
 
+pub mod cfg;
+
 #[derive(Serialize)]
 pub struct ABIParam {
     pub name: String,

+ 20 - 8
src/test.rs

@@ -87,7 +87,7 @@ mod tests {
         }
     }
 
-    fn build_solidity(src: &'static str) -> (ModuleRef, ContractStorage, String) {
+    fn build_solidity(ctx: &inkwell::context::Context, src: &'static str) -> (ModuleRef, ContractStorage, String) {
         let s = parser::parse(src).expect("parse should succeed");
 
         // resolve
@@ -103,7 +103,7 @@ mod tests {
         let abi = contracts[0].generate_abi();
 
         // codegen
-        let contract = emit::Contract::new(&contracts[0], &"foo.sol");
+        let contract = emit::Contract::new(ctx, &contracts[0], &"foo.sol");
 
         let obj = contract.wasm("default").expect("llvm wasm emit should work");
 
@@ -125,8 +125,10 @@ mod tests {
 
     #[test]
     fn simple_solidiy_compile_and_run() {
+        let ctx = inkwell::context::Context::create();
+
         // parse
-        let (main, _, _) = build_solidity(
+        let (main, _, _) = build_solidity(&ctx,
             "
             contract test {
                 function foo() public returns (uint32) {
@@ -144,7 +146,9 @@ mod tests {
 
     #[test]
     fn simple_loops() {
-        let (main, _, _) = build_solidity(
+        let ctx = inkwell::context::Context::create();
+
+        let (main, _, _) = build_solidity(&ctx,
             r##"
 contract test3 {
 	function foo(uint32 a) public returns (uint32) {
@@ -250,7 +254,9 @@ contract test3 {
 
     #[test]
     fn stack_test() {
-        let (main, _, _) = build_solidity(
+        let ctx = inkwell::context::Context::create();
+
+        let (main, _, _) = build_solidity(&ctx,
             r##"
 contract test3 {
 	function foo() public returns (bool) {
@@ -271,7 +277,9 @@ contract test3 {
 
     #[test]
     fn abi_call_return_test() {
-        let (wasm, store, abi) = build_solidity(
+        let ctx = inkwell::context::Context::create();
+
+        let (wasm, store, abi) = build_solidity(&ctx,
             r##"
 contract test {
 	function foo() public returns (uint32) {
@@ -320,7 +328,9 @@ contract test {
 
     #[test]
     fn abi_call_pass_return_test() {
-        let (wasm, store, abi) = build_solidity(
+        let ctx = inkwell::context::Context::create();
+
+        let (wasm, store, abi) = build_solidity(&ctx,
             r##"
 contract test {
 	function foo(uint32 a) public returns (uint32) {
@@ -370,7 +380,9 @@ contract test {
 
     #[test]
     fn contract_storage_test() {
-        let (wasm, mut store, abi) = build_solidity(
+        let ctx = inkwell::context::Context::create();
+
+        let (wasm, mut store, abi) = build_solidity(&ctx,
             r##"
 contract test {
     uint32 foo;

二進制
stdlib/stdlib.bc


+ 1 - 1
stdlib/stdlib.c

@@ -1,4 +1,4 @@
-// clang --target=wasm32 -c -emit-llvm -O3 -fno-builtin -Wall stdlib.c
+// clang --target=wasm32 -c -emit-llvm -O3 -ffreestanding -fno-builtin -Wall stdlib.c
 #include <stdint.h>
 #include <stddef.h>
 #include <stdbool.h>