Note function entry points.

This commit is contained in:
chriseth 2020-05-07 14:46:47 +02:00
parent faca036837
commit f9c94d7c42
33 changed files with 252 additions and 26 deletions

View File

@ -6,6 +6,7 @@ Language Features:
Compiler Features:
* Standard JSON / combined JSON: New artifact "functionDebugData" that contains bytecode offsets of entry points of functions and potentially more information in the future.
* Yul Optimizer: Evaluate ``keccak256(a, c)``, when the value at memory location ``a`` is known at compile time and ``c`` is a constant ``<= 32``.

View File

@ -344,6 +344,7 @@ Input Description
// storageLayout - Slots, offsets and types of the contract's state variables.
// evm.assembly - New assembly format
// evm.legacyAssembly - Old-style assembly format in JSON
// evm.bytecode.functionDebugData - Debugging information at function level
// evm.bytecode.object - Bytecode object
// evm.bytecode.opcodes - Opcodes list
// evm.bytecode.sourceMap - Source mapping (useful for debugging)
@ -476,6 +477,17 @@ Output Description
"legacyAssembly": {},
// Bytecode and related details.
"bytecode": {
// Debugging data at the level of functions.
"functionDebugData": {
// Now follows a set of functions including compiler-internal and
// user-defined function. The set does not have to be complete.
"@mint_13": { // Internal name of the function
"entryPoint": 128, // Byte offset into the bytecode where the function starts (optional)
"id": 13, // AST ID of the function definition or null for compiler-internal functions (optional)
"parameterSlots": 2, // Number of EVM stack slots for the function parameters (optional)
"returnSlots": 1 // Number of EVM stack slots for the return values (optional)
}
},
// The bytecode as a hex string.
"object": "00fe",
// Opcodes list (string)

View File

@ -348,12 +348,18 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices)
return root;
}
AssemblyItem Assembly::namedTag(string const& _name)
AssemblyItem Assembly::namedTag(string const& _name, size_t _params, size_t _returns, optional<uint64_t> _sourceID)
{
assertThrow(!_name.empty(), AssemblyException, "Empty named tag.");
if (!m_namedTags.count(_name))
m_namedTags[_name] = static_cast<size_t>(newTag().data());
return AssemblyItem{Tag, m_namedTags.at(_name)};
if (m_namedTags.count(_name))
{
assertThrow(m_namedTags.at(_name).params == _params, AssemblyException, "");
assertThrow(m_namedTags.at(_name).returns == _returns, AssemblyException, "");
assertThrow(m_namedTags.at(_name).sourceID == _sourceID, AssemblyException, "");
}
else
m_namedTags[_name] = {static_cast<size_t>(newTag().data()), _sourceID, _params, _returns};
return AssemblyItem{Tag, m_namedTags.at(_name).id};
}
AssemblyItem Assembly::newPushLibraryAddress(string const& _identifier)
@ -722,13 +728,16 @@ LinkerObject const& Assembly::assemble() const
ret.bytecode.resize(ret.bytecode.size() + 20);
break;
case Tag:
{
assertThrow(i.data() != 0, AssemblyException, "Invalid tag position.");
assertThrow(i.splitForeignPushTag().first == numeric_limits<size_t>::max(), AssemblyException, "Foreign tag.");
size_t tagId = static_cast<size_t>(i.data());
assertThrow(ret.bytecode.size() < 0xffffffffL, AssemblyException, "Tag too large.");
assertThrow(m_tagPositionsInBytecode[static_cast<size_t>(i.data())] == numeric_limits<size_t>::max(), AssemblyException, "Duplicate tag position.");
m_tagPositionsInBytecode[static_cast<size_t>(i.data())] = ret.bytecode.size();
assertThrow(m_tagPositionsInBytecode[tagId] == numeric_limits<size_t>::max(), AssemblyException, "Duplicate tag position.");
m_tagPositionsInBytecode[tagId] = ret.bytecode.size();
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::JUMPDEST));
break;
}
default:
assertThrow(false, InvalidOpcode, "Unexpected opcode while assembling.");
}
@ -770,6 +779,17 @@ LinkerObject const& Assembly::assemble() const
bytesRef r(ret.bytecode.data() + i.first, bytesPerTag);
toBigEndian(pos, r);
}
for (auto const& [name, tagInfo]: m_namedTags)
{
size_t position = m_tagPositionsInBytecode.at(tagInfo.id);
ret.functionDebugData[name] = {
position == numeric_limits<size_t>::max() ? nullopt : optional<size_t>{position},
tagInfo.sourceID,
tagInfo.params,
tagInfo.returns
};
}
for (auto const& dataItem: m_data)
{
auto references = dataRef.equal_range(dataItem.first);

View File

@ -35,6 +35,7 @@
#include <iostream>
#include <sstream>
#include <memory>
#include <map>
namespace solidity::evmasm
{
@ -49,7 +50,7 @@ public:
AssemblyItem newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); }
AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); }
/// Returns a tag identified by the given name. Creates it if it does not yet exist.
AssemblyItem namedTag(std::string const& _name);
AssemblyItem namedTag(std::string const& _name, size_t _params, size_t _returns, std::optional<uint64_t> _sourceID);
AssemblyItem newData(bytes const& _data) { util::h256 h(util::keccak256(util::asString(_data))); m_data[h] = _data; return AssemblyItem(PushData, h); }
bytes const& data(util::h256 const& _i) const { return m_data.at(_i); }
AssemblyItem newSub(AssemblyPointer const& _sub) { m_subs.push_back(_sub); return AssemblyItem(PushSub, m_subs.size() - 1); }
@ -184,7 +185,16 @@ private:
protected:
/// 0 is reserved for exception
unsigned m_usedTags = 1;
std::map<std::string, size_t> m_namedTags;
struct NamedTagInfo
{
size_t id;
std::optional<size_t> sourceID;
size_t params;
size_t returns;
};
std::map<std::string, NamedTagInfo> m_namedTags;
AssemblyItems m_items;
std::map<util::h256, bytes> m_data;
/// Data that is appended to the very end of the contract.

View File

@ -45,6 +45,17 @@ struct LinkerObject
/// to a list of offsets into the bytecode that refer to their values.
std::map<u256, std::pair<std::string, std::vector<size_t>>> immutableReferences;
struct FunctionDebugData
{
std::optional<size_t> bytecodeOffset;
std::optional<size_t> sourceID;
size_t params = {};
size_t returns = {};
};
/// Bytecode offsets of named tags like function entry points.
std::map<std::string, FunctionDebugData> functionDebugData;
/// Appends the bytecode of @a _other and incorporates its link references.
void append(LinkerObject const& _other);

View File

@ -148,7 +148,7 @@ void CompilerContext::callYulFunction(
m_externallyUsedYulFunctions.insert(_name);
auto const retTag = pushNewTag();
CompilerUtils(*this).moveIntoStack(_inArgs);
appendJumpTo(namedTag(_name), evmasm::AssemblyItem::JumpType::IntoFunction);
appendJumpTo(namedTag(_name, _inArgs, _outArgs, {}), evmasm::AssemblyItem::JumpType::IntoFunction);
adjustStackOffset(static_cast<int>(_outArgs) - 1 - static_cast<int>(_inArgs));
*this << retTag.tag();
}
@ -596,7 +596,23 @@ evmasm::AssemblyItem CompilerContext::FunctionCompilationQueue::entryLabel(
auto res = m_entryLabels.find(&_declaration);
if (res == m_entryLabels.end())
{
evmasm::AssemblyItem tag(_context.newTag());
size_t params = 0;
size_t returns = 0;
if (auto const* function = dynamic_cast<FunctionDefinition const*>(&_declaration))
{
FunctionType functionType(*function, FunctionType::Kind::Internal);
params = CompilerUtils::sizeOnStack(functionType.parameterTypes());
returns = CompilerUtils::sizeOnStack(functionType.returnParameterTypes());
}
// some name that cannot clash with yul function names.
string labelName = "@" + _declaration.name() + "_" + to_string(_declaration.id());
evmasm::AssemblyItem tag = _context.namedTag(
labelName,
params,
returns,
_declaration.id()
);
m_entryLabels.insert(make_pair(&_declaration, tag));
m_functionsToCompile.push(&_declaration);
return tag.tag();

View File

@ -216,7 +216,10 @@ public:
/// @returns a new tag without pushing any opcodes or data
evmasm::AssemblyItem newTag() { return m_asm->newTag(); }
/// @returns a new tag identified by name.
evmasm::AssemblyItem namedTag(std::string const& _name) { return m_asm->namedTag(_name); }
evmasm::AssemblyItem namedTag(std::string const& _name, size_t _params, size_t _returns, std::optional<uint64_t> _sourceID)
{
return m_asm->namedTag(_name, _params, _returns, _sourceID);
}
/// Adds a subroutine to the code (in the data section) and pushes its size (via a tag)
/// on the stack. @returns the pushsub assembly item.
evmasm::AssemblyItem addSubroutine(evmasm::AssemblyPointer const& _assembly) { return m_asm->appendSubroutine(_assembly); }

View File

@ -241,7 +241,7 @@ bool isArtifactRequested(Json::Value const& _outputSelection, string const& _fil
vector<string> evmObjectComponents(string const& _objectKind)
{
solAssert(_objectKind == "bytecode" || _objectKind == "deployedBytecode", "");
vector<string> components{"", ".object", ".opcodes", ".sourceMap", ".generatedSources", ".linkReferences"};
vector<string> components{"", ".object", ".opcodes", ".sourceMap", ".functionDebugData", ".generatedSources", ".linkReferences"};
if (_objectKind == "deployedBytecode")
components.push_back(".immutableReferences");
return util::applyMap(components, [&](auto const& _s) { return "evm." + _objectKind + _s; });
@ -388,6 +388,8 @@ Json::Value collectEVMObject(
output["opcodes"] = evmasm::disassemble(_object.bytecode);
if (_artifactRequested("sourceMap"))
output["sourceMap"] = _sourceMap ? *_sourceMap : "";
if (_artifactRequested("functionDebugData"))
output["functionDebugData"] = StandardCompiler::formatFunctionDebugData(_object.functionDebugData);
if (_artifactRequested("linkReferences"))
output["linkReferences"] = formatLinkReferences(_object.linkReferences);
if (_runtimeObject && _artifactRequested("immutableReferences"))
@ -614,6 +616,7 @@ std::variant<OptimiserSettings, Json::Value> parseOptimizerSettings(Json::Value
}
std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler::parseInput(Json::Value const& _input)
{
InputsAndSettings ret;
@ -1423,3 +1426,27 @@ string StandardCompiler::compile(string const& _input) noexcept
return "{\"errors\":[{\"type\":\"JSONError\",\"component\":\"general\",\"severity\":\"error\",\"message\":\"Error writing output JSON.\"}]}";
}
}
Json::Value StandardCompiler::formatFunctionDebugData(
map<string, evmasm::LinkerObject::FunctionDebugData> const& _debugInfo
)
{
Json::Value ret(Json::objectValue);
for (auto const& [name, info]: _debugInfo)
{
Json::Value fun;
if (info.sourceID)
fun["id"] = Json::UInt64(*info.sourceID);
else
fun["id"] = Json::nullValue;
if (info.bytecodeOffset)
fun["entryPoint"] = Json::UInt64(*info.bytecodeOffset);
else
fun["entryPoint"] = Json::nullValue;
fun["parameterSlots"] = Json::UInt64(info.params);
fun["returnSlots"] = Json::UInt64(info.returns);
ret[name] = move(fun);
}
return ret;
}

View File

@ -58,6 +58,10 @@ public:
/// output. Parsing errors are returned as regular errors.
std::string compile(std::string const& _input) noexcept;
static Json::Value formatFunctionDebugData(
std::map<std::string, evmasm::LinkerObject::FunctionDebugData> const& _debugInfo
);
private:
struct InputsAndSettings
{

View File

@ -30,6 +30,7 @@
#include <functional>
#include <memory>
#include <optional>
namespace solidity::langutil
{
@ -74,7 +75,7 @@ public:
/// Generate a new unique label.
virtual LabelID newLabelId() = 0;
/// Returns a label identified by the given name. Creates it if it does not yet exist.
virtual LabelID namedLabel(std::string const& _name) = 0;
virtual LabelID namedLabel(std::string const& _name, size_t _params, size_t _returns, std::optional<size_t> _sourceID) = 0;
/// Append a reference to a to-be-linked symbol.
/// Currently, we assume that the value is always a 20 byte number.
virtual void appendLinkerSymbol(std::string const& _name) = 0;

View File

@ -78,7 +78,7 @@ EVMAssembly::LabelID EVMAssembly::newLabelId()
return m_nextLabelId++;
}
AbstractAssembly::LabelID EVMAssembly::namedLabel(string const& _name)
AbstractAssembly::LabelID EVMAssembly::namedLabel(string const& _name, size_t, size_t, std::optional<size_t>)
{
yulAssert(!_name.empty(), "");
if (!m_namedLabels.count(_name))

View File

@ -58,7 +58,7 @@ public:
/// Generate a new unique label.
LabelID newLabelId() override;
/// Returns a label identified by the given name. Creates it if it does not yet exist.
LabelID namedLabel(std::string const& _name) override;
LabelID namedLabel(std::string const& _name, size_t _params, size_t _returns, std::optional<size_t> _sourceID) override;
/// Append a reference to a to-be-linked symbol.
/// Currently, we assume that the value is always a 20 byte number.
void appendLinkerSymbol(std::string const& _name) override;

View File

@ -578,7 +578,7 @@ AbstractAssembly::LabelID CodeTransform::functionEntryID(YulString _name, Scope:
{
AbstractAssembly::LabelID id =
m_useNamedLabelsForFunctions ?
m_assembly.namedLabel(_name.str()) :
m_assembly.namedLabel(_name.str(), _function.arguments.size(), _function.returns.size(), {}) :
m_assembly.newLabelId();
m_context->functionEntryIDs[&_function] = id;
}

View File

@ -84,9 +84,9 @@ size_t EthAssemblyAdapter::newLabelId()
return assemblyTagToIdentifier(m_assembly.newTag());
}
size_t EthAssemblyAdapter::namedLabel(std::string const& _name)
size_t EthAssemblyAdapter::namedLabel(std::string const& _name, size_t _params, size_t _returns, std::optional<size_t> _sourceID)
{
return assemblyTagToIdentifier(m_assembly.namedTag(_name));
return assemblyTagToIdentifier(m_assembly.namedTag(_name, _params, _returns, _sourceID));
}
void EthAssemblyAdapter::appendLinkerSymbol(std::string const& _linkerSymbol)

View File

@ -46,7 +46,7 @@ public:
void appendLabel(LabelID _labelId) override;
void appendLabelReference(LabelID _labelId) override;
size_t newLabelId() override;
size_t namedLabel(std::string const& _name) override;
size_t namedLabel(std::string const& _name, size_t _params, size_t _returns, std::optional<size_t> _sourceID) override;
void appendLinkerSymbol(std::string const& _linkerSymbol) override;
void appendVerbatim(bytes _data, size_t _arguments, size_t _returnVariables) override;
void appendJump(int _stackDiffAfter, JumpType _jumpType) override;

View File

@ -59,7 +59,7 @@ NoOutputAssembly::LabelID NoOutputAssembly::newLabelId()
return 1;
}
AbstractAssembly::LabelID NoOutputAssembly::namedLabel(string const&)
AbstractAssembly::LabelID NoOutputAssembly::namedLabel(string const&, size_t, size_t, optional<size_t>)
{
return 1;
}

View File

@ -56,7 +56,7 @@ public:
void appendLabel(LabelID _labelId) override;
void appendLabelReference(LabelID _labelId) override;
LabelID newLabelId() override;
LabelID namedLabel(std::string const& _name) override;
LabelID namedLabel(std::string const& _name, size_t _params, size_t _returns, std::optional<size_t> _sourceID) override;
void appendLinkerSymbol(std::string const& _name) override;
void appendVerbatim(bytes _data, size_t _arguments, size_t _returnVariables) override;

View File

@ -189,6 +189,8 @@ static string const g_strSources = "sources";
static string const g_strSourceList = "sourceList";
static string const g_strSrcMap = "srcmap";
static string const g_strSrcMapRuntime = "srcmap-runtime";
static string const g_strFunDebug = "function-debug";
static string const g_strFunDebugRuntime = "function-debug-runtime";
static string const g_strStandardJSON = "standard-json";
static string const g_strStrictAssembly = "strict-assembly";
static string const g_strSwarm = "swarm";
@ -257,6 +259,8 @@ static set<string> const g_combinedJsonArgs
g_strBinary,
g_strBinaryRuntime,
g_strCompactJSON,
g_strFunDebug,
g_strFunDebugRuntime,
g_strGeneratedSources,
g_strGeneratedSourcesRuntime,
g_strInterface,
@ -1672,6 +1676,14 @@ void CommandLineInterface::handleCombinedJSON()
auto map = m_compiler->runtimeSourceMapping(contractName);
contractData[g_strSrcMapRuntime] = map ? *map : "";
}
if (requests.count(g_strFunDebug) && m_compiler->compilationSuccessful())
contractData[g_strFunDebug] = StandardCompiler::formatFunctionDebugData(
m_compiler->object(contractName).functionDebugData
);
if (requests.count(g_strFunDebugRuntime) && m_compiler->compilationSuccessful())
contractData[g_strFunDebugRuntime] = StandardCompiler::formatFunctionDebugData(
m_compiler->runtimeObject(contractName).functionDebugData
);
if (requests.count(g_strSignatureHashes))
contractData[g_strSignatureHashes] = m_compiler->methodIdentifiers(contractName);
if (requests.count(g_strNatspecDev))

View File

@ -0,0 +1 @@
--optimize --combined-json function-debug,function-debug-runtime --pretty-json

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,11 @@
pragma solidity >=0.0;
// SPDX-License-Identifier: GPL-3.0
contract C {
function f(uint[] calldata x) pure external returns (uint) { return x[0]; }
// This will be optimized out
function g() pure internal {}
mapping(uint => uint) public t;
constructor(uint x) {
t[0] = x;
}
}

View File

@ -0,0 +1,57 @@
{
"contracts":
{
"function_debug_info/input.sol:C":
{
"function-debug":
{
"@_34":
{
"id": 34,
"parameterSlots": 1,
"returnSlots": 0
},
"abi_decode_tuple_t_uint256_fromMemory":
{
"entryPoint": 94,
"parameterSlots": 2,
"returnSlots": 1
}
},
"function-debug-runtime":
{
"@f_14":
{
"entryPoint": 128,
"id": 14,
"parameterSlots": 2,
"returnSlots": 1
},
"@t_22":
{
"id": 22,
"parameterSlots": 0,
"returnSlots": 0
},
"abi_decode_tuple_t_array$_t_uint256_$dyn_calldata_ptr":
{
"entryPoint": 178,
"parameterSlots": 2,
"returnSlots": 2
},
"abi_decode_tuple_t_uint256":
{
"entryPoint": 295,
"parameterSlots": 2,
"returnSlots": 1
},
"abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed":
{
"parameterSlots": 2,
"returnSlots": 1
}
}
}
},
"version": "<VERSION REMOVED>"
}

View File

@ -0,0 +1 @@
--experimental-via-ir --optimize --combined-json function-debug,function-debug-runtime --pretty-json

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,7 @@
pragma solidity >=0.0;
// SPDX-License-Identifier: GPL-3.0
contract C {
function f(uint[] calldata x) pure external returns (uint) { return x[0]; }
// This will be optimized out
function g() pure internal {}
}

View File

@ -0,0 +1,11 @@
{
"contracts":
{
"function_debug_info_via_yul/input.sol:C":
{
"function-debug": {},
"function-debug-runtime": {}
}
},
"version": "<VERSION REMOVED>"
}

View File

@ -0,0 +1,18 @@
{
"language": "Solidity",
"sources": {
"a.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; pragma abicoder v2; contract A { function f(uint[] memory x) public pure returns (uint256) { return x[0] + x[1];} }"
}
},
"settings": {
"outputSelection": {
"*": {
"A": [
"evm.deployedBytecode.functionDebugData",
"evm.bytecode.functionDebugData"
]
}
}
}
}

View File

@ -0,0 +1 @@
{"contracts":{"a.sol":{"A":{"evm":{"bytecode":{"functionDebugData":{}},"deployedBytecode":{"functionDebugData":{"@f_19":{"entryPoint":96,"id":19,"parameterSlots":1,"returnSlots":1},"abi_decode_available_length_t_array$_t_uint256_$dyn_memory_ptr":{"entryPoint":247,"id":null,"parameterSlots":3,"returnSlots":1},"abi_decode_t_array$_t_uint256_$dyn_memory_ptr":{"entryPoint":359,"id":null,"parameterSlots":2,"returnSlots":1},"abi_decode_t_uint256":{"entryPoint":405,"id":null,"parameterSlots":2,"returnSlots":1},"abi_decode_tuple_t_array$_t_uint256_$dyn_memory_ptr":{"entryPoint":426,"id":null,"parameterSlots":2,"returnSlots":1},"abi_encode_t_uint256_to_t_uint256_fromStack":{"entryPoint":499,"id":null,"parameterSlots":2,"returnSlots":0},"abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed":{"entryPoint":514,"id":null,"parameterSlots":2,"returnSlots":1},"allocate_memory":{"entryPoint":541,"id":null,"parameterSlots":1,"returnSlots":1},"allocate_unbounded":{"entryPoint":568,"id":null,"parameterSlots":0,"returnSlots":1},"array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr":{"entryPoint":578,"id":null,"parameterSlots":1,"returnSlots":1},"checked_add_t_uint256":{"entryPoint":622,"id":null,"parameterSlots":2,"returnSlots":1},"cleanup_t_uint256":{"entryPoint":708,"id":null,"parameterSlots":1,"returnSlots":1},"finalize_allocation":{"entryPoint":718,"id":null,"parameterSlots":2,"returnSlots":0},"panic_error_0x11":{"entryPoint":767,"id":null,"parameterSlots":0,"returnSlots":0},"panic_error_0x41":{"entryPoint":814,"id":null,"parameterSlots":0,"returnSlots":0},"revert_error_1b9f4a0a5773e33b91aa01db23bf8c55fce1411167c872835e7fa00a4f17d46d":{"entryPoint":861,"id":null,"parameterSlots":0,"returnSlots":0},"revert_error_81385d8c0b31fffe14be1da910c8bd3a80be4cfa248e04f42ec0faea3132a8ef":{"entryPoint":866,"id":null,"parameterSlots":0,"returnSlots":0},"revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db":{"entryPoint":871,"id":null,"parameterSlots":0,"returnSlots":0},"revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b":{"entryPoint":876,"id":null,"parameterSlots":0,"returnSlots":0},"round_up_to_mul_of_32":{"entryPoint":881,"id":null,"parameterSlots":1,"returnSlots":1},"validator_revert_t_uint256":{"entryPoint":898,"id":null,"parameterSlots":1,"returnSlots":0}}}}}}},"sources":{"a.sol":{"id":0}}}

View File

@ -14,7 +14,7 @@
sstore
/* \"A\":0:42 */
pop
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"object\" {
","bytecode":{"functionDebugData":{},"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"object\" {
code {
let x := mload(0)
sstore(add(x, 0), 0)

View File

@ -13,7 +13,7 @@
pop
stop
data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"NamedObject\" {
","bytecode":{"functionDebugData":{},"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"NamedObject\" {
code {
let x := dataoffset(\"DataName\")
sstore(add(x, 0), 0)

View File

@ -22,7 +22,7 @@ sub_0: assembly {
/* \"A\":137:149 */
revert
}
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"},"deployedBytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"NamedObject\" {
","bytecode":{"functionDebugData":{},"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"},"deployedBytecode":{"functionDebugData":{},"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"NamedObject\" {
code {
let x := dataoffset(\"DataName\")
sstore(add(x, 0), 0)

View File

@ -13,7 +13,7 @@
/* \"A\":20:40 */
sstore
pop
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"object\" {
","bytecode":{"functionDebugData":{},"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"object\" {
code {
let x := mload(0)
sstore(add(x, 0), 0)

View File

@ -5,7 +5,7 @@
mload
/* \"A\":20:40 */
sstore
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"object\" {
","bytecode":{"functionDebugData":{},"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"object\" {
code {
let x := mload(0)
sstore(add(x, 0), 0)