mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #6600 from sifmelcara/wasm-dialect-transpiler
Add a transformation that replace every u256 variable with four u64 variables
This commit is contained in:
		
						commit
						befadea0c6
					
				@ -40,6 +40,8 @@ add_library(yul
 | 
			
		||||
	backends/evm/NoOutputAssembly.cpp
 | 
			
		||||
	backends/wasm/WasmDialect.cpp
 | 
			
		||||
	backends/wasm/WasmDialect.h
 | 
			
		||||
	backends/wasm/WordSizeTransform.cpp
 | 
			
		||||
	backends/wasm/WordSizeTransform.h
 | 
			
		||||
	optimiser/ASTCopier.cpp
 | 
			
		||||
	optimiser/ASTCopier.h
 | 
			
		||||
	optimiser/ASTWalker.cpp
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										238
									
								
								libyul/backends/wasm/WordSizeTransform.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								libyul/backends/wasm/WordSizeTransform.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,238 @@
 | 
			
		||||
/*
 | 
			
		||||
	This file is part of solidity.
 | 
			
		||||
 | 
			
		||||
	solidity is free software: you can redistribute it and/or modify
 | 
			
		||||
	it under the terms of the GNU General Public License as published by
 | 
			
		||||
	the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
	(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
	solidity is distributed in the hope that it will be useful,
 | 
			
		||||
	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
	GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
	You should have received a copy of the GNU General Public License
 | 
			
		||||
	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include <libyul/AsmData.h>
 | 
			
		||||
#include <libyul/backends/wasm/WordSizeTransform.h>
 | 
			
		||||
#include <libyul/Utilities.h>
 | 
			
		||||
 | 
			
		||||
#include <libdevcore/CommonData.h>
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
using namespace dev;
 | 
			
		||||
using namespace yul;
 | 
			
		||||
 | 
			
		||||
void WordSizeTransform::operator()(FunctionDefinition& _fd)
 | 
			
		||||
{
 | 
			
		||||
	rewriteVarDeclList(_fd.parameters);
 | 
			
		||||
	rewriteVarDeclList(_fd.returnVariables);
 | 
			
		||||
	(*this)(_fd.body);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WordSizeTransform::operator()(FunctionalInstruction& _ins)
 | 
			
		||||
{
 | 
			
		||||
	rewriteFunctionCallArguments(_ins.arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WordSizeTransform::operator()(FunctionCall& _fc)
 | 
			
		||||
{
 | 
			
		||||
	rewriteFunctionCallArguments(_fc.arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WordSizeTransform::operator()(If&)
 | 
			
		||||
{
 | 
			
		||||
	yulAssert(false, "If statement not implemented.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WordSizeTransform::operator()(Switch&)
 | 
			
		||||
{
 | 
			
		||||
	yulAssert(false, "Switch statement not implemented.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WordSizeTransform::operator()(Block& _block)
 | 
			
		||||
{
 | 
			
		||||
	iterateReplacing(
 | 
			
		||||
		_block.statements,
 | 
			
		||||
		[&](Statement& _s) -> boost::optional<vector<Statement>>
 | 
			
		||||
		{
 | 
			
		||||
			if (_s.type() == typeid(VariableDeclaration))
 | 
			
		||||
			{
 | 
			
		||||
				VariableDeclaration& varDecl = boost::get<VariableDeclaration>(_s);
 | 
			
		||||
				if (
 | 
			
		||||
					!varDecl.value ||
 | 
			
		||||
					varDecl.value->type() == typeid(FunctionalInstruction) ||
 | 
			
		||||
					varDecl.value->type() == typeid(FunctionCall)
 | 
			
		||||
				)
 | 
			
		||||
				{
 | 
			
		||||
					if (varDecl.value) visit(*varDecl.value);
 | 
			
		||||
					rewriteVarDeclList(varDecl.variables);
 | 
			
		||||
					return boost::none;
 | 
			
		||||
				}
 | 
			
		||||
				else if (
 | 
			
		||||
					varDecl.value->type() == typeid(Identifier) ||
 | 
			
		||||
					varDecl.value->type() == typeid(Literal)
 | 
			
		||||
				)
 | 
			
		||||
				{
 | 
			
		||||
					yulAssert(varDecl.variables.size() == 1, "");
 | 
			
		||||
					auto newRhs = expandValue(*varDecl.value);
 | 
			
		||||
					auto newLhs = generateU64IdentifierNames(varDecl.variables[0].name);
 | 
			
		||||
					vector<Statement> ret;
 | 
			
		||||
					for (int i = 0; i < 4; i++)
 | 
			
		||||
						ret.push_back(
 | 
			
		||||
							VariableDeclaration{
 | 
			
		||||
								varDecl.location,
 | 
			
		||||
								{TypedName{varDecl.location, newLhs[i], "u64"_yulstring}},
 | 
			
		||||
								std::move(newRhs[i])
 | 
			
		||||
							}
 | 
			
		||||
						);
 | 
			
		||||
					return ret;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					yulAssert(false, "");
 | 
			
		||||
			}
 | 
			
		||||
			else if (_s.type() == typeid(Assignment))
 | 
			
		||||
			{
 | 
			
		||||
				Assignment& assignment = boost::get<Assignment>(_s);
 | 
			
		||||
				yulAssert(assignment.value, "");
 | 
			
		||||
				if (
 | 
			
		||||
					assignment.value->type() == typeid(FunctionalInstruction) ||
 | 
			
		||||
					assignment.value->type() == typeid(FunctionCall)
 | 
			
		||||
				)
 | 
			
		||||
				{
 | 
			
		||||
					if (assignment.value) visit(*assignment.value);
 | 
			
		||||
					rewriteIdentifierList(assignment.variableNames);
 | 
			
		||||
					return boost::none;
 | 
			
		||||
				}
 | 
			
		||||
				else if (
 | 
			
		||||
					assignment.value->type() == typeid(Identifier) ||
 | 
			
		||||
					assignment.value->type() == typeid(Literal)
 | 
			
		||||
				)
 | 
			
		||||
				{
 | 
			
		||||
					yulAssert(assignment.variableNames.size() == 1, "");
 | 
			
		||||
					auto newRhs = expandValue(*assignment.value);
 | 
			
		||||
					YulString lhsName = assignment.variableNames[0].name;
 | 
			
		||||
					vector<Statement> ret;
 | 
			
		||||
					for (int i = 0; i < 4; i++)
 | 
			
		||||
						ret.push_back(
 | 
			
		||||
							Assignment{
 | 
			
		||||
								assignment.location,
 | 
			
		||||
								{Identifier{assignment.location, m_variableMapping.at(lhsName)[i]}},
 | 
			
		||||
								std::move(newRhs[i])
 | 
			
		||||
							}
 | 
			
		||||
						);
 | 
			
		||||
					return ret;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					yulAssert(false, "");
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
				visit(_s);
 | 
			
		||||
			return boost::none;
 | 
			
		||||
		}
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WordSizeTransform::run(Block& _ast, NameDispenser& _nameDispenser)
 | 
			
		||||
{
 | 
			
		||||
	WordSizeTransform{_nameDispenser}(_ast);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WordSizeTransform::rewriteVarDeclList(TypedNameList& _nameList)
 | 
			
		||||
{
 | 
			
		||||
	iterateReplacing(
 | 
			
		||||
		_nameList,
 | 
			
		||||
		[&](TypedName const& _n) -> boost::optional<TypedNameList>
 | 
			
		||||
		{
 | 
			
		||||
			TypedNameList ret;
 | 
			
		||||
			yulAssert(m_variableMapping.find(_n.name) == m_variableMapping.end(), "");
 | 
			
		||||
			for (int i = 0; i < 4; i++)
 | 
			
		||||
			{
 | 
			
		||||
				auto newName = m_nameDispenser.newName(_n.name);
 | 
			
		||||
				m_variableMapping[_n.name][i] = newName;
 | 
			
		||||
				ret.push_back(TypedName{_n.location, newName, "u64"_yulstring});
 | 
			
		||||
			}
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WordSizeTransform::rewriteIdentifierList(vector<Identifier>& _ids)
 | 
			
		||||
{
 | 
			
		||||
	iterateReplacing(
 | 
			
		||||
		_ids,
 | 
			
		||||
		[&](Identifier const& _id) -> boost::optional<vector<Identifier>>
 | 
			
		||||
		{
 | 
			
		||||
			vector<Identifier> ret;
 | 
			
		||||
			for (auto newId: m_variableMapping.at(_id.name))
 | 
			
		||||
				ret.push_back(Identifier{_id.location, newId});
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WordSizeTransform::rewriteFunctionCallArguments(vector<Expression>& _args)
 | 
			
		||||
{
 | 
			
		||||
	iterateReplacing(
 | 
			
		||||
		_args,
 | 
			
		||||
		[&](Expression& _e) -> boost::optional<vector<Expression>>
 | 
			
		||||
		{
 | 
			
		||||
			// ExpressionSplitter guarantees arguments to be Identifier or Literal
 | 
			
		||||
			yulAssert(_e.type() == typeid(Identifier) || _e.type() == typeid(Literal), "");
 | 
			
		||||
			vector<Expression> ret;
 | 
			
		||||
			for (auto& v: expandValue(_e))
 | 
			
		||||
				ret.push_back(*v);
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
array<YulString, 4> WordSizeTransform::generateU64IdentifierNames(YulString const& _s)
 | 
			
		||||
{
 | 
			
		||||
	yulAssert(m_variableMapping.find(_s) == m_variableMapping.end(), "");
 | 
			
		||||
	array<YulString, 4> ret;
 | 
			
		||||
	for (int i = 0; i < 4; i++)
 | 
			
		||||
	{
 | 
			
		||||
		auto newName = m_nameDispenser.newName(_s);
 | 
			
		||||
		m_variableMapping[_s][i] = newName;
 | 
			
		||||
		ret[i] = newName;
 | 
			
		||||
	}
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
array<unique_ptr<Expression>, 4> WordSizeTransform::expandValue(Expression const& _e)
 | 
			
		||||
{
 | 
			
		||||
	array<unique_ptr<Expression>, 4> ret;
 | 
			
		||||
	if (_e.type() == typeid(Identifier))
 | 
			
		||||
	{
 | 
			
		||||
		Identifier const& id = boost::get<Identifier>(_e);
 | 
			
		||||
		for (int i = 0; i < 4; i++)
 | 
			
		||||
			ret[i] = make_unique<Expression>(Identifier{id.location, m_variableMapping.at(id.name)[i]});
 | 
			
		||||
	}
 | 
			
		||||
	else if (_e.type() == typeid(Literal))
 | 
			
		||||
	{
 | 
			
		||||
		Literal const& lit = boost::get<Literal>(_e);
 | 
			
		||||
		u256 val = valueOfLiteral(lit);
 | 
			
		||||
		for (int i = 3; i >= 0; i--)
 | 
			
		||||
		{
 | 
			
		||||
			u256 currentVal = val & std::numeric_limits<uint64_t>::max();
 | 
			
		||||
			val >>= 64;
 | 
			
		||||
			ret[i] = make_unique<Expression>(
 | 
			
		||||
				Literal{
 | 
			
		||||
					lit.location,
 | 
			
		||||
					LiteralKind::Number,
 | 
			
		||||
					YulString(currentVal.str()),
 | 
			
		||||
					"u64"_yulstring
 | 
			
		||||
				}
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		yulAssert(false, "");
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										81
									
								
								libyul/backends/wasm/WordSizeTransform.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								libyul/backends/wasm/WordSizeTransform.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,81 @@
 | 
			
		||||
/*
 | 
			
		||||
	This file is part of solidity.
 | 
			
		||||
 | 
			
		||||
	solidity is free software: you can redistribute it and/or modify
 | 
			
		||||
	it under the terms of the GNU General Public License as published by
 | 
			
		||||
	the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
	(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
	solidity is distributed in the hope that it will be useful,
 | 
			
		||||
	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
	GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
	You should have received a copy of the GNU General Public License
 | 
			
		||||
	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
/**
 | 
			
		||||
 * Replace every u256 variable with four u64 variables.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <libyul/optimiser/ASTWalker.h>
 | 
			
		||||
#include <libyul/optimiser/NameDispenser.h>
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace yul
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A stage that replace every u256 variable with four u64 variables.
 | 
			
		||||
 * This transformation stage is required because values in EVM are 256 bits,
 | 
			
		||||
 * but wasm only supports values up to 64 bits, so we use four u64 values to simulate
 | 
			
		||||
 * one u256 value.
 | 
			
		||||
 *
 | 
			
		||||
 * For FunctionalInstruction that accepts or returns u256 values, they accepts or returns
 | 
			
		||||
 * four times the number of values after this transformation, with the order of significance,
 | 
			
		||||
 * from the most significant to the least significant.
 | 
			
		||||
 *
 | 
			
		||||
 * For example, the FunctionalInstruction MUL supplied by code generator
 | 
			
		||||
 * should take 8 arguments and return 4 values (instead of 2 and 1) after this transformation.
 | 
			
		||||
 *
 | 
			
		||||
 * mul(a1, a2, a3, a4, b1, b2, b3, b4) -> c1, c2, c3, c4
 | 
			
		||||
 *
 | 
			
		||||
 * the value of c4 should be
 | 
			
		||||
 *	((a1*(2^192) + a2*(2^128) + a3(2^64) + a4) * (b1*(2^192) + b2*(2^128) + b3(2^64) + b4)) & ((1<<64)-1)
 | 
			
		||||
 *
 | 
			
		||||
 * Prerequisite: Disambiguator, ExpressionSplitter
 | 
			
		||||
 */
 | 
			
		||||
class WordSizeTransform: public ASTModifier
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	void operator()(FunctionDefinition&) override;
 | 
			
		||||
	void operator()(FunctionalInstruction&) override;
 | 
			
		||||
	void operator()(FunctionCall&) override;
 | 
			
		||||
	void operator()(If&) override;
 | 
			
		||||
	void operator()(Switch&) override;
 | 
			
		||||
	void operator()(Block& _block) override;
 | 
			
		||||
 | 
			
		||||
	static void run(Block& _ast, NameDispenser& _nameDispenser);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	explicit WordSizeTransform(NameDispenser& _nameDispenser):
 | 
			
		||||
		m_nameDispenser(_nameDispenser)
 | 
			
		||||
	{ }
 | 
			
		||||
 | 
			
		||||
	void rewriteVarDeclList(std::vector<TypedName>&);
 | 
			
		||||
	void rewriteIdentifierList(std::vector<Identifier>&);
 | 
			
		||||
	void rewriteFunctionCallArguments(std::vector<Expression>&);
 | 
			
		||||
 | 
			
		||||
	std::array<YulString, 4> generateU64IdentifierNames(YulString const& _s);
 | 
			
		||||
	std::array<std::unique_ptr<Expression>, 4> expandValue(Expression const& _e);
 | 
			
		||||
 | 
			
		||||
	NameDispenser& m_nameDispenser;
 | 
			
		||||
	/// maps original u256 variable's name to corresponding u64 variables' names
 | 
			
		||||
	std::map<YulString, std::array<YulString, 4>> m_variableMapping;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -45,6 +45,7 @@
 | 
			
		||||
#include <libyul/optimiser/StackCompressor.h>
 | 
			
		||||
#include <libyul/optimiser/Suite.h>
 | 
			
		||||
#include <libyul/backends/evm/EVMDialect.h>
 | 
			
		||||
#include <libyul/backends/wasm/WordSizeTransform.h>
 | 
			
		||||
#include <libyul/AsmPrinter.h>
 | 
			
		||||
#include <libyul/AsmParser.h>
 | 
			
		||||
#include <libyul/AsmAnalysis.h>
 | 
			
		||||
@ -264,6 +265,13 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
 | 
			
		||||
		StackCompressor::run(m_dialect, *m_ast, true, maxIterations);
 | 
			
		||||
		(BlockFlattener{})(*m_ast);
 | 
			
		||||
	}
 | 
			
		||||
	else if (m_optimizerStep == "wordSizeTransform")
 | 
			
		||||
	{
 | 
			
		||||
		disambiguate();
 | 
			
		||||
		NameDispenser nameDispenser{*m_dialect, *m_ast}; // TODO: Support WasmDialect in yulOptimizerTest
 | 
			
		||||
		ExpressionSplitter{*m_dialect, nameDispenser}(*m_ast);
 | 
			
		||||
		WordSizeTransform::run(*m_ast, nameDispenser);
 | 
			
		||||
	}
 | 
			
		||||
	else if (m_optimizerStep == "fullSuite")
 | 
			
		||||
		OptimiserSuite::run(m_dialect, *m_ast, *m_analysisInfo, true);
 | 
			
		||||
	else
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,18 @@
 | 
			
		||||
{
 | 
			
		||||
  let val := 1234567890123456789012345678901234567890123456789012345678901234567890
 | 
			
		||||
  val := 9876543219876543219876543219876543219876543219876543219876543219876543210
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ====
 | 
			
		||||
// step: wordSizeTransform
 | 
			
		||||
// ----
 | 
			
		||||
// {
 | 
			
		||||
//     let val_1 := 196678011949
 | 
			
		||||
//     let val_2 := 17592899865401375162
 | 
			
		||||
//     let val_3 := 3392951883154430155
 | 
			
		||||
//     let val_4 := 12452437124710337234
 | 
			
		||||
//     val_1 := 1573424111353538
 | 
			
		||||
//     val_2 := 11180339179422519519
 | 
			
		||||
//     val_3 := 5225342777609112214
 | 
			
		||||
//     val_4 := 12264064093151869674
 | 
			
		||||
// }
 | 
			
		||||
@ -0,0 +1,43 @@
 | 
			
		||||
{
 | 
			
		||||
    function swap(x, y) -> a, b
 | 
			
		||||
    {
 | 
			
		||||
        a := y
 | 
			
		||||
        b := x
 | 
			
		||||
    }
 | 
			
		||||
    function main(v1, v2) -> r1, r2
 | 
			
		||||
    {
 | 
			
		||||
        let tmp := 11111111111111111111111111111111111111111111111111111111111111111111111111111
 | 
			
		||||
        r1, r2 := swap(v1, tmp)
 | 
			
		||||
        r1, r2 := swap(2222222222222222222222222222222222222222222222222222222222222222222, r2)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ====
 | 
			
		||||
// step: wordSizeTransform
 | 
			
		||||
// ----
 | 
			
		||||
// {
 | 
			
		||||
//     function swap(x_2, x_3, x_4, x_5, y_6, y_7, y_8, y_9) -> a_10, a_11, a_12, a_13, b_14, b_15, b_16, b_17
 | 
			
		||||
//     {
 | 
			
		||||
//         a_10 := y_6
 | 
			
		||||
//         a_11 := y_7
 | 
			
		||||
//         a_12 := y_8
 | 
			
		||||
//         a_13 := y_9
 | 
			
		||||
//         b_14 := x_2
 | 
			
		||||
//         b_15 := x_3
 | 
			
		||||
//         b_16 := x_4
 | 
			
		||||
//         b_17 := x_5
 | 
			
		||||
//     }
 | 
			
		||||
//     function main(v1_18, v1_19, v1_20, v1_21, v2_22, v2_23, v2_24, v2_25) -> r1_26, r1_27, r1_28, r1_29, r2_30, r2_31, r2_32, r2_33
 | 
			
		||||
//     {
 | 
			
		||||
//         let tmp_34 := 1770102123480502530
 | 
			
		||||
//         let tmp_35 := 591943673742124792
 | 
			
		||||
//         let tmp_36 := 13663686148824196892
 | 
			
		||||
//         let tmp_37 := 8198552921648689607
 | 
			
		||||
//         r1_26, r1_27, r1_28, r1_29, r2_30, r2_31, r2_32, r2_33 := swap(v1_18, v1_19, v1_20, v1_21, tmp_34, tmp_35, tmp_36, tmp_37)
 | 
			
		||||
//         let _1_38 := 354020424
 | 
			
		||||
//         let _1_39 := 12840787883880108911
 | 
			
		||||
//         let _1_40 := 12527970737989311368
 | 
			
		||||
//         let _1_41 := 16397105843297379214
 | 
			
		||||
//         r1_26, r1_27, r1_28, r1_29, r2_30, r2_31, r2_32, r2_33 := swap(_1_38, _1_39, _1_40, _1_41, r2_30, r2_31, r2_32, r2_33)
 | 
			
		||||
//     }
 | 
			
		||||
// }
 | 
			
		||||
@ -0,0 +1,17 @@
 | 
			
		||||
{
 | 
			
		||||
    let x := add(999999999999999999999999999999999999999999999999999999999999999, 77777777777777777777777777777777777777777777777777777777777777)
 | 
			
		||||
}
 | 
			
		||||
// ====
 | 
			
		||||
// step: wordSizeTransform
 | 
			
		||||
// ----
 | 
			
		||||
// {
 | 
			
		||||
//     let _1_3 := 12390
 | 
			
		||||
//     let _1_4 := 13186919961226471680
 | 
			
		||||
//     let _1_5 := 18324050535993369984
 | 
			
		||||
//     let _1_6 := 15884696285694336113
 | 
			
		||||
//     let _2_7 := 159309
 | 
			
		||||
//     let _2_8 := 3525417123811528497
 | 
			
		||||
//     let _2_9 := 6328259118096044006
 | 
			
		||||
//     let _2_10 := 9223372036854775807
 | 
			
		||||
//     let x_11, x_12, x_13, x_14 := add(_2_7, _2_8, _2_9, _2_10, _1_3, _1_4, _1_5, _1_6)
 | 
			
		||||
// }
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user