Skip to content

Commit df369d7

Browse files
committed
eof: Enable eofcreate in inline assebly for EOF. Introduce objectName suffix for contract name in inline assembly for EOF
1 parent 4f23c18 commit df369d7

File tree

7 files changed

+80
-31
lines changed

7 files changed

+80
-31
lines changed

Diff for: libsolidity/analysis/ReferencesResolver.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
329329
return;
330330
}
331331

332-
static std::set<std::string> suffixes{"slot", "offset", "length", "address", "selector"};
332+
static std::set<std::string> suffixes{"slot", "offset", "length", "address", "selector", "objectName"};
333333
std::string suffix;
334334
for (std::string const& s: suffixes)
335335
if (boost::algorithm::ends_with(_identifier.name.str(), "." + s))

Diff for: libsolidity/analysis/TypeChecker.cpp

+30-3
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
815815
if (!identifierInfo.suffix.empty())
816816
{
817817
std::string const& suffix = identifierInfo.suffix;
818-
solAssert((std::set<std::string>{"offset", "slot", "length", "selector", "address"}).count(suffix), "");
818+
solAssert((std::set<std::string>{"offset", "slot", "length", "selector", "address", "objectName"}).count(suffix), "");
819819
if (!var->isConstant() && (var->isStateVariable() || var->type()->dataStoredIn(DataLocation::Storage)))
820820
{
821821
if (suffix != "slot" && suffix != "offset")
@@ -896,9 +896,36 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
896896
return false;
897897
}
898898
}
899+
else if (dynamic_cast<ContractDefinition const*>(declaration) && !identifierInfo.suffix.empty())
900+
{
901+
if (identifierInfo.suffix != "objectName" || !m_eofVersion.has_value())
902+
{
903+
m_errorReporter.typeError(
904+
1342_error,
905+
nativeLocationOf(_identifier),
906+
"\".objectName\" suffix is supported only for contract name identifier when compiling to EOF."
907+
);
908+
return false;
909+
}
910+
}
899911
else if (!identifierInfo.suffix.empty())
900912
{
901-
m_errorReporter.typeError(7944_error, nativeLocationOf(_identifier), "The suffixes \".offset\", \".slot\" and \".length\" can only be used with variables.");
913+
if (m_eofVersion.has_value())
914+
{
915+
m_errorReporter.typeError(
916+
9479_error,
917+
nativeLocationOf(_identifier),
918+
"The suffixes \".offset\", \".slot\" and \".length\" can only be used with variables or the suffix \"objectName\" can be used with a contract name identifier."
919+
);
920+
}
921+
else
922+
{
923+
m_errorReporter.typeError(
924+
7944_error,
925+
nativeLocationOf(_identifier),
926+
"The suffixes \".offset\", \".slot\" and \".length\" can only be used with variables."
927+
);
928+
}
902929
return false;
903930
}
904931
else if (_context == yul::IdentifierContext::LValue)
@@ -923,7 +950,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
923950
}
924951
else if (auto contract = dynamic_cast<ContractDefinition const*>(declaration))
925952
{
926-
if (!contract->isLibrary())
953+
if (!contract->isLibrary() && identifierInfo.suffix != "objectName")
927954
{
928955
m_errorReporter.typeError(4977_error, nativeLocationOf(_identifier), "Expected a library.");
929956
return false;

Diff for: libsolidity/analysis/ViewPureChecker.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,11 @@ class AssemblyViewPureChecker
6868
{
6969
if (yul::EVMDialect const* dialect = dynamic_cast<decltype(dialect)>(&m_dialect))
7070
if (yul::BuiltinFunctionForEVM const* builtin = resolveBuiltinFunctionForEVM(_funCall.functionName, *dialect))
71+
{
72+
solAssert(builtin->instruction.has_value());
7173
if (builtin->instruction)
7274
checkInstruction(nativeLocationOf(_funCall), *builtin->instruction);
75+
}
7376

7477
for (auto const& arg: _funCall.arguments)
7578
std::visit(*this, arg);

Diff for: libsolidity/codegen/ir/IRGeneratorForStatements.cpp

+17-1
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,27 @@ struct CopyTranslate: public yul::ASTCopier
105105
yul::Expression translateReference(yul::Identifier const& _identifier)
106106
{
107107
auto const& reference = m_references.at(&_identifier);
108+
std::string value;
109+
110+
if (auto const contractDefinition = dynamic_cast<ContractDefinition const*>(reference.declaration))
111+
{
112+
// Already verified in TypeChecker
113+
solAssert(reference.suffix == "objectName");
114+
solAssert(m_context.eofVersion().has_value());
115+
116+
// Add sub-object as it's referenced from this context
117+
m_context.addSubObject(contractDefinition);
118+
return yul::Literal{
119+
_identifier.debugData,
120+
yul::LiteralKind::String,
121+
yul::LiteralValue{IRNames::creationObject(*contractDefinition)}
122+
};
123+
}
124+
108125
auto const varDecl = dynamic_cast<VariableDeclaration const*>(reference.declaration);
109126
solUnimplementedAssert(varDecl);
110127
std::string const& suffix = reference.suffix;
111128

112-
std::string value;
113129
if (suffix.empty() && varDecl->isLocalVariable())
114130
{
115131
auto const& var = m_context.localVariable(*varDecl);

Diff for: libyul/AsmAnalysis.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -790,12 +790,12 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
790790
yulAssert(m_evmVersion.hasBitwiseShifting() == m_evmVersion.hasCreate2(), "");
791791

792792
// These instructions are disabled in the dialect.
793+
// EOFCREATE instruction is enabled to run ViewPureChecker validation.
793794
yulAssert(
794795
_instr != evmasm::Instruction::JUMP &&
795796
_instr != evmasm::Instruction::JUMPI &&
796797
_instr != evmasm::Instruction::JUMPDEST &&
797798
_instr != evmasm::Instruction::DATALOADN &&
798-
_instr != evmasm::Instruction::EOFCREATE &&
799799
_instr != evmasm::Instruction::RETURNCONTRACT &&
800800
_instr != evmasm::Instruction::RJUMP &&
801801
_instr != evmasm::Instruction::RJUMPI &&
@@ -863,7 +863,8 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
863863
else if (!m_eofVersion.has_value() && (
864864
_instr == evmasm::Instruction::EXTCALL ||
865865
_instr == evmasm::Instruction::EXTDELEGATECALL ||
866-
_instr == evmasm::Instruction::EXTSTATICCALL
866+
_instr == evmasm::Instruction::EXTSTATICCALL ||
867+
_instr == evmasm::Instruction::EOFCREATE
867868
))
868869
{
869870
m_errorReporter.typeError(

Diff for: libyul/backends/evm/EVMDialect.cpp

+25-23
Original file line numberDiff line numberDiff line change
@@ -404,29 +404,6 @@ std::vector<std::optional<BuiltinFunctionForEVM>> createBuiltins(langutil::EVMVe
404404
}
405405
));
406406

407-
builtins.emplace_back(createFunction(
408-
"eofcreate",
409-
5,
410-
1,
411-
EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::EOFCREATE),
412-
ControlFlowSideEffects::fromInstruction(evmasm::Instruction::EOFCREATE),
413-
{LiteralKind::String, std::nullopt, std::nullopt, std::nullopt, std::nullopt},
414-
[](
415-
FunctionCall const& _call,
416-
AbstractAssembly& _assembly,
417-
BuiltinContext& context
418-
) {
419-
yulAssert(_call.arguments.size() == 5);
420-
Literal const* literal = std::get_if<Literal>(&_call.arguments.front());
421-
auto const formattedLiteral = formatLiteral(*literal);
422-
yulAssert(!util::contains(formattedLiteral, '.'));
423-
auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral);
424-
yulAssert(containerID != nullptr);
425-
yulAssert(*containerID <= std::numeric_limits<AbstractAssembly::ContainerID>::max());
426-
_assembly.appendEOFCreate(static_cast<AbstractAssembly::ContainerID>(*containerID));
427-
}
428-
));
429-
430407
builtins.emplace_back(createFunction(
431408
"returncontract",
432409
3,
@@ -451,6 +428,31 @@ std::vector<std::optional<BuiltinFunctionForEVM>> createBuiltins(langutil::EVMVe
451428
}
452429
));
453430
}
431+
432+
builtins.emplace_back(createFunction(
433+
"eofcreate",
434+
5,
435+
1,
436+
EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::EOFCREATE),
437+
ControlFlowSideEffects::fromInstruction(evmasm::Instruction::EOFCREATE),
438+
// TODO: Personaly I don't like this solution but cannot find any better way to prevent 9114 error in asm analysis.
439+
{_objectAccess ? LiteralKind::String : std::optional<LiteralKind>{}, std::nullopt, std::nullopt, std::nullopt, std::nullopt},
440+
[](
441+
FunctionCall const& _call,
442+
AbstractAssembly& _assembly,
443+
BuiltinContext& context
444+
) {
445+
yulAssert(_call.arguments.size() == 5);
446+
Literal const* literal = std::get_if<Literal>(&_call.arguments.front());
447+
auto const formattedLiteral = formatLiteral(*literal);
448+
yulAssert(!util::contains(formattedLiteral, '.'));
449+
auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral);
450+
yulAssert(containerID != nullptr);
451+
yulAssert(*containerID <= std::numeric_limits<AbstractAssembly::ContainerID>::max());
452+
_assembly.appendEOFCreate(static_cast<AbstractAssembly::ContainerID>(*containerID));
453+
}
454+
));
455+
(*builtins.back()).instruction = evmasm::Instruction::EOFCREATE;
454456
}
455457
yulAssert(
456458
ranges::all_of(builtins, [](std::optional<BuiltinFunctionForEVM> const& _builtinFunction){

Diff for: test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
// ----
2020
// DeclarationError 7223: (6-18): Builtin function "auxdataloadn" is only available in EOF.
2121
// DeclarationError 4619: (26-35): Function "dataloadn" not found.
22-
// DeclarationError 7223: (43-52): Builtin function "eofcreate" is only available in EOF.
22+
// TypeError 4328: (43-52): The "eofcreate" instruction is only available in EOF.
2323
// DeclarationError 7223: (77-91): Builtin function "returncontract" is only available in EOF.
2424
// DeclarationError 4619: (110-115): Function "rjump" not found.
2525
// DeclarationError 4619: (122-128): Function "rjumpi" not found.

0 commit comments

Comments
 (0)