Debug information for immutable references.

This commit is contained in:
Daniel Kirchner 2020-04-02 17:27:35 +02:00
parent 8451639f17
commit 81652686be
6 changed files with 60 additions and 19 deletions

View File

@ -530,7 +530,7 @@ LinkerObject const& Assembly::assemble() const
LinkerObject& ret = m_assembledObject;
size_t subTagSize = 1;
map<u256, vector<size_t>> immutableReferencesBySub;
map<u256, pair<string, vector<size_t>>> immutableReferencesBySub;
for (auto const& sub: m_subs)
{
auto const& linkerObject = sub->assemble();
@ -554,7 +554,7 @@ LinkerObject const& Assembly::assemble() const
for (auto const& i: m_items)
if (i.type() == AssignImmutable)
{
i.setImmutableOccurrences(immutableReferencesBySub[i.data()].size());
i.setImmutableOccurrences(immutableReferencesBySub[i.data()].second.size());
setsImmutables = true;
}
else if (i.type() == PushImmutable)
@ -660,11 +660,12 @@ LinkerObject const& Assembly::assemble() const
break;
case PushImmutable:
ret.bytecode.push_back(uint8_t(Instruction::PUSH32));
ret.immutableReferences[i.data()].emplace_back(ret.bytecode.size());
ret.immutableReferences[i.data()].first = m_immutables.at(i.data());
ret.immutableReferences[i.data()].second.emplace_back(ret.bytecode.size());
ret.bytecode.resize(ret.bytecode.size() + 32);
break;
case AssignImmutable:
for (auto const& offset: immutableReferencesBySub[i.data()])
for (auto const& offset: immutableReferencesBySub[i.data()].second)
{
ret.bytecode.push_back(uint8_t(Instruction::DUP1));
// TODO: should we make use of the constant optimizer methods for pushing the offsets?

View File

@ -40,9 +40,9 @@ struct LinkerObject
/// need to be replaced by the actual addresses by the linker.
std::map<size_t, std::string> linkReferences;
/// Map from hashes of the identifiers of immutable variables to a list of offsets into the bytecode
/// that refer to their values.
std::map<u256, std::vector<size_t>> immutableReferences;
/// Map from hashes of the identifiers of immutable variables to the full identifier of the immutable and
/// 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;
/// Appends the bytecode of @a _other and incorporates its link references.
void append(LinkerObject const& _other);

View File

@ -90,13 +90,7 @@ size_t CompilerContext::immutableMemoryOffset(VariableDeclaration const& _variab
vector<string> CompilerContext::immutableVariableSlotNames(VariableDeclaration const& _variable)
{
string baseName =
_variable.annotation().contract->fullyQualifiedName() +
"." +
_variable.name() +
" (" +
to_string(_variable.id()) +
")";
string baseName = to_string(_variable.id());
solAssert(_variable.annotation().type->sizeOnStack() > 0, "");
if (_variable.annotation().type->sizeOnStack() == 1)
return {baseName};

View File

@ -234,6 +234,7 @@ bool isBinaryRequested(Json::Value const& _outputSelection)
"wast", "wasm", "ewasm.wast", "ewasm.wasm",
"evm.deployedBytecode", "evm.deployedBytecode.object", "evm.deployedBytecode.opcodes",
"evm.deployedBytecode.sourceMap", "evm.deployedBytecode.linkReferences",
"evm.deployedBytecode.immutableReferences",
"evm.bytecode", "evm.bytecode.object", "evm.bytecode.opcodes", "evm.bytecode.sourceMap",
"evm.bytecode.linkReferences",
"evm.gasEstimates", "evm.legacyAssembly", "evm.assembly"
@ -309,13 +310,36 @@ Json::Value formatLinkReferences(std::map<size_t, std::string> const& linkRefere
return ret;
}
Json::Value collectEVMObject(evmasm::LinkerObject const& _object, string const* _sourceMap)
Json::Value formatImmutableReferences(map<u256, pair<string, vector<size_t>>> const& _immutableReferences)
{
Json::Value ret(Json::objectValue);
for (auto const& immutableReference: _immutableReferences)
{
auto const& [identifier, byteOffsets] = immutableReference.second;
Json::Value array(Json::arrayValue);
for (size_t byteOffset: byteOffsets)
{
Json::Value byteRange(Json::arrayValue);
byteRange.append(Json::UInt(byteOffset));
byteRange.append(Json::UInt(32)); // immutable references are currently always 32 bytes wide
array.append(byteRange);
}
ret[identifier] = array;
}
return ret;
}
Json::Value collectEVMObject(evmasm::LinkerObject const& _object, string const* _sourceMap, bool _runtimeObject)
{
Json::Value output = Json::objectValue;
output["object"] = _object.toHex();
output["opcodes"] = evmasm::disassemble(_object.bytecode);
output["sourceMap"] = _sourceMap ? *_sourceMap : "";
output["linkReferences"] = formatLinkReferences(_object.linkReferences);
if (_runtimeObject)
output["immutableReferences"] = formatImmutableReferences(_object.immutableReferences);
return output;
}
@ -982,19 +1006,21 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
))
evmData["bytecode"] = collectEVMObject(
compilerStack.object(contractName),
compilerStack.sourceMapping(contractName)
compilerStack.sourceMapping(contractName),
false
);
if (compilationSuccess && isArtifactRequested(
_inputsAndSettings.outputSelection,
file,
name,
{ "evm.deployedBytecode", "evm.deployedBytecode.object", "evm.deployedBytecode.opcodes", "evm.deployedBytecode.sourceMap", "evm.deployedBytecode.linkReferences" },
{ "evm.deployedBytecode", "evm.deployedBytecode.object", "evm.deployedBytecode.opcodes", "evm.deployedBytecode.sourceMap", "evm.deployedBytecode.linkReferences", "evm.deployedBytecode.immutableReferences" },
wildcardMatchesExperimental
))
evmData["deployedBytecode"] = collectEVMObject(
compilerStack.runtimeObject(contractName),
compilerStack.runtimeSourceMapping(contractName)
compilerStack.runtimeSourceMapping(contractName),
true
);
if (!evmData.empty())
@ -1081,7 +1107,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
{ "evm.bytecode", "evm.bytecode.object", "evm.bytecode.opcodes", "evm.bytecode.sourceMap", "evm.bytecode.linkReferences" },
wildcardMatchesExperimental
))
output["contracts"][sourceName][contractName]["evm"]["bytecode"] = collectEVMObject(*object.bytecode, object.sourceMappings.get());
output["contracts"][sourceName][contractName]["evm"]["bytecode"] = collectEVMObject(*object.bytecode, object.sourceMappings.get(), false);
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "irOptimized", wildcardMatchesExperimental))
output["contracts"][sourceName][contractName]["irOptimized"] = stack.print();

View File

@ -0,0 +1,18 @@
{
"language": "Solidity",
"sources": {
"a.sol": {
"content": "contract A { uint256 immutable x = 1; function f() public view returns (uint256) { return x; } }"
}
},
"settings": {
"evmVersion": "petersburg",
"outputSelection": {
"*": {
"A": [
"evm.deployedBytecode.immutableReferences"
]
}
}
}
}

View File

@ -0,0 +1,2 @@
{"contracts":{"a.sol":{"A":{"evm":{"deployedBytecode":{"immutableReferences":{"3":[[77,32]]},"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"0:96:0:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;0:96:0;;;;;;;;;;;;;;;;12:1:-1;9;2:12;38:56:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;72:7;90:1;83:8;;38:56;:::o"}}}}},"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"}],"sources":{"a.sol":{"id":0}}}