Merge pull request #7650 from ethereum/develop

Merge develop into develop_060
This commit is contained in:
chriseth
2019-11-06 21:56:55 +01:00
committed by GitHub
30 changed files with 1081 additions and 135 deletions
+4 -2
View File
@@ -108,14 +108,16 @@ bool BMC::shouldInlineFunctionCall(FunctionCall const& _funCall)
bool BMC::visit(ContractDefinition const& _contract)
{
SMTEncoder::visit(_contract);
initContract(_contract);
/// Check targets created by state variable initialization.
smt::Expression constraints = m_context.assertions();
checkVerificationTargets(constraints);
m_verificationTargets.clear();
return true;
SMTEncoder::visit(_contract);
return false;
}
void BMC::endVisit(ContractDefinition const& _contract)
+3 -4
View File
@@ -62,8 +62,7 @@ bool CHC::visit(ContractDefinition const& _contract)
reset();
if (!SMTEncoder::visit(_contract))
return false;
initContract(_contract);
m_stateVariables = _contract.stateVariablesIncludingInherited();
@@ -89,7 +88,6 @@ bool CHC::visit(ContractDefinition const& _contract)
// If the contract has a constructor it is handled as a function.
// Otherwise we zero-initialize all state vars.
// TODO take into account state vars init values.
if (!_contract.constructor())
{
string constructorName = "constructor_" + _contract.name() + "_" + to_string(_contract.id());
@@ -108,7 +106,8 @@ bool CHC::visit(ContractDefinition const& _contract)
connectBlocks(constructorPred, interface());
}
return true;
SMTEncoder::visit(_contract);
return false;
}
void CHC::endVisit(ContractDefinition const& _contract)
+1 -2
View File
@@ -50,8 +50,7 @@ void CVC4Interface::pop()
void CVC4Interface::declareVariable(string const& _name, Sort const& _sort)
{
if (!m_variables.count(_name))
m_variables.insert({_name, m_context.mkVar(_name.c_str(), cvc4Sort(_sort))});
m_variables[_name] = m_context.mkVar(_name.c_str(), cvc4Sort(_sort));
}
void CVC4Interface::addAssertion(Expression const& _expr)
+37 -4
View File
@@ -36,12 +36,37 @@ SMTEncoder::SMTEncoder(smt::EncodingContext& _context):
bool SMTEncoder::visit(ContractDefinition const& _contract)
{
solAssert(m_currentContract == nullptr, "");
m_currentContract = &_contract;
solAssert(m_currentContract, "");
initializeStateVariables(_contract);
for (auto const& node: _contract.subNodes())
if (!dynamic_pointer_cast<FunctionDefinition>(node))
node->accept(*this);
return true;
vector<FunctionDefinition const*> resolvedFunctions = _contract.definedFunctions();
for (auto const& base: _contract.annotation().linearizedBaseContracts)
for (auto const& baseFunction: base->definedFunctions())
{
if (baseFunction->isConstructor())
continue;
bool overridden = false;
for (auto const& function: resolvedFunctions)
if (
function->name() == baseFunction->name() &&
FunctionType(*function).asCallableFunction(false)->
hasEqualParameterTypes(*FunctionType(*baseFunction).asCallableFunction(false))
)
{
overridden = true;
break;
}
if (!overridden)
resolvedFunctions.push_back(baseFunction);
}
for (auto const& function: resolvedFunctions)
function->accept(*this);
return false;
}
void SMTEncoder::endVisit(ContractDefinition const& _contract)
@@ -512,6 +537,14 @@ void SMTEncoder::endVisit(FunctionCall const& _funCall)
}
}
void SMTEncoder::initContract(ContractDefinition const& _contract)
{
solAssert(m_currentContract == nullptr, "");
m_currentContract = &_contract;
initializeStateVariables(_contract);
}
void SMTEncoder::initFunction(FunctionDefinition const& _function)
{
solAssert(m_callStack.empty(), "");
+1
View File
@@ -108,6 +108,7 @@ protected:
void compareOperation(BinaryOperation const& _op);
void booleanOperation(BinaryOperation const& _op);
void initContract(ContractDefinition const& _contract);
void initFunction(FunctionDefinition const& _function);
void visitAssert(FunctionCall const& _funCall);
void visitRequire(FunctionCall const& _funCall);
+9 -7
View File
@@ -54,18 +54,20 @@ void Z3Interface::declareVariable(string const& _name, Sort const& _sort)
{
if (_sort.kind == Kind::Function)
declareFunction(_name, _sort);
else if (!m_constants.count(_name))
m_constants.insert({_name, m_context.constant(_name.c_str(), z3Sort(_sort))});
else if (m_constants.count(_name))
m_constants.at(_name) = m_context.constant(_name.c_str(), z3Sort(_sort));
else
m_constants.emplace(_name, m_context.constant(_name.c_str(), z3Sort(_sort)));
}
void Z3Interface::declareFunction(string const& _name, Sort const& _sort)
{
solAssert(_sort.kind == smt::Kind::Function, "");
if (!m_functions.count(_name))
{
FunctionSort fSort = dynamic_cast<FunctionSort const&>(_sort);
m_functions.insert({_name, m_context.function(_name.c_str(), z3Sort(fSort.domain), z3Sort(*fSort.codomain))});
}
FunctionSort fSort = dynamic_cast<FunctionSort const&>(_sort);
if (m_functions.count(_name))
m_functions.at(_name) = m_context.function(_name.c_str(), z3Sort(fSort.domain), z3Sort(*fSort.codomain));
else
m_functions.emplace(_name, m_context.function(_name.c_str(), z3Sort(fSort.domain), z3Sort(*fSort.codomain)));
}
void Z3Interface::addAssertion(Expression const& _expr)
+11 -1
View File
@@ -586,6 +586,14 @@ string const& CompilerStack::eWasm(string const& _contractName) const
return contract(_contractName).eWasm;
}
eth::LinkerObject const& CompilerStack::eWasmObject(string const& _contractName) const
{
if (m_stackState != CompilationSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
return contract(_contractName).eWasmObject;
}
eth::LinkerObject const& CompilerStack::object(string const& _contractName) const
{
if (m_stackState != CompilationSuccessful)
@@ -1055,7 +1063,9 @@ void CompilerStack::generateEWasm(ContractDefinition const& _contract)
//cout << yul::AsmPrinter{}(*ewasmStack.parserResult()->code) << endl;
// Turn into eWasm text representation.
compiledContract.eWasm = ewasmStack.assemble(yul::AssemblyStack::Machine::eWasm).assembly;
auto result = ewasmStack.assemble(yul::AssemblyStack::Machine::eWasm);
compiledContract.eWasm = std::move(result.assembly);
compiledContract.eWasmObject = std::move(*result.bytecode);
}
CompilerStack::Contract const& CompilerStack::contract(string const& _contractName) const
+7 -3
View File
@@ -243,9 +243,12 @@ public:
/// @returns the optimized IR representation of a contract.
std::string const& yulIROptimized(std::string const& _contractName) const;
/// @returns the eWasm (text) representation of a contract.
/// @returns the eWasm text representation of a contract.
std::string const& eWasm(std::string const& _contractName) const;
/// @returns the eWasm representation of a contract.
eth::LinkerObject const& eWasmObject(std::string const& _contractName) const;
/// @returns the assembled object for a contract.
eth::LinkerObject const& object(std::string const& _contractName) const;
@@ -323,7 +326,8 @@ private:
eth::LinkerObject runtimeObject; ///< Runtime object.
std::string yulIR; ///< Experimental Yul IR code.
std::string yulIROptimized; ///< Optimized experimental Yul IR code.
std::string eWasm; ///< Experimental eWasm code (text representation).
std::string eWasm; ///< Experimental eWasm text representation
eth::LinkerObject eWasmObject; ///< Experimental eWasm code
mutable std::unique_ptr<std::string const> metadata; ///< The metadata json that will be hashed into the chain.
mutable std::unique_ptr<Json::Value const> abi;
mutable std::unique_ptr<Json::Value const> userDocumentation;
@@ -357,7 +361,7 @@ private:
/// The IR is stored but otherwise unused.
void generateIR(ContractDefinition const& _contract);
/// Generate eWasm text representation for a single contract.
/// Generate eWasm representation for a single contract.
void generateEWasm(ContractDefinition const& _contract);
/// Links all the known library addresses in the available objects. Any unknown
@@ -925,6 +925,8 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
// eWasm
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "ewasm.wast", wildcardMatchesExperimental))
contractData["ewasm"]["wast"] = compilerStack.eWasm(contractName);
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "ewasm.wasm", wildcardMatchesExperimental))
contractData["ewasm"]["wasm"] = compilerStack.eWasmObject(contractName).toHex();
// EVM
Json::Value evmData(Json::objectValue);