From 7f1593baa08ccab165cdfc578508a519eb6ae176 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 31 Oct 2019 17:59:08 +0100 Subject: [PATCH] [WASM] datasize and dataoffset only return a single value. --- libyul/backends/wasm/WasmDialect.cpp | 4 +- libyul/backends/wasm/WordSizeTransform.cpp | 48 +++++++++++++++++++ .../standard_eWasm_requested/output.json | 29 ++--------- 3 files changed, 53 insertions(+), 28 deletions(-) diff --git a/libyul/backends/wasm/WasmDialect.cpp b/libyul/backends/wasm/WasmDialect.cpp index f781292ae..2f4cc87af 100644 --- a/libyul/backends/wasm/WasmDialect.cpp +++ b/libyul/backends/wasm/WasmDialect.cpp @@ -63,8 +63,8 @@ WasmDialect::WasmDialect(): m_functions["unreachable"_yulstring].sideEffects.invalidatesStorage = false; m_functions["unreachable"_yulstring].sideEffects.invalidatesMemory = false; - addFunction("datasize", 1, 4, true, true); - addFunction("dataoffset", 1, 4, true, true); + addFunction("datasize", 1, 1, true, true); + addFunction("dataoffset", 1, 1, true, true); addEthereumExternals(); } diff --git a/libyul/backends/wasm/WordSizeTransform.cpp b/libyul/backends/wasm/WordSizeTransform.cpp index 7314715d4..81c80da99 100644 --- a/libyul/backends/wasm/WordSizeTransform.cpp +++ b/libyul/backends/wasm/WordSizeTransform.cpp @@ -87,6 +87,30 @@ void WordSizeTransform::operator()(Block& _block) if (_s.type() == typeid(VariableDeclaration)) { VariableDeclaration& varDecl = boost::get(_s); + + // Special handling for datasize and dataoffset - they will only need one variable. + if (varDecl.value && varDecl.value->type() == typeid(FunctionCall)) + if (BuiltinFunction const* f = m_inputDialect.builtin(boost::get(*varDecl.value).functionName.name)) + if (f->literalArguments) + { + yulAssert(f->name == "datasize"_yulstring || f->name == "dataoffset"_yulstring, ""); + yulAssert(varDecl.variables.size() == 1, ""); + auto newLhs = generateU64IdentifierNames(varDecl.variables[0].name); + vector ret; + for (int i = 0; i < 3; i++) + ret.push_back(VariableDeclaration{ + varDecl.location, + {TypedName{varDecl.location, newLhs[i], "u64"_yulstring}}, + make_unique(Literal{locationOf(*varDecl.value), LiteralKind::Number, "0"_yulstring, "u64"_yulstring}) + }); + ret.push_back(VariableDeclaration{ + varDecl.location, + {TypedName{varDecl.location, newLhs[3], "u64"_yulstring}}, + std::move(varDecl.value) + }); + return {std::move(ret)}; + } + if ( !varDecl.value || varDecl.value->type() == typeid(FunctionalInstruction) || @@ -123,6 +147,30 @@ void WordSizeTransform::operator()(Block& _block) { Assignment& assignment = boost::get(_s); yulAssert(assignment.value, ""); + + // Special handling for datasize and dataoffset - they will only need one variable. + if (assignment.value->type() == typeid(FunctionCall)) + if (BuiltinFunction const* f = m_inputDialect.builtin(boost::get(*assignment.value).functionName.name)) + if (f->literalArguments) + { + yulAssert(f->name == "datasize"_yulstring || f->name == "dataoffset"_yulstring, ""); + yulAssert(assignment.variableNames.size() == 1, ""); + auto newLhs = generateU64IdentifierNames(assignment.variableNames[0].name); + vector ret; + for (int i = 0; i < 3; i++) + ret.push_back(Assignment{ + assignment.location, + {Identifier{assignment.location, newLhs[i]}}, + make_unique(Literal{locationOf(*assignment.value), LiteralKind::Number, "0"_yulstring, "u64"_yulstring}) + }); + ret.push_back(Assignment{ + assignment.location, + {Identifier{assignment.location, newLhs[3]}}, + std::move(assignment.value) + }); + return {std::move(ret)}; + } + if ( assignment.value->type() == typeid(FunctionalInstruction) || assignment.value->type() == typeid(FunctionCall) diff --git a/test/cmdlineTests/standard_eWasm_requested/output.json b/test/cmdlineTests/standard_eWasm_requested/output.json index fce2ef6b1..396f0f43c 100644 --- a/test/cmdlineTests/standard_eWasm_requested/output.json +++ b/test/cmdlineTests/standard_eWasm_requested/output.json @@ -62,9 +62,6 @@ (import \"ethereum\" \"finish\" (func $eth.finish (param i32 i32))) (memory $memory (export \"memory\") 1) (export \"main\" (func $main)) - (global $global_ (mut i64) (i64.const 0)) - (global $global__1 (mut i64) (i64.const 0)) - (global $global__2 (mut i64) (i64.const 0)) (func $main (local $_1 i64) @@ -73,13 +70,6 @@ (local $y i64) (local $hi_1 i64) (local $_3 i64) - (local $_4 i64) - (local $_5 i64) - (local $_6 i64) - (local $_7 i64) - (local $_8 i64) - (local $_9 i64) - (local $_10 i64) (local.set $_1 (i64.const 0)) (local.set $_2 (i64.add (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 64)) (i64.const 64))) (local.set $hi (i64.shl (i64.or (i64.shl (i64.or (i64.and (i64.shl (local.get $_1) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (local.get $_1) (i64.const 8)) (i64.const 255))) (i64.const 16)) (call $endian_swap_16 (i64.shr_u (local.get $_1) (i64.const 16)))) (i64.const 32))) @@ -89,22 +79,9 @@ (i64.store (i64.add (local.get $_2) (i64.const 16)) (local.get $y)) (local.set $hi_1 (i64.shl (call $endian_swap_32 (i64.const 128)) (i64.const 32))) (i64.store (i64.add (local.get $_2) (i64.const 24)) (i64.or (local.get $hi_1) (call $endian_swap_32 (i64.shr_u (i64.const 128) (i64.const 32))))) - (block - (local.set $_3 (datasize \"C_2_deployed\")) - (local.set $_4 (global.get $global_)) - (local.set $_5 (global.get $global__1)) - (local.set $_6 (global.get $global__2)) - - ) - (block - (local.set $_7 (dataoffset \"C_2_deployed\")) - (local.set $_8 (global.get $global_)) - (local.set $_9 (global.get $global__1)) - (local.set $_10 (global.get $global__2)) - - ) - (call $eth.codeCopy (i64.add (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1)) (i64.const 64)) (call $u256_to_i32 (local.get $_7) (local.get $_8) (local.get $_9) (local.get $_10)) (call $u256_to_i32 (local.get $_3) (local.get $_4) (local.get $_5) (local.get $_6))) - (call $eth.finish (i64.add (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1)) (i64.const 64)) (call $u256_to_i32 (local.get $_3) (local.get $_4) (local.get $_5) (local.get $_6))) + (local.set $_3 (datasize \"C_2_deployed\")) + (call $eth.codeCopy (i64.add (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1)) (i64.const 64)) (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (dataoffset \"C_2_deployed\")) (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_3))) + (call $eth.finish (i64.add (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1)) (i64.const 64)) (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_3))) ) (func $u256_to_i32