Browse Source

Load stdlib only once (#838)

Signed-off-by: Lucas Steuernagel <lucas.tnagel@gmail.com>
Lucas Steuernagel 3 years ago
parent
commit
83e78b1522

+ 26 - 19
src/emit/binary.rs

@@ -62,20 +62,29 @@ impl<'a> Binary<'a> {
         opt: OptimizationLevel,
         opt: OptimizationLevel,
         math_overflow_check: bool,
         math_overflow_check: bool,
     ) -> Self {
     ) -> Self {
+        let std_lib = load_stdlib(context, &ns.target);
         match ns.target {
         match ns.target {
             Target::Substrate { .. } => substrate::SubstrateTarget::build(
             Target::Substrate { .. } => substrate::SubstrateTarget::build(
                 context,
                 context,
+                &std_lib,
+                contract,
+                ns,
+                filename,
+                opt,
+                math_overflow_check,
+            ),
+            Target::Ewasm => ewasm::EwasmTarget::build(
+                context,
+                &std_lib,
                 contract,
                 contract,
                 ns,
                 ns,
                 filename,
                 filename,
                 opt,
                 opt,
                 math_overflow_check,
                 math_overflow_check,
             ),
             ),
-            Target::Ewasm => {
-                ewasm::EwasmTarget::build(context, contract, ns, filename, opt, math_overflow_check)
-            }
             Target::Solana => solana::SolanaTarget::build(
             Target::Solana => solana::SolanaTarget::build(
                 context,
                 context,
+                &std_lib,
                 contract,
                 contract,
                 ns,
                 ns,
                 filename,
                 filename,
@@ -95,7 +104,15 @@ impl<'a> Binary<'a> {
     ) -> Self {
     ) -> Self {
         assert!(namespaces.iter().all(|ns| ns.target == Target::Solana));
         assert!(namespaces.iter().all(|ns| ns.target == Target::Solana));
 
 
-        solana::SolanaTarget::build_bundle(context, namespaces, filename, opt, math_overflow_check)
+        let std_lib = load_stdlib(context, &Target::Solana);
+        solana::SolanaTarget::build_bundle(
+            context,
+            &std_lib,
+            namespaces,
+            filename,
+            opt,
+            math_overflow_check,
+        )
     }
     }
 
 
     /// Compile the bin and return the code as bytes. The result is
     /// Compile the bin and return the code as bytes. The result is
@@ -228,6 +245,7 @@ impl<'a> Binary<'a> {
         filename: &str,
         filename: &str,
         opt: OptimizationLevel,
         opt: OptimizationLevel,
         math_overflow_check: bool,
         math_overflow_check: bool,
+        std_lib: &Module<'a>,
         runtime: Option<Box<Binary<'a>>>,
         runtime: Option<Box<Binary<'a>>>,
     ) -> Self {
     ) -> Self {
         LLVM_INIT.get_or_init(|| {
         LLVM_INIT.get_or_init(|| {
@@ -241,9 +259,7 @@ impl<'a> Binary<'a> {
         module.set_triple(&triple);
         module.set_triple(&triple);
         module.set_source_file_name(filename);
         module.set_source_file_name(filename);
 
 
-        // stdlib
-        let intr = load_stdlib(context, &target);
-        module.link_in_module(intr).unwrap();
+        module.link_in_module(std_lib.clone()).unwrap();
 
 
         let selector =
         let selector =
             module.add_global(context.i32_type(), Some(AddressSpace::Generic), "selector");
             module.add_global(context.i32_type(), Some(AddressSpace::Generic), "selector");
@@ -912,8 +928,7 @@ impl<'a> Binary<'a> {
             Some(s) => self.emit_global_string("const_string", s, true),
             Some(s) => self.emit_global_string("const_string", s, true),
         };
         };
 
 
-        let v = self
-            .builder
+        self.builder
             .build_call(
             .build_call(
                 self.module.get_function("vector_new").unwrap(),
                 self.module.get_function("vector_new").unwrap(),
                 &[size.into(), elem_size.into(), init.into()],
                 &[size.into(), elem_size.into(), init.into()],
@@ -921,16 +936,8 @@ impl<'a> Binary<'a> {
             )
             )
             .try_as_basic_value()
             .try_as_basic_value()
             .left()
             .left()
-            .unwrap();
-
-        self.builder.build_pointer_cast(
-            v.into_pointer_value(),
-            self.module
-                .get_struct_type("struct.vector")
-                .unwrap()
-                .ptr_type(AddressSpace::Generic),
-            "vector",
-        )
+            .unwrap()
+            .into_pointer_value()
     }
     }
 
 
     /// Number of element in a vector
     /// Number of element in a vector

+ 1 - 11
src/emit/ethabiencoder.rs

@@ -3076,21 +3076,11 @@ impl EthAbiDecoder {
                     .left()
                     .left()
                     .unwrap();
                     .unwrap();
 
 
-                let v = binary.builder.build_pointer_cast(
-                    v.into_pointer_value(),
-                    binary
-                        .module
-                        .get_struct_type("struct.vector")
-                        .unwrap()
-                        .ptr_type(AddressSpace::Generic),
-                    "string",
-                );
-
                 if let Some(to) = to {
                 if let Some(to) = to {
                     binary.builder.build_store(to, v);
                     binary.builder.build_store(to, v);
                 }
                 }
 
 
-                v.into()
+                v
             }
             }
             ast::Type::UserType(no) => self.decode_primitive(
             ast::Type::UserType(no) => self.decode_primitive(
                 binary,
                 binary,

+ 4 - 1
src/emit/ewasm.rs

@@ -8,7 +8,7 @@ use std::str;
 
 
 use inkwell::attributes::{Attribute, AttributeLoc};
 use inkwell::attributes::{Attribute, AttributeLoc};
 use inkwell::context::Context;
 use inkwell::context::Context;
-use inkwell::module::Linkage;
+use inkwell::module::{Linkage, Module};
 use inkwell::types::IntType;
 use inkwell::types::IntType;
 use inkwell::values::{
 use inkwell::values::{
     ArrayValue, BasicMetadataValueEnum, BasicValueEnum, FunctionValue, IntValue, PointerValue,
     ArrayValue, BasicMetadataValueEnum, BasicValueEnum, FunctionValue, IntValue, PointerValue,
@@ -28,6 +28,7 @@ pub struct EwasmTarget {
 impl EwasmTarget {
 impl EwasmTarget {
     pub fn build<'a>(
     pub fn build<'a>(
         context: &'a Context,
         context: &'a Context,
+        std_lib: &Module<'a>,
         contract: &'a ast::Contract,
         contract: &'a ast::Contract,
         ns: &'a ast::Namespace,
         ns: &'a ast::Namespace,
         filename: &'a str,
         filename: &'a str,
@@ -45,6 +46,7 @@ impl EwasmTarget {
             filename,
             filename,
             opt,
             opt,
             math_overflow_check,
             math_overflow_check,
+            std_lib,
             None,
             None,
         );
         );
 
 
@@ -74,6 +76,7 @@ impl EwasmTarget {
             filename,
             filename,
             opt,
             opt,
             math_overflow_check,
             math_overflow_check,
+            std_lib,
             Some(Box::new(runtime_code)),
             Some(Box::new(runtime_code)),
         );
         );
 
 

+ 7 - 52
src/emit/mod.rs

@@ -485,7 +485,7 @@ pub trait TargetRuntime<'a> {
                         "invalid",
                         "invalid",
                     );
                     );
 
 
-                    let v = bin
+                    let dest = bin
                         .builder
                         .builder
                         .build_call(
                         .build_call(
                             bin.module.get_function("vector_new").unwrap(),
                             bin.module.get_function("vector_new").unwrap(),
@@ -497,15 +497,6 @@ pub trait TargetRuntime<'a> {
                         .unwrap()
                         .unwrap()
                         .into_pointer_value();
                         .into_pointer_value();
 
 
-                    let dest = bin.builder.build_pointer_cast(
-                        v,
-                        bin.module
-                            .get_struct_type("struct.vector")
-                            .unwrap()
-                            .ptr_type(AddressSpace::Generic),
-                        "vector",
-                    );
-
                     // get the slot for the elements
                     // get the slot for the elements
                     // this hashes in-place
                     // this hashes in-place
                     self.keccak256_hash(
                     self.keccak256_hash(
@@ -1257,8 +1248,7 @@ pub trait TargetRuntime<'a> {
                     true,
                     true,
                 );
                 );
 
 
-                let v = bin
-                    .builder
+                bin.builder
                     .build_call(
                     .build_call(
                         bin.module.get_function("vector_new").unwrap(),
                         bin.module.get_function("vector_new").unwrap(),
                         &[size.into(), elem_size.into(), init.into()],
                         &[size.into(), elem_size.into(), init.into()],
@@ -1266,18 +1256,7 @@ pub trait TargetRuntime<'a> {
                     )
                     )
                     .try_as_basic_value()
                     .try_as_basic_value()
                     .left()
                     .left()
-                    .unwrap();
-
-                bin.builder
-                    .build_pointer_cast(
-                        v.into_pointer_value(),
-                        bin.module
-                            .get_struct_type("struct.vector")
-                            .unwrap()
-                            .ptr_type(AddressSpace::Generic),
-                        "vector",
-                    )
-                    .into()
+                    .unwrap()
             }
             }
             Expression::Add(_, _, unchecked, l, r) => {
             Expression::Add(_, _, unchecked, l, r) => {
                 let left = self
                 let left = self
@@ -2159,8 +2138,7 @@ pub trait TargetRuntime<'a> {
                     "",
                     "",
                 );
                 );
 
 
-                let v = bin
-                    .builder
+                bin.builder
                     .build_call(
                     .build_call(
                         bin.module.get_function("vector_new").unwrap(),
                         bin.module.get_function("vector_new").unwrap(),
                         &[size.into(), elem_size.into(), init.into()],
                         &[size.into(), elem_size.into(), init.into()],
@@ -2168,18 +2146,7 @@ pub trait TargetRuntime<'a> {
                     )
                     )
                     .try_as_basic_value()
                     .try_as_basic_value()
                     .left()
                     .left()
-                    .unwrap();
-
-                bin.builder
-                    .build_pointer_cast(
-                        v.into_pointer_value(),
-                        bin.module
-                            .get_struct_type("struct.vector")
-                            .unwrap()
-                            .ptr_type(AddressSpace::Generic),
-                        "vector",
-                    )
-                    .into()
+                    .unwrap()
             }
             }
             Expression::BytesCast(_, Type::DynamicBytes, Type::Bytes(n), e) => {
             Expression::BytesCast(_, Type::DynamicBytes, Type::Bytes(n), e) => {
                 let array = self.expression(bin, e, vartab, function, ns);
                 let array = self.expression(bin, e, vartab, function, ns);
@@ -2668,8 +2635,7 @@ pub trait TargetRuntime<'a> {
                 let (left, left_len) = self.string_location(bin, l, vartab, function, ns);
                 let (left, left_len) = self.string_location(bin, l, vartab, function, ns);
                 let (right, right_len) = self.string_location(bin, r, vartab, function, ns);
                 let (right, right_len) = self.string_location(bin, r, vartab, function, ns);
 
 
-                let v = bin
-                    .builder
+                bin.builder
                     .build_call(
                     .build_call(
                         bin.module.get_function("concat").unwrap(),
                         bin.module.get_function("concat").unwrap(),
                         &[left.into(), left_len.into(), right.into(), right_len.into()],
                         &[left.into(), left_len.into(), right.into(), right_len.into()],
@@ -2677,18 +2643,7 @@ pub trait TargetRuntime<'a> {
                     )
                     )
                     .try_as_basic_value()
                     .try_as_basic_value()
                     .left()
                     .left()
-                    .unwrap();
-
-                bin.builder
-                    .build_pointer_cast(
-                        v.into_pointer_value(),
-                        bin.module
-                            .get_struct_type("struct.vector")
-                            .unwrap()
-                            .ptr_type(AddressSpace::Generic),
-                        "vector",
-                    )
-                    .into()
+                    .unwrap()
             }
             }
             Expression::ReturnData(_) => self.return_data(bin, function).into(),
             Expression::ReturnData(_) => self.return_data(bin, function).into(),
             Expression::StorageArrayLength { array, elem_ty, .. } => {
             Expression::StorageArrayLength { array, elem_ty, .. } => {

+ 5 - 1
src/emit/solana.rs

@@ -5,7 +5,7 @@ use crate::{codegen, Target};
 use std::collections::HashMap;
 use std::collections::HashMap;
 use std::str;
 use std::str;
 
 
-use inkwell::module::Linkage;
+use inkwell::module::{Linkage, Module};
 use inkwell::types::{BasicType, IntType};
 use inkwell::types::{BasicType, IntType};
 use inkwell::values::{
 use inkwell::values::{
     ArrayValue, BasicMetadataValueEnum, BasicValueEnum, FunctionValue, IntValue, PointerValue,
     ArrayValue, BasicMetadataValueEnum, BasicValueEnum, FunctionValue, IntValue, PointerValue,
@@ -37,6 +37,7 @@ pub struct Contract<'a> {
 impl SolanaTarget {
 impl SolanaTarget {
     pub fn build<'a>(
     pub fn build<'a>(
         context: &'a Context,
         context: &'a Context,
+        std_lib: &Module<'a>,
         contract: &'a ast::Contract,
         contract: &'a ast::Contract,
         ns: &'a ast::Namespace,
         ns: &'a ast::Namespace,
         filename: &'a str,
         filename: &'a str,
@@ -55,6 +56,7 @@ impl SolanaTarget {
             filename,
             filename,
             opt,
             opt,
             math_overflow_check,
             math_overflow_check,
+            std_lib,
             None,
             None,
         );
         );
 
 
@@ -113,6 +115,7 @@ impl SolanaTarget {
     /// Build a bundle of contracts from the same namespace
     /// Build a bundle of contracts from the same namespace
     pub fn build_bundle<'a>(
     pub fn build_bundle<'a>(
         context: &'a Context,
         context: &'a Context,
+        std_lib: &Module<'a>,
         namespaces: &'a [ast::Namespace],
         namespaces: &'a [ast::Namespace],
         filename: &str,
         filename: &str,
         opt: OptimizationLevel,
         opt: OptimizationLevel,
@@ -130,6 +133,7 @@ impl SolanaTarget {
             filename,
             filename,
             opt,
             opt,
             math_overflow_check,
             math_overflow_check,
+            std_lib,
             None,
             None,
         );
         );
 
 

+ 7 - 39
src/emit/substrate.rs

@@ -3,7 +3,7 @@ use crate::codegen::cfg::HashTy;
 use crate::parser::pt;
 use crate::parser::pt;
 use crate::sema::ast;
 use crate::sema::ast;
 use inkwell::context::Context;
 use inkwell::context::Context;
-use inkwell::module::Linkage;
+use inkwell::module::{Linkage, Module};
 use inkwell::types::{BasicType, IntType};
 use inkwell::types::{BasicType, IntType};
 use inkwell::values::{
 use inkwell::values::{
     ArrayValue, BasicValueEnum, CallableValue, FunctionValue, IntValue, PointerValue,
     ArrayValue, BasicValueEnum, CallableValue, FunctionValue, IntValue, PointerValue,
@@ -27,6 +27,7 @@ pub struct SubstrateTarget {
 impl SubstrateTarget {
 impl SubstrateTarget {
     pub fn build<'a>(
     pub fn build<'a>(
         context: &'a Context,
         context: &'a Context,
+        std_lib: &Module<'a>,
         contract: &'a ast::Contract,
         contract: &'a ast::Contract,
         ns: &'a ast::Namespace,
         ns: &'a ast::Namespace,
         filename: &'a str,
         filename: &'a str,
@@ -40,6 +41,7 @@ impl SubstrateTarget {
             filename,
             filename,
             opt,
             opt,
             math_overflow_check,
             math_overflow_check,
+            std_lib,
             None,
             None,
         );
         );
 
 
@@ -939,19 +941,7 @@ impl SubstrateTarget {
                             binary.builder.build_store(elem, val);
                             binary.builder.build_store(elem, val);
                         },
                         },
                     );
                     );
-
-                    binary
-                        .builder
-                        .build_pointer_cast(
-                            v,
-                            binary
-                                .module
-                                .get_struct_type("struct.vector")
-                                .unwrap()
-                                .ptr_type(AddressSpace::Generic),
-                            "string",
-                        )
-                        .into()
+                    v.into()
                 }
                 }
             }
             }
             ast::Type::String | ast::Type::DynamicBytes => {
             ast::Type::String | ast::Type::DynamicBytes => {
@@ -977,18 +967,7 @@ impl SubstrateTarget {
 
 
                 self.check_overrun(binary, function, *data, end, false);
                 self.check_overrun(binary, function, *data, end, false);
 
 
-                binary
-                    .builder
-                    .build_pointer_cast(
-                        v.into_pointer_value(),
-                        binary
-                            .module
-                            .get_struct_type("struct.vector")
-                            .unwrap()
-                            .ptr_type(AddressSpace::Generic),
-                        "string",
-                    )
-                    .into()
+                v
             }
             }
             ast::Type::Ref(ty) => self.decode_ty(binary, function, ty, data, end, ns),
             ast::Type::Ref(ty) => self.decode_ty(binary, function, ty, data, end, ns),
             ast::Type::ExternalFunction { .. } => {
             ast::Type::ExternalFunction { .. } => {
@@ -4198,20 +4177,9 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
                     .left()
                     .left()
                     .unwrap();
                     .unwrap();
 
 
-                // vector_new should return vector* but after llvm module merging, this can be vector.1*
-                let v = binary.builder.build_pointer_cast(
-                    v.into_pointer_value(),
-                    binary
-                        .module
-                        .get_struct_type("struct.vector")
-                        .unwrap()
-                        .ptr_type(AddressSpace::Generic),
-                    "calldata",
-                );
-
                 let data = unsafe {
                 let data = unsafe {
                     binary.builder.build_gep(
                     binary.builder.build_gep(
-                        v,
+                        v.into_pointer_value(),
                         &[
                         &[
                             binary.context.i32_type().const_zero(),
                             binary.context.i32_type().const_zero(),
                             binary.context.i32_type().const_int(2, false),
                             binary.context.i32_type().const_int(2, false),
@@ -4248,7 +4216,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
                     "",
                     "",
                 );
                 );
 
 
-                v.into()
+                v
             }
             }
             codegen::Expression::Builtin(_, _, codegen::Builtin::BlockNumber, _) => {
             codegen::Expression::Builtin(_, _, codegen::Builtin::BlockNumber, _) => {
                 let block_number =
                 let block_number =

+ 9 - 0
tests/codegen_testcases/llvm_type.sol

@@ -0,0 +1,9 @@
+// RUN: --target ewasm --emit cfg
+contract  Ownable  {
+
+// BEGIN-CHECK: Ownable::Ownable::function::_msgData
+    function  _msgData()  internal  view  returns  (bytes  memory)  {
+        // CHECK: return (builtin Calldata ())
+        return msg.data;
+    }
+}

+ 158 - 0
tests/contract_testcases/ewasm/llvm_type.dot

@@ -0,0 +1,158 @@
+strict digraph "tests/contract_testcases/ewasm/llvm_type.sol" {
+	OwnershipTransferred [label="name:OwnershipTransferred\ncontract: 1\ntests/contract_testcases/ewasm/llvm_type.sol:14:16-36\nfield name:previousOwner ty:address indexed:yes\nfield name:newOwner ty:address indexed:yes"]
+	contract [label="contract Context\ntests/contract_testcases/ewasm/llvm_type.sol:1:1-30"]
+	_msgSender [label="function _msgSender\ncontract: Context\ntests/contract_testcases/ewasm/llvm_type.sol:2:9-85\nsignature _msgSender()\nvisibility internal\nmutability view\nvirtual"]
+	returns [label="returns\naddress payable "]
+	return [label="return\ntests/contract_testcases/ewasm/llvm_type.sol:3:17-44"]
+	builtins [label="builtin Sender\ntests/contract_testcases/ewasm/llvm_type.sol:3:33-43"]
+	_msgData [label="function _msgData\ncontract: Context\ntests/contract_testcases/ewasm/llvm_type.sol:5:9-80\nsignature _msgData()\nvisibility internal\nmutability view\nvirtual"]
+	returns_9 [label="returns\nbytes "]
+	expr [label="expression\ntests/contract_testcases/ewasm/llvm_type.sol:6:17-21"]
+	builtins_11 [label="builtin GetAddress\ntests/contract_testcases/ewasm/llvm_type.sol:6:17-21"]
+	return_12 [label="return\ntests/contract_testcases/ewasm/llvm_type.sol:7:17-33"]
+	builtins_13 [label="builtin Calldata\ntests/contract_testcases/ewasm/llvm_type.sol:7:25-33"]
+	contract_14 [label="contract Ownable\ntests/contract_testcases/ewasm/llvm_type.sol:10:1-11:31"]
+	base [label="base Context\ntests/contract_testcases/ewasm/llvm_type.sol:11:24-31"]
+	var [label="variable _owner\nvisibility private\ntests/contract_testcases/ewasm/llvm_type.sol:12:9-33"]
+	node_17 [label="constructor \ncontract: Ownable\ntests/contract_testcases/ewasm/llvm_type.sol:15:9-26\nsignature ()\nvisibility public\nmutability nonpayable"]
+	var_decl [label="variable decl address msgSender\ntests/contract_testcases/ewasm/llvm_type.sol:16:17-52"]
+	cast [label="cast address\ntests/contract_testcases/ewasm/llvm_type.sol:16:40-52"]
+	call_internal_function [label="call internal function\ntests/contract_testcases/ewasm/llvm_type.sol:16:40-52"]
+	internal_function [label="function() internal view returns (address payable)\nsignature _msgSender()\nContext._msgSender\ntests/contract_testcases/ewasm/llvm_type.sol:16:40-52"]
+	expr_22 [label="expression\ntests/contract_testcases/ewasm/llvm_type.sol:17:17-37"]
+	assign [label="assign\naddress storage\ntests/contract_testcases/ewasm/llvm_type.sol:17:17-23"]
+	storage_var [label="storage variable\nOwnable._owner\naddress storage\ntests/contract_testcases/ewasm/llvm_type.sol:17:17-23"]
+	variable [label="variable: msgSender\naddress\ntests/contract_testcases/ewasm/llvm_type.sol:17:28-37"]
+	emit [label="emit\nevent Ownable.OwnershipTransferred\ntests/contract_testcases/ewasm/llvm_type.sol:18:17-67"]
+	number_literal [label="address literal: 0\ntests/contract_testcases/ewasm/llvm_type.sol:18:44-54"]
+	variable_28 [label="variable: msgSender\naddress\ntests/contract_testcases/ewasm/llvm_type.sol:18:57-66"]
+	owner [label="function owner\ncontract: Ownable\ntests/contract_testcases/ewasm/llvm_type.sol:20:9-60\nsignature owner()\nvisibility public\nmutability view"]
+	returns_30 [label="returns\naddress "]
+	return_31 [label="return\ntests/contract_testcases/ewasm/llvm_type.sol:21:17-31"]
+	storage_load [label="storage load address\ntests/contract_testcases/ewasm/llvm_type.sol:21:17-31"]
+	storage_var_33 [label="storage variable\nOwnable._owner\naddress storage\ntests/contract_testcases/ewasm/llvm_type.sol:21:25-31"]
+	onlyOwner [label="modifier onlyOwner\ncontract: Ownable\ntests/contract_testcases/ewasm/llvm_type.sol:24:9-32\nmutability nonpayable"]
+	expr_35 [label="expression\ntests/contract_testcases/ewasm/llvm_type.sol:25:17-92"]
+	builtins_36 [label="builtin Require\ntests/contract_testcases/ewasm/llvm_type.sol:25:17-24"]
+	equal [label="equal\ntests/contract_testcases/ewasm/llvm_type.sol:25:25-49"]
+	storage_load_38 [label="storage load address\ntests/contract_testcases/ewasm/llvm_type.sol:25:25-31"]
+	storage_var_39 [label="storage variable\nOwnable._owner\naddress storage\ntests/contract_testcases/ewasm/llvm_type.sol:25:25-31"]
+	cast_40 [label="cast address\ntests/contract_testcases/ewasm/llvm_type.sol:25:37-49"]
+	call_internal_function_41 [label="call internal function\ntests/contract_testcases/ewasm/llvm_type.sol:25:37-49"]
+	internal_function_42 [label="function() internal view returns (address payable)\nsignature _msgSender()\nContext._msgSender\ntests/contract_testcases/ewasm/llvm_type.sol:25:37-49"]
+	alloc_array [label="alloc array string\ninitializer: 4f776e61626c653a202063616c6c65722020697320206e6f74202074686520206f776e6572\ntests/contract_testcases/ewasm/llvm_type.sol:25:52-91"]
+	number_literal_44 [label="uint32 literal: 37\ntests/contract_testcases/ewasm/llvm_type.sol:25:52-91"]
+	underscore [label="undersore\ntests/contract_testcases/ewasm/llvm_type.sol:26:17-18"]
+	waiveOwnership [label="function waiveOwnership\ncontract: Ownable\ntests/contract_testcases/ewasm/llvm_type.sol:29:9-63\nsignature waiveOwnership()\nvisibility public\nmutability nonpayable\nvirtual"]
+	emit_47 [label="emit\nevent Ownable.OwnershipTransferred\ntests/contract_testcases/ewasm/llvm_type.sol:30:17-64"]
+	storage_load_48 [label="storage load address\ntests/contract_testcases/ewasm/llvm_type.sol:30:44-50"]
+	storage_var_49 [label="storage variable\nOwnable._owner\naddress storage\ntests/contract_testcases/ewasm/llvm_type.sol:30:44-50"]
+	number_literal_50 [label="address literal: 0\ntests/contract_testcases/ewasm/llvm_type.sol:30:53-63"]
+	expr_51 [label="expression\ntests/contract_testcases/ewasm/llvm_type.sol:31:17-38"]
+	assign_52 [label="assign\naddress storage\ntests/contract_testcases/ewasm/llvm_type.sol:31:17-23"]
+	storage_var_53 [label="storage variable\nOwnable._owner\naddress storage\ntests/contract_testcases/ewasm/llvm_type.sol:31:17-23"]
+	number_literal_54 [label="address literal: 0\ntests/contract_testcases/ewasm/llvm_type.sol:31:28-38"]
+	transferOwnership [label="function transferOwnership\ncontract: Ownable\ntests/contract_testcases/ewasm/llvm_type.sol:34:9-83\nsignature transferOwnership(address)\nvisibility public\nmutability nonpayable\nvirtual"]
+	parameters [label="parameters\naddress newOwner"]
+	expr_57 [label="expression\ntests/contract_testcases/ewasm/llvm_type.sol:35:17-99"]
+	builtins_58 [label="builtin Require\ntests/contract_testcases/ewasm/llvm_type.sol:35:17-24"]
+	not [label="not\ntests/contract_testcases/ewasm/llvm_type.sol:35:25-49"]
+	equal_60 [label="equal\ntests/contract_testcases/ewasm/llvm_type.sol:35:25-49"]
+	variable_61 [label="variable: newOwner\naddress\ntests/contract_testcases/ewasm/llvm_type.sol:35:25-33"]
+	number_literal_62 [label="address literal: 0\ntests/contract_testcases/ewasm/llvm_type.sol:35:39-49"]
+	alloc_array_63 [label="alloc array string\ninitializer: 4f776e61626c653a20206e657720206f776e657220206973202074686520207a65726f202061646472657373\ntests/contract_testcases/ewasm/llvm_type.sol:35:52-98"]
+	number_literal_64 [label="uint32 literal: 44\ntests/contract_testcases/ewasm/llvm_type.sol:35:52-98"]
+	emit_65 [label="emit\nevent Ownable.OwnershipTransferred\ntests/contract_testcases/ewasm/llvm_type.sol:36:17-62"]
+	storage_load_66 [label="storage load address\ntests/contract_testcases/ewasm/llvm_type.sol:36:44-50"]
+	storage_var_67 [label="storage variable\nOwnable._owner\naddress storage\ntests/contract_testcases/ewasm/llvm_type.sol:36:44-50"]
+	variable_68 [label="variable: newOwner\naddress\ntests/contract_testcases/ewasm/llvm_type.sol:36:53-61"]
+	expr_69 [label="expression\ntests/contract_testcases/ewasm/llvm_type.sol:37:17-36"]
+	assign_70 [label="assign\naddress storage\ntests/contract_testcases/ewasm/llvm_type.sol:37:17-23"]
+	storage_var_71 [label="storage variable\nOwnable._owner\naddress storage\ntests/contract_testcases/ewasm/llvm_type.sol:37:17-23"]
+	variable_72 [label="variable: newOwner\naddress\ntests/contract_testcases/ewasm/llvm_type.sol:37:28-36"]
+	getTime [label="function getTime\ncontract: Ownable\ntests/contract_testcases/ewasm/llvm_type.sol:40:9-62\nsignature getTime()\nvisibility public\nmutability view"]
+	returns_74 [label="returns\nuint256 "]
+	return_75 [label="return\ntests/contract_testcases/ewasm/llvm_type.sol:41:17-40"]
+	zero_ext [label="zero extend uint256\ntests/contract_testcases/ewasm/llvm_type.sol:41:17-40"]
+	builtins_77 [label="builtin Timestamp\ntests/contract_testcases/ewasm/llvm_type.sol:41:25-40"]
+	diagnostic [label="found abstract contract 'Context'\nlevel Debug\ntests/contract_testcases/ewasm/llvm_type.sol:1:1-30"]
+	diagnostic_80 [label="found contract 'Ownable'\nlevel Debug\ntests/contract_testcases/ewasm/llvm_type.sol:10:1-11:31"]
+	events -> OwnershipTransferred
+	contracts -> contract
+	contract -> _msgSender [label="function"]
+	_msgSender -> returns [label="returns"]
+	_msgSender -> return [label="body"]
+	return -> builtins [label="expr"]
+	contract -> _msgData [label="function"]
+	_msgData -> returns_9 [label="returns"]
+	_msgData -> expr [label="body"]
+	expr -> builtins_11 [label="expr"]
+	expr -> return_12 [label="next"]
+	return_12 -> builtins_13 [label="expr"]
+	contracts -> contract_14
+	contract_14 -> base [label="base"]
+	contract_14 -> var [label="variable"]
+	contract_14 -> node_17 [label="constructor"]
+	node_17 -> var_decl [label="body"]
+	var_decl -> cast [label="init"]
+	cast -> call_internal_function [label="expr"]
+	call_internal_function -> internal_function [label="function"]
+	var_decl -> expr_22 [label="next"]
+	expr_22 -> assign [label="expr"]
+	assign -> storage_var [label="left"]
+	assign -> variable [label="right"]
+	expr_22 -> emit [label="next"]
+	emit -> number_literal [label="arg #0"]
+	emit -> variable_28 [label="arg #1"]
+	contract_14 -> owner [label="function"]
+	owner -> returns_30 [label="returns"]
+	owner -> return_31 [label="body"]
+	return_31 -> storage_load [label="expr"]
+	storage_load -> storage_var_33 [label="expr"]
+	contract_14 -> onlyOwner [label="modifier"]
+	onlyOwner -> expr_35 [label="body"]
+	expr_35 -> builtins_36 [label="expr"]
+	builtins_36 -> equal [label="arg #0"]
+	equal -> storage_load_38 [label="left"]
+	storage_load_38 -> storage_var_39 [label="expr"]
+	equal -> cast_40 [label="right"]
+	cast_40 -> call_internal_function_41 [label="expr"]
+	call_internal_function_41 -> internal_function_42 [label="function"]
+	builtins_36 -> alloc_array [label="arg #1"]
+	alloc_array -> number_literal_44 [label="length"]
+	expr_35 -> underscore [label="next"]
+	contract_14 -> waiveOwnership [label="function"]
+	waiveOwnership -> emit_47 [label="body"]
+	emit_47 -> storage_load_48 [label="arg #0"]
+	storage_load_48 -> storage_var_49 [label="expr"]
+	emit_47 -> number_literal_50 [label="arg #1"]
+	emit_47 -> expr_51 [label="next"]
+	expr_51 -> assign_52 [label="expr"]
+	assign_52 -> storage_var_53 [label="left"]
+	assign_52 -> number_literal_54 [label="right"]
+	contract_14 -> transferOwnership [label="function"]
+	transferOwnership -> parameters [label="parameters"]
+	transferOwnership -> expr_57 [label="body"]
+	expr_57 -> builtins_58 [label="expr"]
+	builtins_58 -> not [label="arg #0"]
+	not -> equal_60 [label="expr"]
+	equal_60 -> variable_61 [label="left"]
+	equal_60 -> number_literal_62 [label="right"]
+	builtins_58 -> alloc_array_63 [label="arg #1"]
+	alloc_array_63 -> number_literal_64 [label="length"]
+	expr_57 -> emit_65 [label="next"]
+	emit_65 -> storage_load_66 [label="arg #0"]
+	storage_load_66 -> storage_var_67 [label="expr"]
+	emit_65 -> variable_68 [label="arg #1"]
+	emit_65 -> expr_69 [label="next"]
+	expr_69 -> assign_70 [label="expr"]
+	assign_70 -> storage_var_71 [label="left"]
+	assign_70 -> variable_72 [label="right"]
+	contract_14 -> getTime [label="function"]
+	getTime -> returns_74 [label="returns"]
+	getTime -> return_75 [label="body"]
+	return_75 -> zero_ext [label="expr"]
+	zero_ext -> builtins_77 [label="expr"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_80 [label="Debug"]
+}

+ 43 - 0
tests/contract_testcases/ewasm/llvm_type.sol

@@ -0,0 +1,43 @@
+abstract  contract  Context  {
+        function  _msgSender()  internal  view  virtual  returns  (address  payable)  {
+                return  payable(msg.sender);
+        }
+        function  _msgData()  internal  view  virtual  returns  (bytes  memory)  {
+                this;
+                return  msg.data;
+        }
+}
+
+contract  Ownable  is  Context  {
+        address  private  _owner;
+      
+        event  OwnershipTransferred(address  indexed  previousOwner,  address  indexed  newOwner);
+        constructor  ()  {
+                address  msgSender  =  _msgSender();
+                _owner  =  msgSender;
+                emit  OwnershipTransferred(address(0),  msgSender);
+        }
+        function  owner()  public  view  returns  (address)  {
+                return  _owner;
+        }
+
+        modifier  onlyOwner()  {
+                require(_owner  ==  _msgSender(),  "Ownable:  caller  is  not  the  owner");
+                _;
+        }
+
+        function  waiveOwnership()  public  virtual  onlyOwner  {
+                emit  OwnershipTransferred(_owner,  address(0));
+                _owner  =  address(0);
+        }
+
+        function  transferOwnership(address  newOwner)  public  virtual  onlyOwner  {
+                require(newOwner  !=  address(0),  "Ownable:  new  owner  is  the  zero  address");
+                emit  OwnershipTransferred(_owner,  newOwner);
+                _owner  =  newOwner;
+        }
+        
+        function  getTime()  public  view  returns  (uint256)  {
+                return  block.timestamp;
+        }
+}