mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #14490 from ethereum/purge-using-namespace-std-from-libsolidity-codegen
Purge using namespace std from libsolidity/codegen
This commit is contained in:
commit
f085572e24
@ -30,12 +30,11 @@
|
||||
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
string ABIFunctions::tupleEncoder(
|
||||
std::string ABIFunctions::tupleEncoder(
|
||||
TypePointers const& _givenTypes,
|
||||
TypePointers _targetTypes,
|
||||
bool _encodeAsLibraryTypes,
|
||||
@ -56,7 +55,7 @@ string ABIFunctions::tupleEncoder(
|
||||
solAssert(t, "");
|
||||
}
|
||||
|
||||
string functionName = string("abi_encode_tuple_");
|
||||
std::string functionName = std::string("abi_encode_tuple_");
|
||||
for (auto const& t: _givenTypes)
|
||||
functionName += t->identifier() + "_";
|
||||
functionName += "_to_";
|
||||
@ -76,8 +75,8 @@ string ABIFunctions::tupleEncoder(
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
size_t const headSize_ = headSize(_targetTypes);
|
||||
templ("headSize", to_string(headSize_));
|
||||
string encodeElements;
|
||||
templ("headSize", std::to_string(headSize_));
|
||||
std::string encodeElements;
|
||||
size_t headPos = 0;
|
||||
size_t stackPos = 0;
|
||||
for (size_t i = 0; i < _givenTypes.size(); ++i)
|
||||
@ -88,24 +87,24 @@ string ABIFunctions::tupleEncoder(
|
||||
bool dynamic = _targetTypes[i]->isDynamicallyEncoded();
|
||||
Whiskers elementTempl(
|
||||
dynamic ?
|
||||
string(R"(
|
||||
std::string(R"(
|
||||
mstore(add(headStart, <pos>), sub(tail, headStart))
|
||||
tail := <abiEncode>(<values> tail)
|
||||
)") :
|
||||
string(R"(
|
||||
std::string(R"(
|
||||
<abiEncode>(<values> add(headStart, <pos>))
|
||||
)")
|
||||
);
|
||||
string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack);
|
||||
std::string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack);
|
||||
elementTempl("values", values.empty() ? "" : values + ", ");
|
||||
elementTempl("pos", to_string(headPos));
|
||||
elementTempl("pos", std::to_string(headPos));
|
||||
elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], options));
|
||||
encodeElements += elementTempl.render();
|
||||
headPos += _targetTypes[i]->calldataHeadSize();
|
||||
stackPos += sizeOnStack;
|
||||
}
|
||||
solAssert(headPos == headSize_, "");
|
||||
string valueParams =
|
||||
std::string valueParams =
|
||||
_reversed ?
|
||||
suffixedVariableNameList("value", stackPos, 0) :
|
||||
suffixedVariableNameList("value", 0, stackPos);
|
||||
@ -116,7 +115,7 @@ string ABIFunctions::tupleEncoder(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::tupleEncoderPacked(
|
||||
std::string ABIFunctions::tupleEncoderPacked(
|
||||
TypePointers const& _givenTypes,
|
||||
TypePointers _targetTypes,
|
||||
bool _reversed
|
||||
@ -135,7 +134,7 @@ string ABIFunctions::tupleEncoderPacked(
|
||||
solAssert(t, "");
|
||||
}
|
||||
|
||||
string functionName = string("abi_encode_tuple_packed_");
|
||||
std::string functionName = std::string("abi_encode_tuple_packed_");
|
||||
for (auto const& t: _givenTypes)
|
||||
functionName += t->identifier() + "_";
|
||||
functionName += "_to_";
|
||||
@ -154,7 +153,7 @@ string ABIFunctions::tupleEncoderPacked(
|
||||
}
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
string encodeElements;
|
||||
std::string encodeElements;
|
||||
size_t stackPos = 0;
|
||||
for (size_t i = 0; i < _givenTypes.size(); ++i)
|
||||
{
|
||||
@ -164,23 +163,23 @@ string ABIFunctions::tupleEncoderPacked(
|
||||
bool dynamic = _targetTypes[i]->isDynamicallyEncoded();
|
||||
Whiskers elementTempl(
|
||||
dynamic ?
|
||||
string(R"(
|
||||
std::string(R"(
|
||||
pos := <abiEncode>(<values> pos)
|
||||
)") :
|
||||
string(R"(
|
||||
std::string(R"(
|
||||
<abiEncode>(<values> pos)
|
||||
pos := add(pos, <calldataEncodedSize>)
|
||||
)")
|
||||
);
|
||||
string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack);
|
||||
std::string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack);
|
||||
elementTempl("values", values.empty() ? "" : values + ", ");
|
||||
if (!dynamic)
|
||||
elementTempl("calldataEncodedSize", to_string(_targetTypes[i]->calldataEncodedSize(false)));
|
||||
elementTempl("calldataEncodedSize", std::to_string(_targetTypes[i]->calldataEncodedSize(false)));
|
||||
elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], options));
|
||||
encodeElements += elementTempl.render();
|
||||
stackPos += sizeOnStack;
|
||||
}
|
||||
string valueParams =
|
||||
std::string valueParams =
|
||||
_reversed ?
|
||||
suffixedVariableNameList("value", stackPos, 0) :
|
||||
suffixedVariableNameList("value", 0, stackPos);
|
||||
@ -190,9 +189,9 @@ string ABIFunctions::tupleEncoderPacked(
|
||||
return templ.render();
|
||||
});
|
||||
}
|
||||
string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
|
||||
std::string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
|
||||
{
|
||||
string functionName = string("abi_decode_tuple_");
|
||||
std::string functionName = std::string("abi_decode_tuple_");
|
||||
for (auto const& t: _types)
|
||||
functionName += t->identifier();
|
||||
if (_fromMemory)
|
||||
@ -211,10 +210,10 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
templ("revertString", revertReasonIfDebugFunction("ABI decoding: tuple data too short"));
|
||||
templ("minimumSize", to_string(headSize(decodingTypes)));
|
||||
templ("minimumSize", std::to_string(headSize(decodingTypes)));
|
||||
|
||||
string decodeElements;
|
||||
vector<string> valueReturnParams;
|
||||
std::string decodeElements;
|
||||
std::vector<std::string> valueReturnParams;
|
||||
size_t headPos = 0;
|
||||
size_t stackPos = 0;
|
||||
for (size_t i = 0; i < _types.size(); ++i)
|
||||
@ -224,11 +223,11 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
|
||||
size_t sizeOnStack = _types[i]->sizeOnStack();
|
||||
solAssert(sizeOnStack == decodingTypes[i]->sizeOnStack(), "");
|
||||
solAssert(sizeOnStack > 0, "");
|
||||
vector<string> valueNamesLocal;
|
||||
std::vector<std::string> valueNamesLocal;
|
||||
for (size_t j = 0; j < sizeOnStack; j++)
|
||||
{
|
||||
valueNamesLocal.emplace_back("value" + to_string(stackPos));
|
||||
valueReturnParams.emplace_back("value" + to_string(stackPos));
|
||||
valueNamesLocal.emplace_back("value" + std::to_string(stackPos));
|
||||
valueReturnParams.emplace_back("value" + std::to_string(stackPos));
|
||||
stackPos++;
|
||||
}
|
||||
Whiskers elementTempl(R"(
|
||||
@ -247,7 +246,7 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
|
||||
elementTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid tuple offset"));
|
||||
elementTempl("load", _fromMemory ? "mload" : "calldataload");
|
||||
elementTempl("values", boost::algorithm::join(valueNamesLocal, ", "));
|
||||
elementTempl("pos", to_string(headPos));
|
||||
elementTempl("pos", std::to_string(headPos));
|
||||
elementTempl("abiDecode", abiDecodingFunction(*_types[i], _fromMemory, true));
|
||||
decodeElements += elementTempl.render();
|
||||
headPos += decodingTypes[i]->calldataHeadSize();
|
||||
@ -260,9 +259,9 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::EncodingOptions::toFunctionNameSuffix() const
|
||||
std::string ABIFunctions::EncodingOptions::toFunctionNameSuffix() const
|
||||
{
|
||||
string suffix;
|
||||
std::string suffix;
|
||||
if (!padded)
|
||||
suffix += "_nonPadded";
|
||||
if (dynamicInplace)
|
||||
@ -274,7 +273,7 @@ string ABIFunctions::EncodingOptions::toFunctionNameSuffix() const
|
||||
return suffix;
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunction(
|
||||
std::string ABIFunctions::abiEncodingFunction(
|
||||
Type const& _from,
|
||||
Type const& _to,
|
||||
EncodingOptions const& _options
|
||||
@ -349,7 +348,7 @@ string ABIFunctions::abiEncodingFunction(
|
||||
solAssert(_from.sizeOnStack() == 1, "");
|
||||
solAssert(to.isValueType(), "");
|
||||
solAssert(to.calldataEncodedSize() == 32, "");
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -376,7 +375,7 @@ string ABIFunctions::abiEncodingFunction(
|
||||
}
|
||||
else
|
||||
{
|
||||
string cleanupConvert;
|
||||
std::string cleanupConvert;
|
||||
if (_from == to)
|
||||
cleanupConvert = m_utils.cleanupFunction(_from) + "(value)";
|
||||
else
|
||||
@ -389,21 +388,21 @@ string ABIFunctions::abiEncodingFunction(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodeAndReturnUpdatedPosFunction(
|
||||
std::string ABIFunctions::abiEncodeAndReturnUpdatedPosFunction(
|
||||
Type const& _givenType,
|
||||
Type const& _targetType,
|
||||
ABIFunctions::EncodingOptions const& _options
|
||||
)
|
||||
{
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encodeUpdatedPos_" +
|
||||
_givenType.identifier() +
|
||||
"_to_" +
|
||||
_targetType.identifier() +
|
||||
_options.toFunctionNameSuffix();
|
||||
return createFunction(functionName, [&]() {
|
||||
string values = suffixedVariableNameList("value", 0, numVariablesForType(_givenType, _options));
|
||||
string encoder = abiEncodingFunction(_givenType, _targetType, _options);
|
||||
std::string values = suffixedVariableNameList("value", 0, numVariablesForType(_givenType, _options));
|
||||
std::string encoder = abiEncodingFunction(_givenType, _targetType, _options);
|
||||
Type const* targetEncoding = _targetType.fullEncodingType(_options.encodeAsLibraryTypes, true, false);
|
||||
solAssert(targetEncoding, "");
|
||||
if (targetEncoding->isDynamicallyEncoded())
|
||||
@ -435,7 +434,7 @@ string ABIFunctions::abiEncodeAndReturnUpdatedPosFunction(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
|
||||
std::string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
|
||||
Type const& _from,
|
||||
Type const& _to,
|
||||
EncodingOptions const& _options
|
||||
@ -461,7 +460,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
|
||||
""
|
||||
);
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -522,13 +521,13 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionSimpleArray(
|
||||
std::string ABIFunctions::abiEncodingFunctionSimpleArray(
|
||||
ArrayType const& _from,
|
||||
ArrayType const& _to,
|
||||
EncodingOptions const& _options
|
||||
)
|
||||
{
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -548,7 +547,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
|
||||
EncodingOptions subOptions(_options);
|
||||
subOptions.encodeFunctionFromStack = false;
|
||||
subOptions.padded = true;
|
||||
string elementValues = suffixedVariableNameList("elementValue", 0, numVariablesForType(*_from.baseType(), subOptions));
|
||||
std::string elementValues = suffixedVariableNameList("elementValue", 0, numVariablesForType(*_from.baseType(), subOptions));
|
||||
Whiskers templ(
|
||||
usesTail ?
|
||||
R"(
|
||||
@ -632,13 +631,13 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionMemoryByteArray(
|
||||
std::string ABIFunctions::abiEncodingFunctionMemoryByteArray(
|
||||
ArrayType const& _from,
|
||||
ArrayType const& _to,
|
||||
EncodingOptions const& _options
|
||||
)
|
||||
{
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -669,13 +668,13 @@ string ABIFunctions::abiEncodingFunctionMemoryByteArray(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionCompactStorageArray(
|
||||
std::string ABIFunctions::abiEncodingFunctionCompactStorageArray(
|
||||
ArrayType const& _from,
|
||||
ArrayType const& _to,
|
||||
EncodingOptions const& _options
|
||||
)
|
||||
{
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -791,13 +790,13 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
|
||||
templ("useSpill", "1");
|
||||
else
|
||||
templ("useSpill", "0");
|
||||
templ("itemsPerSlot", to_string(itemsPerSlot));
|
||||
templ("itemsPerSlot", std::to_string(itemsPerSlot));
|
||||
templ("stride", toCompactHexWithPrefix(_to.calldataStride()));
|
||||
|
||||
EncodingOptions subOptions(_options);
|
||||
subOptions.encodeFunctionFromStack = false;
|
||||
subOptions.padded = true;
|
||||
string encodeToMemoryFun = abiEncodingFunction(
|
||||
std::string encodeToMemoryFun = abiEncodingFunction(
|
||||
*_from.baseType(),
|
||||
*_to.baseType(),
|
||||
subOptions
|
||||
@ -820,13 +819,13 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionStruct(
|
||||
std::string ABIFunctions::abiEncodingFunctionStruct(
|
||||
StructType const& _from,
|
||||
StructType const& _to,
|
||||
EncodingOptions const& _options
|
||||
)
|
||||
{
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -867,7 +866,7 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
templ("init", _from.dataStoredIn(DataLocation::Storage) ? "let slotValue := 0" : "");
|
||||
u256 previousSlotOffset(-1);
|
||||
u256 encodingOffset = 0;
|
||||
vector<map<string, string>> members;
|
||||
std::vector<std::map<std::string, std::string>> members;
|
||||
for (auto const& member: _to.members(nullptr))
|
||||
{
|
||||
solAssert(member.type, "");
|
||||
@ -890,7 +889,7 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
solAssert(memberTypeFrom->isValueType() == memberTypeTo->isValueType(), "");
|
||||
u256 storageSlotOffset;
|
||||
size_t intraSlotOffset;
|
||||
tie(storageSlotOffset, intraSlotOffset) = _from.storageOffsetsOfMember(member.name);
|
||||
std::tie(storageSlotOffset, intraSlotOffset) = _from.storageOffsetsOfMember(member.name);
|
||||
if (memberTypeFrom->isValueType())
|
||||
{
|
||||
if (storageSlotOffset != previousSlotOffset)
|
||||
@ -910,13 +909,13 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
}
|
||||
case DataLocation::Memory:
|
||||
{
|
||||
string sourceOffset = toCompactHexWithPrefix(_from.memoryOffsetOfMember(member.name));
|
||||
std::string sourceOffset = toCompactHexWithPrefix(_from.memoryOffsetOfMember(member.name));
|
||||
members.back()["retrieveValue"] = "mload(add(value, " + sourceOffset + "))";
|
||||
break;
|
||||
}
|
||||
case DataLocation::CallData:
|
||||
{
|
||||
string sourceOffset = toCompactHexWithPrefix(_from.calldataOffsetOfMember(member.name));
|
||||
std::string sourceOffset = toCompactHexWithPrefix(_from.calldataOffsetOfMember(member.name));
|
||||
members.back()["retrieveValue"] = calldataAccessFunction(*memberTypeFrom) + "(value, add(value, " + sourceOffset + "))";
|
||||
break;
|
||||
}
|
||||
@ -929,10 +928,10 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
// Like with arrays, struct members are always padded.
|
||||
subOptions.padded = true;
|
||||
|
||||
string memberValues = suffixedVariableNameList("memberValue", 0, numVariablesForType(*memberTypeFrom, subOptions));
|
||||
std::string memberValues = suffixedVariableNameList("memberValue", 0, numVariablesForType(*memberTypeFrom, subOptions));
|
||||
members.back()["memberValues"] = memberValues;
|
||||
|
||||
string encode;
|
||||
std::string encode;
|
||||
if (_options.dynamicInplace)
|
||||
encode = Whiskers{"pos := <encode>(<memberValues>, pos)"}
|
||||
("encode", abiEncodeAndReturnUpdatedPosFunction(*memberTypeFrom, *memberTypeTo, subOptions))
|
||||
@ -942,7 +941,7 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
{
|
||||
Whiskers encodeTempl(
|
||||
dynamicMember ?
|
||||
string(R"(
|
||||
std::string(R"(
|
||||
mstore(add(pos, <encodingOffset>), sub(tail, pos))
|
||||
tail := <abiEncode>(<memberValues>, tail)
|
||||
)") :
|
||||
@ -966,7 +965,7 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionStringLiteral(
|
||||
std::string ABIFunctions::abiEncodingFunctionStringLiteral(
|
||||
Type const& _from,
|
||||
Type const& _to,
|
||||
EncodingOptions const& _options
|
||||
@ -974,7 +973,7 @@ string ABIFunctions::abiEncodingFunctionStringLiteral(
|
||||
{
|
||||
solAssert(_from.category() == Type::Category::StringLiteral, "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -982,7 +981,7 @@ string ABIFunctions::abiEncodingFunctionStringLiteral(
|
||||
_options.toFunctionNameSuffix();
|
||||
return createFunction(functionName, [&]() {
|
||||
auto const& strType = dynamic_cast<StringLiteralType const&>(_from);
|
||||
string const& value = strType.value();
|
||||
std::string const& value = strType.value();
|
||||
solAssert(_from.sizeOnStack() == 0, "");
|
||||
|
||||
if (_to.isDynamicallySized())
|
||||
@ -998,12 +997,12 @@ string ABIFunctions::abiEncodingFunctionStringLiteral(
|
||||
templ("functionName", functionName);
|
||||
|
||||
// TODO this can make use of CODECOPY for large strings once we have that in Yul
|
||||
templ("length", to_string(value.size()));
|
||||
templ("length", std::to_string(value.size()));
|
||||
templ("storeLength", arrayStoreLengthForEncodingFunction(dynamic_cast<ArrayType const&>(_to), _options));
|
||||
if (_options.padded)
|
||||
templ("overallSize", to_string(((value.size() + 31) / 32) * 32));
|
||||
templ("overallSize", std::to_string(((value.size() + 31) / 32) * 32));
|
||||
else
|
||||
templ("overallSize", to_string(value.size()));
|
||||
templ("overallSize", std::to_string(value.size()));
|
||||
templ("storeLiteralInMemory", m_utils.storeLiteralInMemoryFunction(value));
|
||||
return templ.render();
|
||||
}
|
||||
@ -1023,7 +1022,7 @@ string ABIFunctions::abiEncodingFunctionStringLiteral(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionFunctionType(
|
||||
std::string ABIFunctions::abiEncodingFunctionFunctionType(
|
||||
FunctionType const& _from,
|
||||
Type const& _to,
|
||||
EncodingOptions const& _options
|
||||
@ -1036,7 +1035,7 @@ string ABIFunctions::abiEncodingFunctionFunctionType(
|
||||
"Invalid function type conversion requested"
|
||||
);
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -1069,7 +1068,7 @@ string ABIFunctions::abiEncodingFunctionFunctionType(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bool _forUseOnStack)
|
||||
std::string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bool _forUseOnStack)
|
||||
{
|
||||
// The decoding function has to perform bounds checks unless it decodes a value type.
|
||||
// Conversely, bounds checks have to be performed before the decoding function
|
||||
@ -1104,7 +1103,7 @@ string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bo
|
||||
return abiDecodingFunctionValueType(_type, _fromMemory);
|
||||
}
|
||||
|
||||
string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromMemory)
|
||||
std::string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromMemory)
|
||||
{
|
||||
Type const* decodingType = _type.decodingType();
|
||||
solAssert(decodingType, "");
|
||||
@ -1113,7 +1112,7 @@ string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromM
|
||||
solAssert(!decodingType->isDynamicallyEncoded(), "");
|
||||
solAssert(decodingType->calldataEncodedSize() == 32, "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_" +
|
||||
_type.identifier() +
|
||||
(_fromMemory ? "_fromMemory" : "");
|
||||
@ -1134,17 +1133,17 @@ string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromM
|
||||
|
||||
}
|
||||
|
||||
string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _fromMemory)
|
||||
std::string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _fromMemory)
|
||||
{
|
||||
solAssert(_type.dataStoredIn(DataLocation::Memory), "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_" +
|
||||
_type.identifier() +
|
||||
(_fromMemory ? "_fromMemory" : "");
|
||||
|
||||
return createFunction(functionName, [&]() {
|
||||
string load = _fromMemory ? "mload" : "calldataload";
|
||||
std::string load = _fromMemory ? "mload" : "calldataload";
|
||||
Whiskers templ(
|
||||
R"(
|
||||
// <readableTypeName>
|
||||
@ -1166,14 +1165,14 @@ string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _from
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
|
||||
std::string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
|
||||
{
|
||||
solAssert(_type.dataStoredIn(DataLocation::Memory), "");
|
||||
if (_type.isByteArrayOrString())
|
||||
return abiDecodingFunctionByteArrayAvailableLength(_type, _fromMemory);
|
||||
solAssert(_type.calldataStride() > 0, "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_available_length_" +
|
||||
_type.identifier() +
|
||||
(_fromMemory ? "_fromMemory" : "");
|
||||
@ -1224,7 +1223,7 @@ string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _t
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
|
||||
std::string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
|
||||
{
|
||||
solAssert(_type.dataStoredIn(DataLocation::CallData), "");
|
||||
if (!_type.isDynamicallySized())
|
||||
@ -1232,7 +1231,7 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
|
||||
solAssert(_type.calldataStride() > 0, "");
|
||||
solAssert(_type.calldataStride() < u256("0xffffffffffffffff"), "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_" +
|
||||
_type.identifier();
|
||||
return createFunction(functionName, [&]() {
|
||||
@ -1273,12 +1272,12 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
|
||||
std::string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
|
||||
{
|
||||
solAssert(_type.dataStoredIn(DataLocation::Memory), "");
|
||||
solAssert(_type.isByteArrayOrString(), "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_available_length_" +
|
||||
_type.identifier() +
|
||||
(_fromMemory ? "_fromMemory" : "");
|
||||
@ -1302,10 +1301,10 @@ string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiDecodingFunctionCalldataStruct(StructType const& _type)
|
||||
std::string ABIFunctions::abiDecodingFunctionCalldataStruct(StructType const& _type)
|
||||
{
|
||||
solAssert(_type.dataStoredIn(DataLocation::CallData), "");
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_" +
|
||||
_type.identifier();
|
||||
|
||||
@ -1321,15 +1320,15 @@ string ABIFunctions::abiDecodingFunctionCalldataStruct(StructType const& _type)
|
||||
w("revertString", revertReasonIfDebugFunction("ABI decoding: struct calldata too short"));
|
||||
w("functionName", functionName);
|
||||
w("readableTypeName", _type.toString(true));
|
||||
w("minimumSize", to_string(_type.isDynamicallyEncoded() ? _type.calldataEncodedTailSize() : _type.calldataEncodedSize(true)));
|
||||
w("minimumSize", std::to_string(_type.isDynamicallyEncoded() ? _type.calldataEncodedTailSize() : _type.calldataEncodedSize(true)));
|
||||
return w.render();
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fromMemory)
|
||||
std::string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fromMemory)
|
||||
{
|
||||
solAssert(!_type.dataStoredIn(DataLocation::CallData), "");
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_" +
|
||||
_type.identifier() +
|
||||
(_fromMemory ? "_fromMemory" : "");
|
||||
@ -1356,7 +1355,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr
|
||||
solAssert(_type.memoryDataSize() < u256("0xffffffffffffffff"), "");
|
||||
templ("memorySize", toCompactHexWithPrefix(_type.memoryDataSize()));
|
||||
size_t headPos = 0;
|
||||
vector<map<string, string>> members;
|
||||
std::vector<std::map<std::string, std::string>> members;
|
||||
for (auto const& member: _type.members(nullptr))
|
||||
{
|
||||
solAssert(member.type, "");
|
||||
@ -1376,7 +1375,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr
|
||||
// TODO add test
|
||||
memberTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid struct offset"));
|
||||
memberTempl("load", _fromMemory ? "mload" : "calldataload");
|
||||
memberTempl("pos", to_string(headPos));
|
||||
memberTempl("pos", std::to_string(headPos));
|
||||
memberTempl("memoryOffset", toCompactHexWithPrefix(_type.memoryOffsetOfMember(member.name)));
|
||||
memberTempl("abiDecode", abiDecodingFunction(*member.type, _fromMemory, false));
|
||||
|
||||
@ -1391,11 +1390,11 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiDecodingFunctionFunctionType(FunctionType const& _type, bool _fromMemory, bool _forUseOnStack)
|
||||
std::string ABIFunctions::abiDecodingFunctionFunctionType(FunctionType const& _type, bool _fromMemory, bool _forUseOnStack)
|
||||
{
|
||||
solAssert(_type.kind() == FunctionType::Kind::External, "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_" +
|
||||
_type.identifier() +
|
||||
(_fromMemory ? "_fromMemory" : "") +
|
||||
@ -1430,10 +1429,10 @@ string ABIFunctions::abiDecodingFunctionFunctionType(FunctionType const& _type,
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::calldataAccessFunction(Type const& _type)
|
||||
std::string ABIFunctions::calldataAccessFunction(Type const& _type)
|
||||
{
|
||||
solAssert(_type.isValueType() || _type.dataStoredIn(DataLocation::CallData), "");
|
||||
string functionName = "calldata_access_" + _type.identifier();
|
||||
std::string functionName = "calldata_access_" + _type.identifier();
|
||||
return createFunction(functionName, [&]() {
|
||||
if (_type.isDynamicallyEncoded())
|
||||
{
|
||||
@ -1477,7 +1476,7 @@ string ABIFunctions::calldataAccessFunction(Type const& _type)
|
||||
}
|
||||
else if (_type.isValueType())
|
||||
{
|
||||
string decodingFunction;
|
||||
std::string decodingFunction;
|
||||
if (auto const* functionType = dynamic_cast<FunctionType const*>(&_type))
|
||||
decodingFunction = abiDecodingFunctionFunctionType(*functionType, false, false);
|
||||
else
|
||||
@ -1510,9 +1509,9 @@ string ABIFunctions::calldataAccessFunction(Type const& _type)
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::arrayStoreLengthForEncodingFunction(ArrayType const& _type, EncodingOptions const& _options)
|
||||
std::string ABIFunctions::arrayStoreLengthForEncodingFunction(ArrayType const& _type, EncodingOptions const& _options)
|
||||
{
|
||||
string functionName = "array_storeLengthForEncoding_" + _type.identifier() + _options.toFunctionNameSuffix();
|
||||
std::string functionName = "array_storeLengthForEncoding_" + _type.identifier() + _options.toFunctionNameSuffix();
|
||||
return createFunction(functionName, [&]() {
|
||||
if (_type.isDynamicallySized() && !_options.dynamicInplace)
|
||||
return Whiskers(R"(
|
||||
@ -1534,7 +1533,7 @@ string ABIFunctions::arrayStoreLengthForEncodingFunction(ArrayType const& _type,
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::createFunction(string const& _name, function<string ()> const& _creator)
|
||||
std::string ABIFunctions::createFunction(std::string const& _name, std::function<std::string ()> const& _creator)
|
||||
{
|
||||
return m_functionCollector.createFunction(_name, _creator);
|
||||
}
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include <libevmasm/Instruction.h>
|
||||
#include <liblangutil/Exceptions.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::evmasm;
|
||||
using namespace solidity::frontend;
|
||||
@ -314,7 +313,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
|
||||
if (!_sourceType.isByteArrayOrString())
|
||||
convertLengthToSize(_sourceType);
|
||||
|
||||
string routine = "calldatacopy(target, source, len)\n";
|
||||
std::string routine = "calldatacopy(target, source, len)\n";
|
||||
if (_padToWordBoundaries)
|
||||
routine += R"(
|
||||
// Set padding suffix to zero
|
||||
@ -890,7 +889,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
|
||||
sstore(ref, slot_value)
|
||||
})");
|
||||
code("panicSelector", util::selectorFromSignatureU256("Panic(uint256)").str());
|
||||
code("emptyArrayPop", to_string(unsigned(util::PanicCode::EmptyArrayPop)));
|
||||
code("emptyArrayPop", std::to_string(unsigned(util::PanicCode::EmptyArrayPop)));
|
||||
m_context.appendInlineAssembly(code.render(), {"ref", "slot_value", "length"});
|
||||
m_context << Instruction::POP << Instruction::POP << Instruction::POP;
|
||||
}
|
||||
|
@ -26,13 +26,12 @@
|
||||
#include <libsolidity/codegen/ContractCompiler.h>
|
||||
#include <libevmasm/Assembly.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
void Compiler::compileContract(
|
||||
ContractDefinition const& _contract,
|
||||
std::map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers,
|
||||
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers,
|
||||
bytes const& _metadata
|
||||
)
|
||||
{
|
||||
|
@ -55,7 +55,6 @@
|
||||
#undef SOL_OUTPUT_ASM
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::evmasm;
|
||||
@ -68,7 +67,7 @@ void CompilerContext::addStateVariable(
|
||||
unsigned _byteOffset
|
||||
)
|
||||
{
|
||||
m_stateVariables[&_declaration] = make_pair(_storageOffset, _byteOffset);
|
||||
m_stateVariables[&_declaration] = std::make_pair(_storageOffset, _byteOffset);
|
||||
}
|
||||
|
||||
void CompilerContext::addImmutable(VariableDeclaration const& _variable)
|
||||
@ -88,14 +87,14 @@ size_t CompilerContext::immutableMemoryOffset(VariableDeclaration const& _variab
|
||||
return m_immutableVariables.at(&_variable);
|
||||
}
|
||||
|
||||
vector<string> CompilerContext::immutableVariableSlotNames(VariableDeclaration const& _variable)
|
||||
std::vector<std::string> CompilerContext::immutableVariableSlotNames(VariableDeclaration const& _variable)
|
||||
{
|
||||
string baseName = to_string(_variable.id());
|
||||
std::string baseName = std::to_string(_variable.id());
|
||||
solAssert(_variable.annotation().type->sizeOnStack() > 0, "");
|
||||
if (_variable.annotation().type->sizeOnStack() == 1)
|
||||
return {baseName};
|
||||
vector<string> names;
|
||||
auto collectSlotNames = [&](string const& _baseName, Type const* type, auto const& _recurse) -> void {
|
||||
std::vector<std::string> names;
|
||||
auto collectSlotNames = [&](std::string const& _baseName, Type const* type, auto const& _recurse) -> void {
|
||||
for (auto const& [slot, type]: type->stackItems())
|
||||
if (type)
|
||||
_recurse(_baseName + " " + slot, type, _recurse);
|
||||
@ -121,10 +120,10 @@ void CompilerContext::startFunction(Declaration const& _function)
|
||||
}
|
||||
|
||||
void CompilerContext::callLowLevelFunction(
|
||||
string const& _name,
|
||||
std::string const& _name,
|
||||
unsigned _inArgs,
|
||||
unsigned _outArgs,
|
||||
function<void(CompilerContext&)> const& _generator
|
||||
std::function<void(CompilerContext&)> const& _generator
|
||||
)
|
||||
{
|
||||
evmasm::AssemblyItem retTag = pushNewTag();
|
||||
@ -138,7 +137,7 @@ void CompilerContext::callLowLevelFunction(
|
||||
}
|
||||
|
||||
void CompilerContext::callYulFunction(
|
||||
string const& _name,
|
||||
std::string const& _name,
|
||||
unsigned _inArgs,
|
||||
unsigned _outArgs
|
||||
)
|
||||
@ -152,10 +151,10 @@ void CompilerContext::callYulFunction(
|
||||
}
|
||||
|
||||
evmasm::AssemblyItem CompilerContext::lowLevelFunctionTag(
|
||||
string const& _name,
|
||||
std::string const& _name,
|
||||
unsigned _inArgs,
|
||||
unsigned _outArgs,
|
||||
function<void(CompilerContext&)> const& _generator
|
||||
std::function<void(CompilerContext&)> const& _generator
|
||||
)
|
||||
{
|
||||
auto it = m_lowLevelFunctions.find(_name);
|
||||
@ -174,10 +173,10 @@ void CompilerContext::appendMissingLowLevelFunctions()
|
||||
{
|
||||
while (!m_lowLevelFunctionGenerationQueue.empty())
|
||||
{
|
||||
string name;
|
||||
std::string name;
|
||||
unsigned inArgs;
|
||||
unsigned outArgs;
|
||||
function<void(CompilerContext&)> generator;
|
||||
std::function<void(CompilerContext&)> generator;
|
||||
tie(name, inArgs, outArgs, generator) = m_lowLevelFunctionGenerationQueue.front();
|
||||
m_lowLevelFunctionGenerationQueue.pop();
|
||||
|
||||
@ -195,7 +194,7 @@ void CompilerContext::appendYulUtilityFunctions(OptimiserSettings const& _optimi
|
||||
solAssert(!m_appendYulUtilityFunctionsRan, "requestedYulFunctions called more than once.");
|
||||
m_appendYulUtilityFunctionsRan = true;
|
||||
|
||||
string code = m_yulFunctionCollector.requestedFunctions();
|
||||
std::string code = m_yulFunctionCollector.requestedFunctions();
|
||||
if (!code.empty())
|
||||
{
|
||||
appendInlineAssembly(
|
||||
@ -233,7 +232,7 @@ void CompilerContext::removeVariable(Declaration const& _declaration)
|
||||
|
||||
void CompilerContext::removeVariablesAboveStackHeight(unsigned _stackHeight)
|
||||
{
|
||||
vector<Declaration const*> toRemove;
|
||||
std::vector<Declaration const*> toRemove;
|
||||
for (auto _var: m_localVariables)
|
||||
{
|
||||
solAssert(!_var.second.empty(), "");
|
||||
@ -250,14 +249,14 @@ unsigned CompilerContext::numberOfLocalVariables() const
|
||||
return static_cast<unsigned>(m_localVariables.size());
|
||||
}
|
||||
|
||||
shared_ptr<evmasm::Assembly> CompilerContext::compiledContract(ContractDefinition const& _contract) const
|
||||
std::shared_ptr<evmasm::Assembly> CompilerContext::compiledContract(ContractDefinition const& _contract) const
|
||||
{
|
||||
auto ret = m_otherCompilers.find(&_contract);
|
||||
solAssert(ret != m_otherCompilers.end(), "Compiled contract not found.");
|
||||
return ret->second->assemblyPtr();
|
||||
}
|
||||
|
||||
shared_ptr<evmasm::Assembly> CompilerContext::compiledContractRuntime(ContractDefinition const& _contract) const
|
||||
std::shared_ptr<evmasm::Assembly> CompilerContext::compiledContractRuntime(ContractDefinition const& _contract) const
|
||||
{
|
||||
auto ret = m_otherCompilers.find(&_contract);
|
||||
solAssert(ret != m_otherCompilers.end(), "Compiled contract not found.");
|
||||
@ -320,7 +319,7 @@ unsigned CompilerContext::currentToBaseStackOffset(unsigned _offset) const
|
||||
return static_cast<unsigned>(m_asm->deposit()) - _offset - 1;
|
||||
}
|
||||
|
||||
pair<u256, unsigned> CompilerContext::storageLocationOfVariable(Declaration const& _declaration) const
|
||||
std::pair<u256, unsigned> CompilerContext::storageLocationOfVariable(Declaration const& _declaration) const
|
||||
{
|
||||
auto it = m_stateVariables.find(&_declaration);
|
||||
solAssert(it != m_stateVariables.end(), "Variable not found in storage.");
|
||||
@ -349,13 +348,13 @@ CompilerContext& CompilerContext::appendConditionalPanic(util::PanicCode _code)
|
||||
return *this;
|
||||
}
|
||||
|
||||
CompilerContext& CompilerContext::appendRevert(string const& _message)
|
||||
CompilerContext& CompilerContext::appendRevert(std::string const& _message)
|
||||
{
|
||||
appendInlineAssembly("{ " + revertReasonIfDebug(_message) + " }");
|
||||
return *this;
|
||||
}
|
||||
|
||||
CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnData, string const& _message)
|
||||
CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnData, std::string const& _message)
|
||||
{
|
||||
if (_forwardReturnData && m_evmVersion.supportsReturndata())
|
||||
appendInlineAssembly(R"({
|
||||
@ -372,24 +371,24 @@ CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnDat
|
||||
|
||||
void CompilerContext::resetVisitedNodes(ASTNode const* _node)
|
||||
{
|
||||
stack<ASTNode const*> newStack;
|
||||
std::stack<ASTNode const*> newStack;
|
||||
newStack.push(_node);
|
||||
std::swap(m_visitedNodes, newStack);
|
||||
updateSourceLocation();
|
||||
}
|
||||
|
||||
void CompilerContext::appendInlineAssembly(
|
||||
string const& _assembly,
|
||||
vector<string> const& _localVariables,
|
||||
set<string> const& _externallyUsedFunctions,
|
||||
std::string const& _assembly,
|
||||
std::vector<std::string> const& _localVariables,
|
||||
std::set<std::string> const& _externallyUsedFunctions,
|
||||
bool _system,
|
||||
OptimiserSettings const& _optimiserSettings,
|
||||
string _sourceName
|
||||
std::string _sourceName
|
||||
)
|
||||
{
|
||||
unsigned startStackHeight = stackHeight();
|
||||
|
||||
set<yul::YulString> externallyUsedIdentifiers;
|
||||
std::set<yul::YulString> externallyUsedIdentifiers;
|
||||
for (auto const& fun: _externallyUsedFunctions)
|
||||
externallyUsedIdentifiers.insert(yul::YulString(fun));
|
||||
for (auto const& var: _localVariables)
|
||||
@ -438,19 +437,19 @@ void CompilerContext::appendInlineAssembly(
|
||||
ErrorReporter errorReporter(errors);
|
||||
langutil::CharStream charStream(_assembly, _sourceName);
|
||||
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion);
|
||||
optional<langutil::SourceLocation> locationOverride;
|
||||
std::optional<langutil::SourceLocation> locationOverride;
|
||||
if (!_system)
|
||||
locationOverride = m_asm->currentSourceLocation();
|
||||
shared_ptr<yul::Block> parserResult =
|
||||
std::shared_ptr<yul::Block> parserResult =
|
||||
yul::Parser(errorReporter, dialect, std::move(locationOverride))
|
||||
.parse(charStream);
|
||||
#ifdef SOL_OUTPUT_ASM
|
||||
cout << yul::AsmPrinter(&dialect)(*parserResult) << endl;
|
||||
#endif
|
||||
|
||||
auto reportError = [&](string const& _context)
|
||||
auto reportError = [&](std::string const& _context)
|
||||
{
|
||||
string message =
|
||||
std::string message =
|
||||
"Error parsing/analyzing inline assembly block:\n" +
|
||||
_context + "\n"
|
||||
"------------------ Input: -----------------\n" +
|
||||
@ -483,7 +482,7 @@ void CompilerContext::appendInlineAssembly(
|
||||
{
|
||||
yul::Object obj;
|
||||
obj.code = parserResult;
|
||||
obj.analysisInfo = make_shared<yul::AsmAnalysisInfo>(analysisInfo);
|
||||
obj.analysisInfo = std::make_shared<yul::AsmAnalysisInfo>(analysisInfo);
|
||||
|
||||
solAssert(!dialect.providesObjectAccess());
|
||||
optimizeYul(obj, dialect, _optimiserSettings, externallyUsedIdentifiers);
|
||||
@ -493,7 +492,7 @@ void CompilerContext::appendInlineAssembly(
|
||||
// Store as generated sources, but first re-parse to update the source references.
|
||||
solAssert(m_generatedYulUtilityCode.empty(), "");
|
||||
m_generatedYulUtilityCode = yul::AsmPrinter(dialect)(*obj.code);
|
||||
string code = yul::AsmPrinter{dialect}(*obj.code);
|
||||
std::string code = yul::AsmPrinter{dialect}(*obj.code);
|
||||
langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName);
|
||||
obj.code = yul::Parser(errorReporter, dialect).parse(charStream);
|
||||
*obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj);
|
||||
@ -548,7 +547,7 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _
|
||||
_optimiserSettings.optimizeStackAllocation,
|
||||
_optimiserSettings.yulOptimiserSteps,
|
||||
_optimiserSettings.yulOptimiserCleanupSteps,
|
||||
isCreation? nullopt : make_optional(_optimiserSettings.expectedExecutionsPerDeployment),
|
||||
isCreation? std::nullopt : std::make_optional(_optimiserSettings.expectedExecutionsPerDeployment),
|
||||
_externalIdentifiers
|
||||
);
|
||||
|
||||
@ -558,11 +557,11 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _
|
||||
#endif
|
||||
}
|
||||
|
||||
string CompilerContext::revertReasonIfDebug(string const& _message)
|
||||
std::string CompilerContext::revertReasonIfDebug(std::string const& _message)
|
||||
{
|
||||
return YulUtilFunctions::revertReasonIfDebugBody(
|
||||
m_revertStrings,
|
||||
"mload(" + to_string(CompilerUtils::freeMemoryPointer) + ")",
|
||||
"mload(" + std::to_string(CompilerUtils::freeMemoryPointer) + ")",
|
||||
_message
|
||||
);
|
||||
}
|
||||
@ -590,14 +589,14 @@ evmasm::AssemblyItem CompilerContext::FunctionCompilationQueue::entryLabel(
|
||||
}
|
||||
|
||||
// some name that cannot clash with yul function names.
|
||||
string labelName = "@" + _declaration.name() + "_" + to_string(_declaration.id());
|
||||
std::string labelName = "@" + _declaration.name() + "_" + std::to_string(_declaration.id());
|
||||
evmasm::AssemblyItem tag = _context.namedTag(
|
||||
labelName,
|
||||
params,
|
||||
returns,
|
||||
_declaration.id()
|
||||
);
|
||||
m_entryLabels.insert(make_pair(&_declaration, tag));
|
||||
m_entryLabels.insert(std::make_pair(&_declaration, tag));
|
||||
m_functionsToCompile.push(&_declaration);
|
||||
return tag.tag();
|
||||
}
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include <libsolutil/Whiskers.h>
|
||||
#include <libsolutil/StackTooDeepString.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::evmasm;
|
||||
using namespace solidity::frontend;
|
||||
@ -105,9 +104,9 @@ void CompilerUtils::revertWithStringData(Type const& _argumentType)
|
||||
}
|
||||
|
||||
void CompilerUtils::revertWithError(
|
||||
string const& _signature,
|
||||
vector<Type const*> const& _parameterTypes,
|
||||
vector<Type const*> const& _argumentTypes
|
||||
std::string const& _signature,
|
||||
std::vector<Type const*> const& _parameterTypes,
|
||||
std::vector<Type const*> const& _argumentTypes
|
||||
)
|
||||
{
|
||||
fetchFreeMemoryPointer();
|
||||
@ -215,7 +214,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
|
||||
m_context << Instruction::DUP1;
|
||||
storeStringData(bytesConstRef(str->value()));
|
||||
if (_padToWordBoundaries)
|
||||
m_context << u256(max<size_t>(32, ((str->value().size() + 31) / 32) * 32));
|
||||
m_context << u256(std::max<size_t>(32, ((str->value().size() + 31) / 32) * 32));
|
||||
else
|
||||
m_context << u256(str->value().size());
|
||||
m_context << Instruction::ADD;
|
||||
@ -264,7 +263,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
|
||||
Whiskers templ(R"({
|
||||
if lt(len, <encodedSize>) { <revertString> }
|
||||
})");
|
||||
templ("encodedSize", to_string(encodedSize));
|
||||
templ("encodedSize", std::to_string(encodedSize));
|
||||
templ("revertString", m_context.revertReasonIfDebug("Calldata too short"));
|
||||
m_context.appendInlineAssembly(templ.render(), {"len"});
|
||||
|
||||
@ -320,7 +319,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
|
||||
mstore(dst, array_length)
|
||||
dst := add(dst, 0x20)
|
||||
})");
|
||||
templ("item_size", to_string(arrayType.calldataStride()));
|
||||
templ("item_size", std::to_string(arrayType.calldataStride()));
|
||||
// TODO add test
|
||||
templ("revertStringPointer", m_context.revertReasonIfDebug("ABI memory decoding: invalid data pointer"));
|
||||
templ("revertStringStart", m_context.revertReasonIfDebug("ABI memory decoding: invalid data start"));
|
||||
@ -374,7 +373,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
|
||||
m_context.appendInlineAssembly(Whiskers(R"({
|
||||
if or(
|
||||
gt(array_length, 0x100000000),
|
||||
gt(add(data_ptr, mul(array_length, )" + to_string(arrayType.calldataStride()) + R"()), input_end)
|
||||
gt(add(data_ptr, mul(array_length, )" + std::to_string(arrayType.calldataStride()) + R"()), input_end)
|
||||
) { <revertString> }
|
||||
})")
|
||||
("revertString", m_context.revertReasonIfDebug("ABI calldata decoding: invalid data pointer"))
|
||||
@ -618,7 +617,7 @@ void CompilerUtils::abiEncodeV2(
|
||||
|
||||
// stack: <$value0> <$value1> ... <$value(n-1)> <$headStart>
|
||||
|
||||
string encoderName =
|
||||
std::string encoderName =
|
||||
_padToWordBoundaries ?
|
||||
m_context.abiFunctions().tupleEncoderReversed(_givenTypes, _targetTypes, _encodeAsLibraryTypes) :
|
||||
m_context.abiFunctions().tupleEncoderPackedReversed(_givenTypes, _targetTypes);
|
||||
@ -631,7 +630,7 @@ void CompilerUtils::abiDecodeV2(TypePointers const& _parameterTypes, bool _fromM
|
||||
m_context << Instruction::DUP2 << Instruction::ADD;
|
||||
m_context << Instruction::SWAP1;
|
||||
// stack: <end> <start>
|
||||
string decoderName = m_context.abiFunctions().tupleDecoder(_parameterTypes, _fromMemory);
|
||||
std::string decoderName = m_context.abiFunctions().tupleDecoder(_parameterTypes, _fromMemory);
|
||||
m_context.callYulFunction(decoderName, 2, sizeOnStack(_parameterTypes));
|
||||
}
|
||||
|
||||
@ -646,7 +645,7 @@ void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type)
|
||||
calldatacopy(memptr, calldatasize(), size)
|
||||
memptr := add(memptr, size)
|
||||
})");
|
||||
templ("element_size", to_string(_type.memoryStride()));
|
||||
templ("element_size", std::to_string(_type.memoryStride()));
|
||||
m_context.appendInlineAssembly(templ.render(), {"length", "memptr"});
|
||||
}
|
||||
else
|
||||
@ -842,7 +841,7 @@ void CompilerUtils::convertType(
|
||||
m_context << Instruction::POP << u256(0);
|
||||
else if (targetType.numBytes() > typeOnStack.numBytes() || _cleanupNeeded)
|
||||
{
|
||||
unsigned bytes = min(typeOnStack.numBytes(), targetType.numBytes());
|
||||
unsigned bytes = std::min(typeOnStack.numBytes(), targetType.numBytes());
|
||||
m_context << ((u256(1) << (256 - bytes * 8)) - 1);
|
||||
m_context << Instruction::NOT << Instruction::AND;
|
||||
}
|
||||
@ -960,7 +959,7 @@ void CompilerUtils::convertType(
|
||||
case Type::Category::StringLiteral:
|
||||
{
|
||||
auto const& literalType = dynamic_cast<StringLiteralType const&>(_typeOnStack);
|
||||
string const& value = literalType.value();
|
||||
std::string const& value = literalType.value();
|
||||
bytesConstRef data(value);
|
||||
if (targetTypeCategory == Type::Category::FixedBytes)
|
||||
{
|
||||
@ -1186,7 +1185,7 @@ void CompilerUtils::convertType(
|
||||
for (auto const& member: typeOnStack->members(nullptr))
|
||||
{
|
||||
solAssert(!member.type->containsNestedMapping());
|
||||
pair<u256, unsigned> const& offsets = typeOnStack->storageOffsetsOfMember(member.name);
|
||||
std::pair<u256, unsigned> const& offsets = typeOnStack->storageOffsetsOfMember(member.name);
|
||||
_context << offsets.first << Instruction::DUP3 << Instruction::ADD;
|
||||
_context << u256(offsets.second);
|
||||
StorageItem(_context, *member.type).retrieveValue(SourceLocation(), true);
|
||||
@ -1268,7 +1267,7 @@ void CompilerUtils::convertType(
|
||||
if (sourceSize > 0 || targetSize > 0)
|
||||
{
|
||||
// Move it back into its place.
|
||||
for (unsigned j = 0; j < min(sourceSize, targetSize); ++j)
|
||||
for (unsigned j = 0; j < std::min(sourceSize, targetSize); ++j)
|
||||
m_context <<
|
||||
swapInstruction(depth + targetSize - sourceSize) <<
|
||||
Instruction::POP;
|
||||
@ -1375,7 +1374,7 @@ void CompilerUtils::pushZeroValue(Type const& _type)
|
||||
[type](CompilerContext& _context) {
|
||||
CompilerUtils utils(_context);
|
||||
|
||||
utils.allocateMemory(max<u256>(32u, type->memoryDataSize()));
|
||||
utils.allocateMemory(std::max<u256>(32u, type->memoryDataSize()));
|
||||
_context << Instruction::DUP1;
|
||||
|
||||
if (auto structType = dynamic_cast<StructType const*>(type))
|
||||
@ -1493,7 +1492,7 @@ void CompilerUtils::popAndJump(unsigned _toHeight, evmasm::AssemblyItem const& _
|
||||
m_context.adjustStackOffset(static_cast<int>(amount));
|
||||
}
|
||||
|
||||
unsigned CompilerUtils::sizeOnStack(vector<Type const*> const& _variableTypes)
|
||||
unsigned CompilerUtils::sizeOnStack(std::vector<Type const*> const& _variableTypes)
|
||||
{
|
||||
unsigned size = 0;
|
||||
for (Type const* type: _variableTypes)
|
||||
@ -1509,7 +1508,7 @@ void CompilerUtils::computeHashStatic()
|
||||
|
||||
void CompilerUtils::copyContractCodeToMemory(ContractDefinition const& contract, bool _creation)
|
||||
{
|
||||
string which = _creation ? "Creation" : "Runtime";
|
||||
std::string which = _creation ? "Creation" : "Runtime";
|
||||
m_context.callLowLevelFunction(
|
||||
"$copyContract" + which + "CodeToMemory_" + contract.type()->identifier(),
|
||||
1,
|
||||
@ -1517,7 +1516,7 @@ void CompilerUtils::copyContractCodeToMemory(ContractDefinition const& contract,
|
||||
[&contract, _creation](CompilerContext& _context)
|
||||
{
|
||||
// copy the contract's code into memory
|
||||
shared_ptr<evmasm::Assembly> assembly =
|
||||
std::shared_ptr<evmasm::Assembly> assembly =
|
||||
_creation ?
|
||||
_context.compiledContract(contract) :
|
||||
_context.compiledContractRuntime(contract);
|
||||
|
@ -55,7 +55,6 @@
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::evmasm;
|
||||
using namespace solidity::frontend;
|
||||
@ -80,7 +79,7 @@ public:
|
||||
{
|
||||
solAssert(
|
||||
m_context.stackHeight() == stackHeight,
|
||||
std::string("I sense a disturbance in the stack: ") + to_string(m_context.stackHeight()) + " vs " + to_string(stackHeight)
|
||||
std::string("I sense a disturbance in the stack: ") + std::to_string(m_context.stackHeight()) + " vs " + std::to_string(stackHeight)
|
||||
);
|
||||
}
|
||||
private:
|
||||
@ -92,7 +91,7 @@ private:
|
||||
|
||||
void ContractCompiler::compileContract(
|
||||
ContractDefinition const& _contract,
|
||||
map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers
|
||||
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers
|
||||
)
|
||||
{
|
||||
CompilerContext::LocationSetter locationSetter(m_context, _contract);
|
||||
@ -111,7 +110,7 @@ void ContractCompiler::compileContract(
|
||||
|
||||
size_t ContractCompiler::compileConstructor(
|
||||
ContractDefinition const& _contract,
|
||||
std::map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers
|
||||
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers
|
||||
)
|
||||
{
|
||||
CompilerContext::LocationSetter locationSetter(m_context, _contract);
|
||||
@ -126,7 +125,7 @@ size_t ContractCompiler::compileConstructor(
|
||||
|
||||
void ContractCompiler::initializeContext(
|
||||
ContractDefinition const& _contract,
|
||||
map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers
|
||||
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers
|
||||
)
|
||||
{
|
||||
m_context.setUseABICoderV2(*_contract.sourceUnit().annotation().useABICoderV2);
|
||||
@ -187,7 +186,7 @@ size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _cont
|
||||
CompilerContext::LocationSetter locationSetter(m_context, _contract);
|
||||
m_context << deployRoutine;
|
||||
|
||||
solAssert(m_context.runtimeSub() != numeric_limits<size_t>::max(), "Runtime sub not registered");
|
||||
solAssert(m_context.runtimeSub() != std::numeric_limits<size_t>::max(), "Runtime sub not registered");
|
||||
|
||||
ContractType contractType(_contract);
|
||||
auto const& immutables = contractType.immutableVariables();
|
||||
@ -231,7 +230,7 @@ size_t ContractCompiler::deployLibrary(ContractDefinition const& _contract)
|
||||
|
||||
CompilerContext::LocationSetter locationSetter(m_context, _contract);
|
||||
|
||||
solAssert(m_context.runtimeSub() != numeric_limits<size_t>::max(), "Runtime sub not registered");
|
||||
solAssert(m_context.runtimeSub() != std::numeric_limits<size_t>::max(), "Runtime sub not registered");
|
||||
m_context.pushSubroutineSize(m_context.runtimeSub());
|
||||
m_context.pushSubroutineOffset(m_context.runtimeSub());
|
||||
// This code replaces the address added by appendDeployTimeAddress().
|
||||
@ -324,8 +323,8 @@ void ContractCompiler::appendDelegatecallCheck()
|
||||
}
|
||||
|
||||
void ContractCompiler::appendInternalSelector(
|
||||
map<FixedHash<4>, evmasm::AssemblyItem const> const& _entryPoints,
|
||||
vector<FixedHash<4>> const& _ids,
|
||||
std::map<FixedHash<4>, evmasm::AssemblyItem const> const& _entryPoints,
|
||||
std::vector<FixedHash<4>> const& _ids,
|
||||
evmasm::AssemblyItem const& _notFoundTag,
|
||||
size_t _runs
|
||||
)
|
||||
@ -369,11 +368,11 @@ void ContractCompiler::appendInternalSelector(
|
||||
m_context << dupInstruction(1) << u256(FixedHash<4>::Arith(pivot)) << Instruction::GT;
|
||||
evmasm::AssemblyItem lessTag{m_context.appendConditionalJump()};
|
||||
// Here, we have funid >= pivot
|
||||
vector<FixedHash<4>> larger{_ids.begin() + static_cast<ptrdiff_t>(pivotIndex), _ids.end()};
|
||||
std::vector<FixedHash<4>> larger{_ids.begin() + static_cast<ptrdiff_t>(pivotIndex), _ids.end()};
|
||||
appendInternalSelector(_entryPoints, larger, _notFoundTag, _runs);
|
||||
m_context << lessTag;
|
||||
// Here, we have funid < pivot
|
||||
vector<FixedHash<4>> smaller{_ids.begin(), _ids.begin() + static_cast<ptrdiff_t>(pivotIndex)};
|
||||
std::vector<FixedHash<4>> smaller{_ids.begin(), _ids.begin() + static_cast<ptrdiff_t>(pivotIndex)};
|
||||
appendInternalSelector(_entryPoints, smaller, _notFoundTag, _runs);
|
||||
}
|
||||
else
|
||||
@ -411,8 +410,8 @@ bool hasPayableFunctions(ContractDefinition const& _contract)
|
||||
|
||||
void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contract)
|
||||
{
|
||||
map<FixedHash<4>, FunctionTypePointer> interfaceFunctions = _contract.interfaceFunctions();
|
||||
map<FixedHash<4>, evmasm::AssemblyItem const> callDataUnpackerEntryPoints;
|
||||
std::map<FixedHash<4>, FunctionTypePointer> interfaceFunctions = _contract.interfaceFunctions();
|
||||
std::map<FixedHash<4>, evmasm::AssemblyItem const> callDataUnpackerEntryPoints;
|
||||
|
||||
if (_contract.isLibrary())
|
||||
{
|
||||
@ -448,7 +447,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
|
||||
CompilerUtils(m_context).loadFromMemory(0, IntegerType(CompilerUtils::dataStartOffset * 8), true, false);
|
||||
|
||||
// stack now is: <can-call-non-view-functions>? <funhash>
|
||||
vector<FixedHash<4>> sortedIDs;
|
||||
std::vector<FixedHash<4>> sortedIDs;
|
||||
for (auto const& it: interfaceFunctions)
|
||||
{
|
||||
callDataUnpackerEntryPoints.emplace(it.first, m_context.newTag());
|
||||
@ -572,7 +571,7 @@ void ContractCompiler::appendReturnValuePacker(TypePointers const& _typeParamete
|
||||
void ContractCompiler::registerStateVariables(ContractDefinition const& _contract)
|
||||
{
|
||||
for (auto const& var: ContractType(_contract).stateVariables())
|
||||
m_context.addStateVariable(*get<0>(var), get<1>(var), get<2>(var));
|
||||
m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var));
|
||||
}
|
||||
|
||||
void ContractCompiler::registerImmutableVariables(ContractDefinition const& _contract)
|
||||
@ -645,7 +644,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
|
||||
m_breakTags.clear();
|
||||
m_continueTags.clear();
|
||||
m_currentFunction = &_function;
|
||||
m_modifierDepth = numeric_limits<unsigned>::max();
|
||||
m_modifierDepth = std::numeric_limits<unsigned>::max();
|
||||
m_scopeStackHeight.clear();
|
||||
m_context.setModifierDepth(0);
|
||||
|
||||
@ -662,10 +661,10 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
|
||||
unsigned const c_argumentsSize = CompilerUtils::sizeOnStack(_function.parameters());
|
||||
unsigned const c_returnValuesSize = CompilerUtils::sizeOnStack(_function.returnParameters());
|
||||
|
||||
vector<int> stackLayout;
|
||||
std::vector<int> stackLayout;
|
||||
if (!_function.isConstructor() && !_function.isFallback())
|
||||
stackLayout.push_back(static_cast<int>(c_returnValuesSize)); // target of return address
|
||||
stackLayout += vector<int>(c_argumentsSize, -1); // discard all arguments
|
||||
stackLayout += std::vector<int>(c_argumentsSize, -1); // discard all arguments
|
||||
for (size_t i = 0; i < c_returnValuesSize; ++i)
|
||||
stackLayout.push_back(static_cast<int>(i));
|
||||
|
||||
@ -684,7 +683,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
|
||||
else
|
||||
{
|
||||
m_context << swapInstruction(static_cast<unsigned>(stackLayout.size()) - static_cast<unsigned>(stackLayout.back()) - 1u);
|
||||
swap(stackLayout[static_cast<size_t>(stackLayout.back())], stackLayout.back());
|
||||
std::swap(stackLayout[static_cast<size_t>(stackLayout.back())], stackLayout.back());
|
||||
}
|
||||
for (size_t i = 0; i < stackLayout.size(); ++i)
|
||||
if (stackLayout[i] != static_cast<int>(i))
|
||||
@ -790,7 +789,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
unsigned stackDiff = static_cast<unsigned>(_assembly.stackHeight()) - m_context.baseStackOffsetOfVariable(*variable);
|
||||
if (!ref->second.suffix.empty())
|
||||
{
|
||||
string const& suffix = ref->second.suffix;
|
||||
std::string const& suffix = ref->second.suffix;
|
||||
if (variable->type()->dataStoredIn(DataLocation::Storage))
|
||||
{
|
||||
solAssert(suffix == "offset" || suffix == "slot", "");
|
||||
@ -865,7 +864,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
// lvalue context
|
||||
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;
|
||||
std::string const& suffix = ref->second.suffix;
|
||||
if (variable->type()->dataStoredIn(DataLocation::Storage))
|
||||
{
|
||||
solAssert(
|
||||
@ -928,7 +927,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
yul::AsmAnalysisInfo* analysisInfo = _inlineAssembly.annotation().analysisInfo.get();
|
||||
|
||||
// Only used in the scope below, but required to live outside to keep the
|
||||
// shared_ptr's alive
|
||||
// std::shared_ptr's alive
|
||||
yul::Object object = {};
|
||||
|
||||
// The optimiser cannot handle external references
|
||||
@ -941,8 +940,8 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
solAssert(dialect, "");
|
||||
|
||||
// Create a modifiable copy of the code and analysis
|
||||
object.code = make_shared<yul::Block>(yul::ASTCopier().translate(*code));
|
||||
object.analysisInfo = make_shared<yul::AsmAnalysisInfo>(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object));
|
||||
object.code = std::make_shared<yul::Block>(yul::ASTCopier().translate(*code));
|
||||
object.analysisInfo = std::make_shared<yul::AsmAnalysisInfo>(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object));
|
||||
|
||||
m_context.optimizeYul(object, *dialect, m_optimiserSettings);
|
||||
|
||||
@ -989,10 +988,10 @@ bool ContractCompiler::visit(TryStatement const& _tryStatement)
|
||||
TryCatchClause const& successClause = *_tryStatement.clauses().front();
|
||||
if (successClause.parameters())
|
||||
{
|
||||
vector<Type const*> exprTypes{_tryStatement.externalCall().annotation().type};
|
||||
std::vector<Type const*> exprTypes{_tryStatement.externalCall().annotation().type};
|
||||
if (auto tupleType = dynamic_cast<TupleType const*>(exprTypes.front()))
|
||||
exprTypes = tupleType->components();
|
||||
vector<ASTPointer<VariableDeclaration>> const& params = successClause.parameters()->parameters();
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& params = successClause.parameters()->parameters();
|
||||
solAssert(exprTypes.size() == params.size(), "");
|
||||
for (size_t i = 0; i < exprTypes.size(); ++i)
|
||||
solAssert(params[i] && exprTypes[i] && *params[i]->annotation().type == *exprTypes[i], "");
|
||||
@ -1008,7 +1007,7 @@ bool ContractCompiler::visit(TryStatement const& _tryStatement)
|
||||
return false;
|
||||
}
|
||||
|
||||
void ContractCompiler::handleCatch(vector<ASTPointer<TryCatchClause>> const& _catchClauses)
|
||||
void ContractCompiler::handleCatch(std::vector<ASTPointer<TryCatchClause>> const& _catchClauses)
|
||||
{
|
||||
// Stack is empty.
|
||||
ASTPointer<TryCatchClause> error{};
|
||||
@ -1285,7 +1284,7 @@ bool ContractCompiler::visit(Return const& _return)
|
||||
if (Expression const* expression = _return.expression())
|
||||
{
|
||||
solAssert(_return.annotation().functionReturnParameters, "Invalid return parameters pointer.");
|
||||
vector<ASTPointer<VariableDeclaration>> const& returnParameters =
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& returnParameters =
|
||||
_return.annotation().functionReturnParameters->parameters();
|
||||
TypePointers types;
|
||||
for (auto const& retVariable: returnParameters)
|
||||
@ -1432,7 +1431,7 @@ void ContractCompiler::appendModifierOrFunctionCode()
|
||||
solAssert(m_currentFunction, "");
|
||||
unsigned stackSurplus = 0;
|
||||
Block const* codeBlock = nullptr;
|
||||
vector<VariableDeclaration const*> addedVariables;
|
||||
std::vector<VariableDeclaration const*> addedVariables;
|
||||
|
||||
m_modifierDepth++;
|
||||
m_context.setModifierDepth(m_modifierDepth);
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::evmasm;
|
||||
using namespace solidity::frontend;
|
||||
@ -242,7 +241,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(returnTypes[i]))
|
||||
if (!arrayType->isByteArrayOrString())
|
||||
continue;
|
||||
pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
|
||||
std::pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
|
||||
m_context << Instruction::DUP1 << u256(offsets.first) << Instruction::ADD << u256(offsets.second);
|
||||
Type const* memberType = structType->memberType(names[i]);
|
||||
StorageItem(m_context, *memberType).retrieveValue(SourceLocation(), true);
|
||||
@ -370,7 +369,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple)
|
||||
ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type);
|
||||
|
||||
solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array.");
|
||||
utils().allocateMemory(max(u256(32u), arrayType.memoryDataSize()));
|
||||
utils().allocateMemory(std::max(u256(32u), arrayType.memoryDataSize()));
|
||||
m_context << Instruction::DUP1;
|
||||
|
||||
for (auto const& component: _tuple.components())
|
||||
@ -383,7 +382,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple)
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<unique_ptr<LValue>> lvalues;
|
||||
std::vector<std::unique_ptr<LValue>> lvalues;
|
||||
for (auto const& component: _tuple.components())
|
||||
if (component)
|
||||
{
|
||||
@ -395,13 +394,13 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple)
|
||||
}
|
||||
}
|
||||
else if (_tuple.annotation().willBeWrittenTo)
|
||||
lvalues.push_back(unique_ptr<LValue>());
|
||||
lvalues.push_back(std::unique_ptr<LValue>());
|
||||
if (_tuple.annotation().willBeWrittenTo)
|
||||
{
|
||||
if (_tuple.components().size() == 1)
|
||||
m_currentLValue = std::move(lvalues[0]);
|
||||
else
|
||||
m_currentLValue = make_unique<TupleObject>(m_context, std::move(lvalues));
|
||||
m_currentLValue = std::make_unique<TupleObject>(m_context, std::move(lvalues));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -524,7 +523,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
|
||||
m_context << u256(0) << Instruction::SUB;
|
||||
break;
|
||||
default:
|
||||
solAssert(false, "Invalid unary operator: " + string(TokenTraits::toString(_unaryOperation.getOperator())));
|
||||
solAssert(false, "Invalid unary operator: " + std::string(TokenTraits::toString(_unaryOperation.getOperator())));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -659,14 +658,14 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
|
||||
TypePointers parameterTypes = functionType->parameterTypes();
|
||||
|
||||
vector<ASTPointer<Expression const>> const& arguments = _functionCall.sortedArguments();
|
||||
std::vector<ASTPointer<Expression const>> const& arguments = _functionCall.sortedArguments();
|
||||
|
||||
if (functionCallKind == FunctionCallKind::StructConstructorCall)
|
||||
{
|
||||
TypeType const& type = dynamic_cast<TypeType const&>(*_functionCall.expression().annotation().type);
|
||||
auto const& structType = dynamic_cast<StructType const&>(*type.actualType());
|
||||
|
||||
utils().allocateMemory(max(u256(32u), structType.memoryDataSize()));
|
||||
utils().allocateMemory(std::max(u256(32u), structType.memoryDataSize()));
|
||||
m_context << Instruction::DUP1;
|
||||
|
||||
for (unsigned i = 0; i < arguments.size(); ++i)
|
||||
@ -992,7 +991,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::Error:
|
||||
{
|
||||
_functionCall.expression().accept(*this);
|
||||
vector<Type const*> argumentTypes;
|
||||
std::vector<Type const*> argumentTypes;
|
||||
for (ASTPointer<Expression const> const& arg: _functionCall.sortedArguments())
|
||||
{
|
||||
arg->accept(*this);
|
||||
@ -1060,7 +1059,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::RIPEMD160:
|
||||
{
|
||||
_functionCall.expression().accept(*this);
|
||||
static map<FunctionType::Kind, u256> const contractAddresses{
|
||||
static std::map<FunctionType::Kind, u256> const contractAddresses{
|
||||
{FunctionType::Kind::ECRecover, 1},
|
||||
{FunctionType::Kind::SHA256, 2},
|
||||
{FunctionType::Kind::RIPEMD160, 3}
|
||||
@ -1151,8 +1150,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::BytesConcat:
|
||||
{
|
||||
_functionCall.expression().accept(*this);
|
||||
vector<Type const*> argumentTypes;
|
||||
vector<Type const*> targetTypes;
|
||||
std::vector<Type const*> argumentTypes;
|
||||
std::vector<Type const*> targetTypes;
|
||||
for (auto const& argument: arguments)
|
||||
{
|
||||
argument->accept(*this);
|
||||
@ -1416,7 +1415,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
// stack: <memory pointer> <selector>
|
||||
|
||||
// load current memory, mask and combine the selector
|
||||
string mask = formatNumber((u256(-1) >> 32));
|
||||
std::string mask = formatNumber((u256(-1) >> 32));
|
||||
m_context.appendInlineAssembly(R"({
|
||||
let data_start := add(mem_ptr, 0x20)
|
||||
let data := mload(data_start)
|
||||
@ -1476,7 +1475,7 @@ bool ExpressionCompiler::visit(FunctionCallOptions const& _functionCallOptions)
|
||||
// Desired Stack: [salt], [gas], [value]
|
||||
enum Option { Salt, Gas, Value };
|
||||
|
||||
vector<Option> presentOptions;
|
||||
std::vector<Option> presentOptions;
|
||||
FunctionType const& funType = dynamic_cast<FunctionType const&>(
|
||||
*_functionCallOptions.expression().annotation().type
|
||||
);
|
||||
@ -1486,7 +1485,7 @@ bool ExpressionCompiler::visit(FunctionCallOptions const& _functionCallOptions)
|
||||
|
||||
for (size_t i = 0; i < _functionCallOptions.options().size(); ++i)
|
||||
{
|
||||
string const& name = *_functionCallOptions.names()[i];
|
||||
std::string const& name = *_functionCallOptions.names()[i];
|
||||
Type const* requiredType = TypeProvider::uint256();
|
||||
Option newOption;
|
||||
if (name == "salt")
|
||||
@ -1818,7 +1817,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
);
|
||||
m_context << Instruction::EXTCODEHASH;
|
||||
}
|
||||
else if ((set<string>{"send", "transfer"}).count(member))
|
||||
else if ((std::set<std::string>{"send", "transfer"}).count(member))
|
||||
{
|
||||
solAssert(dynamic_cast<AddressType const&>(*_memberAccess.expression().annotation().type).stateMutability() == StateMutability::Payable, "");
|
||||
utils().convertType(
|
||||
@ -1827,7 +1826,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
true
|
||||
);
|
||||
}
|
||||
else if ((set<string>{"call", "callcode", "delegatecall", "staticcall"}).count(member))
|
||||
else if ((std::set<std::string>{"call", "callcode", "delegatecall", "staticcall"}).count(member))
|
||||
utils().convertType(
|
||||
*_memberAccess.expression().annotation().type,
|
||||
*TypeProvider::address(),
|
||||
@ -1910,7 +1909,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
Whiskers(R"({
|
||||
mstore(start, sub(end, add(start, 0x20)))
|
||||
mstore(<free>, and(add(end, 31), not(31)))
|
||||
})")("free", to_string(CompilerUtils::freeMemoryPointer)).render(),
|
||||
})")("free", std::to_string(CompilerUtils::freeMemoryPointer)).render(),
|
||||
{"start", "end"}
|
||||
);
|
||||
m_context << Instruction::POP;
|
||||
@ -1946,7 +1945,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
solAssert(false, "min/max not available for the given type.");
|
||||
|
||||
}
|
||||
else if ((set<string>{"encode", "encodePacked", "encodeWithSelector", "encodeWithSignature", "decode"}).count(member))
|
||||
else if ((std::set<std::string>{"encode", "encodePacked", "encodeWithSelector", "encodeWithSignature", "decode"}).count(member))
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
@ -1961,7 +1960,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
{
|
||||
case DataLocation::Storage:
|
||||
{
|
||||
pair<u256, unsigned> const& offsets = type.storageOffsetsOfMember(member);
|
||||
std::pair<u256, unsigned> const& offsets = type.storageOffsetsOfMember(member);
|
||||
m_context << offsets.first << Instruction::ADD << u256(offsets.second);
|
||||
setLValueToStorageItem(_memberAccess);
|
||||
break;
|
||||
@ -2454,7 +2453,7 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token _operator, Type cons
|
||||
IntegerType const& type = dynamic_cast<IntegerType const&>(_type);
|
||||
if (m_context.arithmetic() == Arithmetic::Checked)
|
||||
{
|
||||
string functionName;
|
||||
std::string functionName;
|
||||
switch (_operator)
|
||||
{
|
||||
case Token::Add:
|
||||
@ -2620,7 +2619,7 @@ void ExpressionCompiler::appendExpOperatorCode(Type const& _valueType, Type cons
|
||||
|
||||
void ExpressionCompiler::appendExternalFunctionCall(
|
||||
FunctionType const& _functionType,
|
||||
vector<ASTPointer<Expression const>> const& _arguments,
|
||||
std::vector<ASTPointer<Expression const>> const& _arguments,
|
||||
bool _tryCall
|
||||
)
|
||||
{
|
||||
|
@ -30,7 +30,6 @@
|
||||
|
||||
#include <libsolutil/StackTooDeepString.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::evmasm;
|
||||
using namespace solidity::frontend;
|
||||
@ -410,7 +409,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
|
||||
if (sourceType.location() == DataLocation::Storage)
|
||||
{
|
||||
// stack layout: source_ref target_ref
|
||||
pair<u256, unsigned> const& offsets = sourceType.storageOffsetsOfMember(member.name);
|
||||
std::pair<u256, unsigned> const& offsets = sourceType.storageOffsetsOfMember(member.name);
|
||||
m_context << offsets.first << Instruction::DUP3 << Instruction::ADD;
|
||||
m_context << u256(offsets.second);
|
||||
// stack: source_ref target_ref source_member_ref source_member_off
|
||||
@ -427,7 +426,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
|
||||
// stack layout: source_ref target_ref source_value...
|
||||
}
|
||||
unsigned stackSize = sourceMemberType->sizeOnStack();
|
||||
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name);
|
||||
std::pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name);
|
||||
m_context << dupInstruction(1 + stackSize) << offsets.first << Instruction::ADD;
|
||||
m_context << u256(offsets.second);
|
||||
// stack: source_ref target_ref target_off source_value... target_member_ref target_member_byte_off
|
||||
@ -469,7 +468,7 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const
|
||||
Type const* memberType = member.type;
|
||||
if (memberType->category() == Type::Category::Mapping)
|
||||
continue;
|
||||
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name);
|
||||
std::pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name);
|
||||
m_context
|
||||
<< offsets.first << Instruction::DUP3 << Instruction::ADD
|
||||
<< u256(offsets.second);
|
||||
@ -592,7 +591,7 @@ void TupleObject::storeValue(Type const& _sourceType, SourceLocation const& _loc
|
||||
// We will assign from right to left to optimize stack layout.
|
||||
for (size_t i = 0; i < m_lvalues.size(); ++i)
|
||||
{
|
||||
unique_ptr<LValue> const& lvalue = m_lvalues[m_lvalues.size() - i - 1];
|
||||
std::unique_ptr<LValue> const& lvalue = m_lvalues[m_lvalues.size() - i - 1];
|
||||
Type const* valType = valueTypes[valueTypes.size() - i - 1];
|
||||
unsigned stackHeight = m_context.stackHeight();
|
||||
solAssert(!valType == !lvalue, "");
|
||||
|
@ -26,44 +26,43 @@
|
||||
#include <libsolutil/Whiskers.h>
|
||||
#include <libsolutil/StringUtils.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::util;
|
||||
|
||||
string MultiUseYulFunctionCollector::requestedFunctions()
|
||||
std::string MultiUseYulFunctionCollector::requestedFunctions()
|
||||
{
|
||||
string result = std::move(m_code);
|
||||
std::string result = std::move(m_code);
|
||||
m_code.clear();
|
||||
m_requestedFunctions.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
string MultiUseYulFunctionCollector::createFunction(string const& _name, function<string ()> const& _creator)
|
||||
std::string MultiUseYulFunctionCollector::createFunction(std::string const& _name, std::function<std::string()> const& _creator)
|
||||
{
|
||||
if (!m_requestedFunctions.count(_name))
|
||||
{
|
||||
m_requestedFunctions.insert(_name);
|
||||
string fun = _creator();
|
||||
std::string fun = _creator();
|
||||
solAssert(!fun.empty(), "");
|
||||
solAssert(fun.find("function " + _name + "(") != string::npos, "Function not properly named.");
|
||||
solAssert(fun.find("function " + _name + "(") != std::string::npos, "Function not properly named.");
|
||||
m_code += std::move(fun);
|
||||
}
|
||||
return _name;
|
||||
}
|
||||
|
||||
string MultiUseYulFunctionCollector::createFunction(
|
||||
string const& _name,
|
||||
function<string(vector<string>&, vector<string>&)> const& _creator
|
||||
std::string MultiUseYulFunctionCollector::createFunction(
|
||||
std::string const& _name,
|
||||
std::function<std::string(std::vector<std::string>&, std::vector<std::string>&)> const& _creator
|
||||
)
|
||||
{
|
||||
solAssert(!_name.empty(), "");
|
||||
if (!m_requestedFunctions.count(_name))
|
||||
{
|
||||
m_requestedFunctions.insert(_name);
|
||||
vector<string> arguments;
|
||||
vector<string> returnParameters;
|
||||
string body = _creator(arguments, returnParameters);
|
||||
std::vector<std::string> arguments;
|
||||
std::vector<std::string> returnParameters;
|
||||
std::string body = _creator(arguments, returnParameters);
|
||||
solAssert(!body.empty(), "");
|
||||
|
||||
m_code += Whiskers(R"(
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -24,7 +24,6 @@
|
||||
|
||||
#include <libyul/AsmPrinter.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::util;
|
||||
@ -41,110 +40,110 @@ YulArity YulArity::fromType(FunctionType const& _functionType)
|
||||
};
|
||||
}
|
||||
|
||||
string IRNames::externalFunctionABIWrapper(Declaration const& _functionOrVarDecl)
|
||||
std::string IRNames::externalFunctionABIWrapper(Declaration const& _functionOrVarDecl)
|
||||
{
|
||||
if (auto const* function = dynamic_cast<FunctionDefinition const*>(&_functionOrVarDecl))
|
||||
solAssert(!function->isConstructor());
|
||||
|
||||
return "external_fun_" + _functionOrVarDecl.name() + "_" + to_string(_functionOrVarDecl.id());
|
||||
return "external_fun_" + _functionOrVarDecl.name() + "_" + std::to_string(_functionOrVarDecl.id());
|
||||
}
|
||||
|
||||
string IRNames::function(FunctionDefinition const& _function)
|
||||
std::string IRNames::function(FunctionDefinition const& _function)
|
||||
{
|
||||
if (_function.isConstructor())
|
||||
return constructor(*_function.annotation().contract);
|
||||
|
||||
return "fun_" + _function.name() + "_" + to_string(_function.id());
|
||||
return "fun_" + _function.name() + "_" + std::to_string(_function.id());
|
||||
}
|
||||
|
||||
string IRNames::function(VariableDeclaration const& _varDecl)
|
||||
std::string IRNames::function(VariableDeclaration const& _varDecl)
|
||||
{
|
||||
return "getter_fun_" + _varDecl.name() + "_" + to_string(_varDecl.id());
|
||||
return "getter_fun_" + _varDecl.name() + "_" + std::to_string(_varDecl.id());
|
||||
}
|
||||
|
||||
string IRNames::modifierInvocation(ModifierInvocation const& _modifierInvocation)
|
||||
std::string IRNames::modifierInvocation(ModifierInvocation const& _modifierInvocation)
|
||||
{
|
||||
// This uses the ID of the modifier invocation because it has to be unique
|
||||
// for each invocation.
|
||||
solAssert(!_modifierInvocation.name().path().empty(), "");
|
||||
string const& modifierName = _modifierInvocation.name().path().back();
|
||||
std::string const& modifierName = _modifierInvocation.name().path().back();
|
||||
solAssert(!modifierName.empty(), "");
|
||||
return "modifier_" + modifierName + "_" + to_string(_modifierInvocation.id());
|
||||
return "modifier_" + modifierName + "_" + std::to_string(_modifierInvocation.id());
|
||||
}
|
||||
|
||||
string IRNames::functionWithModifierInner(FunctionDefinition const& _function)
|
||||
std::string IRNames::functionWithModifierInner(FunctionDefinition const& _function)
|
||||
{
|
||||
return "fun_" + _function.name() + "_" + to_string(_function.id()) + "_inner";
|
||||
return "fun_" + _function.name() + "_" + std::to_string(_function.id()) + "_inner";
|
||||
}
|
||||
|
||||
string IRNames::creationObject(ContractDefinition const& _contract)
|
||||
std::string IRNames::creationObject(ContractDefinition const& _contract)
|
||||
{
|
||||
return _contract.name() + "_" + toString(_contract.id());
|
||||
}
|
||||
|
||||
string IRNames::deployedObject(ContractDefinition const& _contract)
|
||||
std::string IRNames::deployedObject(ContractDefinition const& _contract)
|
||||
{
|
||||
return _contract.name() + "_" + toString(_contract.id()) + "_deployed";
|
||||
}
|
||||
|
||||
string IRNames::internalDispatch(YulArity const& _arity)
|
||||
std::string IRNames::internalDispatch(YulArity const& _arity)
|
||||
{
|
||||
return "dispatch_internal"
|
||||
"_in_" + to_string(_arity.in) +
|
||||
"_out_" + to_string(_arity.out);
|
||||
"_in_" + std::to_string(_arity.in) +
|
||||
"_out_" + std::to_string(_arity.out);
|
||||
}
|
||||
|
||||
string IRNames::constructor(ContractDefinition const& _contract)
|
||||
std::string IRNames::constructor(ContractDefinition const& _contract)
|
||||
{
|
||||
return "constructor_" + _contract.name() + "_" + to_string(_contract.id());
|
||||
return "constructor_" + _contract.name() + "_" + std::to_string(_contract.id());
|
||||
}
|
||||
|
||||
string IRNames::libraryAddressImmutable()
|
||||
std::string IRNames::libraryAddressImmutable()
|
||||
{
|
||||
return "library_deploy_address";
|
||||
}
|
||||
|
||||
string IRNames::constantValueFunction(VariableDeclaration const& _constant)
|
||||
std::string IRNames::constantValueFunction(VariableDeclaration const& _constant)
|
||||
{
|
||||
solAssert(_constant.isConstant(), "");
|
||||
return "constant_" + _constant.name() + "_" + to_string(_constant.id());
|
||||
return "constant_" + _constant.name() + "_" + std::to_string(_constant.id());
|
||||
}
|
||||
|
||||
string IRNames::localVariable(VariableDeclaration const& _declaration)
|
||||
std::string IRNames::localVariable(VariableDeclaration const& _declaration)
|
||||
{
|
||||
return "var_" + _declaration.name() + '_' + std::to_string(_declaration.id());
|
||||
}
|
||||
|
||||
string IRNames::localVariable(Expression const& _expression)
|
||||
std::string IRNames::localVariable(Expression const& _expression)
|
||||
{
|
||||
return "expr_" + to_string(_expression.id());
|
||||
return "expr_" + std::to_string(_expression.id());
|
||||
}
|
||||
|
||||
string IRNames::trySuccessConditionVariable(Expression const& _expression)
|
||||
std::string IRNames::trySuccessConditionVariable(Expression const& _expression)
|
||||
{
|
||||
auto annotation = dynamic_cast<FunctionCallAnnotation const*>(&_expression.annotation());
|
||||
solAssert(annotation, "");
|
||||
solAssert(annotation->tryCall, "Parameter must be a FunctionCall with tryCall-annotation set.");
|
||||
|
||||
return "trySuccessCondition_" + to_string(_expression.id());
|
||||
return "trySuccessCondition_" + std::to_string(_expression.id());
|
||||
}
|
||||
|
||||
string IRNames::tupleComponent(size_t _i)
|
||||
std::string IRNames::tupleComponent(size_t _i)
|
||||
{
|
||||
return "component_" + to_string(_i + 1);
|
||||
return "component_" + std::to_string(_i + 1);
|
||||
}
|
||||
|
||||
string IRNames::zeroValue(Type const& _type, string const& _variableName)
|
||||
std::string IRNames::zeroValue(Type const& _type, std::string const& _variableName)
|
||||
{
|
||||
return "zero_" + _type.identifier() + _variableName;
|
||||
}
|
||||
|
||||
string dispenseLocationComment(langutil::SourceLocation const& _location, IRGenerationContext& _context)
|
||||
std::string dispenseLocationComment(langutil::SourceLocation const& _location, IRGenerationContext& _context)
|
||||
{
|
||||
solAssert(_location.sourceName, "");
|
||||
_context.markSourceUsed(*_location.sourceName);
|
||||
|
||||
string debugInfo = AsmPrinter::formatSourceLocation(
|
||||
std::string debugInfo = AsmPrinter::formatSourceLocation(
|
||||
_location,
|
||||
_context.sourceIndices(),
|
||||
_context.debugInfoSelection(),
|
||||
@ -154,7 +153,7 @@ string dispenseLocationComment(langutil::SourceLocation const& _location, IRGene
|
||||
return debugInfo.empty() ? "" : "/// " + debugInfo;
|
||||
}
|
||||
|
||||
string dispenseLocationComment(ASTNode const& _node, IRGenerationContext& _context)
|
||||
std::string dispenseLocationComment(ASTNode const& _node, IRGenerationContext& _context)
|
||||
{
|
||||
return dispenseLocationComment(_node.location(), _context);
|
||||
}
|
||||
|
@ -32,14 +32,13 @@
|
||||
|
||||
#include <range/v3/view/map.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
string IRGenerationContext::enqueueFunctionForCodeGeneration(FunctionDefinition const& _function)
|
||||
std::string IRGenerationContext::enqueueFunctionForCodeGeneration(FunctionDefinition const& _function)
|
||||
{
|
||||
string name = IRNames::function(_function);
|
||||
std::string name = IRNames::function(_function);
|
||||
|
||||
if (!m_functions.contains(name))
|
||||
m_functionGenerationQueue.insert(&_function);
|
||||
@ -121,12 +120,12 @@ void IRGenerationContext::addStateVariable(
|
||||
unsigned _byteOffset
|
||||
)
|
||||
{
|
||||
m_stateVariables[&_declaration] = make_pair(std::move(_storageOffset), _byteOffset);
|
||||
m_stateVariables[&_declaration] = std::make_pair(std::move(_storageOffset), _byteOffset);
|
||||
}
|
||||
|
||||
string IRGenerationContext::newYulVariable()
|
||||
std::string IRGenerationContext::newYulVariable()
|
||||
{
|
||||
return "_" + to_string(++m_varCounter);
|
||||
return "_" + std::to_string(++m_varCounter);
|
||||
}
|
||||
|
||||
void IRGenerationContext::initializeInternalDispatch(InternalDispatchMap _internalDispatch)
|
||||
|
@ -43,18 +43,18 @@
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::util;
|
||||
using namespace std::string_literals;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void verifyCallGraph(
|
||||
set<CallableDeclaration const*, ASTNode::CompareByID> const& _expectedCallables,
|
||||
set<FunctionDefinition const*> _generatedFunctions
|
||||
std::set<CallableDeclaration const*, ASTNode::CompareByID> const& _expectedCallables,
|
||||
std::set<FunctionDefinition const*> _generatedFunctions
|
||||
)
|
||||
{
|
||||
for (auto const& expectedCallable: _expectedCallables)
|
||||
@ -73,47 +73,47 @@ void verifyCallGraph(
|
||||
);
|
||||
}
|
||||
|
||||
set<CallableDeclaration const*, ASTNode::CompareByID> collectReachableCallables(
|
||||
std::set<CallableDeclaration const*, ASTNode::CompareByID> collectReachableCallables(
|
||||
CallGraph const& _graph
|
||||
)
|
||||
{
|
||||
set<CallableDeclaration const*, ASTNode::CompareByID> reachableCallables;
|
||||
std::set<CallableDeclaration const*, ASTNode::CompareByID> reachableCallables;
|
||||
for (CallGraph::Node const& reachableNode: _graph.edges | ranges::views::keys)
|
||||
if (holds_alternative<CallableDeclaration const*>(reachableNode))
|
||||
reachableCallables.emplace(get<CallableDeclaration const*>(reachableNode));
|
||||
if (std::holds_alternative<CallableDeclaration const*>(reachableNode))
|
||||
reachableCallables.emplace(std::get<CallableDeclaration const*>(reachableNode));
|
||||
|
||||
return reachableCallables;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
string IRGenerator::run(
|
||||
std::string IRGenerator::run(
|
||||
ContractDefinition const& _contract,
|
||||
bytes const& _cborMetadata,
|
||||
map<ContractDefinition const*, string_view const> const& _otherYulSources
|
||||
std::map<ContractDefinition const*, std::string_view const> const& _otherYulSources
|
||||
)
|
||||
{
|
||||
return yul::reindent(generate(_contract, _cborMetadata, _otherYulSources));
|
||||
}
|
||||
|
||||
string IRGenerator::generate(
|
||||
std::string IRGenerator::generate(
|
||||
ContractDefinition const& _contract,
|
||||
bytes const& _cborMetadata,
|
||||
map<ContractDefinition const*, string_view const> const& _otherYulSources
|
||||
std::map<ContractDefinition const*, std::string_view const> const& _otherYulSources
|
||||
)
|
||||
{
|
||||
auto subObjectSources = [&_otherYulSources](std::set<ContractDefinition const*, ASTNode::CompareByID> const& subObjects) -> string
|
||||
auto subObjectSources = [&_otherYulSources](std::set<ContractDefinition const*, ASTNode::CompareByID> const& subObjects) -> std::string
|
||||
{
|
||||
std::string subObjectsSources;
|
||||
for (ContractDefinition const* subObject: subObjects)
|
||||
subObjectsSources += _otherYulSources.at(subObject);
|
||||
return subObjectsSources;
|
||||
};
|
||||
auto formatUseSrcMap = [](IRGenerationContext const& _context) -> string
|
||||
auto formatUseSrcMap = [](IRGenerationContext const& _context) -> std::string
|
||||
{
|
||||
return joinHumanReadable(
|
||||
ranges::views::transform(_context.usedSourceNames(), [_context](string const& _sourceName) {
|
||||
return to_string(_context.sourceIndices().at(_sourceName)) + ":" + escapeAndQuoteString(_sourceName);
|
||||
ranges::views::transform(_context.usedSourceNames(), [_context](std::string const& _sourceName) {
|
||||
return std::to_string(_context.sourceIndices().at(_sourceName)) + ":" + escapeAndQuoteString(_sourceName);
|
||||
}),
|
||||
", "
|
||||
);
|
||||
@ -162,7 +162,7 @@ string IRGenerator::generate(
|
||||
|
||||
FunctionDefinition const* constructor = _contract.constructor();
|
||||
t("callValueCheck", !constructor || !constructor->isPayable() ? callValueCheck() : "");
|
||||
vector<string> constructorParams;
|
||||
std::vector<std::string> constructorParams;
|
||||
if (constructor && !constructor->parameters().empty())
|
||||
{
|
||||
for (size_t i = 0; i < CompilerUtils::sizeOnStack(constructor->parameters()); ++i)
|
||||
@ -178,7 +178,7 @@ string IRGenerator::generate(
|
||||
|
||||
t("deploy", deployCode(_contract));
|
||||
generateConstructors(_contract);
|
||||
set<FunctionDefinition const*> creationFunctionList = generateQueuedFunctions();
|
||||
std::set<FunctionDefinition const*> creationFunctionList = generateQueuedFunctions();
|
||||
InternalDispatchMap internalDispatchMap = generateInternalDispatchFunctions(_contract);
|
||||
|
||||
t("functions", m_context.functionCollector().requestedFunctions());
|
||||
@ -201,7 +201,7 @@ string IRGenerator::generate(
|
||||
t("sourceLocationCommentDeployed", dispenseLocationComment(_contract));
|
||||
t("library_address", IRNames::libraryAddressImmutable());
|
||||
t("dispatch", dispatchRoutine(_contract));
|
||||
set<FunctionDefinition const*> deployedFunctionList = generateQueuedFunctions();
|
||||
std::set<FunctionDefinition const*> deployedFunctionList = generateQueuedFunctions();
|
||||
generateInternalDispatchFunctions(_contract);
|
||||
t("deployedFunctions", m_context.functionCollector().requestedFunctions());
|
||||
t("deployedSubObjects", subObjectSources(m_context.subObjectsCreated()));
|
||||
@ -222,16 +222,16 @@ string IRGenerator::generate(
|
||||
return t.render();
|
||||
}
|
||||
|
||||
string IRGenerator::generate(Block const& _block)
|
||||
std::string IRGenerator::generate(Block const& _block)
|
||||
{
|
||||
IRGeneratorForStatements generator(m_context, m_utils);
|
||||
generator.generate(_block);
|
||||
return generator.code();
|
||||
}
|
||||
|
||||
set<FunctionDefinition const*> IRGenerator::generateQueuedFunctions()
|
||||
std::set<FunctionDefinition const*> IRGenerator::generateQueuedFunctions()
|
||||
{
|
||||
set<FunctionDefinition const*> functions;
|
||||
std::set<FunctionDefinition const*> functions;
|
||||
|
||||
while (!m_context.functionGenerationQueueEmpty())
|
||||
{
|
||||
@ -256,7 +256,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
|
||||
InternalDispatchMap internalDispatchMap = m_context.consumeInternalDispatchMap();
|
||||
for (YulArity const& arity: internalDispatchMap | ranges::views::keys)
|
||||
{
|
||||
string funName = IRNames::internalDispatch(arity);
|
||||
std::string funName = IRNames::internalDispatch(arity);
|
||||
m_context.functionCollector().createFunction(funName, [&]() {
|
||||
Whiskers templ(R"(
|
||||
<sourceLocationComment>
|
||||
@ -278,7 +278,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
|
||||
templ("in", suffixedVariableNameList("in_", 0, arity.in));
|
||||
templ("out", suffixedVariableNameList("out_", 0, arity.out));
|
||||
|
||||
vector<map<string, string>> cases;
|
||||
std::vector<std::map<std::string, std::string>> cases;
|
||||
for (FunctionDefinition const* function: internalDispatchMap.at(arity))
|
||||
{
|
||||
solAssert(function, "");
|
||||
@ -291,8 +291,8 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
|
||||
solAssert(function->id() != 0, "Unexpected function ID: 0");
|
||||
solAssert(m_context.functionCollector().contains(IRNames::function(*function)), "");
|
||||
|
||||
cases.emplace_back(map<string, string>{
|
||||
{"funID", to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(function))},
|
||||
cases.emplace_back(std::map<std::string, std::string>{
|
||||
{"funID", std::to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(function))},
|
||||
{"name", IRNames::function(*function)}
|
||||
});
|
||||
}
|
||||
@ -311,9 +311,9 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
|
||||
return internalDispatchMap;
|
||||
}
|
||||
|
||||
string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
||||
std::string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
||||
{
|
||||
string functionName = IRNames::function(_function);
|
||||
std::string functionName = IRNames::function(_function);
|
||||
return m_context.functionCollector().createFunction(functionName, [&]() {
|
||||
m_context.resetLocalVariables();
|
||||
Whiskers t(R"(
|
||||
@ -326,7 +326,7 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
||||
)");
|
||||
|
||||
if (m_context.debugInfoSelection().astID)
|
||||
t("astIDComment", "/// @ast-id " + to_string(_function.id()) + "\n");
|
||||
t("astIDComment", "/// @ast-id " + std::to_string(_function.id()) + "\n");
|
||||
else
|
||||
t("astIDComment", "");
|
||||
t("sourceLocationComment", dispenseLocationComment(_function));
|
||||
@ -336,12 +336,12 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
||||
);
|
||||
|
||||
t("functionName", functionName);
|
||||
vector<string> params;
|
||||
std::vector<std::string> params;
|
||||
for (auto const& varDecl: _function.parameters())
|
||||
params += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
t("params", joinHumanReadable(params));
|
||||
vector<string> retParams;
|
||||
string retInit;
|
||||
std::vector<std::string> retParams;
|
||||
std::string retInit;
|
||||
for (auto const& varDecl: _function.returnParameters())
|
||||
{
|
||||
retParams += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
@ -358,14 +358,14 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
||||
for (size_t i = 0; i < _function.modifiers().size(); ++i)
|
||||
{
|
||||
ModifierInvocation const& modifier = *_function.modifiers().at(i);
|
||||
string next =
|
||||
std::string next =
|
||||
i + 1 < _function.modifiers().size() ?
|
||||
IRNames::modifierInvocation(*_function.modifiers().at(i + 1)) :
|
||||
IRNames::functionWithModifierInner(_function);
|
||||
generateModifier(modifier, _function, next);
|
||||
}
|
||||
t("body",
|
||||
(retParams.empty() ? string{} : joinHumanReadable(retParams) + " := ") +
|
||||
(retParams.empty() ? std::string{} : joinHumanReadable(retParams) + " := ") +
|
||||
IRNames::modifierInvocation(*_function.modifiers().at(0)) +
|
||||
"(" +
|
||||
joinHumanReadable(retParams + params) +
|
||||
@ -378,13 +378,13 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
||||
});
|
||||
}
|
||||
|
||||
string IRGenerator::generateModifier(
|
||||
std::string IRGenerator::generateModifier(
|
||||
ModifierInvocation const& _modifierInvocation,
|
||||
FunctionDefinition const& _function,
|
||||
string const& _nextFunction
|
||||
std::string const& _nextFunction
|
||||
)
|
||||
{
|
||||
string functionName = IRNames::modifierInvocation(_modifierInvocation);
|
||||
std::string functionName = IRNames::modifierInvocation(_modifierInvocation);
|
||||
return m_context.functionCollector().createFunction(functionName, [&]() {
|
||||
m_context.resetLocalVariables();
|
||||
Whiskers t(R"(
|
||||
@ -398,15 +398,15 @@ string IRGenerator::generateModifier(
|
||||
)");
|
||||
|
||||
t("functionName", functionName);
|
||||
vector<string> retParamsIn;
|
||||
std::vector<std::string> retParamsIn;
|
||||
for (auto const& varDecl: _function.returnParameters())
|
||||
retParamsIn += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
vector<string> params = retParamsIn;
|
||||
std::vector<std::string> params = retParamsIn;
|
||||
for (auto const& varDecl: _function.parameters())
|
||||
params += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
t("params", joinHumanReadable(params));
|
||||
vector<string> retParams;
|
||||
string assignRetParams;
|
||||
std::vector<std::string> retParams;
|
||||
std::string assignRetParams;
|
||||
for (size_t i = 0; i < retParamsIn.size(); ++i)
|
||||
{
|
||||
retParams.emplace_back(m_context.newYulVariable());
|
||||
@ -421,7 +421,7 @@ string IRGenerator::generateModifier(
|
||||
solAssert(modifier, "");
|
||||
|
||||
if (m_context.debugInfoSelection().astID)
|
||||
t("astIDComment", "/// @ast-id " + to_string(modifier->id()) + "\n");
|
||||
t("astIDComment", "/// @ast-id " + std::to_string(modifier->id()) + "\n");
|
||||
else
|
||||
t("astIDComment", "");
|
||||
t("sourceLocationComment", dispenseLocationComment(*modifier));
|
||||
@ -463,7 +463,7 @@ string IRGenerator::generateModifier(
|
||||
|
||||
t("evalArgs", expressionEvaluator.code());
|
||||
IRGeneratorForStatements generator(m_context, m_utils, [&]() {
|
||||
string ret = joinHumanReadable(retParams);
|
||||
std::string ret = joinHumanReadable(retParams);
|
||||
return
|
||||
(ret.empty() ? "" : ret + " := ") +
|
||||
_nextFunction + "(" + joinHumanReadable(params) + ")\n";
|
||||
@ -474,9 +474,9 @@ string IRGenerator::generateModifier(
|
||||
});
|
||||
}
|
||||
|
||||
string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition const& _function)
|
||||
std::string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition const& _function)
|
||||
{
|
||||
string functionName = IRNames::functionWithModifierInner(_function);
|
||||
std::string functionName = IRNames::functionWithModifierInner(_function);
|
||||
return m_context.functionCollector().createFunction(functionName, [&]() {
|
||||
m_context.resetLocalVariables();
|
||||
Whiskers t(R"(
|
||||
@ -493,17 +493,17 @@ string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition const&
|
||||
dispenseLocationComment(m_context.mostDerivedContract())
|
||||
);
|
||||
t("functionName", functionName);
|
||||
vector<string> retParams;
|
||||
vector<string> retParamsIn;
|
||||
std::vector<std::string> retParams;
|
||||
std::vector<std::string> retParamsIn;
|
||||
for (auto const& varDecl: _function.returnParameters())
|
||||
retParams += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
string assignRetParams;
|
||||
std::string assignRetParams;
|
||||
for (size_t i = 0; i < retParams.size(); ++i)
|
||||
{
|
||||
retParamsIn.emplace_back(m_context.newYulVariable());
|
||||
assignRetParams += retParams.at(i) + " := " + retParamsIn.at(i) + "\n";
|
||||
}
|
||||
vector<string> params = retParamsIn;
|
||||
std::vector<std::string> params = retParamsIn;
|
||||
for (auto const& varDecl: _function.parameters())
|
||||
params += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
t("params", joinHumanReadable(params));
|
||||
@ -514,9 +514,9 @@ string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition const&
|
||||
});
|
||||
}
|
||||
|
||||
string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
{
|
||||
string functionName = IRNames::function(_varDecl);
|
||||
std::string functionName = IRNames::function(_varDecl);
|
||||
return m_context.functionCollector().createFunction(functionName, [&]() {
|
||||
Type const* type = _varDecl.annotation().type;
|
||||
|
||||
@ -538,7 +538,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
(
|
||||
"astIDComment",
|
||||
m_context.debugInfoSelection().astID ?
|
||||
"/// @ast-id " + to_string(_varDecl.id()) + "\n" :
|
||||
"/// @ast-id " + std::to_string(_varDecl.id()) + "\n" :
|
||||
""
|
||||
)
|
||||
("sourceLocationComment", dispenseLocationComment(_varDecl))
|
||||
@ -547,7 +547,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
dispenseLocationComment(m_context.mostDerivedContract())
|
||||
)
|
||||
("functionName", functionName)
|
||||
("id", to_string(_varDecl.id()))
|
||||
("id", std::to_string(_varDecl.id()))
|
||||
.render();
|
||||
}
|
||||
else if (_varDecl.isConstant())
|
||||
@ -563,7 +563,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
(
|
||||
"astIDComment",
|
||||
m_context.debugInfoSelection().astID ?
|
||||
"/// @ast-id " + to_string(_varDecl.id()) + "\n" :
|
||||
"/// @ast-id " + std::to_string(_varDecl.id()) + "\n" :
|
||||
""
|
||||
)
|
||||
("sourceLocationComment", dispenseLocationComment(_varDecl))
|
||||
@ -577,7 +577,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
.render();
|
||||
}
|
||||
|
||||
string code;
|
||||
std::string code;
|
||||
|
||||
auto const& location = m_context.storageLocationOfStateVariable(_varDecl);
|
||||
code += Whiskers(R"(
|
||||
@ -585,7 +585,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
let offset := <offset>
|
||||
)")
|
||||
("slot", location.first.str())
|
||||
("offset", to_string(location.second))
|
||||
("offset", std::to_string(location.second))
|
||||
.render();
|
||||
|
||||
if (!paramTypes.empty())
|
||||
@ -601,8 +601,8 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
// The initial value of @a currentType is only used if we skip the loop completely.
|
||||
Type const* currentType = _varDecl.annotation().type;
|
||||
|
||||
vector<string> parameters;
|
||||
vector<string> returnVariables;
|
||||
std::vector<std::string> parameters;
|
||||
std::vector<std::string> returnVariables;
|
||||
|
||||
for (size_t i = 0; i < paramTypes.size(); ++i)
|
||||
{
|
||||
@ -610,7 +610,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
ArrayType const* arrayType = dynamic_cast<ArrayType const*>(currentType);
|
||||
solAssert(mappingType || arrayType, "");
|
||||
|
||||
vector<string> keys = IRVariable("key_" + to_string(i),
|
||||
std::vector<std::string> keys = IRVariable("key_" + std::to_string(i),
|
||||
mappingType ? *mappingType->keyType() : *TypeProvider::uint256()
|
||||
).stackSlots();
|
||||
parameters += keys;
|
||||
@ -653,8 +653,8 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
)
|
||||
continue;
|
||||
|
||||
pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
|
||||
vector<string> retVars = IRVariable("ret_" + to_string(returnVariables.size()), *returnTypes[i]).stackSlots();
|
||||
std::pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
|
||||
std::vector<std::string> retVars = IRVariable("ret_" + std::to_string(returnVariables.size()), *returnTypes[i]).stackSlots();
|
||||
returnVariables += retVars;
|
||||
code += Whiskers(R"(
|
||||
<ret> := <readStorage>(add(slot, <slotOffset>))
|
||||
@ -671,7 +671,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
auto const* arrayType = dynamic_cast<ArrayType const*>(returnTypes.front());
|
||||
if (arrayType)
|
||||
solAssert(arrayType->isByteArrayOrString(), "");
|
||||
vector<string> retVars = IRVariable("ret", *returnTypes.front()).stackSlots();
|
||||
std::vector<std::string> retVars = IRVariable("ret", *returnTypes.front()).stackSlots();
|
||||
returnVariables += retVars;
|
||||
code += Whiskers(R"(
|
||||
<ret> := <readStorage>(slot, offset)
|
||||
@ -695,7 +695,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
(
|
||||
"astIDComment",
|
||||
m_context.debugInfoSelection().astID ?
|
||||
"/// @ast-id " + to_string(_varDecl.id()) + "\n" :
|
||||
"/// @ast-id " + std::to_string(_varDecl.id()) + "\n" :
|
||||
""
|
||||
)
|
||||
("sourceLocationComment", dispenseLocationComment(_varDecl))
|
||||
@ -707,10 +707,10 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
});
|
||||
}
|
||||
|
||||
string IRGenerator::generateExternalFunction(ContractDefinition const& _contract, FunctionType const& _functionType)
|
||||
std::string IRGenerator::generateExternalFunction(ContractDefinition const& _contract, FunctionType const& _functionType)
|
||||
{
|
||||
string functionName = IRNames::externalFunctionABIWrapper(_functionType.declaration());
|
||||
return m_context.functionCollector().createFunction(functionName, [&](vector<string>&, vector<string>&) -> string {
|
||||
std::string functionName = IRNames::externalFunctionABIWrapper(_functionType.declaration());
|
||||
return m_context.functionCollector().createFunction(functionName, [&](std::vector<std::string>&, std::vector<std::string>&) -> std::string {
|
||||
Whiskers t(R"X(
|
||||
<callValueCheck>
|
||||
<?+params>let <params> := </+params> <abiDecode>(4, calldatasize())
|
||||
@ -721,8 +721,8 @@ string IRGenerator::generateExternalFunction(ContractDefinition const& _contract
|
||||
)X");
|
||||
t("callValueCheck", (_functionType.isPayable() || _contract.isLibrary()) ? "" : callValueCheck());
|
||||
|
||||
unsigned paramVars = make_shared<TupleType>(_functionType.parameterTypes())->sizeOnStack();
|
||||
unsigned retVars = make_shared<TupleType>(_functionType.returnParameterTypes())->sizeOnStack();
|
||||
unsigned paramVars = std::make_shared<TupleType>(_functionType.parameterTypes())->sizeOnStack();
|
||||
unsigned retVars = std::make_shared<TupleType>(_functionType.returnParameterTypes())->sizeOnStack();
|
||||
|
||||
ABIFunctions abiFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector());
|
||||
t("abiDecode", abiFunctions.tupleDecoder(_functionType.parameterTypes()));
|
||||
@ -745,14 +745,14 @@ string IRGenerator::generateExternalFunction(ContractDefinition const& _contract
|
||||
});
|
||||
}
|
||||
|
||||
string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDecl)
|
||||
std::string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDecl)
|
||||
{
|
||||
IRGeneratorForStatements generator(m_context, m_utils);
|
||||
generator.initializeLocalVar(_varDecl);
|
||||
return generator.code();
|
||||
}
|
||||
|
||||
pair<string, map<ContractDefinition const*, vector<string>>> IRGenerator::evaluateConstructorArguments(
|
||||
std::pair<std::string, std::map<ContractDefinition const*, std::vector<std::string>>> IRGenerator::evaluateConstructorArguments(
|
||||
ContractDefinition const& _contract
|
||||
)
|
||||
{
|
||||
@ -765,12 +765,12 @@ pair<string, map<ContractDefinition const*, vector<string>>> IRGenerator::evalua
|
||||
auto it2 = find(linearizedBaseContracts.begin(), linearizedBaseContracts.end(), _c2);
|
||||
return it1 < it2;
|
||||
}
|
||||
vector<ContractDefinition const*> const& linearizedBaseContracts;
|
||||
std::vector<ContractDefinition const*> const& linearizedBaseContracts;
|
||||
} inheritanceOrder{_contract.annotation().linearizedBaseContracts};
|
||||
|
||||
map<ContractDefinition const*, vector<string>> constructorParams;
|
||||
std::map<ContractDefinition const*, std::vector<std::string>> constructorParams;
|
||||
|
||||
map<ContractDefinition const*, std::vector<ASTPointer<Expression>>const *, InheritanceOrder>
|
||||
std::map<ContractDefinition const*, std::vector<ASTPointer<Expression>>const *, InheritanceOrder>
|
||||
baseConstructorArguments(inheritanceOrder);
|
||||
|
||||
for (ASTPointer<InheritanceSpecifier> const& base: _contract.baseContracts())
|
||||
@ -802,7 +802,7 @@ pair<string, map<ContractDefinition const*, vector<string>>> IRGenerator::evalua
|
||||
solAssert(baseContract && arguments, "");
|
||||
if (baseContract->constructor() && !arguments->empty())
|
||||
{
|
||||
vector<string> params;
|
||||
std::vector<std::string> params;
|
||||
for (size_t i = 0; i < arguments->size(); ++i)
|
||||
params += generator.evaluateExpression(
|
||||
*(arguments->at(i)),
|
||||
@ -815,7 +815,7 @@ pair<string, map<ContractDefinition const*, vector<string>>> IRGenerator::evalua
|
||||
return {generator.code(), constructorParams};
|
||||
}
|
||||
|
||||
string IRGenerator::initStateVariables(ContractDefinition const& _contract)
|
||||
std::string IRGenerator::initStateVariables(ContractDefinition const& _contract)
|
||||
{
|
||||
IRGeneratorForStatements generator{m_context, m_utils};
|
||||
for (VariableDeclaration const* variable: _contract.stateVariables())
|
||||
@ -829,16 +829,16 @@ string IRGenerator::initStateVariables(ContractDefinition const& _contract)
|
||||
void IRGenerator::generateConstructors(ContractDefinition const& _contract)
|
||||
{
|
||||
auto listAllParams =
|
||||
[&](map<ContractDefinition const*, vector<string>> const& baseParams) -> vector<string>
|
||||
[&](std::map<ContractDefinition const*, std::vector<std::string>> const& baseParams) -> std::vector<std::string>
|
||||
{
|
||||
vector<string> params;
|
||||
std::vector<std::string> params;
|
||||
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
|
||||
if (baseParams.count(contract))
|
||||
params += baseParams.at(contract);
|
||||
return params;
|
||||
};
|
||||
|
||||
map<ContractDefinition const*, vector<string>> baseConstructorParams;
|
||||
std::map<ContractDefinition const*, std::vector<std::string>> baseConstructorParams;
|
||||
for (size_t i = 0; i < _contract.annotation().linearizedBaseContracts.size(); ++i)
|
||||
{
|
||||
ContractDefinition const* contract = _contract.annotation().linearizedBaseContracts[i];
|
||||
@ -857,13 +857,13 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
|
||||
}
|
||||
<contractSourceLocationComment>
|
||||
)");
|
||||
vector<string> params;
|
||||
std::vector<std::string> params;
|
||||
if (contract->constructor())
|
||||
for (ASTPointer<VariableDeclaration> const& varDecl: contract->constructor()->parameters())
|
||||
params += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
|
||||
if (m_context.debugInfoSelection().astID && contract->constructor())
|
||||
t("astIDComment", "/// @ast-id " + to_string(contract->constructor()->id()) + "\n");
|
||||
t("astIDComment", "/// @ast-id " + std::to_string(contract->constructor()->id()) + "\n");
|
||||
else
|
||||
t("astIDComment", "");
|
||||
t("sourceLocationComment", dispenseLocationComment(
|
||||
@ -877,11 +877,11 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
|
||||
);
|
||||
|
||||
t("params", joinHumanReadable(params));
|
||||
vector<string> baseParams = listAllParams(baseConstructorParams);
|
||||
std::vector<std::string> baseParams = listAllParams(baseConstructorParams);
|
||||
t("baseParams", joinHumanReadable(baseParams));
|
||||
t("comma", !params.empty() && !baseParams.empty() ? ", " : "");
|
||||
t("functionName", IRNames::constructor(*contract));
|
||||
pair<string, map<ContractDefinition const*, vector<string>>> evaluatedArgs = evaluateConstructorArguments(*contract);
|
||||
std::pair<std::string, std::map<ContractDefinition const*, std::vector<std::string>>> evaluatedArgs = evaluateConstructorArguments(*contract);
|
||||
baseConstructorParams.insert(evaluatedArgs.second.begin(), evaluatedArgs.second.end());
|
||||
t("evalBaseArguments", evaluatedArgs.first);
|
||||
if (i < _contract.annotation().linearizedBaseContracts.size() - 1)
|
||||
@ -894,10 +894,10 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
|
||||
else
|
||||
t("hasNextConstructor", false);
|
||||
t("initStateVariables", initStateVariables(*contract));
|
||||
string body;
|
||||
std::string body;
|
||||
if (FunctionDefinition const* constructor = contract->constructor())
|
||||
{
|
||||
vector<ModifierInvocation*> realModifiers;
|
||||
std::vector<ModifierInvocation*> realModifiers;
|
||||
for (auto const& modifierInvocation: constructor->modifiers())
|
||||
// Filter out the base constructor calls
|
||||
if (dynamic_cast<ModifierDefinition const*>(modifierInvocation->name().annotation().referencedDeclaration))
|
||||
@ -909,7 +909,7 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
|
||||
for (size_t i = 0; i < realModifiers.size(); ++i)
|
||||
{
|
||||
ModifierInvocation const& modifier = *realModifiers.at(i);
|
||||
string next =
|
||||
std::string next =
|
||||
i + 1 < realModifiers.size() ?
|
||||
IRNames::modifierInvocation(*realModifiers.at(i + 1)) :
|
||||
IRNames::functionWithModifierInner(*constructor);
|
||||
@ -931,7 +931,7 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
|
||||
}
|
||||
}
|
||||
|
||||
string IRGenerator::deployCode(ContractDefinition const& _contract)
|
||||
std::string IRGenerator::deployCode(ContractDefinition const& _contract)
|
||||
{
|
||||
Whiskers t(R"X(
|
||||
let <codeOffset> := <allocateUnbounded>()
|
||||
@ -945,11 +945,11 @@ string IRGenerator::deployCode(ContractDefinition const& _contract)
|
||||
t("codeOffset", m_context.newYulVariable());
|
||||
t("object", IRNames::deployedObject(_contract));
|
||||
|
||||
vector<map<string, string>> immutables;
|
||||
std::vector<std::map<std::string, std::string>> immutables;
|
||||
if (_contract.isLibrary())
|
||||
{
|
||||
solAssert(ContractType(_contract).immutableVariables().empty(), "");
|
||||
immutables.emplace_back(map<string, string>{
|
||||
immutables.emplace_back(std::map<std::string, std::string>{
|
||||
{"immutableName"s, IRNames::libraryAddressImmutable()},
|
||||
{"value"s, "address()"}
|
||||
});
|
||||
@ -960,21 +960,21 @@ string IRGenerator::deployCode(ContractDefinition const& _contract)
|
||||
{
|
||||
solUnimplementedAssert(immutable->type()->isValueType());
|
||||
solUnimplementedAssert(immutable->type()->sizeOnStack() == 1);
|
||||
immutables.emplace_back(map<string, string>{
|
||||
{"immutableName"s, to_string(immutable->id())},
|
||||
{"value"s, "mload(" + to_string(m_context.immutableMemoryOffset(*immutable)) + ")"}
|
||||
immutables.emplace_back(std::map<std::string, std::string>{
|
||||
{"immutableName"s, std::to_string(immutable->id())},
|
||||
{"value"s, "mload(" + std::to_string(m_context.immutableMemoryOffset(*immutable)) + ")"}
|
||||
});
|
||||
}
|
||||
t("immutables", std::move(immutables));
|
||||
return t.render();
|
||||
}
|
||||
|
||||
string IRGenerator::callValueCheck()
|
||||
std::string IRGenerator::callValueCheck()
|
||||
{
|
||||
return "if callvalue() { " + m_utils.revertReasonIfDebugFunction("Ether sent to non-payable function") + "() }";
|
||||
}
|
||||
|
||||
string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
|
||||
std::string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
|
||||
{
|
||||
Whiskers t(R"X(
|
||||
<?+cases>if iszero(lt(calldatasize(), 4))
|
||||
@ -995,15 +995,15 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
|
||||
<fallback>
|
||||
)X");
|
||||
t("shr224", m_utils.shiftRightFunction(224));
|
||||
vector<map<string, string>> functions;
|
||||
std::vector<std::map<std::string, std::string>> functions;
|
||||
for (auto const& function: _contract.interfaceFunctions())
|
||||
{
|
||||
functions.emplace_back();
|
||||
map<string, string>& templ = functions.back();
|
||||
std::map<std::string, std::string>& templ = functions.back();
|
||||
templ["functionSelector"] = "0x" + function.first.hex();
|
||||
FunctionTypePointer const& type = function.second;
|
||||
templ["functionName"] = type->externalSignature();
|
||||
string delegatecallCheck;
|
||||
std::string delegatecallCheck;
|
||||
if (_contract.isLibrary())
|
||||
{
|
||||
solAssert(!type->isPayable(), "");
|
||||
@ -1031,7 +1031,7 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
|
||||
if (FunctionDefinition const* fallback = _contract.fallbackFunction())
|
||||
{
|
||||
solAssert(!_contract.isLibrary(), "");
|
||||
string fallbackCode;
|
||||
std::string fallbackCode;
|
||||
if (!fallback->isPayable())
|
||||
fallbackCode += callValueCheck() + "\n";
|
||||
if (fallback->parameters().empty())
|
||||
@ -1055,7 +1055,7 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
|
||||
return t.render();
|
||||
}
|
||||
|
||||
string IRGenerator::memoryInit(bool _useMemoryGuard)
|
||||
std::string IRGenerator::memoryInit(bool _useMemoryGuard)
|
||||
{
|
||||
// This function should be called at the beginning of the EVM call frame
|
||||
// and thus can assume all memory to be zero, including the contents of
|
||||
@ -1066,10 +1066,10 @@ string IRGenerator::memoryInit(bool _useMemoryGuard)
|
||||
"mstore(<memPtr>, memoryguard(<freeMemoryStart>))" :
|
||||
"mstore(<memPtr>, <freeMemoryStart>)"
|
||||
}
|
||||
("memPtr", to_string(CompilerUtils::freeMemoryPointer))
|
||||
("memPtr", std::to_string(CompilerUtils::freeMemoryPointer))
|
||||
(
|
||||
"freeMemoryStart",
|
||||
to_string(CompilerUtils::generalPurposeMemoryStart + m_context.reservedMemory())
|
||||
std::to_string(CompilerUtils::generalPurposeMemoryStart + m_context.reservedMemory())
|
||||
).render();
|
||||
}
|
||||
|
||||
@ -1099,10 +1099,10 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon
|
||||
|
||||
m_context.setMostDerivedContract(_contract);
|
||||
for (auto const& var: ContractType(_contract).stateVariables())
|
||||
m_context.addStateVariable(*get<0>(var), get<1>(var), get<2>(var));
|
||||
m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var));
|
||||
}
|
||||
|
||||
string IRGenerator::dispenseLocationComment(ASTNode const& _node)
|
||||
std::string IRGenerator::dispenseLocationComment(ASTNode const& _node)
|
||||
{
|
||||
return ::dispenseLocationComment(_node, m_context);
|
||||
}
|
||||
|
@ -49,7 +49,6 @@
|
||||
|
||||
#include <range/v3/view/transform.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::frontend;
|
||||
@ -95,8 +94,8 @@ struct CopyTranslate: public yul::ASTCopier
|
||||
return ASTCopier::translate(_identifier);
|
||||
|
||||
yul::Expression translated = translateReference(_identifier);
|
||||
solAssert(holds_alternative<yul::Identifier>(translated));
|
||||
return get<yul::Identifier>(std::move(translated));
|
||||
solAssert(std::holds_alternative<yul::Identifier>(translated));
|
||||
return std::get<yul::Identifier>(std::move(translated));
|
||||
}
|
||||
|
||||
private:
|
||||
@ -109,9 +108,9 @@ private:
|
||||
auto const& reference = m_references.at(&_identifier);
|
||||
auto const varDecl = dynamic_cast<VariableDeclaration const*>(reference.declaration);
|
||||
solUnimplementedAssert(varDecl);
|
||||
string const& suffix = reference.suffix;
|
||||
std::string const& suffix = reference.suffix;
|
||||
|
||||
string value;
|
||||
std::string value;
|
||||
if (suffix.empty() && varDecl->isLocalVariable())
|
||||
{
|
||||
auto const& var = m_context.localVariable(*varDecl);
|
||||
@ -165,7 +164,7 @@ private:
|
||||
if (suffix == "slot")
|
||||
value = m_context.storageLocationOfStateVariable(*varDecl).first.str();
|
||||
else if (suffix == "offset")
|
||||
value = to_string(m_context.storageLocationOfStateVariable(*varDecl).second);
|
||||
value = std::to_string(m_context.storageLocationOfStateVariable(*varDecl).second);
|
||||
else
|
||||
solAssert(false);
|
||||
}
|
||||
@ -216,7 +215,7 @@ private:
|
||||
|
||||
}
|
||||
|
||||
string IRGeneratorForStatementsBase::code() const
|
||||
std::string IRGeneratorForStatementsBase::code() const
|
||||
{
|
||||
return m_code.str();
|
||||
}
|
||||
@ -240,7 +239,7 @@ void IRGeneratorForStatementsBase::setLocation(ASTNode const& _node)
|
||||
m_currentLocation = _node.location();
|
||||
}
|
||||
|
||||
string IRGeneratorForStatements::code() const
|
||||
std::string IRGeneratorForStatements::code() const
|
||||
{
|
||||
solAssert(!m_currentLValue, "LValue not reset!");
|
||||
return IRGeneratorForStatementsBase::code();
|
||||
@ -338,11 +337,11 @@ IRVariable IRGeneratorForStatements::evaluateExpression(Expression const& _expre
|
||||
}
|
||||
}
|
||||
|
||||
string IRGeneratorForStatements::constantValueFunction(VariableDeclaration const& _constant)
|
||||
std::string IRGeneratorForStatements::constantValueFunction(VariableDeclaration const& _constant)
|
||||
{
|
||||
try
|
||||
{
|
||||
string functionName = IRNames::constantValueFunction(_constant);
|
||||
std::string functionName = IRNames::constantValueFunction(_constant);
|
||||
return m_context.functionCollector().createFunction(functionName, [&] {
|
||||
Whiskers templ(R"(
|
||||
<sourceLocationComment>
|
||||
@ -410,7 +409,7 @@ bool IRGeneratorForStatements::visit(Conditional const& _conditional)
|
||||
|
||||
setLocation(_conditional);
|
||||
|
||||
string condition = expressionAsType(_conditional.condition(), *TypeProvider::boolean());
|
||||
std::string condition = expressionAsType(_conditional.condition(), *TypeProvider::boolean());
|
||||
declare(_conditional);
|
||||
|
||||
appendCode() << "switch " << condition << "\n" "case 0 {\n";
|
||||
@ -501,7 +500,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple)
|
||||
_tuple.components().size() <<
|
||||
")\n";
|
||||
|
||||
string mpos = IRVariable(_tuple).part("mpos").name();
|
||||
std::string mpos = IRVariable(_tuple).part("mpos").name();
|
||||
Type const& baseType = *arrayType.baseType();
|
||||
for (size_t i = 0; i < _tuple.components().size(); i++)
|
||||
{
|
||||
@ -512,7 +511,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple)
|
||||
appendCode() <<
|
||||
m_utils.writeToMemoryFunction(baseType) <<
|
||||
"(" <<
|
||||
("add(" + mpos + ", " + to_string(i * arrayType.memoryStride()) + ")") <<
|
||||
("add(" + mpos + ", " + std::to_string(i * arrayType.memoryStride()) + ")") <<
|
||||
", " <<
|
||||
converted.commaSeparatedList() <<
|
||||
")\n";
|
||||
@ -535,7 +534,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple)
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<optional<IRLValue>> lvalues;
|
||||
std::vector<std::optional<IRLValue>> lvalues;
|
||||
for (size_t i = 0; i < _tuple.components().size(); ++i)
|
||||
if (auto const& component = _tuple.components()[i])
|
||||
{
|
||||
@ -586,7 +585,7 @@ bool IRGeneratorForStatements::visit(IfStatement const& _ifStatement)
|
||||
{
|
||||
_ifStatement.condition().accept(*this);
|
||||
setLocation(_ifStatement);
|
||||
string condition = expressionAsType(_ifStatement.condition(), *TypeProvider::boolean());
|
||||
std::string condition = expressionAsType(_ifStatement.condition(), *TypeProvider::boolean());
|
||||
|
||||
if (_ifStatement.falseStatement())
|
||||
{
|
||||
@ -658,7 +657,7 @@ void IRGeneratorForStatements::endVisit(Return const& _return)
|
||||
if (Expression const* value = _return.expression())
|
||||
{
|
||||
solAssert(_return.annotation().functionReturnParameters, "Invalid return parameters pointer.");
|
||||
vector<ASTPointer<VariableDeclaration>> const& returnParameters =
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& returnParameters =
|
||||
_return.annotation().functionReturnParameters->parameters();
|
||||
if (returnParameters.size() > 1)
|
||||
for (size_t i = 0; i < returnParameters.size(); ++i)
|
||||
@ -685,7 +684,7 @@ bool IRGeneratorForStatements::visit(UnaryOperation const& _unaryOperation)
|
||||
solAssert(function->returnParameters().size() == 1);
|
||||
solAssert(*function->returnParameters()[0]->type() == *_unaryOperation.annotation().type);
|
||||
|
||||
string argument = expressionAsType(_unaryOperation.subExpression(), *function->parameters()[0]->type());
|
||||
std::string argument = expressionAsType(_unaryOperation.subExpression(), *function->parameters()[0]->type());
|
||||
solAssert(!argument.empty());
|
||||
|
||||
solAssert(_unaryOperation.userDefinedFunctionType()->kind() == FunctionType::Kind::Internal);
|
||||
@ -812,8 +811,8 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
|
||||
solAssert(function->returnParameters().size() == 1);
|
||||
solAssert(*function->returnParameters()[0]->type() == *_binOp.annotation().type);
|
||||
|
||||
string left = expressionAsType(_binOp.leftExpression(), *function->parameters()[0]->type());
|
||||
string right = expressionAsType(_binOp.rightExpression(), *function->parameters()[1]->type());
|
||||
std::string left = expressionAsType(_binOp.leftExpression(), *function->parameters()[0]->type());
|
||||
std::string right = expressionAsType(_binOp.rightExpression(), *function->parameters()[1]->type());
|
||||
solAssert(!left.empty() && !right.empty());
|
||||
|
||||
solAssert(_binOp.userDefinedFunctionType()->kind() == FunctionType::Kind::Internal);
|
||||
@ -853,13 +852,13 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
|
||||
if (auto type = dynamic_cast<IntegerType const*>(commonType))
|
||||
isSigned = type->isSigned();
|
||||
|
||||
string args = expressionAsCleanedType(_binOp.leftExpression(), *commonType);
|
||||
std::string args = expressionAsCleanedType(_binOp.leftExpression(), *commonType);
|
||||
args += ", " + expressionAsCleanedType(_binOp.rightExpression(), *commonType);
|
||||
|
||||
auto functionType = dynamic_cast<FunctionType const*>(commonType);
|
||||
solAssert(functionType ? (op == Token::Equal || op == Token::NotEqual) : true, "Invalid function pointer comparison!");
|
||||
|
||||
string expr;
|
||||
std::string expr;
|
||||
|
||||
if (functionType && functionType->kind() == FunctionType::Kind::External)
|
||||
{
|
||||
@ -879,9 +878,9 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
|
||||
else if (op == Token::NotEqual)
|
||||
expr = "iszero(eq(" + std::move(args) + "))";
|
||||
else if (op == Token::GreaterThanOrEqual)
|
||||
expr = "iszero(" + string(isSigned ? "slt(" : "lt(") + std::move(args) + "))";
|
||||
expr = "iszero(" + std::string(isSigned ? "slt(" : "lt(") + std::move(args) + "))";
|
||||
else if (op == Token::LessThanOrEqual)
|
||||
expr = "iszero(" + string(isSigned ? "sgt(" : "gt(") + std::move(args) + "))";
|
||||
expr = "iszero(" + std::string(isSigned ? "sgt(" : "gt(") + std::move(args) + "))";
|
||||
else if (op == Token::GreaterThan)
|
||||
expr = (isSigned ? "sgt(" : "gt(") + std::move(args) + ")";
|
||||
else if (op == Token::LessThan)
|
||||
@ -925,8 +924,8 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
|
||||
}
|
||||
else
|
||||
{
|
||||
string left = expressionAsType(_binOp.leftExpression(), *commonType);
|
||||
string right = expressionAsType(_binOp.rightExpression(), *commonType);
|
||||
std::string left = expressionAsType(_binOp.leftExpression(), *commonType);
|
||||
std::string right = expressionAsType(_binOp.rightExpression(), *commonType);
|
||||
define(_binOp) << binaryOperation(_binOp.getOperator(), *commonType, left, right) << "\n";
|
||||
}
|
||||
return false;
|
||||
@ -960,7 +959,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
|
||||
TypePointers parameterTypes = functionType->parameterTypes();
|
||||
|
||||
vector<ASTPointer<Expression const>> const& arguments = _functionCall.sortedArguments();
|
||||
std::vector<ASTPointer<Expression const>> const& arguments = _functionCall.sortedArguments();
|
||||
|
||||
if (functionCallKind == FunctionCallKind::StructConstructorCall)
|
||||
{
|
||||
@ -1001,7 +1000,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
|
||||
solAssert(!functionType->takesArbitraryParameters());
|
||||
|
||||
vector<string> args;
|
||||
std::vector<std::string> args;
|
||||
if (functionType->hasBoundFirstArgument())
|
||||
args += IRVariable(_functionCall.expression()).part("self").stackSlots();
|
||||
|
||||
@ -1049,8 +1048,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
TypePointers paramTypes = functionType->parameterTypes();
|
||||
ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector());
|
||||
|
||||
vector<IRVariable> indexedArgs;
|
||||
vector<string> nonIndexedArgs;
|
||||
std::vector<IRVariable> indexedArgs;
|
||||
std::vector<std::string> nonIndexedArgs;
|
||||
TypePointers nonIndexedArgTypes;
|
||||
TypePointers nonIndexedParamTypes;
|
||||
if (!event.isAnonymous())
|
||||
@ -1061,7 +1060,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
Expression const& arg = *arguments[i];
|
||||
if (event.parameters()[i]->isIndexed())
|
||||
{
|
||||
string value;
|
||||
std::string value;
|
||||
if (auto const& referenceType = dynamic_cast<ReferenceType const*>(paramTypes[i]))
|
||||
define(indexedArgs.emplace_back(m_context.newYulVariable(), *TypeProvider::uint256())) <<
|
||||
m_utils.packedHashFunction({arg.annotation().type}, {referenceType}) <<
|
||||
@ -1106,7 +1105,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||
templ("encode", abi.tupleEncoder(nonIndexedArgTypes, nonIndexedParamTypes));
|
||||
templ("nonIndexedArgs", joinHumanReadablePrefixed(nonIndexedArgs));
|
||||
templ("log", "log" + to_string(indexedArgs.size()));
|
||||
templ("log", "log" + std::to_string(indexedArgs.size()));
|
||||
templ("indexedArgs", joinHumanReadablePrefixed(indexedArgs | ranges::views::transform([&](auto const& _arg) {
|
||||
return _arg.commaSeparatedList();
|
||||
})));
|
||||
@ -1152,7 +1151,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
arguments.size() > 1 && m_context.revertStrings() != RevertStrings::Strip ?
|
||||
arguments[1]->annotation().type :
|
||||
nullptr;
|
||||
string requireOrAssertFunction = m_utils.requireOrAssertFunction(
|
||||
std::string requireOrAssertFunction = m_utils.requireOrAssertFunction(
|
||||
functionType->kind() == FunctionType::Kind::Assert,
|
||||
messageArgumentType
|
||||
);
|
||||
@ -1179,9 +1178,9 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
|
||||
TypePointers argumentTypes;
|
||||
TypePointers targetTypes;
|
||||
vector<string> argumentVars;
|
||||
string selector;
|
||||
vector<ASTPointer<Expression const>> argumentsOfEncodeFunction;
|
||||
std::vector<std::string> argumentVars;
|
||||
std::string selector;
|
||||
std::vector<ASTPointer<Expression const>> argumentsOfEncodeFunction;
|
||||
|
||||
if (functionType->kind() == FunctionType::Kind::ABIEncodeCall)
|
||||
{
|
||||
@ -1252,13 +1251,13 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
// TODO This is an abuse of the `allocateUnbounded` function.
|
||||
// We might want to introduce a new set of memory handling functions here
|
||||
// a la "setMemoryCheckPoint" and "freeUntilCheckPoint".
|
||||
string freeMemoryPre = m_context.newYulVariable();
|
||||
std::string freeMemoryPre = m_context.newYulVariable();
|
||||
appendCode() << "let " << freeMemoryPre << " := " << m_utils.allocateUnboundedFunction() << "()\n";
|
||||
IRVariable array = convert(*arguments[0], *TypeProvider::bytesMemory());
|
||||
IRVariable hashVariable(m_context.newYulVariable(), *TypeProvider::fixedBytes(32));
|
||||
|
||||
string dataAreaFunction = m_utils.arrayDataAreaFunction(*TypeProvider::bytesMemory());
|
||||
string arrayLengthFunction = m_utils.arrayLengthFunction(*TypeProvider::bytesMemory());
|
||||
std::string dataAreaFunction = m_utils.arrayDataAreaFunction(*TypeProvider::bytesMemory());
|
||||
std::string arrayLengthFunction = m_utils.arrayLengthFunction(*TypeProvider::bytesMemory());
|
||||
define(hashVariable) <<
|
||||
"keccak256(" <<
|
||||
(dataAreaFunction + "(" + array.commaSeparatedList() + ")") <<
|
||||
@ -1389,8 +1388,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
{
|
||||
auto array = convert(*arguments[0], *arrayType);
|
||||
|
||||
string dataAreaFunction = m_utils.arrayDataAreaFunction(*arrayType);
|
||||
string arrayLengthFunction = m_utils.arrayLengthFunction(*arrayType);
|
||||
std::string dataAreaFunction = m_utils.arrayDataAreaFunction(*arrayType);
|
||||
std::string arrayLengthFunction = m_utils.arrayLengthFunction(*arrayType);
|
||||
define(_functionCall) <<
|
||||
"keccak256(" <<
|
||||
(dataAreaFunction + "(" + array.commaSeparatedList() + ")") <<
|
||||
@ -1453,7 +1452,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::BytesConcat:
|
||||
{
|
||||
TypePointers argumentTypes;
|
||||
vector<string> argumentVars;
|
||||
std::vector<std::string> argumentVars;
|
||||
for (ASTPointer<Expression const> const& argument: arguments)
|
||||
{
|
||||
argumentTypes.emplace_back(&type(*argument));
|
||||
@ -1473,7 +1472,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::AddMod:
|
||||
case FunctionType::Kind::MulMod:
|
||||
{
|
||||
static map<FunctionType::Kind, string> functions = {
|
||||
static std::map<FunctionType::Kind, std::string> functions = {
|
||||
{FunctionType::Kind::AddMod, "addmod"},
|
||||
{FunctionType::Kind::MulMod, "mulmod"},
|
||||
};
|
||||
@ -1487,7 +1486,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
templ("panic", m_utils.panicFunction(PanicCode::DivisionByZero));
|
||||
appendCode() << templ.render();
|
||||
|
||||
string args;
|
||||
std::string args;
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
args += expressionAsType(*arguments[i], *(parameterTypes[i])) + ", ";
|
||||
args += modulus.name();
|
||||
@ -1498,14 +1497,14 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::Selfdestruct:
|
||||
case FunctionType::Kind::BlockHash:
|
||||
{
|
||||
static map<FunctionType::Kind, string> functions = {
|
||||
static std::map<FunctionType::Kind, std::string> functions = {
|
||||
{FunctionType::Kind::GasLeft, "gas"},
|
||||
{FunctionType::Kind::Selfdestruct, "selfdestruct"},
|
||||
{FunctionType::Kind::BlockHash, "blockhash"},
|
||||
};
|
||||
solAssert(functions.find(functionType->kind()) != functions.end());
|
||||
|
||||
string args;
|
||||
std::string args;
|
||||
for (size_t i = 0; i < arguments.size(); ++i)
|
||||
args += (args.empty() ? "" : ", ") + expressionAsType(*arguments[i], *(parameterTypes[i]));
|
||||
define(_functionCall) << functions[functionType->kind()] << "(" << args << ")\n";
|
||||
@ -1520,7 +1519,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
);
|
||||
|
||||
TypePointers argumentTypes;
|
||||
vector<string> constructorParams;
|
||||
std::vector<std::string> constructorParams;
|
||||
for (ASTPointer<Expression const> const& arg: arguments)
|
||||
{
|
||||
argumentTypes.push_back(arg->annotation().type);
|
||||
@ -1575,8 +1574,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::Transfer:
|
||||
{
|
||||
solAssert(arguments.size() == 1 && parameterTypes.size() == 1);
|
||||
string address{IRVariable(_functionCall.expression()).part("address").name()};
|
||||
string value{expressionAsType(*arguments[0], *(parameterTypes[0]))};
|
||||
std::string address{IRVariable(_functionCall.expression()).part("address").name()};
|
||||
std::string value{expressionAsType(*arguments[0], *(parameterTypes[0]))};
|
||||
Whiskers templ(R"(
|
||||
let <gas> := 0
|
||||
if iszero(<value>) { <gas> := <callStipend> }
|
||||
@ -1608,14 +1607,14 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
solAssert(!functionType->gasSet());
|
||||
solAssert(!functionType->hasBoundFirstArgument());
|
||||
|
||||
static map<FunctionType::Kind, std::tuple<unsigned, size_t>> precompiles = {
|
||||
static std::map<FunctionType::Kind, std::tuple<unsigned, size_t>> precompiles = {
|
||||
{FunctionType::Kind::ECRecover, std::make_tuple(1, 0)},
|
||||
{FunctionType::Kind::SHA256, std::make_tuple(2, 0)},
|
||||
{FunctionType::Kind::RIPEMD160, std::make_tuple(3, 12)},
|
||||
};
|
||||
auto [ address, offset ] = precompiles[functionType->kind()];
|
||||
TypePointers argumentTypes;
|
||||
vector<string> argumentStrings;
|
||||
std::vector<std::string> argumentStrings;
|
||||
for (auto const& arg: arguments)
|
||||
{
|
||||
argumentTypes.emplace_back(&type(*arg));
|
||||
@ -1676,11 +1675,11 @@ void IRGeneratorForStatements::endVisit(FunctionCallOptions const& _options)
|
||||
|
||||
// Copy over existing values.
|
||||
for (auto const& item: previousType.stackItems())
|
||||
define(IRVariable(_options).part(get<0>(item)), IRVariable(_options.expression()).part(get<0>(item)));
|
||||
define(IRVariable(_options).part(std::get<0>(item)), IRVariable(_options.expression()).part(std::get<0>(item)));
|
||||
|
||||
for (size_t i = 0; i < _options.names().size(); ++i)
|
||||
{
|
||||
string const& name = *_options.names()[i];
|
||||
std::string const& name = *_options.names()[i];
|
||||
solAssert(name == "salt" || name == "gas" || name == "value");
|
||||
|
||||
define(IRVariable(_options).part(name), *_options.options()[i]);
|
||||
@ -1785,7 +1784,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
")\n";
|
||||
else if (member == "code")
|
||||
{
|
||||
string externalCodeFunction = m_utils.externalCodeFunction();
|
||||
std::string externalCodeFunction = m_utils.externalCodeFunction();
|
||||
define(_memberAccess) <<
|
||||
externalCodeFunction <<
|
||||
"(" <<
|
||||
@ -1797,12 +1796,12 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
"extcodehash(" <<
|
||||
expressionAsType(_memberAccess.expression(), *TypeProvider::address()) <<
|
||||
")\n";
|
||||
else if (set<string>{"send", "transfer"}.count(member))
|
||||
else if (std::set<std::string>{"send", "transfer"}.count(member))
|
||||
{
|
||||
solAssert(dynamic_cast<AddressType const&>(*_memberAccess.expression().annotation().type).stateMutability() == StateMutability::Payable);
|
||||
define(IRVariable{_memberAccess}.part("address"), _memberAccess.expression());
|
||||
}
|
||||
else if (set<string>{"call", "callcode", "delegatecall", "staticcall"}.count(member))
|
||||
else if (std::set<std::string>{"call", "callcode", "delegatecall", "staticcall"}.count(member))
|
||||
define(IRVariable{_memberAccess}.part("address"), _memberAccess.expression());
|
||||
else
|
||||
solAssert(false, "Invalid member access to address");
|
||||
@ -1945,7 +1944,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
{
|
||||
MagicType const* arg = dynamic_cast<MagicType const*>(_memberAccess.expression().annotation().type);
|
||||
|
||||
string requestedValue;
|
||||
std::string requestedValue;
|
||||
if (IntegerType const* integerType = dynamic_cast<IntegerType const*>(arg->typeArgument()))
|
||||
{
|
||||
if (member == "min")
|
||||
@ -1956,16 +1955,16 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
else if (EnumType const* enumType = dynamic_cast<EnumType const*>(arg->typeArgument()))
|
||||
{
|
||||
if (member == "min")
|
||||
requestedValue = to_string(enumType->minValue());
|
||||
requestedValue = std::to_string(enumType->minValue());
|
||||
else
|
||||
requestedValue = to_string(enumType->maxValue());
|
||||
requestedValue = std::to_string(enumType->maxValue());
|
||||
}
|
||||
else
|
||||
solAssert(false, "min/max requested on unexpected type.");
|
||||
|
||||
define(_memberAccess) << requestedValue << "\n";
|
||||
}
|
||||
else if (set<string>{"encode", "encodePacked", "encodeWithSelector", "encodeCall", "encodeWithSignature", "decode"}.count(member))
|
||||
else if (std::set<std::string>{"encode", "encodePacked", "encodeWithSelector", "encodeCall", "encodeWithSignature", "decode"}.count(member))
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
@ -1981,8 +1980,8 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
{
|
||||
case DataLocation::Storage:
|
||||
{
|
||||
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member);
|
||||
string slot = m_context.newYulVariable();
|
||||
std::pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member);
|
||||
std::string slot = m_context.newYulVariable();
|
||||
appendCode() << "let " << slot << " := " <<
|
||||
("add(" + expression.part("slot").name() + ", " + offsets.first.str() + ")\n");
|
||||
setLValue(_memberAccess, IRLValue{
|
||||
@ -1993,7 +1992,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
}
|
||||
case DataLocation::Memory:
|
||||
{
|
||||
string pos = m_context.newYulVariable();
|
||||
std::string pos = m_context.newYulVariable();
|
||||
appendCode() << "let " << pos << " := " <<
|
||||
("add(" + expression.part("mpos").name() + ", " + structType.memoryOffsetOfMember(member).str() + ")\n");
|
||||
setLValue(_memberAccess, IRLValue{
|
||||
@ -2004,9 +2003,9 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
}
|
||||
case DataLocation::CallData:
|
||||
{
|
||||
string baseRef = expression.part("offset").name();
|
||||
string offset = m_context.newYulVariable();
|
||||
appendCode() << "let " << offset << " := " << "add(" << baseRef << ", " << to_string(structType.calldataOffsetOfMember(member)) << ")\n";
|
||||
std::string baseRef = expression.part("offset").name();
|
||||
std::string offset = m_context.newYulVariable();
|
||||
appendCode() << "let " << offset << " := " << "add(" << baseRef << ", " << std::to_string(structType.calldataOffsetOfMember(member)) << ")\n";
|
||||
if (_memberAccess.annotation().type->isDynamicallyEncoded())
|
||||
define(_memberAccess) <<
|
||||
m_utils.accessCalldataTailFunction(*_memberAccess.annotation().type) <<
|
||||
@ -2036,7 +2035,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
case Type::Category::Enum:
|
||||
{
|
||||
EnumType const& type = dynamic_cast<EnumType const&>(*_memberAccess.expression().annotation().type);
|
||||
define(_memberAccess) << to_string(type.memberValue(_memberAccess.memberName())) << "\n";
|
||||
define(_memberAccess) << std::to_string(type.memberValue(_memberAccess.memberName())) << "\n";
|
||||
break;
|
||||
}
|
||||
case Type::Category::Array:
|
||||
@ -2076,7 +2075,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
{
|
||||
auto const& type = dynamic_cast<FixedBytesType const&>(*_memberAccess.expression().annotation().type);
|
||||
if (member == "length")
|
||||
define(_memberAccess) << to_string(type.numBytes()) << "\n";
|
||||
define(_memberAccess) << std::to_string(type.numBytes()) << "\n";
|
||||
else
|
||||
solAssert(false, "Illegal fixed bytes member.");
|
||||
break;
|
||||
@ -2162,7 +2161,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
solAssert(false);
|
||||
}
|
||||
else if (EnumType const* enumType = dynamic_cast<EnumType const*>(&actualType))
|
||||
define(_memberAccess) << to_string(enumType->memberValue(_memberAccess.memberName())) << "\n";
|
||||
define(_memberAccess) << std::to_string(enumType->memberValue(_memberAccess.memberName())) << "\n";
|
||||
else if (dynamic_cast<UserDefinedValueType const*>(&actualType))
|
||||
solAssert(member == "wrap" || member == "unwrap");
|
||||
else if (auto const* arrayType = dynamic_cast<ArrayType const*>(&actualType))
|
||||
@ -2222,7 +2221,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm)
|
||||
|
||||
yul::Statement modified = bodyCopier(_inlineAsm.operations());
|
||||
|
||||
solAssert(holds_alternative<yul::Block>(modified));
|
||||
solAssert(std::holds_alternative<yul::Block>(modified));
|
||||
|
||||
// Do not provide dialect so that we get the full type information.
|
||||
appendCode() << yul::AsmPrinter()(std::get<yul::Block>(modified)) << "\n";
|
||||
@ -2242,7 +2241,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
||||
MappingType const& mappingType = dynamic_cast<MappingType const&>(baseType);
|
||||
Type const& keyType = *_indexAccess.indexExpression()->annotation().type;
|
||||
|
||||
string slot = m_context.newYulVariable();
|
||||
std::string slot = m_context.newYulVariable();
|
||||
Whiskers templ("let <slot> := <indexAccess>(<base><?+key>,<key></+key>)\n");
|
||||
templ("slot", slot);
|
||||
templ("indexAccess", m_utils.mappingIndexAccessFunction(mappingType, keyType));
|
||||
@ -2273,8 +2272,8 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
||||
{
|
||||
case DataLocation::Storage:
|
||||
{
|
||||
string slot = m_context.newYulVariable();
|
||||
string offset = m_context.newYulVariable();
|
||||
std::string slot = m_context.newYulVariable();
|
||||
std::string offset = m_context.newYulVariable();
|
||||
|
||||
appendCode() << Whiskers(R"(
|
||||
let <slot>, <offset> := <indexFunc>(<array>, <index>)
|
||||
@ -2295,13 +2294,13 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
||||
}
|
||||
case DataLocation::Memory:
|
||||
{
|
||||
string const indexAccessFunction = m_utils.memoryArrayIndexAccessFunction(arrayType);
|
||||
string const baseRef = IRVariable(_indexAccess.baseExpression()).part("mpos").name();
|
||||
string const indexExpression = expressionAsType(
|
||||
std::string const indexAccessFunction = m_utils.memoryArrayIndexAccessFunction(arrayType);
|
||||
std::string const baseRef = IRVariable(_indexAccess.baseExpression()).part("mpos").name();
|
||||
std::string const indexExpression = expressionAsType(
|
||||
*_indexAccess.indexExpression(),
|
||||
*TypeProvider::uint256()
|
||||
);
|
||||
string const memAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")";
|
||||
std::string const memAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")";
|
||||
|
||||
setLValue(_indexAccess, IRLValue{
|
||||
*arrayType.baseType(),
|
||||
@ -2311,13 +2310,13 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
||||
}
|
||||
case DataLocation::CallData:
|
||||
{
|
||||
string const indexAccessFunction = m_utils.calldataArrayIndexAccessFunction(arrayType);
|
||||
string const baseRef = IRVariable(_indexAccess.baseExpression()).commaSeparatedList();
|
||||
string const indexExpression = expressionAsType(
|
||||
std::string const indexAccessFunction = m_utils.calldataArrayIndexAccessFunction(arrayType);
|
||||
std::string const baseRef = IRVariable(_indexAccess.baseExpression()).commaSeparatedList();
|
||||
std::string const indexExpression = expressionAsType(
|
||||
*_indexAccess.indexExpression(),
|
||||
*TypeProvider::uint256()
|
||||
);
|
||||
string const calldataAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")";
|
||||
std::string const calldataAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")";
|
||||
|
||||
if (arrayType.isByteArrayOrString())
|
||||
define(_indexAccess) <<
|
||||
@ -2349,7 +2348,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
||||
let <result> := <shl248>(byte(<index>, <array>))
|
||||
)")
|
||||
("index", index.name())
|
||||
("length", to_string(fixedBytesType.numBytes()))
|
||||
("length", std::to_string(fixedBytesType.numBytes()))
|
||||
("panic", m_utils.panicFunction(PanicCode::ArrayOutOfBounds))
|
||||
("array", IRVariable(_indexAccess.baseExpression()).name())
|
||||
("shl248", m_utils.shiftLeftFunction(256 - 8))
|
||||
@ -2538,7 +2537,7 @@ void IRGeneratorForStatements::handleVariableReference(
|
||||
|
||||
void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
FunctionCall const& _functionCall,
|
||||
vector<ASTPointer<Expression const>> const& _arguments
|
||||
std::vector<ASTPointer<Expression const>> const& _arguments
|
||||
)
|
||||
{
|
||||
FunctionType const& funType = dynamic_cast<FunctionType const&>(type(_functionCall.expression()));
|
||||
@ -2559,7 +2558,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
|
||||
TypePointers parameterTypes = funType.parameterTypes();
|
||||
TypePointers argumentTypes;
|
||||
vector<string> argumentStrings;
|
||||
std::vector<std::string> argumentStrings;
|
||||
if (funType.hasBoundFirstArgument())
|
||||
{
|
||||
parameterTypes.insert(parameterTypes.begin(), funType.selfType());
|
||||
@ -2581,7 +2580,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
// We could also just use MLOAD; POP right before the gas calculation, but the optimizer
|
||||
// would remove that, so we use MSTORE here.
|
||||
if (!funType.gasSet() && returnInfo.estimatedReturnSize > 0)
|
||||
appendCode() << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << to_string(returnInfo.estimatedReturnSize) << "), 0)\n";
|
||||
appendCode() << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << std::to_string(returnInfo.estimatedReturnSize) << "), 0)\n";
|
||||
}
|
||||
|
||||
// NOTE: When the expected size of returndata is static, we pass that in to the call opcode and it gets copied automatically.
|
||||
@ -2649,10 +2648,10 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
if (returnInfo.dynamicReturnSize)
|
||||
solAssert(m_context.evmVersion().supportsReturndata());
|
||||
templ("returnDataSizeVar", m_context.newYulVariable());
|
||||
templ("staticReturndataSize", to_string(returnInfo.estimatedReturnSize));
|
||||
templ("staticReturndataSize", std::to_string(returnInfo.estimatedReturnSize));
|
||||
templ("supportsReturnData", m_context.evmVersion().supportsReturndata());
|
||||
|
||||
string const retVars = IRVariable(_functionCall).commaSeparatedList();
|
||||
std::string const retVars = IRVariable(_functionCall).commaSeparatedList();
|
||||
templ("retVars", retVars);
|
||||
solAssert(retVars.empty() == returnInfo.returnTypes.empty());
|
||||
|
||||
@ -2704,7 +2703,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
|
||||
void IRGeneratorForStatements::appendBareCall(
|
||||
FunctionCall const& _functionCall,
|
||||
vector<ASTPointer<Expression const>> const& _arguments
|
||||
std::vector<ASTPointer<Expression const>> const& _arguments
|
||||
)
|
||||
{
|
||||
FunctionType const& funType = dynamic_cast<FunctionType const&>(type(_functionCall.expression()));
|
||||
@ -2807,7 +2806,7 @@ void IRGeneratorForStatements::assignInternalFunctionIDIfNotCalledDirectly(
|
||||
return;
|
||||
|
||||
define(IRVariable(_expression).part("functionIdentifier")) <<
|
||||
to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(&_referencedFunction)) <<
|
||||
std::to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(&_referencedFunction)) <<
|
||||
"\n";
|
||||
m_context.addToInternalDispatch(_referencedFunction);
|
||||
}
|
||||
@ -2864,7 +2863,7 @@ void IRGeneratorForStatements::declare(IRVariable const& _var)
|
||||
|
||||
void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable const& _rhs, bool _declare, bool _forceCleanup)
|
||||
{
|
||||
string output;
|
||||
std::string output;
|
||||
if (_lhs.type() == _rhs.type() && !_forceCleanup)
|
||||
for (auto const& [stackItemName, stackItemType]: _lhs.type().stackItems())
|
||||
if (stackItemType)
|
||||
@ -2894,7 +2893,7 @@ IRVariable IRGeneratorForStatements::zeroValue(Type const& _type, bool _splitFun
|
||||
|
||||
void IRGeneratorForStatements::appendSimpleUnaryOperation(UnaryOperation const& _operation, Expression const& _expr)
|
||||
{
|
||||
string func;
|
||||
std::string func;
|
||||
|
||||
if (_operation.getOperator() == Token::Not)
|
||||
func = "iszero";
|
||||
@ -2913,18 +2912,18 @@ void IRGeneratorForStatements::appendSimpleUnaryOperation(UnaryOperation const&
|
||||
")\n";
|
||||
}
|
||||
|
||||
string IRGeneratorForStatements::binaryOperation(
|
||||
std::string IRGeneratorForStatements::binaryOperation(
|
||||
langutil::Token _operator,
|
||||
Type const& _type,
|
||||
string const& _left,
|
||||
string const& _right
|
||||
std::string const& _left,
|
||||
std::string const& _right
|
||||
)
|
||||
{
|
||||
solAssert(
|
||||
!TokenTraits::isShiftOp(_operator),
|
||||
"Have to use specific shift operation function for shifts."
|
||||
);
|
||||
string fun;
|
||||
std::string fun;
|
||||
if (TokenTraits::isBitOp(_operator))
|
||||
{
|
||||
solAssert(
|
||||
@ -3030,12 +3029,12 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
|
||||
std::visit(
|
||||
util::GenericVisitor{
|
||||
[&](IRLValue::Storage const& _storage) {
|
||||
string offsetArgument;
|
||||
optional<unsigned> offsetStatic;
|
||||
std::string offsetArgument;
|
||||
std::optional<unsigned> offsetStatic;
|
||||
|
||||
std::visit(GenericVisitor{
|
||||
[&](unsigned _offset) { offsetStatic = _offset; },
|
||||
[&](string const& _offset) { offsetArgument = ", " + _offset; }
|
||||
[&](std::string const& _offset) { offsetArgument = ", " + _offset; }
|
||||
}, _storage.offset);
|
||||
|
||||
appendCode() <<
|
||||
@ -3068,7 +3067,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
|
||||
}
|
||||
else if (auto const* literalType = dynamic_cast<StringLiteralType const*>(&_value.type()))
|
||||
{
|
||||
string writeUInt = m_utils.writeToMemoryFunction(*TypeProvider::uint256());
|
||||
std::string writeUInt = m_utils.writeToMemoryFunction(*TypeProvider::uint256());
|
||||
appendCode() <<
|
||||
writeUInt <<
|
||||
"(" <<
|
||||
@ -3099,7 +3098,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
|
||||
IRVariable prepared(m_context.newYulVariable(), _lvalue.type);
|
||||
define(prepared, _value);
|
||||
|
||||
appendCode() << "mstore(" << to_string(memOffset) << ", " << prepared.commaSeparatedList() << ")\n";
|
||||
appendCode() << "mstore(" << std::to_string(memOffset) << ", " << prepared.commaSeparatedList() << ")\n";
|
||||
},
|
||||
[&](IRLValue::Tuple const& _tuple) {
|
||||
auto components = std::move(_tuple.components);
|
||||
@ -3122,13 +3121,13 @@ IRVariable IRGeneratorForStatements::readFromLValue(IRLValue const& _lvalue)
|
||||
[&](IRLValue::Storage const& _storage) {
|
||||
if (!_lvalue.type.isValueType())
|
||||
define(result) << _storage.slot << "\n";
|
||||
else if (std::holds_alternative<string>(_storage.offset))
|
||||
else if (std::holds_alternative<std::string>(_storage.offset))
|
||||
define(result) <<
|
||||
m_utils.readFromStorageDynamic(_lvalue.type, true) <<
|
||||
"(" <<
|
||||
_storage.slot <<
|
||||
", " <<
|
||||
std::get<string>(_storage.offset) <<
|
||||
std::get<std::string>(_storage.offset) <<
|
||||
")\n";
|
||||
else
|
||||
define(result) <<
|
||||
@ -3156,15 +3155,15 @@ IRVariable IRGeneratorForStatements::readFromLValue(IRLValue const& _lvalue)
|
||||
solAssert(_lvalue.type == *_immutable.variable->type());
|
||||
if (m_context.executionContext() == IRGenerationContext::ExecutionContext::Creation)
|
||||
{
|
||||
string readFunction = m_utils.readFromMemory(*_immutable.variable->type());
|
||||
std::string readFunction = m_utils.readFromMemory(*_immutable.variable->type());
|
||||
define(result) <<
|
||||
readFunction <<
|
||||
"(" <<
|
||||
to_string(m_context.immutableMemoryOffset(*_immutable.variable)) <<
|
||||
std::to_string(m_context.immutableMemoryOffset(*_immutable.variable)) <<
|
||||
")\n";
|
||||
}
|
||||
else
|
||||
define(result) << "loadimmutable(\"" << to_string(_immutable.variable->id()) << "\")\n";
|
||||
define(result) << "loadimmutable(\"" << std::to_string(_immutable.variable->id()) << "\")\n";
|
||||
},
|
||||
[&](IRLValue::Tuple const&) {
|
||||
solAssert(false, "Attempted to read from tuple lvalue.");
|
||||
@ -3181,7 +3180,7 @@ void IRGeneratorForStatements::setLValue(Expression const& _expression, IRLValue
|
||||
{
|
||||
m_currentLValue.emplace(std::move(_lvalue));
|
||||
if (_lvalue.type.dataStoredIn(DataLocation::CallData))
|
||||
solAssert(holds_alternative<IRLValue::Stack>(_lvalue.kind));
|
||||
solAssert(std::holds_alternative<IRLValue::Stack>(_lvalue.kind));
|
||||
}
|
||||
else
|
||||
// Only define the expression, if it will not be written to.
|
||||
@ -3196,7 +3195,7 @@ void IRGeneratorForStatements::generateLoop(
|
||||
bool _isDoWhile
|
||||
)
|
||||
{
|
||||
string firstRun;
|
||||
std::string firstRun;
|
||||
|
||||
if (_isDoWhile)
|
||||
{
|
||||
@ -3278,7 +3277,7 @@ bool IRGeneratorForStatements::visit(TryStatement const& _tryStatement)
|
||||
void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
|
||||
{
|
||||
setLocation(_tryStatement);
|
||||
string const runFallback = m_context.newYulVariable();
|
||||
std::string const runFallback = m_context.newYulVariable();
|
||||
appendCode() << "let " << runFallback << " := 1\n";
|
||||
|
||||
// This function returns zero on "short returndata". We have to add a success flag
|
||||
@ -3290,7 +3289,7 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
|
||||
{
|
||||
appendCode() << "case " << selectorFromSignatureU32("Error(string)") << " {\n";
|
||||
setLocation(*errorClause);
|
||||
string const dataVariable = m_context.newYulVariable();
|
||||
std::string const dataVariable = m_context.newYulVariable();
|
||||
appendCode() << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n";
|
||||
appendCode() << "if " << dataVariable << " {\n";
|
||||
appendCode() << runFallback << " := 0\n";
|
||||
@ -3310,8 +3309,8 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
|
||||
{
|
||||
appendCode() << "case " << selectorFromSignatureU32("Panic(uint256)") << " {\n";
|
||||
setLocation(*panicClause);
|
||||
string const success = m_context.newYulVariable();
|
||||
string const code = m_context.newYulVariable();
|
||||
std::string const success = m_context.newYulVariable();
|
||||
std::string const code = m_context.newYulVariable();
|
||||
appendCode() << "let " << success << ", " << code << " := " << m_utils.tryDecodePanicDataFunction() << "()\n";
|
||||
appendCode() << "if " << success << " {\n";
|
||||
appendCode() << runFallback << " := 0\n";
|
||||
@ -3358,9 +3357,9 @@ void IRGeneratorForStatements::handleCatchFallback(TryCatchClause const& _fallba
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::revertWithError(
|
||||
string const& _signature,
|
||||
vector<Type const*> const& _parameterTypes,
|
||||
vector<ASTPointer<Expression const>> const& _errorArguments
|
||||
std::string const& _signature,
|
||||
std::vector<Type const*> const& _parameterTypes,
|
||||
std::vector<ASTPointer<Expression const>> const& _errorArguments
|
||||
)
|
||||
{
|
||||
Whiskers templ(R"({
|
||||
@ -3374,8 +3373,8 @@ void IRGeneratorForStatements::revertWithError(
|
||||
templ("hash", util::selectorFromSignatureU256(_signature).str());
|
||||
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||
|
||||
vector<string> errorArgumentVars;
|
||||
vector<Type const*> errorArgumentTypes;
|
||||
std::vector<std::string> errorArgumentVars;
|
||||
std::vector<Type const*> errorArgumentTypes;
|
||||
for (ASTPointer<Expression const> const& arg: _errorArguments)
|
||||
{
|
||||
errorArgumentVars += IRVariable(*arg).stackSlots();
|
||||
@ -3395,7 +3394,7 @@ bool IRGeneratorForStatements::visit(TryCatchClause const& _clause)
|
||||
return false;
|
||||
}
|
||||
|
||||
string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const
|
||||
std::string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const
|
||||
{
|
||||
solAssert(_library.isLibrary());
|
||||
return "linkersymbol(" + util::escapeAndQuoteString(_library.fullyQualifiedName()) + ")";
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolutil/StringUtils.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::util;
|
||||
@ -41,7 +40,7 @@ IRVariable::IRVariable(Expression const& _expression):
|
||||
{
|
||||
}
|
||||
|
||||
IRVariable IRVariable::part(string const& _name) const
|
||||
IRVariable IRVariable::part(std::string const& _name) const
|
||||
{
|
||||
for (auto const& [itemName, itemType]: m_type.stackItems())
|
||||
if (itemName == _name)
|
||||
@ -63,9 +62,9 @@ bool IRVariable::hasPart(std::string const& _name) const
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<string> IRVariable::stackSlots() const
|
||||
std::vector<std::string> IRVariable::stackSlots() const
|
||||
{
|
||||
vector<string> result;
|
||||
std::vector<std::string> result;
|
||||
for (auto const& [itemName, itemType]: m_type.stackItems())
|
||||
if (itemType)
|
||||
{
|
||||
@ -81,17 +80,17 @@ vector<string> IRVariable::stackSlots() const
|
||||
return result;
|
||||
}
|
||||
|
||||
string IRVariable::commaSeparatedList() const
|
||||
std::string IRVariable::commaSeparatedList() const
|
||||
{
|
||||
return joinHumanReadable(stackSlots());
|
||||
}
|
||||
|
||||
string IRVariable::commaSeparatedListPrefixed() const
|
||||
std::string IRVariable::commaSeparatedListPrefixed() const
|
||||
{
|
||||
return joinHumanReadablePrefixed(stackSlots());
|
||||
}
|
||||
|
||||
string IRVariable::name() const
|
||||
std::string IRVariable::name() const
|
||||
{
|
||||
solAssert(m_type.sizeOnStack() == 1, "");
|
||||
auto const& [itemName, type] = m_type.stackItems().front();
|
||||
@ -108,7 +107,7 @@ IRVariable IRVariable::tupleComponent(size_t _i) const
|
||||
return part(IRNames::tupleComponent(_i));
|
||||
}
|
||||
|
||||
string IRVariable::suffixedName(string const& _suffix) const
|
||||
std::string IRVariable::suffixedName(std::string const& _suffix) const
|
||||
{
|
||||
if (_suffix.empty())
|
||||
return m_baseName;
|
||||
|
@ -27,6 +27,8 @@ NAMESPACE_STD_FREE_FILES=(
|
||||
libsolc/*
|
||||
libsolidity/analysis/*
|
||||
libsolidity/ast/*
|
||||
libsolidity/codegen/ir/*
|
||||
libsolidity/codegen/*
|
||||
)
|
||||
|
||||
(
|
||||
|
Loading…
Reference in New Issue
Block a user