Skip to content
Open
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/ast/ASTJsonImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ ASTPointer<InlineAssembly> ASTJsonImporter::createInlineAssembly(Json const& _no
astAssert(evmVersion.has_value(), "Invalid EVM version!");
astAssert(m_evmVersion == evmVersion, "Imported tree evm version differs from configured evm version!");

yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value(), std::nullopt);
yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value());
ASTPointer<std::vector<ASTPointer<ASTString>>> flags;
if (_node.contains("flags"))
{
Expand Down
3 changes: 1 addition & 2 deletions libsolidity/codegen/CompilerContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ void CompilerContext::appendInlineAssembly(
ErrorList errors;
ErrorReporter errorReporter(errors);
langutil::CharStream charStream(_assembly, _sourceName);
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion, std::nullopt);
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion);
std::optional<langutil::SourceLocation> locationOverride;
if (!_system)
locationOverride = m_asm->currentSourceLocation();
Expand Down Expand Up @@ -521,7 +521,6 @@ void CompilerContext::appendInlineAssembly(
analysisInfo,
*m_asm,
m_evmVersion,
std::nullopt,
identifierAccess.generateCode,
_system,
_optimiserSettings.optimizeStackAllocation
Expand Down
1 change: 0 additions & 1 deletion libsolidity/codegen/ContractCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -958,7 +958,6 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
*analysisInfo,
*m_context.assemblyPtr(),
m_context.evmVersion(),
std::nullopt,
identifierAccessCodeGen,
false,
m_optimiserSettings.optimizeStackAllocation
Expand Down
3 changes: 1 addition & 2 deletions libsolidity/interface/CompilerStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,6 @@ YulStack CompilerStack::loadGeneratedIR(std::string const& _ir) const
{
YulStack stack(
m_evmVersion,
std::nullopt,
m_optimiserSettings,
m_debugInfoSelection,
this, // _soliditySourceProvider
Expand Down Expand Up @@ -937,7 +936,7 @@ Json CompilerStack::generatedSources(std::string const& _contractName, bool _run
ErrorList errors;
ErrorReporter errorReporter(errors);
CharStream charStream(source, sourceName);
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion, std::nullopt);
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion);
std::shared_ptr<yul::AST> parserResult = yul::Parser{errorReporter, dialect}.parse(charStream);
solAssert(parserResult);
sources[0]["ast"] = yul::AsmJsonConverter{dialect, sourceIndex}(parserResult->root());
Expand Down
1 change: 0 additions & 1 deletion libsolidity/interface/StandardCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1780,7 +1780,6 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)

YulStack stack(
_inputsAndSettings.evmVersion,
std::nullopt,
_inputsAndSettings.optimiserSettings,
_inputsAndSettings.debugInfoSelection.has_value() ?
_inputsAndSettings.debugInfoSelection.value() :
Expand Down
2 changes: 1 addition & 1 deletion libsolidity/parsing/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1518,7 +1518,7 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
SourceLocation location = currentLocation();

expectToken(Token::Assembly);
yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion, std::nullopt);
yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion);
if (m_scanner->currentToken() == Token::StringLiteral)
{
if (m_scanner->currentLiteral() != "evmasm")
Expand Down
177 changes: 4 additions & 173 deletions libyul/AsmAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ bool AsmAnalyzer::analyze(Block const& _block)
auto watcher = m_errorReporter.errorWatcher();
try
{
// FIXME: Pass location of the object name. Now it's a location of first code section in yul
validateObjectStructure(nativeLocationOf(_block));
if (!(ScopeFiller(m_info, m_errorReporter))(_block))
return false;

Expand Down Expand Up @@ -336,23 +334,6 @@ void AsmAnalyzer::operator()(FunctionDefinition const& _funDef)
m_activeVariables.insert(&std::get<Scope::Variable>(varScope.identifiers.at(var.name)));
}

if (m_eofVersion.has_value())
{
if (_funDef.parameters.size() >= 0x80)
m_errorReporter.typeError(
8534_error,
nativeLocationOf(_funDef),
"Too many function parameters. At most 127 parameters allowed for EOF"
);

if (_funDef.returnVariables.size() >= 0x80)
m_errorReporter.typeError(
2101_error,
nativeLocationOf(_funDef),
"Too many function return variables. At most 127 return variables allowed for EOF"
);
}

(*this)(_funDef.body);
}

Expand Down Expand Up @@ -504,55 +485,9 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall)
"The \"verbatim_*\" builtins cannot be used with empty bytecode."
);
}
else if (functionName == "eofcreate" || functionName == "returncontract")
{
auto const& argumentAsLiteral = std::get<Literal>(arg);
auto const formattedLiteral = formatLiteral(argumentAsLiteral);

if (util::contains(formattedLiteral, '.'))
m_errorReporter.typeError(
2186_error,
nativeLocationOf(arg),
fmt::format("Name required but path given as \"{}\" argument.", functionName)
);

if (!m_objectStructure.topLevelSubObjectNames().count(formattedLiteral))
{
if (m_objectStructure.containsData(formattedLiteral))
m_errorReporter.typeError(
7575_error,
nativeLocationOf(arg),
fmt::format(
"Data name \"{}\" cannot be used as an argument of eofcreate/returncontract. "
"Only an object name is acceptable.",
formattedLiteral
)
);
else
m_errorReporter.typeError(
8970_error,
nativeLocationOf(arg),
fmt::format("Unknown object \"{}\".", formattedLiteral)
);
}
}
expectUnlimitedStringLiteral(std::get<Literal>(arg));
continue;
}
else if (*literalArgumentKind == LiteralKind::Number)
{
std::string_view functionName = resolveFunctionName(_funCall.functionName, m_dialect);
if (functionName == "auxdataloadn")
{
auto const& argumentAsLiteral = std::get<Literal>(arg);
if (argumentAsLiteral.value.value() > std::numeric_limits<uint16_t>::max())
m_errorReporter.typeError(
5202_error,
nativeLocationOf(arg),
"Invalid auxdataloadn argument value. Offset must be in range 0...0xFFFF"
);
}
}
}
expectExpression(arg);
}
Expand Down Expand Up @@ -753,34 +688,11 @@ void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation cons
bool AsmAnalyzer::validateInstructions(std::string_view _instructionIdentifier, langutil::SourceLocation const& _location)
{
// NOTE: This function uses the default EVM version instead of the currently selected one.
auto const& defaultEVMDialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}, std::nullopt);
auto const& defaultEVMDialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion{});
auto const builtinHandle = defaultEVMDialect.findBuiltin(_instructionIdentifier);
if (builtinHandle && defaultEVMDialect.builtin(*builtinHandle).instruction.has_value())
return validateInstructions(*defaultEVMDialect.builtin(*builtinHandle).instruction, _location);

solAssert(!m_eofVersion.has_value() || *m_eofVersion == 1);
auto const& eofDialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion::firstWithEOF(), 1);
auto const eofBuiltinHandle = eofDialect.findBuiltin(_instructionIdentifier);
if (eofBuiltinHandle)
{
auto const builtin = eofDialect.builtin(*eofBuiltinHandle);
if (builtin.instruction.has_value())
return validateInstructions(*builtin.instruction, _location);
// If builtin is available in EOF but not available in legacy (and we build to legacy) generate custom error.
else if (!m_eofVersion.has_value() && !builtinHandle)
{
m_errorReporter.declarationError(
7223_error,
_location,
fmt::format(
"Builtin function \"{function}\" is only available in EOF.",
fmt::arg("function", _instructionIdentifier)
)
);
return true;
}
}

return false;
}

Expand All @@ -796,17 +708,7 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
yulAssert(
_instr != evmasm::Instruction::JUMP &&
_instr != evmasm::Instruction::JUMPI &&
_instr != evmasm::Instruction::JUMPDEST &&
_instr != evmasm::Instruction::DATALOADN &&
_instr != evmasm::Instruction::EOFCREATE &&
_instr != evmasm::Instruction::RETURNCONTRACT &&
_instr != evmasm::Instruction::RJUMP &&
_instr != evmasm::Instruction::RJUMPI &&
_instr != evmasm::Instruction::CALLF &&
_instr != evmasm::Instruction::JUMPF &&
_instr != evmasm::Instruction::RETF &&
_instr != evmasm::Instruction::DUPN &&
_instr != evmasm::Instruction::SWAPN
_instr != evmasm::Instruction::JUMPDEST
);

auto errorForVM = [&](ErrorId _errorId, std::string const& vmKindMessage) {
Expand Down Expand Up @@ -865,60 +767,16 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
"PC instruction is a low-level EVM feature. "
"Because of that PC is disallowed in strict assembly."
);
else if (!m_eofVersion.has_value() && (
_instr == evmasm::Instruction::EXTCALL ||
_instr == evmasm::Instruction::EXTDELEGATECALL ||
_instr == evmasm::Instruction::EXTSTATICCALL
))
{
m_errorReporter.typeError(
4328_error,
_location,
fmt::format(
"The \"{instruction}\" instruction is only available in EOF.",
fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr, m_evmVersion).name))
)
);
}
else if (m_eofVersion.has_value() && (
_instr == evmasm::Instruction::CALL ||
_instr == evmasm::Instruction::CALLCODE ||
_instr == evmasm::Instruction::DELEGATECALL ||
_instr == evmasm::Instruction::STATICCALL ||
_instr == evmasm::Instruction::SELFDESTRUCT ||
_instr == evmasm::Instruction::JUMP ||
_instr == evmasm::Instruction::JUMPI ||
_instr == evmasm::Instruction::PC ||
_instr == evmasm::Instruction::CREATE ||
_instr == evmasm::Instruction::CREATE2 ||
_instr == evmasm::Instruction::CODESIZE ||
_instr == evmasm::Instruction::CODECOPY ||
_instr == evmasm::Instruction::EXTCODESIZE ||
_instr == evmasm::Instruction::EXTCODECOPY ||
_instr == evmasm::Instruction::EXTCODEHASH ||
_instr == evmasm::Instruction::GAS
))
{
m_errorReporter.typeError(
9132_error,
_location,
fmt::format(
"The \"{instruction}\" instruction is {kind} VMs (you are currently compiling to EOF).",
fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr, m_evmVersion).name)),
fmt::arg("kind", "only available in legacy bytecode")
)
);
}
else
{
// Sanity check
solAssert(m_evmVersion.hasOpcode(_instr, m_eofVersion));
solAssert(m_evmVersion.hasOpcode(_instr, std::nullopt));
return false;
}

// Sanity check
// PC is not available in strict assembly but it is always valid opcode in legacy evm.
solAssert(_instr == evmasm::Instruction::PC || !m_evmVersion.hasOpcode(_instr, m_eofVersion));
solAssert(_instr == evmasm::Instruction::PC || !m_evmVersion.hasOpcode(_instr, std::nullopt));
return true;
}

Expand All @@ -930,33 +788,6 @@ bool AsmAnalyzer::validateInstructions(FunctionCall const& _functionCall)
);
}

void AsmAnalyzer::validateObjectStructure(langutil::SourceLocation const& _astRootLocation)
{
if (m_eofVersion.has_value())
{
if (util::contains(m_objectStructure.objectName, '.')) // No dots in object name for EOF
m_errorReporter.syntaxError(
9822_error,
_astRootLocation,
fmt::format(
"The object name \"{objectName}\" is invalid in EOF context. Object names must not contain 'dot' character.",
fmt::arg("objectName", m_objectStructure.objectName)
)
);
else if (m_objectStructure.topLevelSubObjectNames().size() > 256)
{
m_errorReporter.syntaxError(
1305_error,
_astRootLocation,
fmt::format(
"Too many subobjects in \"{objectName}\". At most 256 subobjects allowed when compiling to EOF",
fmt::arg("objectName", m_objectStructure.objectName)
)
);
}
}
}

void AsmAnalyzer::warnIfFutureKeywordOrReservedIdentifier(YulName _identifier, langutil::SourceLocation const& _location)
{
if (
Expand Down
6 changes: 0 additions & 6 deletions libyul/AsmAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,7 @@ class AsmAnalyzer
m_objectStructure(std::move(_objectStructure))
{
if (EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&m_dialect))
{
m_evmVersion = evmDialect->evmVersion();
m_eofVersion = evmDialect->eofVersion();
}
}

bool analyze(Block const& _block);
Expand Down Expand Up @@ -126,8 +123,6 @@ class AsmAnalyzer
bool validateInstructions(std::string_view _instrIdentifier, langutil::SourceLocation const& _location);
bool validateInstructions(FunctionCall const& _functionCall);

void validateObjectStructure(langutil::SourceLocation const& _astRootLocation);

void warnIfFutureKeywordOrReservedIdentifier(YulName _identifier, langutil::SourceLocation const& _location);

yul::ExternalIdentifierAccess::Resolver m_resolver;
Expand All @@ -138,7 +133,6 @@ class AsmAnalyzer
AsmAnalysisInfo& m_info;
langutil::ErrorReporter& m_errorReporter;
langutil::EVMVersion m_evmVersion;
std::optional<uint8_t> m_eofVersion;
Dialect const& m_dialect;
/// Names of data objects to be referenced by builtin functions with literal arguments.
Object::Structure m_objectStructure;
Expand Down
6 changes: 2 additions & 4 deletions libyul/ObjectOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ void ObjectOptimizer::optimize(Object& _object, Settings const& _settings, bool
);
}

EVMDialect const& dialect = EVMDialect::strictAssemblyForEVMObjects(_settings.evmVersion, _settings.eofVersion);
EVMDialect const& dialect = EVMDialect::strictAssemblyForEVMObjects(_settings.evmVersion);
GasMeter const meter(dialect, _isCreation, _settings.expectedExecutionsPerDeployment);

std::optional<h256> cacheKey = calculateCacheKey(_object.code()->root(), *_object.debugData, _settings, _isCreation);
Expand Down Expand Up @@ -128,7 +128,7 @@ std::optional<h256> ObjectOptimizer::calculateCacheKey(
)
{
AsmPrinter asmPrinter(
EVMDialect::strictAssemblyForEVMObjects(_settings.evmVersion, _settings.eofVersion),
EVMDialect::strictAssemblyForEVMObjects(_settings.evmVersion),
_debugData.sourceNames,
DebugInfoSelection::All()
);
Expand All @@ -145,8 +145,6 @@ std::optional<h256> ObjectOptimizer::calculateCacheKey(
rawKey += h256(u256(_settings.expectedExecutionsPerDeployment)).asBytes();
rawKey += FixedHash<1>(static_cast<uint8_t>(_isCreation)).asBytes();
rawKey += keccak256(_settings.evmVersion.name()).asBytes();
yulAssert(!_settings.eofVersion.has_value() || *_settings.eofVersion > 0);
rawKey += FixedHash<1>(static_cast<uint8_t>(_settings.eofVersion ? *_settings.eofVersion : 0)).asBytes();
rawKey += keccak256(_settings.yulOptimiserSteps).asBytes();
rawKey += keccak256(_settings.yulOptimiserCleanupSteps).asBytes();

Expand Down
1 change: 0 additions & 1 deletion libyul/ObjectOptimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ class ObjectOptimizer
struct Settings
{
langutil::EVMVersion evmVersion;
std::optional<uint8_t> eofVersion;
bool optimizeStackAllocation;
std::string yulOptimiserSteps;
std::string yulOptimiserCleanupSteps;
Expand Down
Loading