Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yul object node names are std string instead of YulString #15261

Merged
merged 1 commit into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libsolidity/interface/StandardCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1638,7 +1638,7 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
return output;
}

std::string contractName = stack.parserResult()->name.str();
std::string contractName = stack.parserResult()->name;

bool const wildcardMatchesExperimental = true;
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ir", wildcardMatchesExperimental))
Expand Down
2 changes: 1 addition & 1 deletion libyul/AsmAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ std::vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
if (functionName == "datasize" || functionName == "dataoffset")
{
auto const& argumentAsLiteral = std::get<Literal>(arg);
if (!m_dataNames.count(YulString(formatLiteral(argumentAsLiteral))))
if (!m_dataNames.count(formatLiteral(argumentAsLiteral)))
m_errorReporter.typeError(
3517_error,
nativeLocationOf(arg),
Expand Down
4 changes: 2 additions & 2 deletions libyul/AsmAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class AsmAnalyzer
langutil::ErrorReporter& _errorReporter,
Dialect const& _dialect,
ExternalIdentifierAccess::Resolver _resolver = ExternalIdentifierAccess::Resolver(),
std::set<YulString> _dataNames = {}
std::set<std::string> _dataNames = {}
):
m_resolver(std::move(_resolver)),
m_info(_analysisInfo),
Expand Down Expand Up @@ -128,7 +128,7 @@ class AsmAnalyzer
langutil::EVMVersion m_evmVersion;
Dialect const& m_dialect;
/// Names of data objects to be referenced by builtin functions with literal arguments.
std::set<YulString> m_dataNames;
std::set<std::string> m_dataNames;
ForLoop const* m_currentForLoop = nullptr;
/// Worst side effects encountered during analysis (including within defined functions).
SideEffects m_sideEffects;
Expand Down
41 changes: 20 additions & 21 deletions libyul/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ using namespace solidity::yul;

std::string Data::toString(Dialect const*, DebugInfoSelection const&, CharStreamProvider const*) const
{
return "data \"" + name.str() + "\" hex\"" + util::toHex(data) + "\"";
return "data \"" + name + "\" hex\"" + util::toHex(data) + "\"";
}

std::string Object::toString(
Expand Down Expand Up @@ -72,7 +72,7 @@ std::string Object::toString(
for (auto const& obj: subObjects)
inner += "\n" + obj->toString(_dialect, _debugInfoSelection, _soliditySourceProvider);

return useSrcComment + "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}";
return useSrcComment + "object \"" + name + "\" {\n" + indent(inner) + "\n}";
}

Json Data::toJson() const
Expand All @@ -97,62 +97,61 @@ Json Object::toJson() const

Json ret;
ret["nodeType"] = "YulObject";
ret["name"] = name.str();
ret["name"] = name;
ret["code"] = codeJson;
ret["subObjects"] = subObjectsJson;
return ret;
}

std::set<YulString> Object::qualifiedDataNames() const
std::set<std::string> Object::qualifiedDataNames() const
{
std::set<YulString> qualifiedNames =
name.empty() || util::contains(name.str(), '.') ?
std::set<YulString>{} :
std::set<YulString>{name};
std::set<std::string> qualifiedNames =
name.empty() || util::contains(name, '.') ?
std::set<std::string>{} :
std::set<std::string>{name};
for (std::shared_ptr<ObjectNode> const& subObjectNode: subObjects)
{
yulAssert(qualifiedNames.count(subObjectNode->name) == 0, "");
if (util::contains(subObjectNode->name.str(), '.'))
if (util::contains(subObjectNode->name, '.'))
continue;
qualifiedNames.insert(subObjectNode->name);
if (auto const* subObject = dynamic_cast<Object const*>(subObjectNode.get()))
for (YulString const& subSubObj: subObject->qualifiedDataNames())
for (auto const& subSubObj: subObject->qualifiedDataNames())
if (subObject->name != subSubObj)
{
yulAssert(qualifiedNames.count(YulString{subObject->name.str() + "." + subSubObj.str()}) == 0, "");
qualifiedNames.insert(YulString{subObject->name.str() + "." + subSubObj.str()});
yulAssert(qualifiedNames.count(subObject->name + "." + subSubObj) == 0, "");
qualifiedNames.insert(subObject->name + "." + subSubObj);
}
}

yulAssert(qualifiedNames.count(YulString{}) == 0, "");
qualifiedNames.erase(YulString{});
yulAssert(qualifiedNames.count("") == 0, "");
return qualifiedNames;
}

std::vector<size_t> Object::pathToSubObject(YulString _qualifiedName) const
std::vector<size_t> Object::pathToSubObject(std::string_view _qualifiedName) const
{
yulAssert(_qualifiedName != name, "");
yulAssert(subIndexByName.count(name) == 0, "");

if (boost::algorithm::starts_with(_qualifiedName.str(), name.str() + "."))
_qualifiedName = YulString{_qualifiedName.str().substr(name.str().length() + 1)};
if (boost::algorithm::starts_with(_qualifiedName, name + "."))
_qualifiedName = _qualifiedName.substr(name.length() + 1);
yulAssert(!_qualifiedName.empty(), "");

std::vector<std::string> subObjectPathComponents;
boost::algorithm::split(subObjectPathComponents, _qualifiedName.str(), boost::is_any_of("."));
boost::algorithm::split(subObjectPathComponents, _qualifiedName, boost::is_any_of("."));

std::vector<size_t> path;
Object const* object = this;
for (std::string const& currentSubObjectName: subObjectPathComponents)
{
yulAssert(!currentSubObjectName.empty(), "");
auto subIndexIt = object->subIndexByName.find(YulString{currentSubObjectName});
auto subIndexIt = object->subIndexByName.find(currentSubObjectName);
yulAssert(
subIndexIt != object->subIndexByName.end(),
"Assembly object <" + _qualifiedName.str() + "> not found or does not contain code."
"Assembly object <" + std::string(_qualifiedName) + "> not found or does not contain code."
);
object = dynamic_cast<Object const*>(object->subObjects[subIndexIt->second].get());
yulAssert(object, "Assembly object <" + _qualifiedName.str() + "> not found or does not contain code.");
yulAssert(object, "Assembly object <" + std::string(_qualifiedName) + "> not found or does not contain code.");
yulAssert(object->subId != std::numeric_limits<size_t>::max(), "");
path.push_back({object->subId});
}
Expand Down
10 changes: 5 additions & 5 deletions libyul/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ struct ObjectNode

/// Name of the object.
/// Can be empty since .yul files can also just contain code, without explicitly placing it in an object.
YulString name;
std::string name;
virtual std::string toString(
Dialect const* _dialect,
langutil::DebugInfoSelection const& _debugInfoSelection,
Expand All @@ -66,7 +66,7 @@ struct ObjectNode
*/
struct Data: public ObjectNode
{
Data(YulString _name, bytes _data): data(std::move(_data)) { name = _name; }
Data(std::string _name, bytes _data): data(std::move(_data)) { name = _name; }

bytes data;

Expand Down Expand Up @@ -102,7 +102,7 @@ struct Object: public ObjectNode
/// @returns the set of names of data objects accessible from within the code of
/// this object, including the name of object itself
/// Handles all names containing dots as reserved identifiers, not accessible as data.
std::set<YulString> qualifiedDataNames() const;
std::set<std::string> qualifiedDataNames() const;

/// @returns vector of subIDs if possible to reach subobject with @a _qualifiedName, throws otherwise
/// For "B.C" should return vector of two values if success (subId of B and subId of C in B).
Expand All @@ -114,14 +114,14 @@ struct Object: public ObjectNode
/// pathToSubObject("E2.F3.H4") == {1, 0, 2}
/// pathToSubObject("A1.E2") == {1}
/// The path must not lead to a @a Data object (will throw in that case).
std::vector<size_t> pathToSubObject(YulString _qualifiedName) const;
std::vector<size_t> pathToSubObject(std::string_view _qualifiedName) const;

/// sub id for object if it is subobject of another object, max value if it is not subobject
size_t subId = std::numeric_limits<size_t>::max();

std::shared_ptr<Block> code;
std::vector<std::shared_ptr<ObjectNode>> subObjects;
std::map<YulString, size_t> subIndexByName;
std::map<std::string, size_t, std::less<>> subIndexByName;
std::shared_ptr<yul::AsmAnalysisInfo> analysisInfo;

std::shared_ptr<ObjectDebugData const> debugData;
Expand Down
18 changes: 11 additions & 7 deletions libyul/ObjectParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ std::shared_ptr<Object> ObjectParser::parse(std::shared_ptr<Scanner> const& _sca
{
// Special case: Code-only form.
object = std::make_shared<Object>();
object->name = "object"_yulstring;
r0qs marked this conversation as resolved.
Show resolved Hide resolved
object->name = "object";
auto sourceNameMapping = tryParseSourceNameMapping();
object->debugData = std::make_shared<ObjectDebugData>(ObjectDebugData{sourceNameMapping});
object->code = parseBlock(sourceNameMapping);
Expand Down Expand Up @@ -185,7 +185,7 @@ void ObjectParser::parseData(Object& _containingObject)
);
advance();

YulString name = parseUniqueName(&_containingObject);
auto const name = parseUniqueName(&_containingObject);

if (currentToken() == Token::HexStringLiteral)
expectToken(Token::HexStringLiteral, false);
Expand All @@ -195,22 +195,26 @@ void ObjectParser::parseData(Object& _containingObject)
advance();
}

YulString ObjectParser::parseUniqueName(Object const* _containingObject)
std::string ObjectParser::parseUniqueName(Object const* _containingObject)
{
expectToken(Token::StringLiteral, false);
YulString name{currentLiteral()};
auto const name = currentLiteral();
if (name.empty())
parserError(3287_error, "Object name cannot be empty.");
else if (_containingObject && _containingObject->name == name)
parserError(8311_error, "Object name cannot be the same as the name of the containing object.");
else if (_containingObject && _containingObject->subIndexByName.count(name))
parserError(8794_error, "Object name \"" + name.str() + "\" already exists inside the containing object.");
parserError(8794_error, "Object name \"" + name + "\" already exists inside the containing object.");
advance();
return name;
}

void ObjectParser::addNamedSubObject(Object& _container, YulString _name, std::shared_ptr<ObjectNode> _subObject)
void ObjectParser::addNamedSubObject(Object& _container, std::string_view const _name, std::shared_ptr<ObjectNode> _subObject)
{
_container.subIndexByName[_name] = _container.subObjects.size();
_container.subIndexByName.emplace(
std::piecewise_construct,
std::forward_as_tuple(_name),
std::forward_as_tuple(_container.subObjects.size())
);
_container.subObjects.emplace_back(std::move(_subObject));
}
4 changes: 2 additions & 2 deletions libyul/ObjectParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ class ObjectParser: public langutil::ParserBase
void parseData(Object& _containingObject);

/// Tries to parse a name that is non-empty and unique inside the containing object.
YulString parseUniqueName(Object const* _containingObject);
void addNamedSubObject(Object& _container, YulString _name, std::shared_ptr<ObjectNode> _subObject);
std::string parseUniqueName(Object const* _containingObject);
void addNamedSubObject(Object& _container, std::string_view _name, std::shared_ptr<ObjectNode> _subObject);

Dialect const& m_dialect;
};
Expand Down
2 changes: 1 addition & 1 deletion libyul/YulStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ void YulStack::optimize(Object& _object, bool _isCreation)
for (auto& subNode: _object.subObjects)
if (auto subObject = dynamic_cast<Object*>(subNode.get()))
{
bool isCreation = !boost::ends_with(subObject->name.str(), "_deployed");
bool isCreation = !boost::ends_with(subObject->name, "_deployed");
optimize(*subObject, isCreation);
}

Expand Down
16 changes: 8 additions & 8 deletions libyul/backends/evm/EVMDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,14 @@ std::map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _
yulAssert(_call.arguments.size() == 1, "");
Expression const& arg = _call.arguments.front();
YulString const dataName (formatLiteral(std::get<Literal>(arg)));
if (_context.currentObject->name == dataName)
if (_context.currentObject->name == dataName.str())
_assembly.appendAssemblySize();
else
{
std::vector<size_t> subIdPath =
_context.subIDs.count(dataName) == 0 ?
_context.currentObject->pathToSubObject(dataName) :
std::vector<size_t>{_context.subIDs.at(dataName)};
_context.subIDs.count(dataName.str()) == 0 ?
_context.currentObject->pathToSubObject(dataName.str()) :
std::vector<size_t>{_context.subIDs.at(dataName.str())};
yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">.");
_assembly.appendDataSize(subIdPath);
}
Expand All @@ -270,14 +270,14 @@ std::map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _
yulAssert(_call.arguments.size() == 1, "");
Expression const& arg = _call.arguments.front();
YulString const dataName (formatLiteral(std::get<Literal>(arg)));
if (_context.currentObject->name == dataName)
if (_context.currentObject->name == dataName.str())
_assembly.appendConstant(0);
else
{
std::vector<size_t> subIdPath =
_context.subIDs.count(dataName) == 0 ?
_context.currentObject->pathToSubObject(dataName) :
std::vector<size_t>{_context.subIDs.at(dataName)};
_context.subIDs.count(dataName.str()) == 0 ?
_context.currentObject->pathToSubObject(dataName.str()) :
std::vector<size_t>{_context.subIDs.at(dataName.str())};
yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">.");
_assembly.appendDataOffset(subIdPath);
}
Expand Down
2 changes: 1 addition & 1 deletion libyul/backends/evm/EVMDialect.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct BuiltinContext
{
Object const* currentObject = nullptr;
/// Mapping from named objects to abstract assembly sub IDs.
std::map<YulString, AbstractAssembly::SubID> subIDs;
std::map<std::string, AbstractAssembly::SubID> subIDs;
};

struct BuiltinFunctionForEVM: public BuiltinFunction
Expand Down
6 changes: 3 additions & 3 deletions libyul/backends/evm/EVMObjectCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize)
for (auto const& subNode: _object.subObjects)
if (auto* subObject = dynamic_cast<Object*>(subNode.get()))
{
bool isCreation = !boost::ends_with(subObject->name.str(), "_deployed");
auto subAssemblyAndID = m_assembly.createSubAssembly(isCreation, subObject->name.str());
bool isCreation = !boost::ends_with(subObject->name, "_deployed");
auto subAssemblyAndID = m_assembly.createSubAssembly(isCreation, subObject->name);
context.subIDs[subObject->name] = subAssemblyAndID.second;
subObject->subId = subAssemblyAndID.second;
compile(*subObject, *subAssemblyAndID.first, m_dialect, _optimize, m_eofVersion);
Expand All @@ -65,7 +65,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize)
{
Data const& data = dynamic_cast<Data const&>(*subNode);
// Special handling of metadata.
if (data.name.str() == Object::metadataName())
if (data.name == Object::metadataName())
m_assembly.appendToAuxiliaryData(data.data);
else
context.subIDs[data.name] = m_assembly.appendData(data.data);
Expand Down
2 changes: 1 addition & 1 deletion test/libsolidity/MemoryGuardTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con
};
handleObject("creation", *object);
size_t deployedIndex = object->subIndexByName.at(
YulString(IRNames::deployedObject(compiler().contractDefinition(contractName)))
IRNames::deployedObject(compiler().contractDefinition(contractName))
);
handleObject("runtime", dynamic_cast<Object const&>(*object->subObjects[deployedIndex]));
}
Expand Down
2 changes: 1 addition & 1 deletion tools/yulPhaser/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ std::variant<std::unique_ptr<Block>, ErrorList> Program::parseObject(Dialect con
// The other object references the nested one which makes analysis fail. Below we try to
// extract just the nested one for that reason. This is just a heuristic. If there's no
// subobject with such a suffix we fall back to accepting the whole object as is.
if (subObject != nullptr && subObject->name.str() == object->name.str() + "_deployed")
if (subObject != nullptr && subObject->name == object->name + "_deployed")
{
deployedObject = dynamic_cast<Object*>(subObject.get());
if (deployedObject != nullptr)
Expand Down