mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8658 from mijovic/createFunctionCall
[Sol->Yul] Enabling creation function call
This commit is contained in:
commit
cfaf69fd02
@ -1337,6 +1337,34 @@ string YulUtilFunctions::allocationFunction()
|
||||
});
|
||||
}
|
||||
|
||||
string YulUtilFunctions::allocationTemporaryMemoryFunction()
|
||||
{
|
||||
string functionName = "allocateTemporaryMemory";
|
||||
return m_functionCollector.createFunction(functionName, [&]() {
|
||||
return Whiskers(R"(
|
||||
function <functionName>() -> memPtr {
|
||||
memPtr := mload(<freeMemoryPointer>)
|
||||
}
|
||||
)")
|
||||
("freeMemoryPointer", to_string(CompilerUtils::freeMemoryPointer))
|
||||
("functionName", functionName)
|
||||
.render();
|
||||
});
|
||||
}
|
||||
|
||||
string YulUtilFunctions::releaseTemporaryMemoryFunction()
|
||||
{
|
||||
string functionName = "releaseTemporaryMemory";
|
||||
return m_functionCollector.createFunction(functionName, [&](){
|
||||
return Whiskers(R"(
|
||||
function <functionName>() {
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
.render();
|
||||
});
|
||||
}
|
||||
|
||||
string YulUtilFunctions::zeroMemoryArrayFunction(ArrayType const& _type)
|
||||
{
|
||||
if (_type.baseType()->hasSimpleZeroValueInMemory())
|
||||
|
@ -253,6 +253,13 @@ public:
|
||||
/// Return value: pointer
|
||||
std::string allocationFunction();
|
||||
|
||||
/// @returns the name of the function that allocates temporary memory with predefined size
|
||||
/// Return value: pointer
|
||||
std::string allocationTemporaryMemoryFunction();
|
||||
|
||||
/// @returns the name of the function that releases previously allocated temporary memory
|
||||
std::string releaseTemporaryMemoryFunction();
|
||||
|
||||
/// @returns the name of a function that zeroes an array.
|
||||
/// signature: (dataStart, dataSizeInBytes) ->
|
||||
std::string zeroMemoryArrayFunction(ArrayType const& _type);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <libsolidity/codegen/ir/IRGenerationContext.h>
|
||||
|
||||
#include <libsolidity/codegen/YulUtilFunctions.h>
|
||||
#include <libsolidity/codegen/ABIFunctions.h>
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolidity/ast/TypeProvider.h>
|
||||
|
||||
@ -96,6 +97,15 @@ string IRGenerationContext::functionName(VariableDeclaration const& _varDecl)
|
||||
return "getter_fun_" + _varDecl.name() + "_" + to_string(_varDecl.id());
|
||||
}
|
||||
|
||||
string IRGenerationContext::creationObjectName(ContractDefinition const& _contract) const
|
||||
{
|
||||
return _contract.name() + "_" + toString(_contract.id());
|
||||
}
|
||||
string IRGenerationContext::runtimeObjectName(ContractDefinition const& _contract) const
|
||||
{
|
||||
return _contract.name() + "_" + toString(_contract.id()) + "_deployed";
|
||||
}
|
||||
|
||||
string IRGenerationContext::newYulVariable()
|
||||
{
|
||||
return "_" + to_string(++m_varCounter);
|
||||
@ -170,6 +180,11 @@ YulUtilFunctions IRGenerationContext::utils()
|
||||
return YulUtilFunctions(m_evmVersion, m_revertStrings, m_functions);
|
||||
}
|
||||
|
||||
ABIFunctions IRGenerationContext::abiFunctions()
|
||||
{
|
||||
return ABIFunctions(m_evmVersion, m_revertStrings, m_functions);
|
||||
}
|
||||
|
||||
std::string IRGenerationContext::revertReasonIfDebug(std::string const& _message)
|
||||
{
|
||||
return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message);
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolidity/codegen/ir/IRVariable.h>
|
||||
#include <libsolidity/interface/OptimiserSettings.h>
|
||||
#include <libsolidity/interface/DebugSettings.h>
|
||||
@ -38,11 +39,8 @@
|
||||
namespace solidity::frontend
|
||||
{
|
||||
|
||||
class ContractDefinition;
|
||||
class VariableDeclaration;
|
||||
class FunctionDefinition;
|
||||
class Expression;
|
||||
class YulUtilFunctions;
|
||||
class ABIFunctions;
|
||||
|
||||
/**
|
||||
* Class that contains contextual information during IR generation.
|
||||
@ -93,6 +91,9 @@ public:
|
||||
std::string functionName(FunctionDefinition const& _function);
|
||||
std::string functionName(VariableDeclaration const& _varDecl);
|
||||
|
||||
std::string creationObjectName(ContractDefinition const& _contract) const;
|
||||
std::string runtimeObjectName(ContractDefinition const& _contract) const;
|
||||
|
||||
std::string newYulVariable();
|
||||
|
||||
std::string internalDispatch(size_t _in, size_t _out);
|
||||
@ -102,6 +103,8 @@ public:
|
||||
|
||||
langutil::EVMVersion evmVersion() const { return m_evmVersion; };
|
||||
|
||||
ABIFunctions abiFunctions();
|
||||
|
||||
/// @returns code that stores @param _message for revert reason
|
||||
/// if m_revertStrings is debug.
|
||||
std::string revertReasonIfDebug(std::string const& _message = "");
|
||||
@ -112,6 +115,8 @@ public:
|
||||
/// function call that was invoked as part of the try statement.
|
||||
std::string trySuccessConditionVariable(Expression const& _expression) const;
|
||||
|
||||
std::set<ContractDefinition const*, ASTNode::CompareByID>& subObjectsCreated() { return m_subObjects; }
|
||||
|
||||
private:
|
||||
langutil::EVMVersion m_evmVersion;
|
||||
RevertStrings m_revertStrings;
|
||||
@ -131,6 +136,8 @@ private:
|
||||
/// long as the order of Yul functions in the generated code is deterministic and the same on
|
||||
/// all platforms - which is a property guaranteed by MultiUseYulFunctionCollector.
|
||||
std::set<FunctionDefinition const*> m_functionGenerationQueue;
|
||||
|
||||
std::set<ContractDefinition const*, ASTNode::CompareByID> m_subObjects;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -48,9 +48,12 @@ using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
pair<string, string> IRGenerator::run(ContractDefinition const& _contract)
|
||||
pair<string, string> IRGenerator::run(
|
||||
ContractDefinition const& _contract,
|
||||
map<ContractDefinition const*, string const> const& _otherYulSources
|
||||
)
|
||||
{
|
||||
string const ir = yul::reindent(generate(_contract));
|
||||
string const ir = yul::reindent(generate(_contract, _otherYulSources));
|
||||
|
||||
yul::AssemblyStack asmStack(m_evmVersion, yul::AssemblyStack::Language::StrictAssembly, m_optimiserSettings);
|
||||
if (!asmStack.parseAndAnalyze("", ir))
|
||||
@ -73,8 +76,19 @@ pair<string, string> IRGenerator::run(ContractDefinition const& _contract)
|
||||
return {warning + ir, warning + asmStack.print()};
|
||||
}
|
||||
|
||||
string IRGenerator::generate(ContractDefinition const& _contract)
|
||||
string IRGenerator::generate(
|
||||
ContractDefinition const& _contract,
|
||||
map<ContractDefinition const*, string const> const& _otherYulSources
|
||||
)
|
||||
{
|
||||
auto subObjectSources = [&_otherYulSources](std::set<ContractDefinition const*, ASTNode::CompareByID> const& subObjects) -> string
|
||||
{
|
||||
std::string subObjectsSources;
|
||||
for (ContractDefinition const* subObject: subObjects)
|
||||
subObjectsSources += _otherYulSources.at(subObject);
|
||||
return subObjectsSources;
|
||||
};
|
||||
|
||||
Whiskers t(R"(
|
||||
object "<CreationObject>" {
|
||||
code {
|
||||
@ -93,13 +107,15 @@ string IRGenerator::generate(ContractDefinition const& _contract)
|
||||
<dispatch>
|
||||
<runtimeFunctions>
|
||||
}
|
||||
<runtimeSubObjects>
|
||||
}
|
||||
<subObjects>
|
||||
}
|
||||
)");
|
||||
|
||||
resetContext(_contract);
|
||||
|
||||
t("CreationObject", creationObjectName(_contract));
|
||||
t("CreationObject", m_context.creationObjectName(_contract));
|
||||
t("memoryInit", memoryInit());
|
||||
t("notLibrary", !_contract.isLibrary());
|
||||
|
||||
@ -112,7 +128,7 @@ string IRGenerator::generate(ContractDefinition const& _contract)
|
||||
constructorParams.emplace_back(m_context.newYulVariable());
|
||||
t(
|
||||
"copyConstructorArguments",
|
||||
m_utils.copyConstructorArgumentsToMemoryFunction(_contract, creationObjectName(_contract))
|
||||
m_utils.copyConstructorArgumentsToMemoryFunction(_contract, m_context.creationObjectName(_contract))
|
||||
);
|
||||
}
|
||||
t("constructorParams", joinHumanReadable(constructorParams));
|
||||
@ -123,12 +139,14 @@ string IRGenerator::generate(ContractDefinition const& _contract)
|
||||
generateImplicitConstructors(_contract);
|
||||
generateQueuedFunctions();
|
||||
t("functions", m_context.functionCollector().requestedFunctions());
|
||||
t("subObjects", subObjectSources(m_context.subObjectsCreated()));
|
||||
|
||||
resetContext(_contract);
|
||||
t("RuntimeObject", runtimeObjectName(_contract));
|
||||
t("RuntimeObject", m_context.runtimeObjectName(_contract));
|
||||
t("dispatch", dispatchRoutine(_contract));
|
||||
generateQueuedFunctions();
|
||||
t("runtimeFunctions", m_context.functionCollector().requestedFunctions());
|
||||
t("runtimeSubObjects", subObjectSources(m_context.subObjectsCreated()));
|
||||
return t.render();
|
||||
}
|
||||
|
||||
@ -313,6 +331,7 @@ string IRGenerator::initStateVariables(ContractDefinition const& _contract)
|
||||
return generator.code();
|
||||
}
|
||||
|
||||
|
||||
void IRGenerator::generateImplicitConstructors(ContractDefinition const& _contract)
|
||||
{
|
||||
auto listAllParams = [&](
|
||||
@ -375,7 +394,7 @@ string IRGenerator::deployCode(ContractDefinition const& _contract)
|
||||
codecopy(0, dataoffset("<object>"), datasize("<object>"))
|
||||
return(0, datasize("<object>"))
|
||||
)X");
|
||||
t("object", runtimeObjectName(_contract));
|
||||
t("object", m_context.runtimeObjectName(_contract));
|
||||
return t.render();
|
||||
}
|
||||
|
||||
@ -384,16 +403,6 @@ string IRGenerator::callValueCheck()
|
||||
return "if callvalue() { revert(0, 0) }";
|
||||
}
|
||||
|
||||
string IRGenerator::creationObjectName(ContractDefinition const& _contract)
|
||||
{
|
||||
return _contract.name() + "_" + to_string(_contract.id());
|
||||
}
|
||||
|
||||
string IRGenerator::runtimeObjectName(ContractDefinition const& _contract)
|
||||
{
|
||||
return _contract.name() + "_" + to_string(_contract.id()) + "_deployed";
|
||||
}
|
||||
|
||||
string IRGenerator::implicitConstructorName(ContractDefinition const& _contract)
|
||||
{
|
||||
return "constructor_" + _contract.name() + "_" + to_string(_contract.id());
|
||||
|
@ -50,10 +50,16 @@ public:
|
||||
|
||||
/// Generates and returns the IR code, in unoptimized and optimized form
|
||||
/// (or just pretty-printed, depending on the optimizer settings).
|
||||
std::pair<std::string, std::string> run(ContractDefinition const& _contract);
|
||||
std::pair<std::string, std::string> run(
|
||||
ContractDefinition const& _contract,
|
||||
std::map<ContractDefinition const*, std::string const> const& _otherYulSources
|
||||
);
|
||||
|
||||
private:
|
||||
std::string generate(ContractDefinition const& _contract);
|
||||
std::string generate(
|
||||
ContractDefinition const& _contract,
|
||||
std::map<ContractDefinition const*, std::string const> const& _otherYulSources
|
||||
);
|
||||
std::string generate(Block const& _block);
|
||||
|
||||
/// Generates code for all the functions from the function generation queue.
|
||||
@ -87,8 +93,6 @@ private:
|
||||
std::string deployCode(ContractDefinition const& _contract);
|
||||
std::string callValueCheck();
|
||||
|
||||
std::string creationObjectName(ContractDefinition const& _contract);
|
||||
std::string runtimeObjectName(ContractDefinition const& _contract);
|
||||
std::string implicitConstructorName(ContractDefinition const& _contract);
|
||||
|
||||
std::string dispatchRoutine(ContractDefinition const& _contract);
|
||||
|
@ -849,11 +849,63 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
templ("pos", m_context.newYulVariable());
|
||||
templ("end", m_context.newYulVariable());
|
||||
templ("freeMemory", freeMemory());
|
||||
templ("encode", abi.tupleEncoder({arguments.front()->annotation().type},{parameterTypes.front()}));
|
||||
templ("encode", abi.tupleEncoder({arguments.front()->annotation().type}, {parameterTypes.front()}));
|
||||
templ("nonIndexedArgs", IRVariable(*arguments.front()).commaSeparatedList());
|
||||
templ("log", "log" + to_string(logNumber));
|
||||
templ("indexedArgs", indexedArgs);
|
||||
m_code << templ.render();
|
||||
|
||||
break;
|
||||
}
|
||||
case FunctionType::Kind::Creation:
|
||||
{
|
||||
solAssert(!functionType->gasSet(), "Gas limit set for contract creation.");
|
||||
solAssert(
|
||||
functionType->returnParameterTypes().size() == 1,
|
||||
"Constructor should return only one type"
|
||||
);
|
||||
|
||||
TypePointers argumentTypes;
|
||||
string constructorParams;
|
||||
for (ASTPointer<Expression const> const& arg: arguments)
|
||||
{
|
||||
argumentTypes.push_back(arg->annotation().type);
|
||||
constructorParams += ", " + IRVariable{*arg}.commaSeparatedList();
|
||||
}
|
||||
|
||||
ContractDefinition const* contract =
|
||||
&dynamic_cast<ContractType const&>(*functionType->returnParameterTypes().front()).contractDefinition();
|
||||
m_context.subObjectsCreated().insert(contract);
|
||||
|
||||
Whiskers t(R"(
|
||||
let <memPos> := <allocateTemporaryMemory>()
|
||||
let <memEnd> := add(<memPos>, datasize("<object>"))
|
||||
if or(gt(<memEnd>, 0xffffffffffffffff), lt(<memEnd>, <memPos>)) { revert(0, 0) }
|
||||
datacopy(<memPos>, dataoffset("<object>"), datasize("<object>"))
|
||||
<memEnd> := <abiEncode>(<memEnd><constructorParams>)
|
||||
<?saltSet>
|
||||
let <retVars> := create2(<value>, <memPos>, sub(<memEnd>, <memPos>), <salt>)
|
||||
<!saltSet>
|
||||
let <retVars> := create(<value>, <memPos>, sub(<memEnd>, <memPos>))
|
||||
</saltSet>
|
||||
<releaseTemporaryMemory>()
|
||||
)");
|
||||
t("memPos", m_context.newYulVariable());
|
||||
t("memEnd", m_context.newYulVariable());
|
||||
t("allocateTemporaryMemory", m_utils.allocationTemporaryMemoryFunction());
|
||||
t("releaseTemporaryMemory", m_utils.releaseTemporaryMemoryFunction());
|
||||
t("object", m_context.creationObjectName(*contract));
|
||||
t("abiEncode",
|
||||
m_context.abiFunctions().tupleEncoder(argumentTypes, functionType->parameterTypes(),false)
|
||||
);
|
||||
t("constructorParams", constructorParams);
|
||||
t("value", functionType->valueSet() ? IRVariable(_functionCall.expression()).part("value").name() : "0");
|
||||
t("saltSet", functionType->saltSet());
|
||||
if (functionType->saltSet())
|
||||
t("salt", IRVariable(_functionCall.expression()).part("salt").name());
|
||||
t("retVars", IRVariable(_functionCall).commaSeparatedList());
|
||||
m_code << t.render();
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -1129,15 +1129,21 @@ void CompilerStack::generateIR(ContractDefinition const& _contract)
|
||||
if (!_contract.canBeDeployed())
|
||||
return;
|
||||
|
||||
map<ContractDefinition const*, string const> otherYulSources;
|
||||
|
||||
Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName());
|
||||
if (!compiledContract.yulIR.empty())
|
||||
return;
|
||||
|
||||
string dependenciesSource;
|
||||
for (auto const* dependency: _contract.annotation().contractDependencies)
|
||||
{
|
||||
generateIR(*dependency);
|
||||
otherYulSources.emplace(dependency, m_contracts.at(dependency->fullyQualifiedName()).yulIR);
|
||||
}
|
||||
|
||||
IRGenerator generator(m_evmVersion, m_revertStrings, m_optimiserSettings);
|
||||
tie(compiledContract.yulIR, compiledContract.yulIROptimized) = generator.run(_contract);
|
||||
tie(compiledContract.yulIR, compiledContract.yulIROptimized) = generator.run(_contract, otherYulSources);
|
||||
}
|
||||
|
||||
void CompilerStack::generateEwasm(ContractDefinition const& _contract)
|
||||
|
@ -0,0 +1 @@
|
||||
--ir-optimized --optimize
|
@ -0,0 +1,7 @@
|
||||
pragma solidity >=0.6.0;
|
||||
|
||||
contract C {
|
||||
constructor() public {}
|
||||
}
|
||||
contract D is C {
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
Optimized IR:
|
||||
/*******************************************************
|
||||
* WARNING *
|
||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||
* It can result in LOSS OF FUNDS or worse *
|
||||
* !USE AT YOUR OWN RISK! *
|
||||
*******************************************************/
|
||||
|
||||
object "C_6" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
if callvalue() { revert(0, 0) }
|
||||
let _1 := datasize("C_6_deployed")
|
||||
codecopy(0, dataoffset("C_6_deployed"), _1)
|
||||
return(0, _1)
|
||||
}
|
||||
}
|
||||
object "C_6_deployed" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Optimized IR:
|
||||
/*******************************************************
|
||||
* WARNING *
|
||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||
* It can result in LOSS OF FUNDS or worse *
|
||||
* !USE AT YOUR OWN RISK! *
|
||||
*******************************************************/
|
||||
|
||||
object "D_9" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
if callvalue() { revert(0, 0) }
|
||||
let _1 := datasize("D_9_deployed")
|
||||
codecopy(0, dataoffset("D_9_deployed"), _1)
|
||||
return(0, _1)
|
||||
}
|
||||
}
|
||||
object "D_9_deployed" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
test/cmdlineTests/ir_compiler_subobjects/args
Normal file
1
test/cmdlineTests/ir_compiler_subobjects/args
Normal file
@ -0,0 +1 @@
|
||||
--ir-optimized --optimize
|
5
test/cmdlineTests/ir_compiler_subobjects/err
Normal file
5
test/cmdlineTests/ir_compiler_subobjects/err
Normal file
@ -0,0 +1,5 @@
|
||||
Warning: Unused local variable.
|
||||
--> ir_compiler_subobjects/input.sol:6:9:
|
||||
|
|
||||
6 | C c = new C();
|
||||
| ^^^
|
8
test/cmdlineTests/ir_compiler_subobjects/input.sol
Normal file
8
test/cmdlineTests/ir_compiler_subobjects/input.sol
Normal file
@ -0,0 +1,8 @@
|
||||
pragma solidity >=0.6.0;
|
||||
|
||||
contract C {}
|
||||
contract D {
|
||||
function f() public {
|
||||
C c = new C();
|
||||
}
|
||||
}
|
96
test/cmdlineTests/ir_compiler_subobjects/output
Normal file
96
test/cmdlineTests/ir_compiler_subobjects/output
Normal file
@ -0,0 +1,96 @@
|
||||
Optimized IR:
|
||||
/*******************************************************
|
||||
* WARNING *
|
||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||
* It can result in LOSS OF FUNDS or worse *
|
||||
* !USE AT YOUR OWN RISK! *
|
||||
*******************************************************/
|
||||
|
||||
object "C_2" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
if callvalue() { revert(0, 0) }
|
||||
let _1 := datasize("C_2_deployed")
|
||||
codecopy(0, dataoffset("C_2_deployed"), _1)
|
||||
return(0, _1)
|
||||
}
|
||||
}
|
||||
object "C_2_deployed" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Optimized IR:
|
||||
/*******************************************************
|
||||
* WARNING *
|
||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||
* It can result in LOSS OF FUNDS or worse *
|
||||
* !USE AT YOUR OWN RISK! *
|
||||
*******************************************************/
|
||||
|
||||
object "D_13" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
if callvalue() { revert(0, 0) }
|
||||
let _1 := datasize("D_13_deployed")
|
||||
codecopy(0, dataoffset("D_13_deployed"), _1)
|
||||
return(0, _1)
|
||||
}
|
||||
}
|
||||
object "D_13_deployed" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
if iszero(lt(calldatasize(), 4))
|
||||
{
|
||||
let _1 := 0
|
||||
if eq(0x26121ff0, shr(224, calldataload(_1)))
|
||||
{
|
||||
if callvalue() { revert(_1, _1) }
|
||||
if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) }
|
||||
let _2 := datasize("C_2")
|
||||
let _3 := add(128, _2)
|
||||
if or(gt(_3, 0xffffffffffffffff), lt(_3, 128)) { revert(_1, _1) }
|
||||
datacopy(128, dataoffset("C_2"), _2)
|
||||
pop(create(_1, 128, _2))
|
||||
return(allocateMemory(_1), _1)
|
||||
}
|
||||
}
|
||||
revert(0, 0)
|
||||
}
|
||||
function allocateMemory(size) -> memPtr
|
||||
{
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { revert(0, 0) }
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
}
|
||||
object "C_2" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
if callvalue() { revert(0, 0) }
|
||||
let _1 := datasize("C_2_deployed")
|
||||
codecopy(0, dataoffset("C_2_deployed"), _1)
|
||||
return(0, _1)
|
||||
}
|
||||
}
|
||||
object "C_2_deployed" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -76,7 +76,9 @@ object \"C_6\" {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"}}},"sources":{"A":{"id":0}}}
|
||||
|
@ -131,7 +131,9 @@ object \"C_10\" {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"}}},"sources":{"A":{"id":0}}}
|
||||
|
@ -99,7 +99,9 @@ object \"C_10\" {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"}}},"sources":{"A":{"id":0}}}
|
||||
|
@ -111,7 +111,9 @@ object \"C_10\" {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"}}},"sources":{"A":{"id":0}}}
|
||||
|
@ -135,7 +135,9 @@ object \"C_10\" {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"}}},"sources":{"A":{"id":0}}}
|
||||
|
@ -111,7 +111,9 @@ object \"C_10\" {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"}}},"sources":{"A":{"id":0}}}
|
||||
|
@ -17,5 +17,7 @@ contract B {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 2, 3, 4, 5, 6, 1000, 1001, 1002, 1003, 1004
|
||||
|
@ -41,5 +41,7 @@ contract C {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 5, 6, 7
|
||||
|
@ -0,0 +1,15 @@
|
||||
contract C {
|
||||
uint public i;
|
||||
constructor() public {
|
||||
i = 2;
|
||||
}
|
||||
}
|
||||
contract D {
|
||||
function f() public returns (uint r) {
|
||||
return new C().i();
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 2
|
@ -0,0 +1,20 @@
|
||||
contract C {
|
||||
uint public i;
|
||||
constructor(uint newI) public {
|
||||
i = newI;
|
||||
}
|
||||
}
|
||||
contract D {
|
||||
C c;
|
||||
constructor(uint v) public {
|
||||
c = new C(v);
|
||||
}
|
||||
function f() public returns (uint r) {
|
||||
return c.i();
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor(): 2 ->
|
||||
// f() -> 2
|
@ -0,0 +1,21 @@
|
||||
contract C {
|
||||
uint public i;
|
||||
constructor(uint newI) public {
|
||||
i = newI;
|
||||
}
|
||||
}
|
||||
contract D {
|
||||
C c;
|
||||
constructor(uint v) public {
|
||||
c = new C{salt: "abc"}(v);
|
||||
}
|
||||
function f() public returns (uint r) {
|
||||
return c.i();
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor(): 2 ->
|
||||
// f() -> 2
|
@ -36,8 +36,10 @@ contract test {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor(), 20 wei ->
|
||||
// sendAmount(uint256): 5 -> 5
|
||||
// outOfGas() -> FAILURE # call to helper should not succeed but amount should be transferred anyway #
|
||||
// checkState() -> false, 15
|
||||
// checkState() -> false, 15
|
||||
|
@ -33,6 +33,8 @@ contract C {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// convertParent() -> 1
|
||||
// convertSubA() -> 1, 2
|
||||
|
@ -19,6 +19,8 @@ contract D {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 1
|
||||
// g() -> 5
|
||||
|
@ -21,5 +21,7 @@ contract B {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// g() -> 42
|
||||
|
@ -21,5 +21,7 @@ contract B {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// g() -> 42
|
||||
|
@ -16,5 +16,7 @@ contract C {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor() ->
|
||||
|
@ -23,6 +23,8 @@ contract C {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 9, 7
|
||||
// t2() -> 9
|
||||
|
@ -15,6 +15,8 @@ contract D {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// constructor(), 27 wei ->
|
||||
// f() -> 27
|
||||
|
@ -32,6 +32,7 @@ contract D {
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// EVMVersion: >=byzantium
|
||||
// ----
|
||||
// f() -> 0x1 # This should work, next should throw #
|
||||
|
@ -34,6 +34,8 @@ contract D {
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 3
|
||||
// g() -> 8
|
||||
|
Loading…
Reference in New Issue
Block a user