mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge remote-tracking branch 'origin/develop' into breaking
This commit is contained in:
commit
a7db4fa4a5
@ -4,7 +4,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# https://solidity.readthedocs.org
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# https://solidity.readthedocs.org
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# Configuration Environment Variables:
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# https://solidity.readthedocs.org
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Contribution Guidelines
|
||||
|
||||
Please see our contribution guidelines in [the Solidity documentation](https://solidity.readthedocs.io/en/latest/contributing.html).
|
||||
Please see our contribution guidelines in [the Solidity documentation](https://docs.soliditylang.org/en/latest/contributing.html).
|
||||
|
||||
Thank you for your help!
|
||||
|
41
Changelog.md
41
Changelog.md
@ -25,43 +25,48 @@ Language Features:
|
||||
AST Changes:
|
||||
* New node type: unchecked block - used for ``unchecked { ... }``.
|
||||
|
||||
### 0.7.6 (unreleased)
|
||||
|
||||
### 0.7.5 (unreleased)
|
||||
|
||||
### 0.7.5 (2020-11-18)
|
||||
|
||||
Language Features:
|
||||
* Ability to select the abi coder using ``pragma abicoder v1`` and ``pragma abicoder v2``.
|
||||
* Inline Assembly: Use ``.offset`` and ``.length`` for calldata variables of dynamic array type to access their calldata offset and length (number of elements). Both of them can also be assigned to.
|
||||
* Immutable variables with literal number values are considered pure.
|
||||
|
||||
Compiler Features:
|
||||
* Command Line Interface: New option ``--experimental-via-ir`` allows switching compilation process to go through
|
||||
the Yul intermediate representation. This is highly experimental and is used for development purposes.
|
||||
* Standard JSON: New option ``settings.viaIR`` allows the same switch as ``--experimental-via-ir`` on the commandline.
|
||||
* Assembler: Perform linking in assembly mode when library addresses are provided.
|
||||
* Command Line Interface: New option ``--experimental-via-ir`` allows switching compilation process to go through the Yul intermediate representation. This is highly experimental and is used for development purposes.
|
||||
* Command Line Interface: New option ``--model-checker-timeout`` sets a timeout in milliseconds for each individual query performed by the SMTChecker.
|
||||
* Command Line Interface: Report error if file could not be read in ``--standard-json`` mode.
|
||||
* Command Line interface: Report proper error for each output file which could not be written. Previously an exception was thrown, and execution aborted, on the first error.
|
||||
* SMTChecker: Add division by zero checks in the CHC engine.
|
||||
* SMTChecker: Support ``selector`` for expressions with value known at compile-time.
|
||||
* SMTChecker: More precise analysis of external calls using ``this``.
|
||||
* Command Line Interface: New option ``--model-checker-timeout`` sets a timeout in milliseconds for each individual query performed by the SMTChecker.
|
||||
* SMTChecker: Support ``selector`` for expressions with value known at compile-time.
|
||||
* Standard JSON: New option ``modelCheckerSettings.timeout`` sets a timeout in milliseconds for each individual query performed by the SMTChecker.
|
||||
* Assembler: Perform linking in assembly mode when library addresses are provided.
|
||||
* Standard JSON: New option ``settings.viaIR`` allows the same switch as ``--experimental-via-ir`` on the commandline.
|
||||
|
||||
|
||||
Bugfixes:
|
||||
* Command Line Interface: Reject duplicate libraries in ``--libraries`` option instead of arbitrarily choosing one.
|
||||
* SMTChecker: Fix lack of reporting potential violations when using only the CHC engine.
|
||||
* SMTChecker: Fix internal error on conversion from string literal to byte.
|
||||
* SMTChecker: Fix internal error when using tuples of rational literals inside the conditional operator.
|
||||
* SMTChecker: Fix internal error when assigning state variable via contract's name.
|
||||
* SMTChecker: Fix incorrect counterexamples reported by the CHC engine.
|
||||
* SMTChecker: Fix false negative in modifier applied multiple times.
|
||||
* SMTChecker: Fix internal error in the BMC engine when inherited contract from a different source unit has private state variables.
|
||||
* SMTChecker: Fix internal error when ``array.push()`` is used as the LHS of an assignment.
|
||||
* Command Line Interface: Fix write error when the directory passed to ``--output-dir`` ends with a slash.
|
||||
* SMTChecker: Fix CHC false positives when branches are used inside modifiers.
|
||||
* Code generator: Fix missing creation dependency tracking for abstract contracts.
|
||||
* Command Line Interface: Fix write error when the directory passed to ``--output-dir`` ends with a slash.
|
||||
* Command Line Interface: Reject duplicate libraries in ``--libraries`` option instead of arbitrarily choosing one.
|
||||
* NatSpec: Fix internal error when inheriting return parameter documentation but the parameter names differ between base and inherited.
|
||||
* SMTChecker: Fix CHC false positives when branches are used inside modifiers.
|
||||
* SMTChecker: Fix false negative in modifier applied multiple times.
|
||||
* SMTChecker: Fix incorrect counterexamples reported by the CHC engine.
|
||||
* SMTChecker: Fix internal error in the BMC engine when inherited contract from a different source unit has private state variables.
|
||||
* SMTChecker: Fix internal error on conversion from string literal to byte.
|
||||
* SMTChecker: Fix internal error when ``array.push()`` is used as the LHS of an assignment.
|
||||
* SMTChecker: Fix internal error when assigning state variable via contract's name.
|
||||
* SMTChecker: Fix internal error when using tuples of rational literals inside the conditional operator.
|
||||
* SMTChecker: Fix lack of reporting potential violations when using only the CHC engine.
|
||||
* Standard JSON: Fix library addresses specified in ``libraries`` being used for linking even if the file names do not match.
|
||||
|
||||
AST Changes:
|
||||
* New member ``suffix`` for inline assembly identifiers. Currently supported values are ``"slot"``, ``"offset"`` and ``"length"`` to access the components of a Solidity variable.
|
||||
|
||||
|
||||
### 0.7.4 (2020-10-19)
|
||||
|
||||
|
14
README.md
14
README.md
@ -29,7 +29,7 @@ number [to indicate this fast pace of change](https://semver.org/#spec-item-4).
|
||||
## Build and Install
|
||||
|
||||
Instructions about how to build and install the Solidity compiler can be
|
||||
found in the [Solidity documentation](https://solidity.readthedocs.io/en/latest/installing-solidity.html#building-from-source).
|
||||
found in the [Solidity documentation](https://docs.soliditylang.org/en/latest/installing-solidity.html#building-from-source).
|
||||
|
||||
|
||||
## Example
|
||||
@ -49,20 +49,20 @@ contract HelloWorld {
|
||||
To get started with Solidity, you can use [Remix](https://remix.ethereum.org/), which is a
|
||||
browser-based IDE. Here are some example contracts:
|
||||
|
||||
1. [Voting](https://solidity.readthedocs.io/en/latest/solidity-by-example.html#voting)
|
||||
2. [Blind Auction](https://solidity.readthedocs.io/en/latest/solidity-by-example.html#blind-auction)
|
||||
3. [Safe remote purchase](https://solidity.readthedocs.io/en/latest/solidity-by-example.html#safe-remote-purchase)
|
||||
4. [Micropayment Channel](https://solidity.readthedocs.io/en/latest/solidity-by-example.html#micropayment-channel)
|
||||
1. [Voting](https://docs.soliditylang.org/en/latest/solidity-by-example.html#voting)
|
||||
2. [Blind Auction](https://docs.soliditylang.org/en/latest/solidity-by-example.html#blind-auction)
|
||||
3. [Safe remote purchase](https://docs.soliditylang.org/en/latest/solidity-by-example.html#safe-remote-purchase)
|
||||
4. [Micropayment Channel](https://docs.soliditylang.org/en/latest/solidity-by-example.html#micropayment-channel)
|
||||
|
||||
## Documentation
|
||||
|
||||
The Solidity documentation is hosted at [Read the docs](https://solidity.readthedocs.io).
|
||||
The Solidity documentation is hosted at [Read the docs](https://docs.soliditylang.org).
|
||||
|
||||
## Development
|
||||
|
||||
Solidity is still under development. Contributions are always welcome!
|
||||
Please follow the
|
||||
[Developers Guide](https://solidity.readthedocs.io/en/latest/contributing.html)
|
||||
[Developers Guide](https://docs.soliditylang.org/en/latest/contributing.html)
|
||||
if you want to help.
|
||||
|
||||
You can find our current feature and bug priorities for forthcoming
|
||||
|
@ -48,5 +48,5 @@ The Solidity team maintains the following JSON-formatted lists of patched securi
|
||||
|
||||
[1]: https://bounty.ethereum.org/
|
||||
[2]: https://bounty.ethereum.org/#rules
|
||||
[3]: https://solidity.readthedocs.io/en/develop/bugs.html
|
||||
[3]: https://docs.soliditylang.org/en/develop/bugs.html
|
||||
[4]: https://github.com/ethereum/solidity/blob/develop/docs/bugs_by_version.json
|
||||
|
13
cmake/templates/ewasm_polyfill.in
Normal file
13
cmake/templates/ewasm_polyfill.in
Normal file
@ -0,0 +1,13 @@
|
||||
// The generation of this file is defined in libyul/CMakeLists.txt.
|
||||
// This file was generated by using the content of libyul/backends/wasm/polyfill/@EWASM_POLYFILL_NAME@.yul.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace solidity::yul::wasm::polyfill
|
||||
{
|
||||
|
||||
static char const @EWASM_POLYFILL_NAME@[] = {
|
||||
@EWASM_POLYFILL_CONTENT@, 0
|
||||
};
|
||||
|
||||
} // namespace solidity::yul::wasm::polyfill
|
@ -135,6 +135,10 @@ inside that slot. To retrieve the slot pointed to by the variable ``x``, you
|
||||
use ``x.slot``, and to retrieve the byte-offset you use ``x.offset``.
|
||||
Using ``x`` itself will result in an error.
|
||||
|
||||
For dynamic calldata arrays, you can access
|
||||
their calldata offset (in bytes) and length (number of elements) using ``x.offset`` and ``x.length``.
|
||||
Both expressions can also be assigned to.
|
||||
|
||||
Local Solidity variables are available for assignments, for example:
|
||||
|
||||
.. code::
|
||||
|
@ -1369,5 +1369,9 @@
|
||||
"0.7.4": {
|
||||
"bugs": [],
|
||||
"released": "2020-10-19"
|
||||
},
|
||||
"0.7.5": {
|
||||
"bugs": [],
|
||||
"released": "2020-11-18"
|
||||
}
|
||||
}
|
@ -94,6 +94,9 @@ in the current directory, installed on the system level, or the ``deps`` folder
|
||||
in the project top level. The required file is called ``libevmone.so`` on Linux
|
||||
systems, ``evmone.dll`` on Windows systems and ``libevmone.dylib`` on macOS.
|
||||
|
||||
On macOS some of the testing scripts expect GNU coreutils to be installed.
|
||||
This can be easiest accomplished using Homebrew: ``brew install coreutils``.
|
||||
|
||||
Running the Tests
|
||||
-----------------
|
||||
|
||||
|
@ -441,7 +441,7 @@ Output Description
|
||||
// If the language used has no contract names, this field should equal to an empty string.
|
||||
"ContractName": {
|
||||
// The Ethereum Contract ABI. If empty, it is represented as an empty array.
|
||||
// See https://solidity.readthedocs.io/en/develop/abi-spec.html
|
||||
// See https://docs.soliditylang.org/en/develop/abi-spec.html
|
||||
"abi": [],
|
||||
// See the Metadata Output documentation (serialised JSON string)
|
||||
"metadata": "{...}",
|
||||
|
@ -215,22 +215,21 @@ void ReferencesResolver::operator()(yul::FunctionDefinition const& _function)
|
||||
|
||||
void ReferencesResolver::operator()(yul::Identifier const& _identifier)
|
||||
{
|
||||
bool isSlot = boost::algorithm::ends_with(_identifier.name.str(), ".slot");
|
||||
bool isOffset = boost::algorithm::ends_with(_identifier.name.str(), ".offset");
|
||||
static set<string> suffixes{"slot", "offset", "length"};
|
||||
string suffix;
|
||||
for (string const& s: suffixes)
|
||||
if (boost::algorithm::ends_with(_identifier.name.str(), "." + s))
|
||||
suffix = s;
|
||||
|
||||
// Could also use `pathFromCurrentScope`, split by '.'
|
||||
auto declarations = m_resolver.nameFromCurrentScope(_identifier.name.str());
|
||||
if (isSlot || isOffset)
|
||||
if (!suffix.empty())
|
||||
{
|
||||
// special mode to access storage variables
|
||||
if (!declarations.empty())
|
||||
// the special identifier exists itself, we should not allow that.
|
||||
return;
|
||||
string realName = _identifier.name.str().substr(0, _identifier.name.str().size() - (
|
||||
isSlot ?
|
||||
string(".slot").size() :
|
||||
string(".offset").size()
|
||||
));
|
||||
string realName = _identifier.name.str().substr(0, _identifier.name.str().size() - suffix.size() - 1);
|
||||
solAssert(!realName.empty(), "Empty name.");
|
||||
declarations = m_resolver.nameFromCurrentScope(realName);
|
||||
if (!declarations.empty())
|
||||
@ -255,7 +254,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
|
||||
m_errorReporter.declarationError(
|
||||
9467_error,
|
||||
_identifier.location,
|
||||
"Identifier not found. Use ``.slot`` and ``.offset`` to access storage variables."
|
||||
"Identifier not found. Use \".slot\" and \".offset\" to access storage variables."
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -270,8 +269,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
|
||||
return;
|
||||
}
|
||||
|
||||
m_yulAnnotation->externalReferences[&_identifier].isSlot = isSlot;
|
||||
m_yulAnnotation->externalReferences[&_identifier].isOffset = isOffset;
|
||||
m_yulAnnotation->externalReferences[&_identifier].suffix = move(suffix);
|
||||
m_yulAnnotation->externalReferences[&_identifier].declaration = declarations.front();
|
||||
}
|
||||
|
||||
|
@ -755,7 +755,6 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
InlineAssemblyAnnotation::ExternalIdentifierInfo& identifierInfo = ref->second;
|
||||
Declaration const* declaration = identifierInfo.declaration;
|
||||
solAssert(!!declaration, "");
|
||||
bool requiresStorage = identifierInfo.isSlot || identifierInfo.isOffset;
|
||||
if (auto var = dynamic_cast<VariableDeclaration const*>(declaration))
|
||||
{
|
||||
solAssert(var->type(), "Expected variable type!");
|
||||
@ -778,7 +777,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
m_errorReporter.typeError(6252_error, _identifier.location, "Constant variables cannot be assigned to.");
|
||||
return false;
|
||||
}
|
||||
else if (requiresStorage)
|
||||
else if (!identifierInfo.suffix.empty())
|
||||
{
|
||||
m_errorReporter.typeError(6617_error, _identifier.location, "The suffixes .offset and .slot can only be used on non-constant storage variables.");
|
||||
return false;
|
||||
@ -804,11 +803,15 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
|
||||
solAssert(!dynamic_cast<FixedPointType const*>(var->type()), "FixedPointType not implemented.");
|
||||
|
||||
if (requiresStorage)
|
||||
if (!identifierInfo.suffix.empty())
|
||||
{
|
||||
if (!var->isStateVariable() && !var->type()->dataStoredIn(DataLocation::Storage))
|
||||
string const& suffix = identifierInfo.suffix;
|
||||
solAssert((set<string>{"offset", "slot", "length"}).count(suffix), "");
|
||||
if (var->isStateVariable() || var->type()->dataStoredIn(DataLocation::Storage))
|
||||
{
|
||||
m_errorReporter.typeError(3622_error, _identifier.location, "The suffixes .offset and .slot can only be used on storage variables.");
|
||||
if (suffix != "slot" && suffix != "offset")
|
||||
{
|
||||
m_errorReporter.typeError(4656_error, _identifier.location, "State variables only support \".slot\" and \".offset\".");
|
||||
return false;
|
||||
}
|
||||
else if (_context == yul::IdentifierContext::LValue)
|
||||
@ -818,37 +821,62 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
m_errorReporter.typeError(4713_error, _identifier.location, "State variables cannot be assigned to - you have to use \"sstore()\".");
|
||||
return false;
|
||||
}
|
||||
else if (identifierInfo.isOffset)
|
||||
else if (suffix != "slot")
|
||||
{
|
||||
m_errorReporter.typeError(9739_error, _identifier.location, "Only .slot can be assigned to.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (
|
||||
auto const* arrayType = dynamic_cast<ArrayType const*>(var->type());
|
||||
arrayType && arrayType->isDynamicallySized() && arrayType->dataStoredIn(DataLocation::CallData)
|
||||
)
|
||||
{
|
||||
if (suffix != "offset" && suffix != "length")
|
||||
{
|
||||
m_errorReporter.typeError(1536_error, _identifier.location, "Calldata variables only support \".offset\" and \".length\".");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
solAssert(identifierInfo.isSlot, "");
|
||||
{
|
||||
m_errorReporter.typeError(3622_error, _identifier.location, "The suffix \"." + suffix + "\" is not supported by this variable or type.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!var->isConstant() && var->isStateVariable())
|
||||
{
|
||||
m_errorReporter.typeError(1408_error, _identifier.location, "Only local variables are supported. To access storage variables, use the .slot and .offset suffixes.");
|
||||
m_errorReporter.typeError(
|
||||
1408_error,
|
||||
_identifier.location,
|
||||
"Only local variables are supported. To access storage variables, use the \".slot\" and \".offset\" suffixes."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
else if (var->type()->dataStoredIn(DataLocation::Storage))
|
||||
{
|
||||
m_errorReporter.typeError(9068_error, _identifier.location, "You have to use the .slot or .offset suffix to access storage reference variables.");
|
||||
m_errorReporter.typeError(9068_error, _identifier.location, "You have to use the \".slot\" or \".offset\" suffix to access storage reference variables.");
|
||||
return false;
|
||||
}
|
||||
else if (var->type()->sizeOnStack() != 1)
|
||||
{
|
||||
if (var->type()->dataStoredIn(DataLocation::CallData))
|
||||
m_errorReporter.typeError(2370_error, _identifier.location, "Call data elements cannot be accessed directly. Copy to a local variable first or use \"calldataload\" or \"calldatacopy\" with manually determined offsets and sizes.");
|
||||
if (
|
||||
auto const* arrayType = dynamic_cast<ArrayType const*>(var->type());
|
||||
arrayType && arrayType->isDynamicallySized() && arrayType->dataStoredIn(DataLocation::CallData)
|
||||
)
|
||||
m_errorReporter.typeError(1397_error, _identifier.location, "Call data elements cannot be accessed directly. Use \".offset\" and \".length\" to access the calldata offset and length of this array and then use \"calldatacopy\".");
|
||||
else
|
||||
{
|
||||
solAssert(!var->type()->dataStoredIn(DataLocation::CallData), "");
|
||||
m_errorReporter.typeError(9857_error, _identifier.location, "Only types that use one stack slot are supported.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (requiresStorage)
|
||||
else if (!identifierInfo.suffix.empty())
|
||||
{
|
||||
m_errorReporter.typeError(7944_error, _identifier.location, "The suffixes .offset and .slot can only be used on storage variables.");
|
||||
m_errorReporter.typeError(7944_error, _identifier.location, "The suffixes \".offset\", \".slot\" and \".length\" can only be used with variables.");
|
||||
return false;
|
||||
}
|
||||
else if (_context == yul::IdentifierContext::LValue)
|
||||
@ -3277,7 +3305,7 @@ void TypeChecker::endVisit(Literal const& _literal)
|
||||
_literal.location(),
|
||||
msg +
|
||||
" If this is not used as an address, please prepend '00'. " +
|
||||
"For more information please see https://solidity.readthedocs.io/en/develop/types.html#address-literals"
|
||||
"For more information please see https://docs.soliditylang.org/en/develop/types.html#address-literals"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -198,8 +198,8 @@ struct InlineAssemblyAnnotation: StatementAnnotation
|
||||
struct ExternalIdentifierInfo
|
||||
{
|
||||
Declaration const* declaration = nullptr;
|
||||
bool isSlot = false; ///< Whether the storage slot of a variable is queried.
|
||||
bool isOffset = false; ///< Whether the intra-slot offset of a storage variable is queried.
|
||||
/// Suffix used, one of "slot", "offset", "length" or empty.
|
||||
std::string suffix;
|
||||
size_t valueSize = size_t(-1);
|
||||
};
|
||||
|
||||
|
@ -224,8 +224,10 @@ Json::Value ASTJsonConverter::inlineAssemblyIdentifierToJson(pair<yul::Identifie
|
||||
Json::Value tuple(Json::objectValue);
|
||||
tuple["src"] = sourceLocationToString(_info.first->location);
|
||||
tuple["declaration"] = idOrNull(_info.second.declaration);
|
||||
tuple["isSlot"] = Json::Value(_info.second.isSlot);
|
||||
tuple["isOffset"] = Json::Value(_info.second.isOffset);
|
||||
tuple["isSlot"] = Json::Value(_info.second.suffix == "slot");
|
||||
tuple["isOffset"] = Json::Value(_info.second.suffix == "offset");
|
||||
if (!_info.second.suffix.empty())
|
||||
tuple["suffix"] = Json::Value(_info.second.suffix);
|
||||
tuple["valueSize"] = Json::Value(Json::LargestUInt(_info.second.valueSize));
|
||||
return tuple;
|
||||
}
|
||||
|
@ -756,9 +756,9 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
else if (m_context.isStateVariable(decl))
|
||||
{
|
||||
auto const& location = m_context.storageLocationOfVariable(*decl);
|
||||
if (ref->second.isSlot)
|
||||
if (ref->second.suffix == "slot")
|
||||
m_context << location.first;
|
||||
else if (ref->second.isOffset)
|
||||
else if (ref->second.suffix == "offset")
|
||||
m_context << u256(location.second);
|
||||
else
|
||||
solAssert(false, "");
|
||||
@ -766,27 +766,45 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
else if (m_context.isLocalVariable(decl))
|
||||
{
|
||||
unsigned stackDiff = static_cast<unsigned>(_assembly.stackHeight()) - m_context.baseStackOffsetOfVariable(*variable);
|
||||
if (ref->second.isSlot || ref->second.isOffset)
|
||||
if (!ref->second.suffix.empty())
|
||||
{
|
||||
solAssert(variable->type()->dataStoredIn(DataLocation::Storage), "");
|
||||
string const& suffix = ref->second.suffix;
|
||||
if (variable->type()->dataStoredIn(DataLocation::Storage))
|
||||
{
|
||||
solAssert(suffix == "offset" || suffix == "slot", "");
|
||||
unsigned size = variable->type()->sizeOnStack();
|
||||
if (size == 2)
|
||||
{
|
||||
// slot plus offset
|
||||
if (ref->second.isOffset)
|
||||
if (suffix == "offset")
|
||||
stackDiff--;
|
||||
}
|
||||
else
|
||||
{
|
||||
solAssert(size == 1, "");
|
||||
// only slot, offset is zero
|
||||
if (ref->second.isOffset)
|
||||
if (suffix == "offset")
|
||||
{
|
||||
_assembly.appendConstant(u256(0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (variable->type()->dataStoredIn(DataLocation::CallData))
|
||||
{
|
||||
auto const* arrayType = dynamic_cast<ArrayType const*>(variable->type());
|
||||
solAssert(
|
||||
arrayType && arrayType->isDynamicallySized() && arrayType->dataStoredIn(DataLocation::CallData),
|
||||
""
|
||||
);
|
||||
solAssert(suffix == "offset" || suffix == "length", "");
|
||||
solAssert(variable->type()->sizeOnStack() == 2, "");
|
||||
if (suffix == "length")
|
||||
stackDiff--;
|
||||
}
|
||||
else
|
||||
solAssert(false, "");
|
||||
}
|
||||
else
|
||||
solAssert(variable->type()->sizeOnStack() == 1, "");
|
||||
if (stackDiff < 1 || stackDiff > 16)
|
||||
@ -795,7 +813,6 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
errinfo_sourceLocation(_inlineAssembly.location()) <<
|
||||
errinfo_comment("Stack too deep, try removing local variables.")
|
||||
);
|
||||
solAssert(variable->type()->sizeOnStack() == 1, "");
|
||||
_assembly.appendInstruction(dupInstruction(stackDiff));
|
||||
}
|
||||
else
|
||||
@ -803,7 +820,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
}
|
||||
else if (auto contract = dynamic_cast<ContractDefinition const*>(decl))
|
||||
{
|
||||
solAssert(!ref->second.isOffset && !ref->second.isSlot, "");
|
||||
solAssert(ref->second.suffix.empty(), "");
|
||||
solAssert(contract->isLibrary(), "");
|
||||
_assembly.appendLinkerSymbol(contract->fullyQualifiedName());
|
||||
}
|
||||
@ -814,20 +831,39 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
else
|
||||
{
|
||||
// lvalue context
|
||||
solAssert(!ref->second.isOffset, "");
|
||||
auto variable = dynamic_cast<VariableDeclaration const*>(decl);
|
||||
unsigned stackDiff = static_cast<unsigned>(_assembly.stackHeight()) - m_context.baseStackOffsetOfVariable(*variable) - 1;
|
||||
string const& suffix = ref->second.suffix;
|
||||
if (variable->type()->dataStoredIn(DataLocation::Storage))
|
||||
{
|
||||
solAssert(
|
||||
!!variable && m_context.isLocalVariable(variable),
|
||||
"Can only assign to stack variables in inline assembly."
|
||||
);
|
||||
solAssert(variable->type()->sizeOnStack() == 1, "");
|
||||
unsigned stackDiff = static_cast<unsigned>(_assembly.stackHeight()) - m_context.baseStackOffsetOfVariable(*variable) - 1;
|
||||
solAssert(suffix == "slot", "");
|
||||
if (stackDiff > 16 || stackDiff < 1)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
StackTooDeepError() <<
|
||||
errinfo_sourceLocation(_inlineAssembly.location()) <<
|
||||
errinfo_comment("Stack too deep(" + to_string(stackDiff) + "), try removing local variables.")
|
||||
);
|
||||
}
|
||||
else if (variable->type()->dataStoredIn(DataLocation::CallData))
|
||||
{
|
||||
auto const* arrayType = dynamic_cast<ArrayType const*>(variable->type());
|
||||
solAssert(
|
||||
arrayType && arrayType->isDynamicallySized() && arrayType->dataStoredIn(DataLocation::CallData),
|
||||
""
|
||||
);
|
||||
solAssert(suffix == "offset" || suffix == "length", "");
|
||||
solAssert(variable->type()->sizeOnStack() == 2, "");
|
||||
if (suffix == "length")
|
||||
stackDiff--;
|
||||
}
|
||||
else
|
||||
solAssert(suffix.empty(), "");
|
||||
|
||||
_assembly.appendInstruction(swapInstruction(stackDiff));
|
||||
_assembly.appendInstruction(Instruction::POP);
|
||||
}
|
||||
|
@ -3157,6 +3157,19 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
|
||||
solUnimplementedAssert(false, "Tuple conversion not implemented.");
|
||||
break;
|
||||
}
|
||||
case Type::Category::TypeType:
|
||||
{
|
||||
TypeType const& typeType = dynamic_cast<decltype(typeType)>(_from);
|
||||
if (
|
||||
auto const* contractType = dynamic_cast<ContractType const*>(typeType.actualType());
|
||||
contractType->contractDefinition().isLibrary() &&
|
||||
_to == *TypeProvider::address()
|
||||
)
|
||||
body = "converted := value";
|
||||
else
|
||||
solAssert(false, "Invalid conversion from " + _from.canonicalName() + " to " + _to.canonicalName());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
solAssert(false, "Invalid conversion from " + _from.canonicalName() + " to " + _to.canonicalName());
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <libsolidity/codegen/CompilerUtils.h>
|
||||
#include <libsolidity/codegen/ReturnInfo.h>
|
||||
#include <libsolidity/ast/TypeProvider.h>
|
||||
#include <libsolidity/ast/ASTUtils.h>
|
||||
|
||||
#include <libevmasm/GasMeter.h>
|
||||
|
||||
@ -68,42 +69,11 @@ struct CopyTranslate: public yul::ASTCopier
|
||||
|
||||
yul::Expression operator()(yul::Identifier const& _identifier) override
|
||||
{
|
||||
// The operator() function is only called in lvalue context. In rvalue context,
|
||||
// only translate(yul::Identifier) is called.
|
||||
if (m_references.count(&_identifier))
|
||||
{
|
||||
auto const& reference = m_references.at(&_identifier);
|
||||
auto const varDecl = dynamic_cast<VariableDeclaration const*>(reference.declaration);
|
||||
solUnimplementedAssert(varDecl, "");
|
||||
|
||||
if (reference.isOffset || reference.isSlot)
|
||||
{
|
||||
solAssert(reference.isOffset != reference.isSlot, "");
|
||||
|
||||
string value;
|
||||
if (varDecl->isStateVariable())
|
||||
value =
|
||||
reference.isSlot ?
|
||||
m_context.storageLocationOfStateVariable(*varDecl).first.str() :
|
||||
to_string(m_context.storageLocationOfStateVariable(*varDecl).second);
|
||||
return translateReference(_identifier);
|
||||
else
|
||||
{
|
||||
solAssert(varDecl->isLocalVariable(), "");
|
||||
if (reference.isSlot)
|
||||
value = IRVariable{*varDecl}.part("slot").name();
|
||||
else if (varDecl->type()->isValueType())
|
||||
value = IRVariable{*varDecl}.part("offset").name();
|
||||
else
|
||||
{
|
||||
solAssert(!IRVariable{*varDecl}.hasPart("offset"), "");
|
||||
value = "0";
|
||||
}
|
||||
}
|
||||
|
||||
if (isdigit(value.front()))
|
||||
return yul::Literal{_identifier.location, yul::LiteralKind::Number, yul::YulString{value}, {}};
|
||||
else
|
||||
return yul::Identifier{_identifier.location, yul::YulString{value}};
|
||||
}
|
||||
}
|
||||
return ASTCopier::operator()(_identifier);
|
||||
}
|
||||
|
||||
@ -124,14 +94,25 @@ struct CopyTranslate: public yul::ASTCopier
|
||||
if (!m_references.count(&_identifier))
|
||||
return ASTCopier::translate(_identifier);
|
||||
|
||||
yul::Expression translated = translateReference(_identifier);
|
||||
solAssert(holds_alternative<yul::Identifier>(translated), "");
|
||||
return get<yul::Identifier>(std::move(translated));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Translates a reference to a local variable, potentially including
|
||||
/// a suffix. Might return a literal, which causes this to be invalid in
|
||||
/// lvalue-context.
|
||||
yul::Expression translateReference(yul::Identifier const& _identifier)
|
||||
{
|
||||
auto const& reference = m_references.at(&_identifier);
|
||||
auto const varDecl = dynamic_cast<VariableDeclaration const*>(reference.declaration);
|
||||
solUnimplementedAssert(varDecl, "");
|
||||
string const& suffix = reference.suffix;
|
||||
|
||||
solAssert(
|
||||
reference.isOffset == false && reference.isSlot == false,
|
||||
"Should not be called for offset/slot"
|
||||
);
|
||||
if (suffix.empty() && !varDecl->isStateVariable())
|
||||
{
|
||||
auto const& var = m_context.localVariable(*varDecl);
|
||||
solAssert(var.type().sizeOnStack() == 1, "");
|
||||
|
||||
@ -141,7 +122,86 @@ struct CopyTranslate: public yul::ASTCopier
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
string value;
|
||||
if (varDecl->isConstant())
|
||||
{
|
||||
VariableDeclaration const* variable = rootConstVariableDeclaration(*varDecl);
|
||||
solAssert(variable, "");
|
||||
|
||||
if (variable->value()->annotation().type->category() == Type::Category::RationalNumber)
|
||||
{
|
||||
u256 intValue = dynamic_cast<RationalNumberType const&>(*variable->value()->annotation().type).literalValue(nullptr);
|
||||
if (auto const* bytesType = dynamic_cast<FixedBytesType const*>(variable->type()))
|
||||
intValue <<= 256 - 8 * bytesType->numBytes();
|
||||
else
|
||||
solAssert(variable->type()->category() == Type::Category::Integer, "");
|
||||
value = intValue.str();
|
||||
}
|
||||
else if (auto const* literal = dynamic_cast<Literal const*>(variable->value().get()))
|
||||
{
|
||||
TypePointer type = literal->annotation().type;
|
||||
|
||||
switch (type->category())
|
||||
{
|
||||
case Type::Category::Bool:
|
||||
case Type::Category::Address:
|
||||
solAssert(type->category() == variable->annotation().type->category(), "");
|
||||
value = toCompactHexWithPrefix(type->literalValue(literal));
|
||||
break;
|
||||
case Type::Category::StringLiteral:
|
||||
{
|
||||
auto const& stringLiteral = dynamic_cast<StringLiteralType const&>(*type);
|
||||
solAssert(variable->type()->category() == Type::Category::FixedBytes, "");
|
||||
unsigned const numBytes = dynamic_cast<FixedBytesType const&>(*variable->type()).numBytes();
|
||||
solAssert(stringLiteral.value().size() <= numBytes, "");
|
||||
value = formatNumber(u256(h256(stringLiteral.value(), h256::AlignLeft)));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
solAssert(false, "");
|
||||
}
|
||||
}
|
||||
else
|
||||
solAssert(false, "Invalid constant in inline assembly.");
|
||||
}
|
||||
else if (varDecl->isStateVariable())
|
||||
{
|
||||
if (suffix == "slot")
|
||||
value = m_context.storageLocationOfStateVariable(*varDecl).first.str();
|
||||
else if (suffix == "offset")
|
||||
value = to_string(m_context.storageLocationOfStateVariable(*varDecl).second);
|
||||
else
|
||||
solAssert(false, "");
|
||||
}
|
||||
else if (varDecl->type()->dataStoredIn(DataLocation::Storage))
|
||||
{
|
||||
solAssert(suffix == "slot" || suffix == "offset", "");
|
||||
solAssert(varDecl->isLocalVariable(), "");
|
||||
if (suffix == "slot")
|
||||
value = IRVariable{*varDecl}.part("slot").name();
|
||||
else if (varDecl->type()->isValueType())
|
||||
value = IRVariable{*varDecl}.part("offset").name();
|
||||
else
|
||||
{
|
||||
solAssert(!IRVariable{*varDecl}.hasPart("offset"), "");
|
||||
value = "0";
|
||||
}
|
||||
}
|
||||
else if (varDecl->type()->dataStoredIn(DataLocation::CallData))
|
||||
{
|
||||
solAssert(suffix == "offset" || suffix == "length", "");
|
||||
value = IRVariable{*varDecl}.part(suffix).name();
|
||||
}
|
||||
else
|
||||
solAssert(false, "");
|
||||
|
||||
if (isdigit(value.front()))
|
||||
return yul::Literal{_identifier.location, yul::LiteralKind::Number, yul::YulString{value}, {}};
|
||||
else
|
||||
return yul::Identifier{_identifier.location, yul::YulString{value}};
|
||||
}
|
||||
|
||||
|
||||
yul::Dialect const& m_dialect;
|
||||
IRGenerationContext& m_context;
|
||||
ExternalRefsMap const& m_references;
|
||||
@ -857,10 +917,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
{
|
||||
solAssert(!functionType->bound(), "");
|
||||
if (auto contractType = dynamic_cast<ContractType const*>(expressionType->actualType()))
|
||||
solUnimplementedAssert(
|
||||
!contractType->contractDefinition().isLibrary() || functionType->kind() == FunctionType::Kind::Internal,
|
||||
"Only internal function calls implemented for libraries"
|
||||
);
|
||||
if (contractType->contractDefinition().isLibrary())
|
||||
solAssert(functionType->kind() == FunctionType::Kind::Internal || functionType->kind() == FunctionType::Kind::DelegateCall, "");
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2143,9 +2201,10 @@ void IRGeneratorForStatements::endVisit(Identifier const& _identifier)
|
||||
}
|
||||
else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(declaration))
|
||||
handleVariableReference(*varDecl, _identifier);
|
||||
else if (dynamic_cast<ContractDefinition const*>(declaration))
|
||||
else if (auto const* contract = dynamic_cast<ContractDefinition const*>(declaration))
|
||||
{
|
||||
// no-op
|
||||
if (contract->isLibrary())
|
||||
define(IRVariable(_identifier).part("address")) << linkerSymbol(*contract) << "\n";
|
||||
}
|
||||
else if (dynamic_cast<EventDefinition const*>(declaration))
|
||||
{
|
||||
@ -2965,3 +3024,9 @@ void IRGeneratorForStatements::setLocation(ASTNode const& _node)
|
||||
{
|
||||
m_currentLocation = _node.location();
|
||||
}
|
||||
|
||||
string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const
|
||||
{
|
||||
solAssert(_library.isLibrary(), "");
|
||||
return "linkersymbol(" + util::escapeAndQuoteString(_library.fullyQualifiedName()) + ")";
|
||||
}
|
||||
|
@ -186,6 +186,8 @@ private:
|
||||
|
||||
void setLocation(ASTNode const& _node);
|
||||
|
||||
std::string linkerSymbol(ContractDefinition const& _library) const;
|
||||
|
||||
std::ostringstream m_code;
|
||||
IRGenerationContext& m_context;
|
||||
YulUtilFunctions& m_utils;
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
/**
|
||||
* Utilities to handle the Contract ABI (https://solidity.readthedocs.io/en/develop/abi-spec.html)
|
||||
* Utilities to handle the Contract ABI (https://docs.soliditylang.org/en/develop/abi-spec.html)
|
||||
*/
|
||||
|
||||
#include <libsolidity/interface/ABI.h>
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
/**
|
||||
* Utilities to handle the Contract ABI (https://solidity.readthedocs.io/en/develop/abi-spec.html)
|
||||
* Utilities to handle the Contract ABI (https://docs.soliditylang.org/en/develop/abi-spec.html)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -61,6 +61,14 @@ add_library(yul
|
||||
backends/wasm/WasmObjectCompiler.h
|
||||
backends/wasm/WordSizeTransform.cpp
|
||||
backends/wasm/WordSizeTransform.h
|
||||
backends/wasm/polyfill/Arithmetic.yul
|
||||
backends/wasm/polyfill/Bitwise.yul
|
||||
backends/wasm/polyfill/Comparison.yul
|
||||
backends/wasm/polyfill/Conversion.yul
|
||||
backends/wasm/polyfill/Interface.yul
|
||||
backends/wasm/polyfill/Keccak.yul
|
||||
backends/wasm/polyfill/Logical.yul
|
||||
backends/wasm/polyfill/Memory.yul
|
||||
optimiser/ASTCopier.cpp
|
||||
optimiser/ASTCopier.h
|
||||
optimiser/ASTWalker.cpp
|
||||
@ -179,4 +187,15 @@ add_library(yul
|
||||
optimiser/VarNameCleaner.h
|
||||
)
|
||||
|
||||
set(POLYFILLS Arithmetic Bitwise Comparison Conversion Interface Keccak Logical Memory)
|
||||
foreach(polyfill IN LISTS POLYFILLS)
|
||||
set(POLYFILL_FILE ${CMAKE_SOURCE_DIR}/libyul/backends/wasm/polyfill/${polyfill}.yul)
|
||||
file(READ ${POLYFILL_FILE} EWASM_POLYFILL_CONTENT HEX)
|
||||
string(REGEX MATCHALL ".." EWASM_POLYFILL_CONTENT "${EWASM_POLYFILL_CONTENT}")
|
||||
string(REGEX REPLACE ";" ",\n\t0x" EWASM_POLYFILL_CONTENT "${EWASM_POLYFILL_CONTENT}")
|
||||
set(EWASM_POLYFILL_CONTENT "0x${EWASM_POLYFILL_CONTENT}")
|
||||
set(EWASM_POLYFILL_NAME ${polyfill})
|
||||
configure_file("${CMAKE_SOURCE_DIR}/cmake/templates/ewasm_polyfill.in" ${CMAKE_BINARY_DIR}/include/ewasmPolyfills/${polyfill}.h @ONLY)
|
||||
endforeach()
|
||||
|
||||
target_link_libraries(yul PUBLIC evmasm solutil langutil smtutil)
|
File diff suppressed because it is too large
Load Diff
396
libyul/backends/wasm/polyfill/Arithmetic.yul
Normal file
396
libyul/backends/wasm/polyfill/Arithmetic.yul
Normal file
@ -0,0 +1,396 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
// NOTE: This file is used to generate `ewasmPolyfills/Arithmetic.h`.
|
||||
|
||||
// returns a + y + c plus carry value on 64 bit values.
|
||||
// c should be at most 1
|
||||
function add_carry(x, y, c) -> r, r_c {
|
||||
let t := i64.add(x, y)
|
||||
r := i64.add(t, c)
|
||||
r_c := i64.extend_i32_u(i32.or(
|
||||
i64.lt_u(t, x),
|
||||
i64.lt_u(r, t)
|
||||
))
|
||||
}
|
||||
|
||||
function add(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
let carry
|
||||
r4, carry := add_carry(x4, y4, 0)
|
||||
r3, carry := add_carry(x3, y3, carry)
|
||||
r2, carry := add_carry(x2, y2, carry)
|
||||
r1, carry := add_carry(x1, y1, carry)
|
||||
}
|
||||
|
||||
function sub(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// x - y = x + (~y + 1)
|
||||
let carry
|
||||
r4, carry := add_carry(x4, bit_negate(y4), 1)
|
||||
r3, carry := add_carry(x3, bit_negate(y3), carry)
|
||||
r2, carry := add_carry(x2, bit_negate(y2), carry)
|
||||
r1, carry := add_carry(x1, bit_negate(y1), carry)
|
||||
}
|
||||
|
||||
function sub320(x1, x2, x3, x4, x5, y1, y2, y3, y4, y5) -> r1, r2, r3, r4, r5 {
|
||||
// x - y = x + (~y + 1)
|
||||
let carry
|
||||
r5, carry := add_carry(x5, bit_negate(y5), 1)
|
||||
r4, carry := add_carry(x4, bit_negate(y4), carry)
|
||||
r3, carry := add_carry(x3, bit_negate(y3), carry)
|
||||
r2, carry := add_carry(x2, bit_negate(y2), carry)
|
||||
r1, carry := add_carry(x1, bit_negate(y1), carry)
|
||||
}
|
||||
|
||||
function sub512(x1, x2, x3, x4, x5, x6, x7, x8, y1, y2, y3, y4, y5, y6, y7, y8) -> r1, r2, r3, r4, r5, r6, r7, r8 {
|
||||
// x - y = x + (~y + 1)
|
||||
let carry
|
||||
r8, carry := add_carry(x8, bit_negate(y8), 1)
|
||||
r7, carry := add_carry(x7, bit_negate(y7), carry)
|
||||
r6, carry := add_carry(x6, bit_negate(y6), carry)
|
||||
r5, carry := add_carry(x5, bit_negate(y5), carry)
|
||||
r4, carry := add_carry(x4, bit_negate(y4), carry)
|
||||
r3, carry := add_carry(x3, bit_negate(y3), carry)
|
||||
r2, carry := add_carry(x2, bit_negate(y2), carry)
|
||||
r1, carry := add_carry(x1, bit_negate(y1), carry)
|
||||
}
|
||||
|
||||
// Multiplies two 64 bit values resulting in a 128 bit
|
||||
// value split into two 64 bit values.
|
||||
function mul_64x64_128(x, y) -> hi, lo {
|
||||
let xh, xl := split(x)
|
||||
let yh, yl := split(y)
|
||||
let t0 := i64.mul(xl, yl)
|
||||
let t1 := i64.mul(xh, yl)
|
||||
let t2 := i64.mul(xl, yh)
|
||||
let t3 := i64.mul(xh, yh)
|
||||
let t0h, t0l := split(t0)
|
||||
let u1 := i64.add(t1, t0h)
|
||||
let u1h, u1l := split(u1)
|
||||
let u2 := i64.add(t2, u1l)
|
||||
lo := i64.or(i64.shl(u2, 32), t0l)
|
||||
hi := i64.add(t3, i64.add(i64.shr_u(u2, 32), u1h))
|
||||
}
|
||||
|
||||
// Multiplies two 128 bit values resulting in a 256 bit
|
||||
// value split into four 64 bit values.
|
||||
function mul_128x128_256(x1, x2, y1, y2) -> r1, r2, r3, r4 {
|
||||
let ah, al := mul_64x64_128(x1, y1)
|
||||
let bh, bl := mul_64x64_128(x1, y2)
|
||||
let ch, cl := mul_64x64_128(x2, y1)
|
||||
let dh, dl := mul_64x64_128(x2, y2)
|
||||
r4 := dl
|
||||
let carry1, carry2
|
||||
let t1, t2
|
||||
r3, carry1 := add_carry(bl, cl, 0)
|
||||
r3, carry2 := add_carry(r3, dh, 0)
|
||||
t1, carry1 := add_carry(bh, ch, carry1)
|
||||
r2, carry2 := add_carry(t1, al, carry2)
|
||||
r1 := i64.add(i64.add(ah, carry1), carry2)
|
||||
}
|
||||
|
||||
// Multiplies two 256 bit values resulting in a 512 bit
|
||||
// value split into eight 64 bit values.
|
||||
function mul_256x256_512(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4, r5, r6, r7, r8 {
|
||||
let a1, a2, a3, a4 := mul_128x128_256(x1, x2, y1, y2)
|
||||
let b1, b2, b3, b4 := mul_128x128_256(x1, x2, y3, y4)
|
||||
let c1, c2, c3, c4 := mul_128x128_256(x3, x4, y1, y2)
|
||||
let d1, d2, d3, d4 := mul_128x128_256(x3, x4, y3, y4)
|
||||
r8 := d4
|
||||
r7 := d3
|
||||
let carry1, carry2
|
||||
let t1, t2
|
||||
r6, carry1 := add_carry(b4, c4, 0)
|
||||
r6, carry2 := add_carry(r6, d2, 0)
|
||||
r5, carry1 := add_carry(b3, c3, carry1)
|
||||
r5, carry2 := add_carry(r5, d1, carry2)
|
||||
r4, carry1 := add_carry(a4, b2, carry1)
|
||||
r4, carry2 := add_carry(r4, c2, carry2)
|
||||
r3, carry1 := add_carry(a3, b1, carry1)
|
||||
r3, carry2 := add_carry(r3, c1, carry2)
|
||||
r2, carry1 := add_carry(a2, carry1, carry2)
|
||||
r1 := i64.add(a1, carry1)
|
||||
}
|
||||
|
||||
function mul(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// TODO it would actually suffice to have mul_128x128_128 for the first two.
|
||||
let b1, b2, b3, b4 := mul_128x128_256(x3, x4, y1, y2)
|
||||
let c1, c2, c3, c4 := mul_128x128_256(x1, x2, y3, y4)
|
||||
let d1, d2, d3, d4 := mul_128x128_256(x3, x4, y3, y4)
|
||||
r4 := d4
|
||||
r3 := d3
|
||||
let t1, t2
|
||||
t1, t2, r1, r2 := add(0, 0, b3, b4, 0, 0, c3, c4)
|
||||
t1, t2, r1, r2 := add(0, 0, r1, r2, 0, 0, d1, d2)
|
||||
}
|
||||
|
||||
function div(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// Based on https://github.com/ewasm/evm2wasm/blob/master/wasm/DIV.wast
|
||||
if iszero256(y1, y2, y3, y4) {
|
||||
leave
|
||||
}
|
||||
|
||||
let m1 := 0
|
||||
let m2 := 0
|
||||
let m3 := 0
|
||||
let m4 := 1
|
||||
|
||||
for {} true {} {
|
||||
if i32.or(i64.eqz(i64.clz(y1)), gte_256x256_64(y1, y2, y3, y4, x1, x2, x3, x4)) {
|
||||
break
|
||||
}
|
||||
y1, y2, y3, y4 := shl_internal(1, y1, y2, y3, y4)
|
||||
m1, m2, m3, m4 := shl_internal(1, m1, m2, m3, m4)
|
||||
}
|
||||
|
||||
for {} or_bool(m1, m2, m3, m4) {} {
|
||||
if gte_256x256_64(x1, x2, x3, x4, y1, y2, y3, y4) {
|
||||
x1, x2, x3, x4 := sub(x1, x2, x3, x4, y1, y2, y3, y4)
|
||||
r1, r2, r3, r4 := add(r1, r2, r3, r4, m1, m2, m3, m4)
|
||||
}
|
||||
y1, y2, y3, y4 := shr_internal(1, y1, y2, y3, y4)
|
||||
m1, m2, m3, m4 := shr_internal(1, m1, m2, m3, m4)
|
||||
}
|
||||
}
|
||||
|
||||
function sdiv(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// Based on https://github.com/ewasm/evm2wasm/blob/master/wasm/SDIV.wast
|
||||
|
||||
let sign:i32 := i32.wrap_i64(i64.shr_u(i64.xor(x1, y1), 63))
|
||||
|
||||
if i64.eqz(i64.clz(x1)) {
|
||||
x1, x2, x3, x4 := xor(
|
||||
x1, x2, x3, x4,
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
x1, x2, x3, x4 := add(x1, x2, x3, x4, 0, 0, 0, 1)
|
||||
}
|
||||
|
||||
if i64.eqz(i64.clz(y1)) {
|
||||
y1, y2, y3, y4 := xor(
|
||||
y1, y2, y3, y4,
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
y1, y2, y3, y4 := add(y1, y2, y3, y4, 0, 0, 0, 1)
|
||||
}
|
||||
|
||||
r1, r2, r3, r4 := div(x1, x2, x3, x4, y1, y2, y3, y4)
|
||||
|
||||
if sign {
|
||||
r1, r2, r3, r4 := xor(
|
||||
r1, r2, r3, r4,
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
r1, r2, r3, r4 := add(r1, r2, r3, r4, 0, 0, 0, 1)
|
||||
}
|
||||
}
|
||||
|
||||
function mod(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// Based on https://github.com/ewasm/evm2wasm/blob/master/wasm/MOD.wast
|
||||
if iszero256(y1, y2, y3, y4) {
|
||||
leave
|
||||
}
|
||||
|
||||
r1 := x1
|
||||
r2 := x2
|
||||
r3 := x3
|
||||
r4 := x4
|
||||
|
||||
let m1 := 0
|
||||
let m2 := 0
|
||||
let m3 := 0
|
||||
let m4 := 1
|
||||
|
||||
for {} true {} {
|
||||
if i32.or(i64.eqz(i64.clz(y1)), gte_256x256_64(y1, y2, y3, y4, r1, r2, r3, r4)) {
|
||||
break
|
||||
}
|
||||
|
||||
y1, y2, y3, y4 := shl_internal(1, y1, y2, y3, y4)
|
||||
m1, m2, m3, m4 := shl_internal(1, m1, m2, m3, m4)
|
||||
}
|
||||
|
||||
for {} or_bool(m1, m2, m3, m4) {} {
|
||||
if gte_256x256_64(r1, r2, r3, r4, y1, y2, y3, y4) {
|
||||
r1, r2, r3, r4 := sub(r1, r2, r3, r4, y1, y2, y3, y4)
|
||||
}
|
||||
|
||||
y1, y2, y3, y4 := shr_internal(1, y1, y2, y3, y4)
|
||||
m1, m2, m3, m4 := shr_internal(1, m1, m2, m3, m4)
|
||||
}
|
||||
}
|
||||
|
||||
function mod320(x1, x2, x3, x4, x5, y1, y2, y3, y4, y5) -> r1, r2, r3, r4, r5 {
|
||||
// Based on https://github.com/ewasm/evm2wasm/blob/master/wasm/mod_320.wast
|
||||
if iszero320(y1, y2, y3, y4, y5) {
|
||||
leave
|
||||
}
|
||||
|
||||
let m1 := 0
|
||||
let m2 := 0
|
||||
let m3 := 0
|
||||
let m4 := 0
|
||||
let m5 := 1
|
||||
|
||||
r1 := x1
|
||||
r2 := x2
|
||||
r3 := x3
|
||||
r4 := x4
|
||||
r5 := x5
|
||||
|
||||
for {} true {} {
|
||||
if i32.or(i64.eqz(i64.clz(y1)), gte_320x320_64(y1, y2, y3, y4, y5, r1, r2, r3, r4, r5)) {
|
||||
break
|
||||
}
|
||||
y1, y2, y3, y4, y5 := shl320_internal(1, y1, y2, y3, y4, y5)
|
||||
m1, m2, m3, m4, m5 := shl320_internal(1, m1, m2, m3, m4, m5)
|
||||
}
|
||||
|
||||
for {} or_bool_320(m1, m2, m3, m4, m5) {} {
|
||||
if gte_320x320_64(r1, r2, r3, r4, r5, y1, y2, y3, y4, y5) {
|
||||
r1, r2, r3, r4, r5 := sub320(r1, r2, r3, r4, r5, y1, y2, y3, y4, y5)
|
||||
}
|
||||
|
||||
y1, y2, y3, y4, y5 := shr320_internal(1, y1, y2, y3, y4, y5)
|
||||
m1, m2, m3, m4, m5 := shr320_internal(1, m1, m2, m3, m4, m5)
|
||||
}
|
||||
}
|
||||
|
||||
function mod512(x1, x2, x3, x4, x5, x6, x7, x8, y1, y2, y3, y4, y5, y6, y7, y8) -> r1, r2, r3, r4, r5, r6, r7, r8 {
|
||||
// Based on https://github.com/ewasm/evm2wasm/blob/master/wasm/mod_512.wast
|
||||
if iszero512(y1, y2, y3, y4, y5, y6, y7, y8) {
|
||||
leave
|
||||
}
|
||||
|
||||
let m1 := 0
|
||||
let m2 := 0
|
||||
let m3 := 0
|
||||
let m4 := 0
|
||||
let m5 := 0
|
||||
let m6 := 0
|
||||
let m7 := 0
|
||||
let m8 := 1
|
||||
|
||||
r1 := x1
|
||||
r2 := x2
|
||||
r3 := x3
|
||||
r4 := x4
|
||||
r5 := x5
|
||||
r6 := x6
|
||||
r7 := x7
|
||||
r8 := x8
|
||||
|
||||
for {} true {} {
|
||||
if i32.or(
|
||||
i64.eqz(i64.clz(y1)),
|
||||
gte_512x512_64(y1, y2, y3, y4, y5, y6, y7, y8, r1, r2, r3, r4, r5, r6, r7, r8)
|
||||
)
|
||||
{
|
||||
break
|
||||
}
|
||||
y1, y2, y3, y4, y5, y6, y7, y8 := shl512_internal(1, y1, y2, y3, y4, y5, y6, y7, y8)
|
||||
m1, m2, m3, m4, m5, m6, m7, m8 := shl512_internal(1, m1, m2, m3, m4, m5, m6, m7, m8)
|
||||
}
|
||||
|
||||
for {} or_bool_512(m1, m2, m3, m4, m5, m6, m7, m8) {} {
|
||||
if gte_512x512_64(r1, r2, r3, r4, r5, r6, r7, r8, y1, y2, y3, y4, y5, y6, y7, y8) {
|
||||
r1, r2, r3, r4, r5, r6, r7, r8 := sub512(r1, r2, r3, r4, r5, r6, r7, r8, y1, y2, y3, y4, y5, y6, y7, y8)
|
||||
}
|
||||
|
||||
y1, y2, y3, y4, y5, y6, y7, y8 := shr512_internal(1, y1, y2, y3, y4, y5, y6, y7, y8)
|
||||
m1, m2, m3, m4, m5, m6, m7, m8 := shr512_internal(1, m1, m2, m3, m4, m5, m6, m7, m8)
|
||||
}
|
||||
}
|
||||
|
||||
function smod(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// Based on https://github.com/ewasm/evm2wasm/blob/master/wasm/SMOD.wast
|
||||
let m1 := 0
|
||||
let m2 := 0
|
||||
let m3 := 0
|
||||
let m4 := 1
|
||||
|
||||
let sign:i32 := i32.wrap_i64(i64.shr_u(x1, 63))
|
||||
|
||||
if i64.eqz(i64.clz(x1)) {
|
||||
x1, x2, x3, x4 := xor(
|
||||
x1, x2, x3, x4,
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
x1, x2, x3, x4 := add(x1, x2, x3, x4, 0, 0, 0, 1)
|
||||
}
|
||||
|
||||
if i64.eqz(i64.clz(y1)) {
|
||||
y1, y2, y3, y4 := xor(
|
||||
y1, y2, y3, y4,
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
y1, y2, y3, y4 := add(y1, y2, y3, y4, 0, 0, 0, 1)
|
||||
}
|
||||
|
||||
r1, r2, r3, r4 := mod(x1, x2, x3, x4, y1, y2, y3, y4)
|
||||
|
||||
if sign {
|
||||
r1, r2, r3, r4 := xor(
|
||||
r1, r2, r3, r4,
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
r1, r2, r3, r4 := add(r1, r2, r3, r4, 0, 0, 0, 1)
|
||||
}
|
||||
}
|
||||
|
||||
function exp(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
r4 := 1
|
||||
for {} or_bool(y1, y2, y3, y4) {} {
|
||||
if i32.wrap_i64(i64.and(y4, 1)) {
|
||||
r1, r2, r3, r4 := mul(r1, r2, r3, r4, x1, x2, x3, x4)
|
||||
}
|
||||
x1, x2, x3, x4 := mul(x1, x2, x3, x4, x1, x2, x3, x4)
|
||||
y1, y2, y3, y4 := shr_internal(1, y1, y2, y3, y4)
|
||||
}
|
||||
}
|
||||
|
||||
function addmod(x1, x2, x3, x4, y1, y2, y3, y4, m1, m2, m3, m4) -> z1, z2, z3, z4 {
|
||||
let carry
|
||||
z4, carry := add_carry(x4, y4, 0)
|
||||
z3, carry := add_carry(x3, y3, carry)
|
||||
z2, carry := add_carry(x2, y2, carry)
|
||||
z1, carry := add_carry(x1, y1, carry)
|
||||
|
||||
let z0
|
||||
z0, z1, z2, z3, z4 := mod320(carry, z1, z2, z3, z4, 0, m1, m2, m3, m4)
|
||||
}
|
||||
|
||||
function mulmod(x1, x2, x3, x4, y1, y2, y3, y4, m1, m2, m3, m4) -> z1, z2, z3, z4 {
|
||||
let r1, r2, r3, r4, r5, r6, r7, r8 := mul_256x256_512(x1, x2, x3, x4, y1, y2, y3, y4)
|
||||
let t1
|
||||
let t2
|
||||
let t3
|
||||
let t4
|
||||
t1, t2, t3, t4, z1, z2, z3, z4 := mod512(r1, r2, r3, r4, r5, r6, r7, r8, 0, 0, 0, 0, m1, m2, m3, m4)
|
||||
}
|
||||
|
||||
function signextend(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
z1 := y1
|
||||
z2 := y2
|
||||
z3 := y3
|
||||
z4 := y4
|
||||
if lt_256x256_64(x1, x2, x3, x4, 0, 0, 0, 32) {
|
||||
let d := i64.mul(i64.sub(31, x4), 8)
|
||||
z1, z2, z3, z4 := shl(0, 0, 0, d, z1, z2, z3, z4)
|
||||
z1, z2, z3, z4 := sar(0, 0, 0, d, z1, z2, z3, z4)
|
||||
}
|
||||
}
|
222
libyul/backends/wasm/polyfill/Bitwise.yul
Normal file
222
libyul/backends/wasm/polyfill/Bitwise.yul
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
// NOTE: This file is used to generate `ewasmPolyfills/Bitwise.h`.
|
||||
|
||||
function bit_negate(x) -> y {
|
||||
y := i64.xor(x, 0xffffffffffffffff)
|
||||
}
|
||||
|
||||
function split(x) -> hi, lo {
|
||||
hi := i64.shr_u(x, 32)
|
||||
lo := i64.and(x, 0xffffffff)
|
||||
}
|
||||
|
||||
function shl_internal(amount, x1, x2, x3, x4) -> r1, r2, r3, r4 {
|
||||
// amount < 64
|
||||
r1 := i64.add(i64.shl(x1, amount), i64.shr_u(x2, i64.sub(64, amount)))
|
||||
r2 := i64.add(i64.shl(x2, amount), i64.shr_u(x3, i64.sub(64, amount)))
|
||||
r3 := i64.add(i64.shl(x3, amount), i64.shr_u(x4, i64.sub(64, amount)))
|
||||
r4 := i64.shl(x4, amount)
|
||||
}
|
||||
|
||||
function shr_internal(amount, x1, x2, x3, x4) -> r1, r2, r3, r4 {
|
||||
// amount < 64
|
||||
r4 := i64.add(i64.shr_u(x4, amount), i64.shl(x3, i64.sub(64, amount)))
|
||||
r3 := i64.add(i64.shr_u(x3, amount), i64.shl(x2, i64.sub(64, amount)))
|
||||
r2 := i64.add(i64.shr_u(x2, amount), i64.shl(x1, i64.sub(64, amount)))
|
||||
r1 := i64.shr_u(x1, amount)
|
||||
}
|
||||
|
||||
function shl320_internal(amount, x1, x2, x3, x4, x5) -> r1, r2, r3, r4, r5 {
|
||||
// amount < 64
|
||||
r1 := i64.add(i64.shl(x1, amount), i64.shr_u(x2, i64.sub(64, amount)))
|
||||
r2 := i64.add(i64.shl(x2, amount), i64.shr_u(x3, i64.sub(64, amount)))
|
||||
r3 := i64.add(i64.shl(x3, amount), i64.shr_u(x4, i64.sub(64, amount)))
|
||||
r4 := i64.add(i64.shl(x4, amount), i64.shr_u(x5, i64.sub(64, amount)))
|
||||
r5 := i64.shl(x5, 1)
|
||||
}
|
||||
|
||||
function shr320_internal(amount, x1, x2, x3, x4, x5) -> r1, r2, r3, r4, r5 {
|
||||
// amount < 64
|
||||
r5 := i64.add(i64.shr_u(x5, amount), i64.shl(x4, i64.sub(64, amount)))
|
||||
r4 := i64.add(i64.shr_u(x4, amount), i64.shl(x3, i64.sub(64, amount)))
|
||||
r3 := i64.add(i64.shr_u(x3, amount), i64.shl(x2, i64.sub(64, amount)))
|
||||
r2 := i64.add(i64.shr_u(x2, amount), i64.shl(x1, i64.sub(64, amount)))
|
||||
r1 := i64.shr_u(x1, 1)
|
||||
}
|
||||
|
||||
function shl512_internal(amount, x1, x2, x3, x4, x5, x6, x7, x8) -> r1, r2, r3, r4, r5, r6, r7, r8 {
|
||||
// amount < 64
|
||||
r1 := i64.add(i64.shl(x1, amount), i64.shr_u(x2, i64.sub(64, amount)))
|
||||
r2 := i64.add(i64.shl(x2, amount), i64.shr_u(x3, i64.sub(64, amount)))
|
||||
r3 := i64.add(i64.shl(x3, amount), i64.shr_u(x4, i64.sub(64, amount)))
|
||||
r4 := i64.add(i64.shl(x4, amount), i64.shr_u(x5, i64.sub(64, amount)))
|
||||
r5 := i64.add(i64.shl(x5, amount), i64.shr_u(x6, i64.sub(64, amount)))
|
||||
r6 := i64.add(i64.shl(x6, amount), i64.shr_u(x7, i64.sub(64, amount)))
|
||||
r7 := i64.add(i64.shl(x7, amount), i64.shr_u(x8, i64.sub(64, amount)))
|
||||
r8 := i64.shl(x8, amount)
|
||||
}
|
||||
|
||||
function shr512_internal(amount, x1, x2, x3, x4, x5, x6, x7, x8) -> r1, r2, r3, r4, r5, r6, r7, r8 {
|
||||
// amount < 64
|
||||
r8 := i64.add(i64.shr_u(x8, amount), i64.shl(x7, i64.sub(64, amount)))
|
||||
r7 := i64.add(i64.shr_u(x7, amount), i64.shl(x6, i64.sub(64, amount)))
|
||||
r6 := i64.add(i64.shr_u(x6, amount), i64.shl(x5, i64.sub(64, amount)))
|
||||
r5 := i64.add(i64.shr_u(x5, amount), i64.shl(x4, i64.sub(64, amount)))
|
||||
r4 := i64.add(i64.shr_u(x4, amount), i64.shl(x3, i64.sub(64, amount)))
|
||||
r3 := i64.add(i64.shr_u(x3, amount), i64.shl(x2, i64.sub(64, amount)))
|
||||
r2 := i64.add(i64.shr_u(x2, amount), i64.shl(x1, i64.sub(64, amount)))
|
||||
r1 := i64.shr_u(x1, amount)
|
||||
}
|
||||
|
||||
function byte(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
if i64.eqz(i64.or(i64.or(x1, x2), x3)) {
|
||||
let component
|
||||
switch i64.div_u(x4, 8)
|
||||
case 0 { component := y1 }
|
||||
case 1 { component := y2 }
|
||||
case 2 { component := y3 }
|
||||
case 3 { component := y4 }
|
||||
x4 := i64.mul(i64.rem_u(x4, 8), 8)
|
||||
r4 := i64.shr_u(component, i64.sub(56, x4))
|
||||
r4 := i64.and(0xff, r4)
|
||||
}
|
||||
}
|
||||
|
||||
function xor(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
r1 := i64.xor(x1, y1)
|
||||
r2 := i64.xor(x2, y2)
|
||||
r3 := i64.xor(x3, y3)
|
||||
r4 := i64.xor(x4, y4)
|
||||
}
|
||||
|
||||
function or(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
r1 := i64.or(x1, y1)
|
||||
r2 := i64.or(x2, y2)
|
||||
r3 := i64.or(x3, y3)
|
||||
r4 := i64.or(x4, y4)
|
||||
}
|
||||
|
||||
function and(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
r1 := i64.and(x1, y1)
|
||||
r2 := i64.and(x2, y2)
|
||||
r3 := i64.and(x3, y3)
|
||||
r4 := i64.and(x4, y4)
|
||||
}
|
||||
|
||||
function not(x1, x2, x3, x4) -> r1, r2, r3, r4 {
|
||||
let mask := 0xffffffffffffffff
|
||||
r1, r2, r3, r4 := xor(x1, x2, x3, x4, mask, mask, mask, mask)
|
||||
}
|
||||
|
||||
function shl_single(a, amount) -> x, y {
|
||||
// amount < 64
|
||||
x := i64.shr_u(a, i64.sub(64, amount))
|
||||
y := i64.shl(a, amount)
|
||||
}
|
||||
|
||||
function shl(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
if i32.and(i64.eqz(x1), i64.eqz(x2)) {
|
||||
if i64.eqz(x3) {
|
||||
if i64.lt_u(x4, 256) {
|
||||
if i64.ge_u(x4, 128) {
|
||||
y1 := y3
|
||||
y2 := y4
|
||||
y3 := 0
|
||||
y4 := 0
|
||||
x4 := i64.sub(x4, 128)
|
||||
}
|
||||
if i64.ge_u(x4, 64) {
|
||||
y1 := y2
|
||||
y2 := y3
|
||||
y3 := y4
|
||||
y4 := 0
|
||||
x4 := i64.sub(x4, 64)
|
||||
}
|
||||
let t, r
|
||||
t, z4 := shl_single(y4, x4)
|
||||
r, z3 := shl_single(y3, x4)
|
||||
z3 := i64.or(z3, t)
|
||||
t, z2 := shl_single(y2, x4)
|
||||
z2 := i64.or(z2, r)
|
||||
r, z1 := shl_single(y1, x4)
|
||||
z1 := i64.or(z1, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function shr_single(a, amount) -> x, y {
|
||||
// amount < 64
|
||||
y := i64.shl(a, i64.sub(64, amount))
|
||||
x := i64.shr_u(a, amount)
|
||||
}
|
||||
|
||||
function shr(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
if i32.and(i64.eqz(x1), i64.eqz(x2)) {
|
||||
if i64.eqz(x3) {
|
||||
if i64.lt_u(x4, 256) {
|
||||
if i64.ge_u(x4, 128) {
|
||||
y4 := y2
|
||||
y3 := y1
|
||||
y2 := 0
|
||||
y1 := 0
|
||||
x4 := i64.sub(x4, 128)
|
||||
}
|
||||
if i64.ge_u(x4, 64) {
|
||||
y4 := y3
|
||||
y3 := y2
|
||||
y2 := y1
|
||||
y1 := 0
|
||||
x4 := i64.sub(x4, 64)
|
||||
}
|
||||
let t
|
||||
z4, t := shr_single(y4, x4)
|
||||
z3, t := shr_single(y3, x4)
|
||||
z4 := i64.or(z4, t)
|
||||
z2, t := shr_single(y2, x4)
|
||||
z3 := i64.or(z3, t)
|
||||
z1, t := shr_single(y1, x4)
|
||||
z2 := i64.or(z2, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sar(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
if i64.gt_u(i64.clz(y1), 0) {
|
||||
z1, z2, z3, z4 := shr(x1, x2, x3, x4, y1, y2, y3, y4)
|
||||
leave
|
||||
}
|
||||
|
||||
if gte_256x256_64(x1, x2, x3, x4, 0, 0, 0, 256) {
|
||||
z1 := 0xffffffffffffffff
|
||||
z2 := 0xffffffffffffffff
|
||||
z3 := 0xffffffffffffffff
|
||||
z4 := 0xffffffffffffffff
|
||||
}
|
||||
if lt_256x256_64(x1, x2, x3, x4, 0, 0, 0, 256) {
|
||||
y1, y2, y3, y4 := shr(0, 0, 0, x4, y1, y2, y3, y4)
|
||||
z1, z2, z3, z4 := shl(
|
||||
0, 0, 0, i64.sub(256, x4),
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
z1, z2, z3, z4 := or(y1, y2, y3, y4, z1, z2, z3, z4)
|
||||
}
|
||||
}
|
169
libyul/backends/wasm/polyfill/Comparison.yul
Normal file
169
libyul/backends/wasm/polyfill/Comparison.yul
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
// NOTE: This file is used to generate `ewasmPolyfills/Comparison.h`.
|
||||
|
||||
function iszero(x1, x2, x3, x4) -> r1, r2, r3, r4 {
|
||||
r4 := i64.extend_i32_u(iszero256(x1, x2, x3, x4))
|
||||
}
|
||||
|
||||
function iszero256(x1, x2, x3, x4) -> r:i32 {
|
||||
r := i64.eqz(i64.or(i64.or(x1, x2), i64.or(x3, x4)))
|
||||
}
|
||||
|
||||
function iszero320(x1, x2, x3, x4, x5) -> r:i32 {
|
||||
r := i64.eqz(i64.or(i64.or(i64.or(x1, x2), i64.or(x3, x4)), x5))
|
||||
}
|
||||
|
||||
function iszero512(x1, x2, x3, x4, x5, x6, x7, x8) -> r:i32 {
|
||||
r := i32.and(iszero256(x1, x2, x3, x4), iszero256(x5, x6, x7, x8))
|
||||
}
|
||||
|
||||
function eq(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
if i64.eq(x1, y1) {
|
||||
if i64.eq(x2, y2) {
|
||||
if i64.eq(x3, y3) {
|
||||
if i64.eq(x4, y4) {
|
||||
r4 := 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// returns 0 if a == b, -1 if a < b and 1 if a > b
|
||||
function cmp(a, b) -> r:i32 {
|
||||
switch i64.lt_u(a, b)
|
||||
case 1:i32 { r := 0xffffffff:i32 }
|
||||
default {
|
||||
r := i64.ne(a, b)
|
||||
}
|
||||
}
|
||||
|
||||
function lt_320x320_64(x1, x2, x3, x4, x5, y1, y2, y3, y4, y5) -> z:i32 {
|
||||
switch cmp(x1, y1)
|
||||
case 0:i32 {
|
||||
switch cmp(x2, y2)
|
||||
case 0:i32 {
|
||||
switch cmp(x3, y3)
|
||||
case 0:i32 {
|
||||
switch cmp(x4, y4)
|
||||
case 0:i32 {
|
||||
z := i64.lt_u(x5, y5)
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
|
||||
function lt_512x512_64(x1, x2, x3, x4, x5, x6, x7, x8, y1, y2, y3, y4, y5, y6, y7, y8) -> z:i32 {
|
||||
switch cmp(x1, y1)
|
||||
case 0:i32 {
|
||||
switch cmp(x2, y2)
|
||||
case 0:i32 {
|
||||
switch cmp(x3, y3)
|
||||
case 0:i32 {
|
||||
switch cmp(x4, y4)
|
||||
case 0:i32 {
|
||||
switch cmp(x5, y5)
|
||||
case 0:i32 {
|
||||
switch cmp(x6, y6)
|
||||
case 0:i32 {
|
||||
switch cmp(x7, y7)
|
||||
case 0:i32 {
|
||||
z := i64.lt_u(x8, y8)
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
|
||||
function lt_256x256_64(x1, x2, x3, x4, y1, y2, y3, y4) -> z:i32 {
|
||||
switch cmp(x1, y1)
|
||||
case 0:i32 {
|
||||
switch cmp(x2, y2)
|
||||
case 0:i32 {
|
||||
switch cmp(x3, y3)
|
||||
case 0:i32 {
|
||||
z := i64.lt_u(x4, y4)
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
case 1:i32 { z := 0:i32 }
|
||||
default { z := 1:i32 }
|
||||
}
|
||||
|
||||
function lt(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
z4 := i64.extend_i32_u(lt_256x256_64(x1, x2, x3, x4, y1, y2, y3, y4))
|
||||
}
|
||||
|
||||
function gte_256x256_64(x1, x2, x3, x4, y1, y2, y3, y4) -> z:i32 {
|
||||
z := i32.eqz(lt_256x256_64(x1, x2, x3, x4, y1, y2, y3, y4))
|
||||
}
|
||||
|
||||
function gte_320x320_64(x1, x2, x3, x4, x5, y1, y2, y3, y4, y5) -> z:i32 {
|
||||
z := i32.eqz(lt_320x320_64(x1, x2, x3, x4, x5, y1, y2, y3, y4, y5))
|
||||
}
|
||||
|
||||
function gte_512x512_64(x1, x2, x3, x4, x5, x6, x7, x8, y1, y2, y3, y4, y5, y6, y7, y8) -> z:i32 {
|
||||
z := i32.eqz(lt_512x512_64(x1, x2, x3, x4, x5, x6, x7, x8, y1, y2, y3, y4, y5, y6, y7, y8))
|
||||
}
|
||||
|
||||
function gt(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
z1, z2, z3, z4 := lt(y1, y2, y3, y4, x1, x2, x3, x4)
|
||||
}
|
||||
|
||||
function slt(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
// TODO correct?
|
||||
x1 := i64.add(x1, 0x8000000000000000)
|
||||
y1 := i64.add(y1, 0x8000000000000000)
|
||||
z1, z2, z3, z4 := lt(x1, x2, x3, x4, y1, y2, y3, y4)
|
||||
}
|
||||
|
||||
function sgt(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
z1, z2, z3, z4 := slt(y1, y2, y3, y4, x1, x2, x3, x4)
|
||||
}
|
78
libyul/backends/wasm/polyfill/Conversion.yul
Normal file
78
libyul/backends/wasm/polyfill/Conversion.yul
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
// NOTE: This file is used to generate `ewasmPolyfills/Conversion.h`.
|
||||
|
||||
function u256_to_u128(x1, x2, x3, x4) -> v1, v2 {
|
||||
if i64.ne(0, i64.or(x1, x2)) { invalid() }
|
||||
v2 := x4
|
||||
v1 := x3
|
||||
}
|
||||
|
||||
function u256_to_i64(x1, x2, x3, x4) -> v {
|
||||
if i64.ne(0, i64.or(i64.or(x1, x2), x3)) { invalid() }
|
||||
v := x4
|
||||
}
|
||||
|
||||
function u256_to_i32(x1, x2, x3, x4) -> v:i32 {
|
||||
if i64.ne(0, i64.or(i64.or(x1, x2), x3)) { invalid() }
|
||||
if i64.ne(0, i64.shr_u(x4, 32)) { invalid() }
|
||||
v := i32.wrap_i64(x4)
|
||||
}
|
||||
|
||||
function u256_to_byte(x1, x2, x3, x4) -> v {
|
||||
if i64.ne(0, i64.or(i64.or(x1, x2), x3)) { invalid() }
|
||||
if i64.gt_u(x4, 255) { invalid() }
|
||||
v := x4
|
||||
}
|
||||
|
||||
function u256_to_i32ptr(x1, x2, x3, x4) -> v:i32 {
|
||||
v := u256_to_i32(x1, x2, x3, x4)
|
||||
}
|
||||
|
||||
function to_internal_i32ptr(x1, x2, x3, x4) -> r:i32 {
|
||||
let p:i32 := u256_to_i32ptr(x1, x2, x3, x4)
|
||||
r := i32.add(p, 64:i32)
|
||||
if i32.lt_u(r, p) { invalid() }
|
||||
}
|
||||
|
||||
function u256_to_address(x1, x2, x3, x4) -> r1, r2, r3 {
|
||||
if i64.ne(0, x1) { invalid() }
|
||||
if i64.ne(0, i64.shr_u(x2, 32)) { invalid() }
|
||||
r1 := x2
|
||||
r2 := x3
|
||||
r3 := x4
|
||||
}
|
||||
|
||||
function bswap16(x) -> y {
|
||||
let hi := i64.and(i64.shl(x, 8), 0xff00)
|
||||
let lo := i64.and(i64.shr_u(x, 8), 0xff)
|
||||
y := i64.or(hi, lo)
|
||||
}
|
||||
|
||||
function bswap32(x) -> y {
|
||||
let hi := i64.shl(bswap16(x), 16)
|
||||
let lo := bswap16(i64.shr_u(x, 16))
|
||||
y := i64.or(hi, lo)
|
||||
}
|
||||
|
||||
function bswap64(x) -> y {
|
||||
let hi := i64.shl(bswap32(x), 32)
|
||||
let lo := bswap32(i64.shr_u(x, 32))
|
||||
y := i64.or(hi, lo)
|
||||
}
|
411
libyul/backends/wasm/polyfill/Interface.yul
Normal file
411
libyul/backends/wasm/polyfill/Interface.yul
Normal file
@ -0,0 +1,411 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
// NOTE: This file is used to generate `ewasmPolyfills/Interface.h`.
|
||||
|
||||
function address() -> z1, z2, z3, z4 {
|
||||
eth.getAddress(0:i32)
|
||||
z1, z2, z3, z4 := mload_internal(0:i32)
|
||||
}
|
||||
|
||||
function balance(x1, x2, x3, x4) -> z1, z2, z3, z4 {
|
||||
mstore_address(0:i32, x1, x2, x3, x4)
|
||||
eth.getExternalBalance(12:i32, 48:i32)
|
||||
z1, z2, z3, z4 := mload_internal(32:i32)
|
||||
}
|
||||
|
||||
function selfbalance() -> z1, z2, z3, z4 {
|
||||
// TODO: not part of current Ewasm spec
|
||||
unreachable()
|
||||
}
|
||||
|
||||
function chainid() -> z1, z2, z3, z4 {
|
||||
// TODO: not part of current Ewasm spec
|
||||
unreachable()
|
||||
}
|
||||
|
||||
function origin() -> z1, z2, z3, z4 {
|
||||
eth.getTxOrigin(0:i32)
|
||||
z1, z2, z3, z4 := mload_internal(0:i32)
|
||||
}
|
||||
|
||||
function caller() -> z1, z2, z3, z4 {
|
||||
eth.getCaller(0:i32)
|
||||
z1, z2, z3, z4 := mload_internal(0:i32)
|
||||
}
|
||||
|
||||
function callvalue() -> z1, z2, z3, z4 {
|
||||
eth.getCallValue(0:i32)
|
||||
z1, z2, z3, z4 := mload_internal(0:i32)
|
||||
}
|
||||
|
||||
function calldataload(x1, x2, x3, x4) -> z1, z2, z3, z4 {
|
||||
eth.callDataCopy(0:i32, u256_to_i32(x1, x2, x3, x4), 32:i32)
|
||||
z1, z2, z3, z4 := mload_internal(0:i32)
|
||||
}
|
||||
|
||||
function calldatasize() -> z1, z2, z3, z4 {
|
||||
z4 := i64.extend_i32_u(eth.getCallDataSize())
|
||||
}
|
||||
|
||||
function calldatacopy(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4) {
|
||||
eth.callDataCopy(
|
||||
to_internal_i32ptr(x1, x2, x3, x4),
|
||||
u256_to_i32(y1, y2, y3, y4),
|
||||
u256_to_i32(z1, z2, z3, z4)
|
||||
)
|
||||
}
|
||||
|
||||
// Needed?
|
||||
function codesize() -> z1, z2, z3, z4 {
|
||||
z4 := i64.extend_i32_u(eth.getCodeSize())
|
||||
}
|
||||
|
||||
function codecopy(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4) {
|
||||
eth.codeCopy(
|
||||
to_internal_i32ptr(x1, x2, x3, x4),
|
||||
u256_to_i32(y1, y2, y3, y4),
|
||||
u256_to_i32(z1, z2, z3, z4)
|
||||
)
|
||||
}
|
||||
|
||||
function datacopy(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4) {
|
||||
// TODO correct?
|
||||
codecopy(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4)
|
||||
}
|
||||
|
||||
function gasprice() -> z1, z2, z3, z4 {
|
||||
eth.getTxGasPrice(0:i32)
|
||||
z1, z2, z3, z4 := mload_internal(0:i32)
|
||||
}
|
||||
|
||||
function extcodesize_internal(x1, x2, x3, x4) -> r:i32 {
|
||||
mstore_address(0:i32, x1, x2, x3, x4)
|
||||
r := eth.getExternalCodeSize(12:i32)
|
||||
}
|
||||
|
||||
function extcodesize(x1, x2, x3, x4) -> z1, z2, z3, z4 {
|
||||
z4 := i64.extend_i32_u(extcodesize_internal(x1, x2, x3, x4))
|
||||
}
|
||||
|
||||
function extcodehash(x1, x2, x3, x4) -> z1, z2, z3, z4 {
|
||||
// TODO: not part of current Ewasm spec
|
||||
unreachable()
|
||||
}
|
||||
|
||||
function extcodecopy(a1, a2, a3, a4, p1, p2, p3, p4, o1, o2, o3, o4, l1, l2, l3, l4) {
|
||||
mstore_address(0:i32, a1, a2, a3, a4)
|
||||
let codeOffset:i32 := u256_to_i32(o1, o2, o3, o4)
|
||||
let codeLength:i32 := u256_to_i32(l1, l2, l3, l4)
|
||||
eth.externalCodeCopy(12:i32, to_internal_i32ptr(p1, p2, p3, p4), codeOffset, codeLength)
|
||||
}
|
||||
|
||||
function returndatasize() -> z1, z2, z3, z4 {
|
||||
z4 := i64.extend_i32_u(eth.getReturnDataSize())
|
||||
}
|
||||
|
||||
function returndatacopy(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4) {
|
||||
eth.returnDataCopy(
|
||||
to_internal_i32ptr(x1, x2, x3, x4),
|
||||
u256_to_i32(y1, y2, y3, y4),
|
||||
u256_to_i32(z1, z2, z3, z4)
|
||||
)
|
||||
}
|
||||
|
||||
function blockhash(x1, x2, x3, x4) -> z1, z2, z3, z4 {
|
||||
let r:i32 := eth.getBlockHash(u256_to_i64(x1, x2, x3, x4), 0:i32)
|
||||
if i32.eqz(r) {
|
||||
z1, z2, z3, z4 := mload_internal(0:i32)
|
||||
}
|
||||
}
|
||||
|
||||
function coinbase() -> z1, z2, z3, z4 {
|
||||
eth.getBlockCoinbase(0:i32)
|
||||
z1, z2, z3, z4 := mload_internal(0:i32)
|
||||
}
|
||||
|
||||
function timestamp() -> z1, z2, z3, z4 {
|
||||
z4 := eth.getBlockTimestamp()
|
||||
}
|
||||
|
||||
function number() -> z1, z2, z3, z4 {
|
||||
z4 := eth.getBlockNumber()
|
||||
}
|
||||
|
||||
function difficulty() -> z1, z2, z3, z4 {
|
||||
eth.getBlockDifficulty(0:i32)
|
||||
z1, z2, z3, z4 := mload_internal(0:i32)
|
||||
}
|
||||
|
||||
function gaslimit() -> z1, z2, z3, z4 {
|
||||
z4 := eth.getBlockGasLimit()
|
||||
}
|
||||
|
||||
function mload(x1, x2, x3, x4) -> z1, z2, z3, z4 {
|
||||
z1, z2, z3, z4 := mload_internal(to_internal_i32ptr(x1, x2, x3, x4))
|
||||
}
|
||||
|
||||
function mload_internal(pos:i32) -> z1, z2, z3, z4 {
|
||||
z1 := bswap64(i64.load(pos))
|
||||
z2 := bswap64(i64.load(i32.add(pos, 8:i32)))
|
||||
z3 := bswap64(i64.load(i32.add(pos, 16:i32)))
|
||||
z4 := bswap64(i64.load(i32.add(pos, 24:i32)))
|
||||
}
|
||||
|
||||
function mstore(x1, x2, x3, x4, y1, y2, y3, y4) {
|
||||
mstore_internal(to_internal_i32ptr(x1, x2, x3, x4), y1, y2, y3, y4)
|
||||
}
|
||||
|
||||
function mstore_internal(pos:i32, y1, y2, y3, y4) {
|
||||
i64.store(pos, bswap64(y1))
|
||||
i64.store(i32.add(pos, 8:i32), bswap64(y2))
|
||||
i64.store(i32.add(pos, 16:i32), bswap64(y3))
|
||||
i64.store(i32.add(pos, 24:i32), bswap64(y4))
|
||||
}
|
||||
|
||||
function mstore_address(pos:i32, a1, a2, a3, a4) {
|
||||
a1, a2, a3 := u256_to_address(a1, a2, a3, a4)
|
||||
mstore_internal(pos, 0, a1, a2, a3)
|
||||
}
|
||||
|
||||
function mstore8(x1, x2, x3, x4, y1, y2, y3, y4) {
|
||||
let v := u256_to_byte(y1, y2, y3, y4)
|
||||
i64.store8(to_internal_i32ptr(x1, x2, x3, x4), v)
|
||||
}
|
||||
|
||||
// Needed?
|
||||
function msize() -> z1, z2, z3, z4 {
|
||||
// TODO implement
|
||||
unreachable()
|
||||
}
|
||||
|
||||
function sload(x1, x2, x3, x4) -> z1, z2, z3, z4 {
|
||||
mstore_internal(0:i32, x1, x2, x3, x4)
|
||||
eth.storageLoad(0:i32, 32:i32)
|
||||
z1, z2, z3, z4 := mload_internal(32:i32)
|
||||
}
|
||||
|
||||
function sstore(x1, x2, x3, x4, y1, y2, y3, y4) {
|
||||
mstore_internal(0:i32, x1, x2, x3, x4)
|
||||
mstore_internal(32:i32, y1, y2, y3, y4)
|
||||
eth.storageStore(0:i32, 32:i32)
|
||||
}
|
||||
|
||||
function gas() -> z1, z2, z3, z4 {
|
||||
z4 := eth.getGasLeft()
|
||||
}
|
||||
|
||||
function log0(p1, p2, p3, p4, s1, s2, s3, s4) {
|
||||
eth.log(
|
||||
to_internal_i32ptr(p1, p2, p3, p4),
|
||||
u256_to_i32(s1, s2, s3, s4),
|
||||
0:i32, 0:i32, 0:i32, 0:i32, 0:i32
|
||||
)
|
||||
}
|
||||
|
||||
function log1(
|
||||
p1, p2, p3, p4, s1, s2, s3, s4,
|
||||
t1_1, t1_2, t1_3, t1_4
|
||||
) {
|
||||
eth.log(
|
||||
to_internal_i32ptr(p1, p2, p3, p4),
|
||||
u256_to_i32(s1, s2, s3, s4),
|
||||
1:i32,
|
||||
to_internal_i32ptr(t1_1, t1_2, t1_3, t1_4),
|
||||
0:i32, 0:i32, 0:i32
|
||||
)
|
||||
}
|
||||
|
||||
function log2(
|
||||
p1, p2, p3, p4, s1, s2, s3, s4,
|
||||
t1_1, t1_2, t1_3, t1_4,
|
||||
t2_1, t2_2, t2_3, t2_4
|
||||
) {
|
||||
eth.log(
|
||||
to_internal_i32ptr(p1, p2, p3, p4),
|
||||
u256_to_i32(s1, s2, s3, s4),
|
||||
2:i32,
|
||||
to_internal_i32ptr(t1_1, t1_2, t1_3, t1_4),
|
||||
to_internal_i32ptr(t2_1, t2_2, t2_3, t2_4),
|
||||
0:i32, 0:i32
|
||||
)
|
||||
}
|
||||
|
||||
function log3(
|
||||
p1, p2, p3, p4, s1, s2, s3, s4,
|
||||
t1_1, t1_2, t1_3, t1_4,
|
||||
t2_1, t2_2, t2_3, t2_4,
|
||||
t3_1, t3_2, t3_3, t3_4
|
||||
) {
|
||||
eth.log(
|
||||
to_internal_i32ptr(p1, p2, p3, p4),
|
||||
u256_to_i32(s1, s2, s3, s4),
|
||||
3:i32,
|
||||
to_internal_i32ptr(t1_1, t1_2, t1_3, t1_4),
|
||||
to_internal_i32ptr(t2_1, t2_2, t2_3, t2_4),
|
||||
to_internal_i32ptr(t3_1, t3_2, t3_3, t3_4),
|
||||
0:i32
|
||||
)
|
||||
}
|
||||
|
||||
function log4(
|
||||
p1, p2, p3, p4, s1, s2, s3, s4,
|
||||
t1_1, t1_2, t1_3, t1_4,
|
||||
t2_1, t2_2, t2_3, t2_4,
|
||||
t3_1, t3_2, t3_3, t3_4,
|
||||
t4_1, t4_2, t4_3, t4_4,
|
||||
) {
|
||||
eth.log(
|
||||
to_internal_i32ptr(p1, p2, p3, p4),
|
||||
u256_to_i32(s1, s2, s3, s4),
|
||||
4:i32,
|
||||
to_internal_i32ptr(t1_1, t1_2, t1_3, t1_4),
|
||||
to_internal_i32ptr(t2_1, t2_2, t2_3, t2_4),
|
||||
to_internal_i32ptr(t3_1, t3_2, t3_3, t3_4),
|
||||
to_internal_i32ptr(t4_1, t4_2, t4_3, t4_4)
|
||||
)
|
||||
}
|
||||
|
||||
function create(
|
||||
x1, x2, x3, x4,
|
||||
y1, y2, y3, y4,
|
||||
z1, z2, z3, z4
|
||||
) -> a1, a2, a3, a4 {
|
||||
let v1, v2 := u256_to_u128(x1, x2, x3, x4)
|
||||
mstore_internal(0:i32, 0, 0, v1, v2)
|
||||
|
||||
let r:i32 := eth.create(0:i32, to_internal_i32ptr(y1, y2, y3, y4), u256_to_i32(z1, z2, z3, z4), 32:i32)
|
||||
if i32.eqz(r) {
|
||||
a1, a2, a3, a4 := mload_internal(32:i32)
|
||||
}
|
||||
}
|
||||
|
||||
function call(
|
||||
a1, a2, a3, a4,
|
||||
b1, b2, b3, b4,
|
||||
c1, c2, c3, c4,
|
||||
d1, d2, d3, d4,
|
||||
e1, e2, e3, e4,
|
||||
f1, f2, f3, f4,
|
||||
g1, g2, g3, g4
|
||||
) -> x1, x2, x3, x4 {
|
||||
let g := u256_to_i64(a1, a2, a3, a4)
|
||||
mstore_address(0:i32, b1, b2, b3, b4)
|
||||
|
||||
let v1, v2 := u256_to_u128(c1, c2, c3, c4)
|
||||
mstore_internal(32:i32, 0, 0, v1, v2)
|
||||
|
||||
x4 := i64.extend_i32_u(eth.call(g, 12:i32, 32:i32, to_internal_i32ptr(d1, d2, d3, d4), u256_to_i32(e1, e2, e3, e4)))
|
||||
}
|
||||
|
||||
function callcode(
|
||||
a1, a2, a3, a4,
|
||||
b1, b2, b3, b4,
|
||||
c1, c2, c3, c4,
|
||||
d1, d2, d3, d4,
|
||||
e1, e2, e3, e4,
|
||||
f1, f2, f3, f4,
|
||||
g1, g2, g3, g4
|
||||
) -> x1, x2, x3, x4 {
|
||||
mstore_address(0:i32, b1, b2, b3, b4)
|
||||
|
||||
let v1, v2 := u256_to_u128(c1, c2, c3, c4)
|
||||
mstore_internal(32:i32, 0, 0, v1, v2)
|
||||
|
||||
x4 := i64.extend_i32_u(eth.callCode(
|
||||
u256_to_i64(a1, a2, a3, a4),
|
||||
12:i32,
|
||||
32:i32,
|
||||
to_internal_i32ptr(d1, d2, d3, d4),
|
||||
u256_to_i32(e1, e2, e3, e4)
|
||||
))
|
||||
}
|
||||
|
||||
function delegatecall(
|
||||
a1, a2, a3, a4,
|
||||
b1, b2, b3, b4,
|
||||
c1, c2, c3, c4,
|
||||
d1, d2, d3, d4,
|
||||
e1, e2, e3, e4,
|
||||
f1, f2, f3, f4
|
||||
) -> x1, x2, x3, x4 {
|
||||
mstore_address(0:i32, b1, b2, b3, b4)
|
||||
|
||||
x4 := i64.extend_i32_u(eth.callDelegate(
|
||||
u256_to_i64(a1, a2, a3, a4),
|
||||
12:i32,
|
||||
to_internal_i32ptr(c1, c2, c3, c4),
|
||||
u256_to_i32(d1, d2, d3, d4)
|
||||
))
|
||||
}
|
||||
|
||||
function staticcall(
|
||||
a1, a2, a3, a4,
|
||||
b1, b2, b3, b4,
|
||||
c1, c2, c3, c4,
|
||||
d1, d2, d3, d4,
|
||||
e1, e2, e3, e4,
|
||||
f1, f2, f3, f4
|
||||
) -> x1, x2, x3, x4 {
|
||||
mstore_address(0:i32, b1, b2, b3, b4)
|
||||
|
||||
x4 := i64.extend_i32_u(eth.callStatic(
|
||||
u256_to_i64(a1, a2, a3, a4),
|
||||
12:i32,
|
||||
to_internal_i32ptr(c1, c2, c3, c4),
|
||||
u256_to_i32(d1, d2, d3, d4)
|
||||
))
|
||||
}
|
||||
|
||||
function create2(
|
||||
a1, a2, a3, a4,
|
||||
b1, b2, b3, b4,
|
||||
c1, c2, c3, c4,
|
||||
d1, d2, d3, d4
|
||||
) -> x1, x2, x3, x4 {
|
||||
// TODO: not part of current Ewasm spec
|
||||
unreachable()
|
||||
}
|
||||
|
||||
function selfdestruct(a1, a2, a3, a4) {
|
||||
mstore_address(0:i32, a1, a2, a3, a4)
|
||||
// In EVM, addresses are padded to 32 bytes, so discard the first 12.
|
||||
eth.selfDestruct(12:i32)
|
||||
}
|
||||
|
||||
function return(x1, x2, x3, x4, y1, y2, y3, y4) {
|
||||
eth.finish(
|
||||
to_internal_i32ptr(x1, x2, x3, x4),
|
||||
u256_to_i32(y1, y2, y3, y4)
|
||||
)
|
||||
}
|
||||
|
||||
function revert(x1, x2, x3, x4, y1, y2, y3, y4) {
|
||||
eth.revert(
|
||||
to_internal_i32ptr(x1, x2, x3, x4),
|
||||
u256_to_i32(y1, y2, y3, y4)
|
||||
)
|
||||
}
|
||||
|
||||
function invalid() {
|
||||
unreachable()
|
||||
}
|
||||
|
||||
function stop() {
|
||||
eth.finish(0:i32, 0:i32)
|
||||
}
|
24
libyul/backends/wasm/polyfill/Keccak.yul
Normal file
24
libyul/backends/wasm/polyfill/Keccak.yul
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
// NOTE: This file is used to generate `ewasmPolyfills/Keccak.h`.
|
||||
|
||||
function keccak256(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
// TODO implement
|
||||
unreachable()
|
||||
}
|
31
libyul/backends/wasm/polyfill/Logical.yul
Normal file
31
libyul/backends/wasm/polyfill/Logical.yul
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
// NOTE: This file is used to generate `ewasmPolyfills/Logical.h`.
|
||||
|
||||
function or_bool(a, b, c, d) -> r:i32 {
|
||||
r := i32.eqz(i64.eqz(i64.or(i64.or(a, b), i64.or(c, d))))
|
||||
}
|
||||
|
||||
function or_bool_320(a, b, c, d, e) -> r:i32 {
|
||||
r := i32.or(or_bool(a, b, c, 0), or_bool(d, e, 0, 0))
|
||||
}
|
||||
|
||||
function or_bool_512(a, b, c, d, e, f, g, h) -> r:i32 {
|
||||
r := i32.or(or_bool(a, b, c, d), or_bool(e, f, g, h))
|
||||
}
|
62
libyul/backends/wasm/polyfill/Memory.yul
Normal file
62
libyul/backends/wasm/polyfill/Memory.yul
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
// NOTE: This file is used to generate `ewasmPolyfills/Memory.h`.
|
||||
|
||||
function save_temp_mem_32() -> t1, t2, t3, t4 {
|
||||
t1 := i64.load(0:i32)
|
||||
t2 := i64.load(8:i32)
|
||||
t3 := i64.load(16:i32)
|
||||
t4 := i64.load(24:i32)
|
||||
}
|
||||
|
||||
function restore_temp_mem_32(t1, t2, t3, t4) {
|
||||
i64.store(0:i32, t1)
|
||||
i64.store(8:i32, t2)
|
||||
i64.store(16:i32, t3)
|
||||
i64.store(24:i32, t4)
|
||||
}
|
||||
|
||||
function save_temp_mem_64() -> t1, t2, t3, t4, t5, t6, t7, t8 {
|
||||
t1 := i64.load(0:i32)
|
||||
t2 := i64.load(8:i32)
|
||||
t3 := i64.load(16:i32)
|
||||
t4 := i64.load(24:i32)
|
||||
t5 := i64.load(32:i32)
|
||||
t6 := i64.load(40:i32)
|
||||
t7 := i64.load(48:i32)
|
||||
t8 := i64.load(54:i32)
|
||||
}
|
||||
|
||||
function restore_temp_mem_64(t1, t2, t3, t4, t5, t6, t7, t8) {
|
||||
i64.store(0:i32, t1)
|
||||
i64.store(8:i32, t2)
|
||||
i64.store(16:i32, t3)
|
||||
i64.store(24:i32, t4)
|
||||
i64.store(32:i32, t5)
|
||||
i64.store(40:i32, t6)
|
||||
i64.store(48:i32, t7)
|
||||
i64.store(54:i32, t8)
|
||||
}
|
||||
|
||||
function pop(x1, x2, x3, x4) {
|
||||
}
|
||||
|
||||
function memoryguard(x:i64) -> y1, y2, y3, y4 {
|
||||
y4 := x
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# https://solidity.readthedocs.org
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
|
@ -11,7 +11,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# http://solidity.readthedocs.io/
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# https://solidity.readthedocs.org
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
|
@ -6,7 +6,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# https://solidity.readthedocs.org
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# https://solidity.readthedocs.org
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
|
@ -37,7 +37,7 @@ REM for those packages.
|
||||
REM
|
||||
REM The documentation for solidity is hosted at:
|
||||
REM
|
||||
REM http://solidity.readthedocs.org
|
||||
REM https://docs.soliditylang.org
|
||||
REM
|
||||
REM ---------------------------------------------------------------------------
|
||||
REM This file is part of solidity.
|
||||
|
@ -6,7 +6,7 @@
|
||||
#
|
||||
# This is an "infrastucture-as-code" alternative to the manual build
|
||||
# instructions pages which we previously maintained at:
|
||||
# http://solidity.readthedocs.io/en/latest/installing-solidity.html
|
||||
# https://docs.soliditylang.org/en/latest/installing-solidity.html
|
||||
#
|
||||
# The aim of this script is to simplify things down to the following basic
|
||||
# flow for all supported operating systems:
|
||||
@ -23,7 +23,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# http://solidity.readthedocs.io/
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
@ -179,7 +179,7 @@ case $(uname -s) in
|
||||
#wheezy
|
||||
echo "Installing solidity dependencies on Debian Wheezy (7.x)."
|
||||
echo "ERROR - 'install_deps.sh' doesn't have Debian Wheezy support yet."
|
||||
echo "See http://solidity.readthedocs.io/en/latest/installing-solidity.html for manual instructions."
|
||||
echo "See https://docs.soliditylang.org/en/latest/installing-solidity.html for manual instructions."
|
||||
echo "If you would like to get 'install_deps.sh' working for Debian Wheezy, that would be fantastic."
|
||||
echo "Drop us a message at https://gitter.im/ethereum/solidity-dev."
|
||||
echo "See also https://github.com/ethereum/webthree-umbrella/issues/495 where we are working through Alpine support."
|
||||
@ -254,7 +254,7 @@ case $(uname -s) in
|
||||
#openSUSE
|
||||
echo "Installing solidity dependencies on openSUSE."
|
||||
echo "ERROR - 'install_deps.sh' doesn't have openSUSE support yet."
|
||||
echo "See http://solidity.readthedocs.io/en/latest/installing-solidity.html for manual instructions."
|
||||
echo "See https://docs.soliditylang.org/en/latest/installing-solidity.html for manual instructions."
|
||||
echo "If you would like to get 'install_deps.sh' working for openSUSE, that would be fantastic."
|
||||
echo "See https://github.com/ethereum/webthree-umbrella/issues/552."
|
||||
exit 1
|
||||
@ -311,7 +311,7 @@ case $(uname -s) in
|
||||
#do not try anything for betsy.
|
||||
echo "Linux Mint Betsy is not supported at the moment as it runs off of Debian."
|
||||
echo "We only support Sylvia, Sonya, Serena, Sarah, Rosa, Rafaela, Rebecca, and Qiana."
|
||||
echo "See http://solidity.readthedocs.io/en/latest/installing-solidity.html for manual instructions."
|
||||
echo "See https://docs.soliditylang.org/en/latest/installing-solidity.html for manual instructions."
|
||||
echo "If you would like to get your distro working, that would be fantastic."
|
||||
echo "Drop us a message at https://gitter.im/ethereum/solidity-dev."
|
||||
exit 1
|
||||
@ -396,7 +396,7 @@ case $(uname -s) in
|
||||
|
||||
#other Linux
|
||||
echo "ERROR - Unsupported or unidentified Linux distro."
|
||||
echo "See http://solidity.readthedocs.io/en/latest/installing-solidity.html for manual instructions."
|
||||
echo "See https://docs.soliditylang.org/en/latest/installing-solidity.html for manual instructions."
|
||||
echo "If you would like to get your distro working, that would be fantastic."
|
||||
echo "Drop us a message at https://gitter.im/ethereum/solidity-dev."
|
||||
exit 1
|
||||
@ -413,7 +413,7 @@ case $(uname -s) in
|
||||
*)
|
||||
#other
|
||||
echo "ERROR - Unsupported or unidentified operating system."
|
||||
echo "See http://solidity.readthedocs.io/en/latest/installing-solidity.html for manual instructions."
|
||||
echo "See https://docs.soliditylang.org/en/latest/installing-solidity.html for manual instructions."
|
||||
echo "If you would like to get your operating system working, that would be fantastic."
|
||||
echo "Drop us a message at https://gitter.im/ethereum/solidity-dev."
|
||||
;;
|
||||
|
@ -5,7 +5,7 @@ REM Batch file for implementing release flow for solidity for Windows.
|
||||
REM
|
||||
REM The documentation for solidity is hosted at:
|
||||
REM
|
||||
REM https://solidity.readthedocs.org
|
||||
REM https://docs.soliditylang.org
|
||||
REM
|
||||
REM ---------------------------------------------------------------------------
|
||||
REM This file is part of solidity.
|
||||
|
@ -8,7 +8,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# https://solidity.readthedocs.org
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# https://solidity.readthedocs.org
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# https://solidity.readthedocs.org
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
|
@ -30,7 +30,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# https://solidity.readthedocs.org
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# https://solidity.readthedocs.org
|
||||
# https://docs.soliditylang.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# This file is part of solidity.
|
||||
|
@ -19,26 +19,26 @@ object "object" {
|
||||
mstore_internal(32:i32, _1, _1, _1, 1)
|
||||
eth.storageStore(0:i32, 32:i32)
|
||||
}
|
||||
function endian_swap_16(x) -> y
|
||||
function bswap16(x) -> y
|
||||
{
|
||||
y := i64.or(i64.and(i64.shl(x, 8), 0xff00), i64.and(i64.shr_u(x, 8), 0xff))
|
||||
}
|
||||
function endian_swap_32(x) -> y
|
||||
function bswap32(x) -> y
|
||||
{
|
||||
let hi := i64.shl(endian_swap_16(x), 16)
|
||||
y := i64.or(hi, endian_swap_16(i64.shr_u(x, 16)))
|
||||
let hi := i64.shl(bswap16(x), 16)
|
||||
y := i64.or(hi, bswap16(i64.shr_u(x, 16)))
|
||||
}
|
||||
function endian_swap(x) -> y
|
||||
function bswap64(x) -> y
|
||||
{
|
||||
let hi := i64.shl(endian_swap_32(x), 32)
|
||||
y := i64.or(hi, endian_swap_32(i64.shr_u(x, 32)))
|
||||
let hi := i64.shl(bswap32(x), 32)
|
||||
y := i64.or(hi, bswap32(i64.shr_u(x, 32)))
|
||||
}
|
||||
function mstore_internal(pos:i32, y1, y2, y3, y4)
|
||||
{
|
||||
i64.store(pos, endian_swap(y1))
|
||||
i64.store(i32.add(pos, 8:i32), endian_swap(y2))
|
||||
i64.store(i32.add(pos, 16:i32), endian_swap(y3))
|
||||
i64.store(i32.add(pos, 24:i32), endian_swap(y4))
|
||||
i64.store(pos, bswap64(y1))
|
||||
i64.store(i32.add(pos, 8:i32), bswap64(y2))
|
||||
i64.store(i32.add(pos, 16:i32), bswap64(y3))
|
||||
i64.store(i32.add(pos, 24:i32), bswap64(y4))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -63,7 +63,7 @@ Text representation:
|
||||
)
|
||||
)
|
||||
|
||||
(func $endian_swap_16
|
||||
(func $bswap16
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
@ -74,27 +74,27 @@ Text representation:
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $endian_swap_32
|
||||
(func $bswap32
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(local $hi i64)
|
||||
(block $label__2
|
||||
(local.set $hi (i64.shl (call $endian_swap_16 (local.get $x)) (i64.const 16)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $endian_swap_16 (i64.shr_u (local.get $x) (i64.const 16)))))
|
||||
(local.set $hi (i64.shl (call $bswap16 (local.get $x)) (i64.const 16)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $bswap16 (i64.shr_u (local.get $x) (i64.const 16)))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $endian_swap
|
||||
(func $bswap64
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(local $hi i64)
|
||||
(block $label__3
|
||||
(local.set $hi (i64.shl (call $endian_swap_32 (local.get $x)) (i64.const 32)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $endian_swap_32 (i64.shr_u (local.get $x) (i64.const 32)))))
|
||||
(local.set $hi (i64.shl (call $bswap32 (local.get $x)) (i64.const 32)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $bswap32 (i64.shr_u (local.get $x) (i64.const 32)))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
@ -107,10 +107,10 @@ Text representation:
|
||||
(param $y3 i64)
|
||||
(param $y4 i64)
|
||||
(block $label__4
|
||||
(i64.store (local.get $pos) (call $endian_swap (local.get $y1)))
|
||||
(i64.store (i32.add (local.get $pos) (i32.const 8)) (call $endian_swap (local.get $y2)))
|
||||
(i64.store (i32.add (local.get $pos) (i32.const 16)) (call $endian_swap (local.get $y3)))
|
||||
(i64.store (i32.add (local.get $pos) (i32.const 24)) (call $endian_swap (local.get $y4)))
|
||||
(i64.store (local.get $pos) (call $bswap64 (local.get $y1)))
|
||||
(i64.store (i32.add (local.get $pos) (i32.const 8)) (call $bswap64 (local.get $y2)))
|
||||
(i64.store (i32.add (local.get $pos) (i32.const 16)) (call $bswap64 (local.get $y3)))
|
||||
(i64.store (i32.add (local.get $pos) (i32.const 24)) (call $bswap64 (local.get $y4)))
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -43,7 +43,7 @@ object "object" {
|
||||
x_7 := x_11
|
||||
}
|
||||
{
|
||||
let _5, _6, _7, _8 := iszero_170_789(_1, _1, _1, lt_172(x_4, x_5, x_6, x_7, _1, _1, _1, 10))
|
||||
let _5, _6, _7, _8 := iszero_169_788(_1, _1, _1, lt_171(x_4, x_5, x_6, x_7, _1, _1, _1, 10))
|
||||
if i32.eqz(i64.eqz(i64.or(i64.or(_5, _6), i64.or(_7, _8)))) { break }
|
||||
if i32.eqz(i64.eqz(i64.or(_3, i64.or(_1, eq(x_4, x_5, x_6, x_7, _1, _1, _1, 2))))) { break }
|
||||
if i32.eqz(i64.eqz(i64.or(_3, i64.or(_1, eq(x_4, x_5, x_6, x_7, _1, _1, _1, 4))))) { continue }
|
||||
@ -67,7 +67,7 @@ object "object" {
|
||||
let r1_1, carry_2 := add_carry(x1, y1, carry_1)
|
||||
r1 := r1_1
|
||||
}
|
||||
function iszero_170_789(x1, x2, x3, x4) -> r1, r2, r3, r4
|
||||
function iszero_169_788(x1, x2, x3, x4) -> r1, r2, r3, r4
|
||||
{
|
||||
r4 := i64.extend_i32_u(i64.eqz(i64.or(i64.or(x1, x2), i64.or(x3, x4))))
|
||||
}
|
||||
@ -87,7 +87,7 @@ object "object" {
|
||||
case 1:i32 { r := 0xffffffff:i32 }
|
||||
default { r := i64.ne(a, b) }
|
||||
}
|
||||
function lt_172(x1, x2, x3, x4, y1, y2, y3, y4) -> z4
|
||||
function lt_171(x1, x2, x3, x4, y1, y2, y3, y4) -> z4
|
||||
{
|
||||
let z:i32 := false
|
||||
switch cmp(x1, y1)
|
||||
@ -106,40 +106,40 @@ object "object" {
|
||||
default { z := 1:i32 }
|
||||
z4 := i64.extend_i32_u(z)
|
||||
}
|
||||
function bswap16(x) -> y
|
||||
{
|
||||
y := i64.or(i64.and(i64.shl(x, 8), 0xff00), i64.and(i64.shr_u(x, 8), 0xff))
|
||||
}
|
||||
function bswap32(x) -> y
|
||||
{
|
||||
let hi := i64.shl(bswap16(x), 16)
|
||||
y := i64.or(hi, bswap16(i64.shr_u(x, 16)))
|
||||
}
|
||||
function bswap64(x) -> y
|
||||
{
|
||||
let hi := i64.shl(bswap32(x), 32)
|
||||
y := i64.or(hi, bswap32(i64.shr_u(x, 32)))
|
||||
}
|
||||
function calldataload(x1, x2, x3, x4) -> z1, z2, z3, z4
|
||||
{
|
||||
if i64.ne(0, i64.or(i64.or(x1, x2), x3)) { unreachable() }
|
||||
if i64.ne(0, i64.shr_u(x4, 32)) { unreachable() }
|
||||
eth.callDataCopy(0:i32, i32.wrap_i64(x4), 32:i32)
|
||||
let z1_1 := endian_swap(i64.load(0:i32))
|
||||
let z2_1 := endian_swap(i64.load(i32.add(0:i32, 8:i32)))
|
||||
let z3_1 := endian_swap(i64.load(i32.add(0:i32, 16:i32)))
|
||||
let z4_1 := endian_swap(i64.load(i32.add(0:i32, 24:i32)))
|
||||
let z1_1 := bswap64(i64.load(0:i32))
|
||||
let z2_1 := bswap64(i64.load(i32.add(0:i32, 8:i32)))
|
||||
let z3_1 := bswap64(i64.load(i32.add(0:i32, 16:i32)))
|
||||
let z4_1 := bswap64(i64.load(i32.add(0:i32, 24:i32)))
|
||||
z1 := z1_1
|
||||
z2 := z2_1
|
||||
z3 := z3_1
|
||||
z4 := z4_1
|
||||
}
|
||||
function endian_swap_16(x) -> y
|
||||
{
|
||||
y := i64.or(i64.and(i64.shl(x, 8), 0xff00), i64.and(i64.shr_u(x, 8), 0xff))
|
||||
}
|
||||
function endian_swap_32(x) -> y
|
||||
{
|
||||
let hi := i64.shl(endian_swap_16(x), 16)
|
||||
y := i64.or(hi, endian_swap_16(i64.shr_u(x, 16)))
|
||||
}
|
||||
function endian_swap(x) -> y
|
||||
{
|
||||
let hi := i64.shl(endian_swap_32(x), 32)
|
||||
y := i64.or(hi, endian_swap_32(i64.shr_u(x, 32)))
|
||||
}
|
||||
function mstore_internal(pos:i32, y1, y2, y3, y4)
|
||||
{
|
||||
i64.store(pos, endian_swap(y1))
|
||||
i64.store(i32.add(pos, 8:i32), endian_swap(y2))
|
||||
i64.store(i32.add(pos, 16:i32), endian_swap(y3))
|
||||
i64.store(i32.add(pos, 24:i32), endian_swap(y4))
|
||||
i64.store(pos, bswap64(y1))
|
||||
i64.store(i32.add(pos, 8:i32), bswap64(y2))
|
||||
i64.store(i32.add(pos, 16:i32), bswap64(y3))
|
||||
i64.store(i32.add(pos, 24:i32), bswap64(y4))
|
||||
}
|
||||
function sstore(x1, x2, x3, x4, y1, y2, y3, y4)
|
||||
{
|
||||
@ -152,7 +152,7 @@ object "object" {
|
||||
|
||||
|
||||
Binary representation:
|
||||
0061736d0100000001480a60000060017e017e60027e7e017f60037e7e7e017e60047e7e7e7e017e60087e7e7e7e7e7e7e7e0060087e7e7e7e7e7e7e7e017e60057f7e7e7e7e0060027f7f0060037f7f7f0002310208657468657265756d0c73746f7261676553746f7265000808657468657265756d0c63616c6c44617461436f70790009030e0d0003060406020604010101070505030100010610037e0142000b7e0142000b7e0142000b071102066d656d6f72790200046d61696e00020af0070da302030b7e017f087e02404200210002402000200020002000100921012300210223012103230221040b20012105200221062003210720042108420121092000200084210a200a200020098484504545210b02400340200b45450d01024002402000200020002005200620072008200020002000420a10081005210c2300210d2301210e2302210f0b200c200d84200e200f8484504504400c030b200a20002005200620072008200020002000420210068484504504400c030b200a20002005200620072008200020002000420410068484504504400c010b0b024020052006200720082000200020002009100421102300211123012112230221130b201021052011210620122107201321080c000b0b20002000200020002005200620072008100e0b0b2901037e0240200020017c2105200520027c21032005200054200320055472ad21040b2004240020030b6c010b7e0240200320077c210c200c42007c210b024020022006200c200354200b200c5472ad1003210d2300210e0b200d210a024020012005200e1003210f230021100b200f2109024020002004201010032111230021120b201121080b20092400200a2401200b240220080b2401047e0240200020018420022003848450ad21070b20052400200624012007240220040b2d01017e024020002004510440200120055104402002200651044020032007510440420121080b0b0b0b0b20080b2701027f024002402000200154210320034101460440417f210205200020015221020b0b0b20020b8a0102017e047f0240410021090240200020041007210a200a41004604400240200120051007210b200b41004604400240200220061007210c200c41004604402003200754210905200c41014604404100210905410121090b0b0b05200b41014604404100210905410121090b0b0b05200a41014604404100210905410121090b0b0b2009ad21080b20080b7601087e024042002000200184200284520440000b42002003422088520440000b41002003a7412010014100290000100c2108410041086a290000100c2109410041106a290000100c210a410041186a290000100c210b2008210420092105200a2106200b21070b20052400200624012007240220040b1f01017e024020004208864280fe0383200042088842ff01838421010b20010b1e01027e02402000100a421086210220022000421088100a8421010b20010b1e01027e02402000100b422086210220022000422088100b8421010b20010b3200024020002001100c370000200041086a2002100c370000200041106a2003100c370000200041186a2004100c3700000b0b2300024041002000200120022003100d41202004200520062007100d4100412010000b0b
|
||||
0061736d0100000001480a60000060017e017e60027e7e017f60037e7e7e017e60047e7e7e7e017e60087e7e7e7e7e7e7e7e0060087e7e7e7e7e7e7e7e017e60057f7e7e7e7e0060027f7f0060037f7f7f0002310208657468657265756d0c73746f7261676553746f7265000808657468657265756d0c63616c6c44617461436f70790009030e0d0003060406020601010104070505030100010610037e0142000b7e0142000b7e0142000b071102066d656d6f72790200046d61696e00020af0070da302030b7e017f087e02404200210002402000200020002000100c21012300210223012103230221040b20012105200221062003210720042108420121092000200084210a200a200020098484504545210b02400340200b45450d01024002402000200020002005200620072008200020002000420a10081005210c2300210d2301210e2302210f0b200c200d84200e200f8484504504400c030b200a20002005200620072008200020002000420210068484504504400c030b200a20002005200620072008200020002000420410068484504504400c010b0b024020052006200720082000200020002009100421102300211123012112230221130b201021052011210620122107201321080c000b0b20002000200020002005200620072008100e0b0b2901037e0240200020017c2105200520027c21032005200054200320055472ad21040b2004240020030b6c010b7e0240200320077c210c200c42007c210b024020022006200c200354200b200c5472ad1003210d2300210e0b200d210a024020012005200e1003210f230021100b200f2109024020002004201010032111230021120b201121080b20092400200a2401200b240220080b2401047e0240200020018420022003848450ad21070b20052400200624012007240220040b2d01017e024020002004510440200120055104402002200651044020032007510440420121080b0b0b0b0b20080b2701027f024002402000200154210320034101460440417f210205200020015221020b0b0b20020b8a0102017e047f0240410021090240200020041007210a200a41004604400240200120051007210b200b41004604400240200220061007210c200c41004604402003200754210905200c41014604404100210905410121090b0b0b05200b41014604404100210905410121090b0b0b05200a41014604404100210905410121090b0b0b2009ad21080b20080b1f01017e024020004208864280fe0383200042088842ff01838421010b20010b1e01027e02402000100942108621022002200042108810098421010b20010b1e01027e02402000100a422086210220022000422088100a8421010b20010b7601087e024042002000200184200284520440000b42002003422088520440000b41002003a7412010014100290000100b2108410041086a290000100b2109410041106a290000100b210a410041186a290000100b210b2008210420092105200a2106200b21070b20052400200624012007240220040b3200024020002001100b370000200041086a2002100b370000200041106a2003100b370000200041186a2004100b3700000b0b2300024041002000200120022003100d41202004200520062007100d4100412010000b0b
|
||||
|
||||
Text representation:
|
||||
(module
|
||||
@ -206,7 +206,7 @@ Text representation:
|
||||
(br_if $label__3 (i32.eqz (i32.eqz (local.get $_4))))
|
||||
(block $label__4
|
||||
(block
|
||||
(local.set $_5 (call $iszero_170_789 (local.get $_1) (local.get $_1) (local.get $_1) (call $lt_172 (local.get $x_4) (local.get $x_5) (local.get $x_6) (local.get $x_7) (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 10))))
|
||||
(local.set $_5 (call $iszero_169_788 (local.get $_1) (local.get $_1) (local.get $_1) (call $lt_171 (local.get $x_4) (local.get $x_5) (local.get $x_6) (local.get $x_7) (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 10))))
|
||||
(local.set $_6 (global.get $global_))
|
||||
(local.set $_7 (global.get $global__1))
|
||||
(local.set $_8 (global.get $global__2))
|
||||
@ -310,7 +310,7 @@ Text representation:
|
||||
(local.get $r1)
|
||||
)
|
||||
|
||||
(func $iszero_170_789
|
||||
(func $iszero_169_788
|
||||
(param $x1 i64)
|
||||
(param $x2 i64)
|
||||
(param $x3 i64)
|
||||
@ -377,7 +377,7 @@ Text representation:
|
||||
(local.get $r)
|
||||
)
|
||||
|
||||
(func $lt_172
|
||||
(func $lt_171
|
||||
(param $x1 i64)
|
||||
(param $x2 i64)
|
||||
(param $x3 i64)
|
||||
@ -437,6 +437,43 @@ Text representation:
|
||||
(local.get $z4)
|
||||
)
|
||||
|
||||
(func $bswap16
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(block $label__15
|
||||
(local.set $y (i64.or (i64.and (i64.shl (local.get $x) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (local.get $x) (i64.const 8)) (i64.const 255))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $bswap32
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(local $hi i64)
|
||||
(block $label__16
|
||||
(local.set $hi (i64.shl (call $bswap16 (local.get $x)) (i64.const 16)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $bswap16 (i64.shr_u (local.get $x) (i64.const 16)))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $bswap64
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(local $hi i64)
|
||||
(block $label__17
|
||||
(local.set $hi (i64.shl (call $bswap32 (local.get $x)) (i64.const 32)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $bswap32 (i64.shr_u (local.get $x) (i64.const 32)))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $calldataload
|
||||
(param $x1 i64)
|
||||
(param $x2 i64)
|
||||
@ -451,16 +488,16 @@ Text representation:
|
||||
(local $z2_1 i64)
|
||||
(local $z3_1 i64)
|
||||
(local $z4_1 i64)
|
||||
(block $label__15
|
||||
(block $label__18
|
||||
(if (i64.ne (i64.const 0) (i64.or (i64.or (local.get $x1) (local.get $x2)) (local.get $x3))) (then
|
||||
(unreachable)))
|
||||
(if (i64.ne (i64.const 0) (i64.shr_u (local.get $x4) (i64.const 32))) (then
|
||||
(unreachable)))
|
||||
(call $eth.callDataCopy (i32.const 0) (i32.wrap_i64 (local.get $x4)) (i32.const 32))
|
||||
(local.set $z1_1 (call $endian_swap (i64.load (i32.const 0))))
|
||||
(local.set $z2_1 (call $endian_swap (i64.load (i32.add (i32.const 0) (i32.const 8)))))
|
||||
(local.set $z3_1 (call $endian_swap (i64.load (i32.add (i32.const 0) (i32.const 16)))))
|
||||
(local.set $z4_1 (call $endian_swap (i64.load (i32.add (i32.const 0) (i32.const 24)))))
|
||||
(local.set $z1_1 (call $bswap64 (i64.load (i32.const 0))))
|
||||
(local.set $z2_1 (call $bswap64 (i64.load (i32.add (i32.const 0) (i32.const 8)))))
|
||||
(local.set $z3_1 (call $bswap64 (i64.load (i32.add (i32.const 0) (i32.const 16)))))
|
||||
(local.set $z4_1 (call $bswap64 (i64.load (i32.add (i32.const 0) (i32.const 24)))))
|
||||
(local.set $z1 (local.get $z1_1))
|
||||
(local.set $z2 (local.get $z2_1))
|
||||
(local.set $z3 (local.get $z3_1))
|
||||
@ -473,43 +510,6 @@ Text representation:
|
||||
(local.get $z1)
|
||||
)
|
||||
|
||||
(func $endian_swap_16
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(block $label__16
|
||||
(local.set $y (i64.or (i64.and (i64.shl (local.get $x) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (local.get $x) (i64.const 8)) (i64.const 255))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $endian_swap_32
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(local $hi i64)
|
||||
(block $label__17
|
||||
(local.set $hi (i64.shl (call $endian_swap_16 (local.get $x)) (i64.const 16)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $endian_swap_16 (i64.shr_u (local.get $x) (i64.const 16)))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $endian_swap
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(local $hi i64)
|
||||
(block $label__18
|
||||
(local.set $hi (i64.shl (call $endian_swap_32 (local.get $x)) (i64.const 32)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $endian_swap_32 (i64.shr_u (local.get $x) (i64.const 32)))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $mstore_internal
|
||||
(param $pos i32)
|
||||
(param $y1 i64)
|
||||
@ -517,10 +517,10 @@ Text representation:
|
||||
(param $y3 i64)
|
||||
(param $y4 i64)
|
||||
(block $label__19
|
||||
(i64.store (local.get $pos) (call $endian_swap (local.get $y1)))
|
||||
(i64.store (i32.add (local.get $pos) (i32.const 8)) (call $endian_swap (local.get $y2)))
|
||||
(i64.store (i32.add (local.get $pos) (i32.const 16)) (call $endian_swap (local.get $y3)))
|
||||
(i64.store (i32.add (local.get $pos) (i32.const 24)) (call $endian_swap (local.get $y4)))
|
||||
(i64.store (local.get $pos) (call $bswap64 (local.get $y1)))
|
||||
(i64.store (i32.add (local.get $pos) (i32.const 8)) (call $bswap64 (local.get $y2)))
|
||||
(i64.store (i32.add (local.get $pos) (i32.const 16)) (call $bswap64 (local.get $y3)))
|
||||
(i64.store (i32.add (local.get $pos) (i32.const 24)) (call $bswap64 (local.get $y4)))
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{"contracts":{"A":{"C":{"ewasm":{"wasm":"0061736d01000000013a0860000060017e017e60047e7e7e7e017f60087e7e7e7e7e7e7e7e00600c7e7e7e7e7e7e7e7e7e7e7e7e0060017f0060027f7f0060037f7f7f0002510408657468657265756d08636f6465436f7079000708657468657265756d06726576657274000608657468657265756d0c67657443616c6c56616c7565000508657468657265756d0666696e6973680006030a090002020401010103030503010001060100071102066d656d6f72790200046d61696e0004009d030c435f325f6465706c6f7965640061736d0100000001160460000060017e017e60047e7e7e7e017f60027f7f0002130108657468657265756d067265766572740003030504000201010503010001060100071102066d656d6f72790200046d61696e00010ab60204ca0104017e027f057e037f02404200210020002000200042c00010022101200141c0006a210220022001490440000b20001003421086210320032000421088100384422086210420042000422088100484210520022005370000200241086a2005370000200241106a20053700004280011003421086210620064280014210881003844220862107200241186a2007428001422088100484370000200020002000200010022108200020002000200010022109200941c0006a210a200a2009490440000b200a200810000b0b2901017f024042002000200184200284520440000b42002003422088520440000b2003a721040b20040b1f01017e024020004208864280fe0383200042088842ff01838421010b20010b1e01027e02402000100342108621022002200042108810038421010b20010b0aec0309dc0103017e027f057e02404200210020002000200042c00010052101200141c0006a210220022001490440000b2000100a210320022003370000200241086a2003370000200241106a2003370000200241186a428001100a370000410010024100290000100a2104410041086a290000100a2105410041106a290000100a210620042005842006410041186a290000100a84845045044020002000200020002000200020002000100c0b4290032107200020002000200020002000200042ce012000200020002007100720002000200020002000200020002007100b0b0b2901017f024042002000200184200284520440000b42002003422088520440000b2003a721040b20040b2601027f0240200020012002200310052105200541c0006a210420042005490440000b0b20040b25000240200020012002200310062004200520062007100520082009200a200b100510000b0b1f01017e024020004208864280fe0383200042088842ff01838421010b20010b1e01027e02402000100842108621022002200042108810088421010b20010b1e01027e02402000100942208621022002200042208810098421010b20010b1b000240200020012002200310062004200520062007100510030b0b1b000240200020012002200310062004200520062007100510010b0b","wast":"(module
|
||||
{"contracts":{"A":{"C":{"ewasm":{"wasm":"0061736d01000000013a0860000060017e017e60047e7e7e7e017f60087e7e7e7e7e7e7e7e00600c7e7e7e7e7e7e7e7e7e7e7e7e0060017f0060027f7f0060037f7f7f0002510408657468657265756d08636f6465436f7079000708657468657265756d06726576657274000608657468657265756d0c67657443616c6c56616c7565000508657468657265756d0666696e6973680006030a090002020101010403030503010001060100071102066d656d6f72790200046d61696e0004009d030c435f325f6465706c6f7965640061736d0100000001160460000060017e017e60047e7e7e7e017f60027f7f0002130108657468657265756d067265766572740003030504000201010503010001060100071102066d656d6f72790200046d61696e00010ab60204ca0104017e027f057e037f02404200210020002000200042c00010022101200141c0006a210220022001490440000b20001003421086210320032000421088100384422086210420042000422088100484210520022005370000200241086a2005370000200241106a20053700004280011003421086210620064280014210881003844220862107200241186a2007428001422088100484370000200020002000200010022108200020002000200010022109200941c0006a210a200a2009490440000b200a200810000b0b2901017f024042002000200184200284520440000b42002003422088520440000b2003a721040b20040b1f01017e024020004208864280fe0383200042088842ff01838421010b20010b1e01027e02402000100342108621022002200042108810038421010b20010b0aec0309dc0103017e027f057e02404200210020002000200042c00010052101200141c0006a210220022001490440000b20001009210320022003370000200241086a2003370000200241106a2003370000200241186a428001100937000041001002410029000010092104410041086a29000010092105410041106a2900001009210620042005842006410041186a290000100984845045044020002000200020002000200020002000100c0b4290032107200020002000200020002000200042ce012000200020002007100a20002000200020002000200020002007100b0b0b2901017f024042002000200184200284520440000b42002003422088520440000b2003a721040b20040b2601027f0240200020012002200310052105200541c0006a210420042005490440000b0b20040b1f01017e024020004208864280fe0383200042088842ff01838421010b20010b1e01027e02402000100742108621022002200042108810078421010b20010b1e01027e02402000100842208621022002200042208810088421010b20010b25000240200020012002200310062004200520062007100520082009200a200b100510000b0b1b000240200020012002200310062004200520062007100510030b0b1b000240200020012002200310062004200520062007100510010b0b","wast":"(module
|
||||
;; custom section for sub-module
|
||||
;; The Keccak-256 hash of the text representation of \"C_2_deployed\": f03f5b9154b9eb6803a947177e38e92e2860de95e90ba0e75eb71a58f18ed589
|
||||
;; The Keccak-256 hash of the text representation of \"C_2_deployed\": 0289c074ac70ccfdbeb7817862087cc066a9f7707de1a981bb8b5b12dd2ce4e9
|
||||
;; (@custom \"C_2_deployed\" \"0061736d0100000001160460000060017e017e60047e7e7e7e017f60027f7f0002130108657468657265756d067265766572740003030504000201010503010001060100071102066d656d6f72790200046d61696e00010ab60204ca0104017e027f057e037f02404200210020002000200042c00010022101200141c0006a210220022001490440000b20001003421086210320032000421088100384422086210420042000422088100484210520022005370000200241086a2005370000200241106a20053700004280011003421086210620064280014210881003844220862107200241186a2007428001422088100484370000200020002000200010022108200020002000200010022109200941c0006a210a200a2009490440000b200a200810000b0b2901017f024042002000200184200284520440000b42002003422088520440000b2003a721040b20040b1f01017e024020004208864280fe0383200042088842ff01838421010b20010b1e01027e02402000100342108621022002200042108810038421010b20010b\")
|
||||
(import \"ethereum\" \"codeCopy\" (func $eth.codeCopy (param i32 i32 i32)))
|
||||
(import \"ethereum\" \"revert\" (func $eth.revert (param i32 i32)))
|
||||
@ -24,16 +24,16 @@
|
||||
(local.set $r (i32.add (local.get $p) (i32.const 64)))
|
||||
(if (i32.lt_u (local.get $r) (local.get $p)) (then
|
||||
(unreachable)))
|
||||
(local.set $_2 (call $endian_swap (local.get $_1)))
|
||||
(local.set $_2 (call $bswap64 (local.get $_1)))
|
||||
(i64.store (local.get $r) (local.get $_2))
|
||||
(i64.store (i32.add (local.get $r) (i32.const 8)) (local.get $_2))
|
||||
(i64.store (i32.add (local.get $r) (i32.const 16)) (local.get $_2))
|
||||
(i64.store (i32.add (local.get $r) (i32.const 24)) (call $endian_swap (i64.const 128)))
|
||||
(i64.store (i32.add (local.get $r) (i32.const 24)) (call $bswap64 (i64.const 128)))
|
||||
(call $eth.getCallValue (i32.const 0))
|
||||
(local.set $z1 (call $endian_swap (i64.load (i32.const 0))))
|
||||
(local.set $z2 (call $endian_swap (i64.load (i32.add (i32.const 0) (i32.const 8)))))
|
||||
(local.set $z3 (call $endian_swap (i64.load (i32.add (i32.const 0) (i32.const 16)))))
|
||||
(if (i32.eqz (i64.eqz (i64.or (i64.or (local.get $z1) (local.get $z2)) (i64.or (local.get $z3) (call $endian_swap (i64.load (i32.add (i32.const 0) (i32.const 24)))))))) (then
|
||||
(local.set $z1 (call $bswap64 (i64.load (i32.const 0))))
|
||||
(local.set $z2 (call $bswap64 (i64.load (i32.add (i32.const 0) (i32.const 8)))))
|
||||
(local.set $z3 (call $bswap64 (i64.load (i32.add (i32.const 0) (i32.const 16)))))
|
||||
(if (i32.eqz (i64.eqz (i64.or (i64.or (local.get $z1) (local.get $z2)) (i64.or (local.get $z3) (call $bswap64 (i64.load (i32.add (i32.const 0) (i32.const 24)))))))) (then
|
||||
(call $revert (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1))))
|
||||
(local.set $_3 (datasize \"C_2_deployed\"))
|
||||
(call $codecopy (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (dataoffset \"C_2_deployed\") (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_3))
|
||||
@ -77,6 +77,43 @@
|
||||
(local.get $r)
|
||||
)
|
||||
|
||||
(func $bswap16
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(block $label__3
|
||||
(local.set $y (i64.or (i64.and (i64.shl (local.get $x) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (local.get $x) (i64.const 8)) (i64.const 255))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $bswap32
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(local $hi i64)
|
||||
(block $label__4
|
||||
(local.set $hi (i64.shl (call $bswap16 (local.get $x)) (i64.const 16)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $bswap16 (i64.shr_u (local.get $x) (i64.const 16)))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $bswap64
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(local $hi i64)
|
||||
(block $label__5
|
||||
(local.set $hi (i64.shl (call $bswap32 (local.get $x)) (i64.const 32)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $bswap32 (i64.shr_u (local.get $x) (i64.const 32)))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $codecopy
|
||||
(param $x1 i64)
|
||||
(param $x2 i64)
|
||||
@ -90,48 +127,11 @@
|
||||
(param $z2 i64)
|
||||
(param $z3 i64)
|
||||
(param $z4 i64)
|
||||
(block $label__3
|
||||
(block $label__6
|
||||
(call $eth.codeCopy (call $to_internal_i32ptr (local.get $x1) (local.get $x2) (local.get $x3) (local.get $x4)) (call $u256_to_i32 (local.get $y1) (local.get $y2) (local.get $y3) (local.get $y4)) (call $u256_to_i32 (local.get $z1) (local.get $z2) (local.get $z3) (local.get $z4)))
|
||||
)
|
||||
)
|
||||
|
||||
(func $endian_swap_16
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(block $label__4
|
||||
(local.set $y (i64.or (i64.and (i64.shl (local.get $x) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (local.get $x) (i64.const 8)) (i64.const 255))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $endian_swap_32
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(local $hi i64)
|
||||
(block $label__5
|
||||
(local.set $hi (i64.shl (call $endian_swap_16 (local.get $x)) (i64.const 16)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $endian_swap_16 (i64.shr_u (local.get $x) (i64.const 16)))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $endian_swap
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(local $hi i64)
|
||||
(block $label__6
|
||||
(local.set $hi (i64.shl (call $endian_swap_32 (local.get $x)) (i64.const 32)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $endian_swap_32 (i64.shr_u (local.get $x) (i64.const 32)))))
|
||||
|
||||
)
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $return
|
||||
(param $x1 i64)
|
||||
(param $x2 i64)
|
||||
|
@ -187,6 +187,7 @@
|
||||
"isOffset": true,
|
||||
"isSlot": false,
|
||||
"src": "106:8:1",
|
||||
"suffix": "offset",
|
||||
"valueSize": 1
|
||||
},
|
||||
{
|
||||
@ -194,6 +195,7 @@
|
||||
"isOffset": false,
|
||||
"isSlot": true,
|
||||
"src": "128:6:1",
|
||||
"suffix": "slot",
|
||||
"valueSize": 1
|
||||
}
|
||||
],
|
||||
|
@ -180,6 +180,7 @@
|
||||
"isOffset": true,
|
||||
"isSlot": false,
|
||||
"src": "106:8:1",
|
||||
"suffix": "offset",
|
||||
"valueSize": 1
|
||||
},
|
||||
{
|
||||
@ -187,6 +188,7 @@
|
||||
"isOffset": false,
|
||||
"isSlot": true,
|
||||
"src": "128:6:1",
|
||||
"suffix": "slot",
|
||||
"valueSize": 1
|
||||
}
|
||||
],
|
||||
|
@ -8,5 +8,7 @@ contract C {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 0x00
|
||||
|
@ -16,6 +16,8 @@ contract C {
|
||||
return fu();
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// library: L
|
||||
// f() -> 7, 8
|
@ -0,0 +1,8 @@
|
||||
contract C {
|
||||
function f(uint[2][] calldata x) public returns (uint[2][] memory r) {
|
||||
assembly { x.offset := 0x44 x.length := 2 }
|
||||
r = x;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// f(uint256[2][]): 0x0, 1, 8, 7, 6, 5 -> 0x20, 2, 8, 7, 6, 5
|
@ -0,0 +1,12 @@
|
||||
contract C {
|
||||
function f(uint[2][] calldata x) public returns (uint o, uint l, uint s) {
|
||||
assembly { l := x.length o := x.offset }
|
||||
uint[2] calldata t = x[1];
|
||||
// statically-sized arrays only use one slot, so we read directly.
|
||||
assembly { s := t }
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f(uint256[2][]): 0x20, 2, 1, 2, 3, 4 -> 0x44, 2, 0x84
|
@ -0,0 +1,10 @@
|
||||
contract C {
|
||||
function f(bytes calldata x) public returns (bytes memory) {
|
||||
assembly { x.offset := 1 x.length := 3 }
|
||||
return x;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f(bytes): 0x20, 0, 0 -> 0x20, 3, 0x5754f80000000000000000000000000000000000000000000000000000000000
|
@ -0,0 +1,9 @@
|
||||
contract C {
|
||||
function f() public pure returns (bytes calldata x) {
|
||||
assembly { x.offset := 0 x.length := 4 }
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 0x20, 4, 0x26121ff000000000000000000000000000000000000000000000000000000000
|
@ -0,0 +1,18 @@
|
||||
contract C {
|
||||
function lenBytesRead(bytes calldata x) public returns (uint l) {
|
||||
assembly { l := x.length }
|
||||
}
|
||||
|
||||
function lenStringRead(string calldata x) public returns (uint l) {
|
||||
assembly { l := x.length }
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// lenBytesRead(bytes): 0x20, 4, "abcd" -> 4
|
||||
// lenBytesRead(bytes): 0x20, 0, "abcd" -> 0x00
|
||||
// lenBytesRead(bytes): 0x20, 0x21, "abcd", "ef" -> 33
|
||||
// lenStringRead(string): 0x20, 4, "abcd" -> 4
|
||||
// lenStringRead(string): 0x20, 0, "abcd" -> 0x00
|
||||
// lenStringRead(string): 0x20, 0x21, "abcd", "ef" -> 33
|
@ -0,0 +1,19 @@
|
||||
contract C {
|
||||
function f(bytes calldata x) public returns (uint r) {
|
||||
assembly { r := x.offset }
|
||||
}
|
||||
|
||||
function f(uint, bytes calldata x, uint) public returns (uint r, uint v) {
|
||||
assembly {
|
||||
r := x.offset
|
||||
v := x.length
|
||||
}
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f(bytes): 0x20, 0, 0 -> 0x44
|
||||
// f(bytes): 0x22, 0, 0, 0 -> 0x46
|
||||
// f(uint256,bytes,uint256): 7, 0x60, 8, 2, 0 -> 0x84, 2
|
||||
// f(uint256,bytes,uint256): 0, 0, 0 -> 0x24, 0x00
|
@ -0,0 +1,18 @@
|
||||
contract C {
|
||||
function f(uint, bytes calldata x, uint) public returns (uint r, uint v) {
|
||||
assembly {
|
||||
x.offset := 8
|
||||
x.length := 20
|
||||
}
|
||||
assembly {
|
||||
r := x.offset
|
||||
v := x.length
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f(uint256,bytes,uint256): 7, 0x60, 8, 2, 0 -> 8, 0x14
|
||||
// f(uint256,bytes,uint256): 0, 0, 0 -> 8, 0x14
|
@ -14,5 +14,7 @@ contract C {
|
||||
}
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 2, left(0xabcd), left(0x616263), true, 0x1212121212121212121212121212121212121212
|
||||
|
@ -22,5 +22,7 @@ contract C {
|
||||
}
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 2, left(0xabcd), left(0x616263), true, 0x1212121212121212121212121212121212121212
|
||||
|
@ -25,6 +25,8 @@ contract C {
|
||||
return data().a;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// get() -> 0
|
||||
// mappingAccess(uint256): 1 -> 0, 0
|
||||
|
@ -0,0 +1,26 @@
|
||||
library L {
|
||||
function run(
|
||||
function(uint256) external returns (uint256) _operation,
|
||||
uint256 _a
|
||||
)
|
||||
external
|
||||
returns (uint256)
|
||||
{
|
||||
return _operation(_a);
|
||||
}
|
||||
}
|
||||
|
||||
contract C {
|
||||
function double(uint256 _a) external returns (uint256) {
|
||||
return _a * _a;
|
||||
}
|
||||
|
||||
function g(uint256 _value) external returns (uint256) {
|
||||
return L.run(this.double, _value);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// library: L
|
||||
// g(uint256): 4 -> 16
|
@ -0,0 +1,19 @@
|
||||
library L {
|
||||
function f(uint256[2] storage _a) external returns (uint256) {
|
||||
return _a[0] * _a[1];
|
||||
}
|
||||
}
|
||||
|
||||
contract C {
|
||||
uint256[2] x;
|
||||
|
||||
function g(uint256 _value) external returns (uint256) {
|
||||
x[0] = x[1] = _value;
|
||||
return L.f(x);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// library: L
|
||||
// g(uint256): 4 -> 16
|
@ -0,0 +1,17 @@
|
||||
library L {
|
||||
function f(mapping(uint256 => uint256) storage _a) external returns (uint256) {
|
||||
return _a[0] * _a[1];
|
||||
}
|
||||
}
|
||||
|
||||
contract C {
|
||||
mapping(uint256 => uint256) x;
|
||||
|
||||
function g(uint256 _value) external returns (uint256) {
|
||||
x[0] = x[1] = _value;
|
||||
return L.f(x);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// library: L
|
||||
// g(uint256): 4 -> 16
|
@ -12,6 +12,8 @@ contract C {
|
||||
return success;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// library: L
|
||||
// g(uint256,uint256): 1, 1 -> true
|
||||
|
@ -0,0 +1,60 @@
|
||||
==== Source: a.sol ====
|
||||
|
||||
import "a.sol" as M;
|
||||
|
||||
library L {
|
||||
function f(uint256 v) external pure returns (uint) {
|
||||
return v * v;
|
||||
}
|
||||
function g(uint256 v) external returns (uint) {
|
||||
return v * v;
|
||||
}
|
||||
}
|
||||
contract C {
|
||||
function addr() public view returns (bool) {
|
||||
return address(M.L) == address(0);
|
||||
}
|
||||
function g(uint256 v) public view returns (uint256) {
|
||||
return M.L.f(v);
|
||||
}
|
||||
function h(uint256 v) public returns (uint256) {
|
||||
(bool success, bytes memory result) = address(M.L).delegatecall(abi.encodeWithSignature("f(uint256)", v));
|
||||
assert(success);
|
||||
return abi.decode(result, (uint256));
|
||||
}
|
||||
function i(uint256 v) public returns (uint256) {
|
||||
(bool success, bytes memory result) = address(M.L).call(abi.encodeWithSignature("f(uint256)", v));
|
||||
assert(success);
|
||||
return abi.decode(result, (uint256));
|
||||
}
|
||||
function j(uint256 v) public returns (uint256) {
|
||||
(bool success, bytes memory result) = address(M.L).delegatecall(abi.encodeWithSignature("g(uint256)", v));
|
||||
assert(success);
|
||||
return abi.decode(result, (uint256));
|
||||
}
|
||||
function k(uint256 v) public returns (uint256) {
|
||||
(bool success, bytes memory result) = address(M.L).call(abi.encodeWithSignature("g(uint256)", v));
|
||||
assert(success);
|
||||
return abi.decode(result, (uint256));
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=byzantium
|
||||
// ----
|
||||
// library: L
|
||||
// addr() -> false
|
||||
// g(uint256): 1 -> 1
|
||||
// g(uint256): 2 -> 4
|
||||
// g(uint256): 4 -> 16
|
||||
// h(uint256): 1 -> 1
|
||||
// h(uint256): 2 -> 4
|
||||
// h(uint256): 4 -> 16
|
||||
// i(uint256): 1 -> 1
|
||||
// i(uint256): 2 -> 4
|
||||
// i(uint256): 4 -> 16
|
||||
// j(uint256): 1 -> 1
|
||||
// j(uint256): 2 -> 4
|
||||
// j(uint256): 4 -> 16
|
||||
// k(uint256): 1 -> FAILURE
|
||||
// k(uint256): 2 -> FAILURE
|
||||
// k(uint256): 4 -> FAILURE
|
@ -6,6 +6,8 @@ contract C {
|
||||
return L.f(v);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// library: L
|
||||
// g(uint256): 1 -> 1
|
||||
|
@ -0,0 +1,14 @@
|
||||
library L {
|
||||
function f(uint256 _a) external returns (uint256) {}
|
||||
}
|
||||
|
||||
contract C {
|
||||
function run(function(uint256) external returns (uint256) _operation) internal returns (uint256) {}
|
||||
function test() public {
|
||||
run(L.f);
|
||||
function(uint256) external returns (uint256) _operation = L.f;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9553: (230-233): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) returns (uint256) to function (uint256) external returns (uint256) requested.
|
||||
// TypeError 9574: (244-305): Type function (uint256) returns (uint256) is not implicitly convertible to expected type function (uint256) external returns (uint256).
|
@ -0,0 +1,9 @@
|
||||
contract C {
|
||||
function f(uint[] calldata bytesAsCalldata) external {
|
||||
assembly {
|
||||
let x := bytesAsCalldata
|
||||
}
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 1397: (112-127): Call data elements cannot be accessed directly. Use ".offset" and ".length" to access the calldata offset and length of this array and then use "calldatacopy".
|
@ -0,0 +1,8 @@
|
||||
contract C {
|
||||
function f(uint[] calldata bytesAsCalldata) external pure {
|
||||
assembly {
|
||||
let x := bytesAsCalldata.offset
|
||||
}
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,9 @@
|
||||
contract C {
|
||||
function f(bytes calldata bytesAsCalldata) external {
|
||||
assembly {
|
||||
let x := bytesAsCalldata.slot
|
||||
}
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 1536: (111-131): Calldata variables only support ".offset" and ".length".
|
@ -6,4 +6,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 2370: (111-126): Call data elements cannot be accessed directly. Copy to a local variable first or use "calldataload" or "calldatacopy" with manually determined offsets and sizes.
|
||||
// TypeError 1397: (111-126): Call data elements cannot be accessed directly. Use ".offset" and ".length" to access the calldata offset and length of this array and then use "calldatacopy".
|
||||
|
@ -7,4 +7,4 @@ contract test {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 1408: (89-90): Only local variables are supported. To access storage variables, use the .slot and .offset suffixes.
|
||||
// TypeError 1408: (89-90): Only local variables are supported. To access storage variables, use the ".slot" and ".offset" suffixes.
|
||||
|
@ -10,4 +10,4 @@ contract test {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 1408: (80-81): Only local variables are supported. To access storage variables, use the .slot and .offset suffixes.
|
||||
// TypeError 1408: (80-81): Only local variables are supported. To access storage variables, use the ".slot" and ".offset" suffixes.
|
||||
|
@ -0,0 +1,12 @@
|
||||
contract test {
|
||||
uint x = 1;
|
||||
function f() public {
|
||||
assembly {
|
||||
let t := x.length
|
||||
x.length := 2
|
||||
}
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 4656: (98-106): State variables only support ".slot" and ".offset".
|
||||
// TypeError 4656: (119-127): State variables only support ".slot" and ".offset".
|
@ -5,4 +5,4 @@ contract c {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 1408: (75-76): Only local variables are supported. To access storage variables, use the .slot and .offset suffixes.
|
||||
// TypeError 1408: (75-76): Only local variables are supported. To access storage variables, use the ".slot" and ".offset" suffixes.
|
||||
|
@ -8,4 +8,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9068: (118-119): You have to use the .slot or .offset suffix to access storage reference variables.
|
||||
// TypeError 9068: (118-119): You have to use the ".slot" or ".offset" suffix to access storage reference variables.
|
||||
|
@ -9,5 +9,5 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// DeclarationError 9467: (118-124): Identifier not found. Use ``.slot`` and ``.offset`` to access storage variables.
|
||||
// DeclarationError 9467: (142-150): Identifier not found. Use ``.slot`` and ``.offset`` to access storage variables.
|
||||
// DeclarationError 9467: (118-124): Identifier not found. Use ".slot" and ".offset" to access storage variables.
|
||||
// DeclarationError 9467: (142-150): Identifier not found. Use ".slot" and ".offset" to access storage variables.
|
||||
|
@ -6,4 +6,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 7944: (84-90): The suffixes .offset and .slot can only be used on storage variables.
|
||||
// TypeError 7944: (84-90): The suffixes ".offset", ".slot" and ".length" can only be used with variables.
|
||||
|
@ -9,5 +9,5 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 3622: (117-123): The suffixes .offset and .slot can only be used on storage variables.
|
||||
// TypeError 3622: (141-149): The suffixes .offset and .slot can only be used on storage variables.
|
||||
// TypeError 3622: (117-123): The suffix ".slot" is not supported by this variable or type.
|
||||
// TypeError 3622: (141-149): The suffix ".offset" is not supported by this variable or type.
|
||||
|
@ -0,0 +1,10 @@
|
||||
contract C {
|
||||
function f() pure external {
|
||||
function() external two_stack_slots;
|
||||
assembly {
|
||||
let x := two_stack_slots
|
||||
}
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9857: (132-147): Only types that use one stack slot are supported.
|
@ -5,4 +5,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// SyntaxError 9429: (64-106): This looks like an address but has an invalid checksum. Correct checksummed address: "0xfA0bFc97E48458494Ccd857e1A85DC91F7F0046E". If this is not used as an address, please prepend '00'. For more information please see https://solidity.readthedocs.io/en/develop/types.html#address-literals
|
||||
// SyntaxError 9429: (64-106): This looks like an address but has an invalid checksum. Correct checksummed address: "0xfA0bFc97E48458494Ccd857e1A85DC91F7F0046E". If this is not used as an address, please prepend '00'. For more information please see https://docs.soliditylang.org/en/develop/types.html#address-literals
|
||||
|
@ -5,4 +5,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// SyntaxError 9429: (64-106): This looks like an address but has an invalid checksum. Correct checksummed address: "0xfA0bFc97E48458494Ccd857e1A85DC91F7F0046E". If this is not used as an address, please prepend '00'. For more information please see https://solidity.readthedocs.io/en/develop/types.html#address-literals
|
||||
// SyntaxError 9429: (64-106): This looks like an address but has an invalid checksum. Correct checksummed address: "0xfA0bFc97E48458494Ccd857e1A85DC91F7F0046E". If this is not used as an address, please prepend '00'. For more information please see https://docs.soliditylang.org/en/develop/types.html#address-literals
|
||||
|
@ -5,4 +5,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// SyntaxError 9429: (64-105): This looks like an address but is not exactly 40 hex digits. It is 39 hex digits. If this is not used as an address, please prepend '00'. For more information please see https://solidity.readthedocs.io/en/develop/types.html#address-literals
|
||||
// SyntaxError 9429: (64-105): This looks like an address but is not exactly 40 hex digits. It is 39 hex digits. If this is not used as an address, please prepend '00'. For more information please see https://docs.soliditylang.org/en/develop/types.html#address-literals
|
||||
|
@ -5,4 +5,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// SyntaxError 9429: (64-107): This looks like an address but is not exactly 40 hex digits. It is 41 hex digits. If this is not used as an address, please prepend '00'. For more information please see https://solidity.readthedocs.io/en/develop/types.html#address-literals
|
||||
// SyntaxError 9429: (64-107): This looks like an address but is not exactly 40 hex digits. It is 41 hex digits. If this is not used as an address, please prepend '00'. For more information please see https://docs.soliditylang.org/en/develop/types.html#address-literals
|
||||
|
@ -0,0 +1,21 @@
|
||||
interface I {}
|
||||
|
||||
library L {}
|
||||
|
||||
contract C {
|
||||
function f() public pure {
|
||||
address(C);
|
||||
address(I);
|
||||
address(L); // This one is allowed
|
||||
|
||||
address(type(C));
|
||||
address(type(I));
|
||||
address(type(L));
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9640: (82-92): Explicit type conversion not allowed from "type(contract C)" to "address".
|
||||
// TypeError 9640: (102-112): Explicit type conversion not allowed from "type(contract I)" to "address".
|
||||
// TypeError 9640: (166-182): Explicit type conversion not allowed from "type(contract C)" to "address".
|
||||
// TypeError 9640: (192-208): Explicit type conversion not allowed from "type(contract I)" to "address".
|
||||
// TypeError 9640: (218-234): Explicit type conversion not allowed from "type(library L)" to "address".
|
@ -0,0 +1,7 @@
|
||||
contract C {
|
||||
function f() public pure {
|
||||
address(super);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9640: (52-66): Explicit type conversion not allowed from "contract super C" to "address".
|
@ -0,0 +1,46 @@
|
||||
struct S {
|
||||
uint x;
|
||||
}
|
||||
|
||||
enum E {A, B, C}
|
||||
|
||||
contract C {
|
||||
function f() public pure {
|
||||
address(uint);
|
||||
address(bytes16);
|
||||
address(bool);
|
||||
address(address);
|
||||
address(fixed);
|
||||
|
||||
address(S);
|
||||
address(E);
|
||||
|
||||
address(uint[]);
|
||||
address(uint[][]);
|
||||
address(uint[5]);
|
||||
address(string);
|
||||
address(bytes);
|
||||
address(S[]);
|
||||
address(E[]);
|
||||
address((uint, uint));
|
||||
|
||||
address(type(uint));
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9640: (96-109): Explicit type conversion not allowed from "type(uint256)" to "address".
|
||||
// TypeError 9640: (119-135): Explicit type conversion not allowed from "type(bytes16)" to "address".
|
||||
// TypeError 9640: (145-158): Explicit type conversion not allowed from "type(bool)" to "address".
|
||||
// TypeError 9640: (168-184): Explicit type conversion not allowed from "type(address)" to "address".
|
||||
// TypeError 9640: (194-208): Explicit type conversion not allowed from "type(fixed128x18)" to "address".
|
||||
// TypeError 9640: (219-229): Explicit type conversion not allowed from "type(struct S storage pointer)" to "address".
|
||||
// TypeError 9640: (239-249): Explicit type conversion not allowed from "type(enum E)" to "address".
|
||||
// TypeError 9640: (260-275): Explicit type conversion not allowed from "type(uint256[] memory)" to "address".
|
||||
// TypeError 9640: (285-302): Explicit type conversion not allowed from "type(uint256[] memory[] memory)" to "address".
|
||||
// TypeError 9640: (312-328): Explicit type conversion not allowed from "type(uint256[5] memory)" to "address".
|
||||
// TypeError 9640: (338-353): Explicit type conversion not allowed from "type(string storage pointer)" to "address".
|
||||
// TypeError 9640: (363-377): Explicit type conversion not allowed from "type(bytes storage pointer)" to "address".
|
||||
// TypeError 9640: (387-399): Explicit type conversion not allowed from "type(struct S memory[] memory)" to "address".
|
||||
// TypeError 9640: (409-421): Explicit type conversion not allowed from "type(enum E[] memory)" to "address".
|
||||
// TypeError 9640: (431-452): Explicit type conversion not allowed from "tuple(type(uint256),type(uint256))" to "address".
|
||||
// TypeError 9640: (463-482): Explicit type conversion not allowed from "type(uint256)" to "address".
|
Loading…
Reference in New Issue
Block a user