diff options
author | chriseth <chris@ethereum.org> | 2018-11-14 02:33:35 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-14 02:33:35 +0800 |
commit | 1d4f565a64988a3400847d2655ca24f73f234bc6 (patch) | |
tree | caaa6c26e307513505349b50ca4f2a8a9506752b /libsolidity/inlineasm | |
parent | 59dbf8f1085b8b92e8b7eb0ce380cbeb642e97eb (diff) | |
parent | 91b6b8a88e76016e0324036cb7a7f9300a1e2439 (diff) | |
download | dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.gz dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.bz2 dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.lz dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.xz dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.zst dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.zip |
Merge pull request #5416 from ethereum/develop
Merge develop into release for 0.5.0
Diffstat (limited to 'libsolidity/inlineasm')
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.cpp | 53 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.h | 6 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmCodeGen.cpp | 10 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmCodeGen.h | 4 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmData.h | 19 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmDataForward.h | 4 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmParser.cpp | 57 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmPrinter.cpp | 53 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmPrinter.h | 9 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmScope.cpp | 12 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmScope.h | 55 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmScopeFiller.cpp | 14 |
12 files changed, 152 insertions, 144 deletions
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index 9f505889..ac019c06 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -57,7 +57,7 @@ bool AsmAnalyzer::operator()(Label const& _label) solAssert(!_label.name.empty(), ""); checkLooseFeature( _label.location, - "The use of labels is deprecated. Please use \"if\", \"switch\", \"for\" or function calls instead." + "The use of labels is disallowed. Please use \"if\", \"switch\", \"for\" or function calls instead." ); m_info.stackHeightInfo[&_label] = m_stackHeight; warnOnInstructions(solidity::Instruction::JUMPDEST, _label.location); @@ -68,7 +68,7 @@ bool AsmAnalyzer::operator()(assembly::Instruction const& _instruction) { checkLooseFeature( _instruction.location, - "The use of non-functional instructions is deprecated. Please use functional notation instead." + "The use of non-functional instructions is disallowed. Please use functional notation instead." ); auto const& info = instructionInfo(_instruction.instruction); m_stackHeight += info.ret - info.args; @@ -79,17 +79,17 @@ bool AsmAnalyzer::operator()(assembly::Instruction const& _instruction) bool AsmAnalyzer::operator()(assembly::Literal const& _literal) { - expectValidType(_literal.type, _literal.location); + expectValidType(_literal.type.str(), _literal.location); ++m_stackHeight; - if (_literal.kind == assembly::LiteralKind::String && _literal.value.size() > 32) + if (_literal.kind == assembly::LiteralKind::String && _literal.value.str().size() > 32) { m_errorReporter.typeError( _literal.location, - "String literal too long (" + boost::lexical_cast<std::string>(_literal.value.size()) + " > 32)" + "String literal too long (" + to_string(_literal.value.str().size()) + " > 32)" ); return false; } - else if (_literal.kind == assembly::LiteralKind::Number && bigint(_literal.value) > u256(-1)) + else if (_literal.kind == assembly::LiteralKind::Number && bigint(_literal.value.str()) > u256(-1)) { m_errorReporter.typeError( _literal.location, @@ -99,8 +99,8 @@ bool AsmAnalyzer::operator()(assembly::Literal const& _literal) } else if (_literal.kind == assembly::LiteralKind::Boolean) { - solAssert(m_flavour == AsmFlavour::IULIA, ""); - solAssert(_literal.value == "true" || _literal.value == "false", ""); + solAssert(m_flavour == AsmFlavour::Yul, ""); + solAssert(_literal.value == YulString{string("true")} || _literal.value == YulString{string("false")}, ""); } m_info.stackHeightInfo[&_literal] = m_stackHeight; return true; @@ -118,7 +118,7 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier) { m_errorReporter.declarationError( _identifier.location, - "Variable " + _identifier.name + " used before it was declared." + "Variable " + _identifier.name.str() + " used before it was declared." ); success = false; } @@ -132,7 +132,7 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier) { m_errorReporter.typeError( _identifier.location, - "Function " + _identifier.name + " used without being called." + "Function " + _identifier.name.str() + " used without being called." ); success = false; } @@ -145,7 +145,7 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier) if (m_resolver) { bool insideFunction = m_currentScope->insideFunction(); - stackSize = m_resolver(_identifier, julia::IdentifierContext::RValue, insideFunction); + stackSize = m_resolver(_identifier, yul::IdentifierContext::RValue, insideFunction); } if (stackSize == size_t(-1)) { @@ -162,7 +162,7 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier) bool AsmAnalyzer::operator()(FunctionalInstruction const& _instr) { - solAssert(m_flavour != AsmFlavour::IULIA, ""); + solAssert(m_flavour != AsmFlavour::Yul, ""); bool success = true; for (auto const& arg: _instr.arguments | boost::adaptors::reversed) if (!expectExpression(arg)) @@ -185,7 +185,7 @@ bool AsmAnalyzer::operator()(assembly::ExpressionStatement const& _statement) Error::Type errorType = m_flavour == AsmFlavour::Loose ? *m_errorTypeForLoose : Error::Type::TypeError; string msg = "Top-level expressions are not supposed to return values (this expression returns " + - boost::lexical_cast<string>(m_stackHeight - initialStackHeight) + + to_string(m_stackHeight - initialStackHeight) + " value" + (m_stackHeight - initialStackHeight == 1 ? "" : "s") + "). Use ``pop()`` or assign them."; @@ -201,7 +201,7 @@ bool AsmAnalyzer::operator()(assembly::StackAssignment const& _assignment) { checkLooseFeature( _assignment.location, - "The use of stack assignment is deprecated. Please use assignment in functional notation instead." + "The use of stack assignment is disallowed. Please use assignment in functional notation instead." ); bool success = checkAssignment(_assignment.variableName, size_t(-1)); m_info.stackHeightInfo[&_assignment] = m_stackHeight; @@ -253,7 +253,7 @@ bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl) for (auto const& variable: _varDecl.variables) { - expectValidType(variable.type, variable.location); + expectValidType(variable.type.str(), variable.location); m_activeVariables.insert(&boost::get<Scope::Variable>(m_currentScope->identifiers.at(variable.name))); } m_info.stackHeightInfo[&_varDecl] = m_stackHeight; @@ -268,7 +268,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef) Scope& varScope = scope(virtualBlock); for (auto const& var: _funDef.parameters + _funDef.returnVariables) { - expectValidType(var.type, var.location); + expectValidType(var.type.str(), var.location); m_activeVariables.insert(&boost::get<Scope::Variable>(varScope.identifiers.at(var.name))); } @@ -322,8 +322,8 @@ bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall) { m_errorReporter.typeError( _funCall.functionName.location, - "Expected " + boost::lexical_cast<string>(arguments) + " arguments but got " + - boost::lexical_cast<string>(_funCall.arguments.size()) + "." + "Expected " + to_string(arguments) + " arguments but got " + + to_string(_funCall.arguments.size()) + "." ); success = false; } @@ -361,7 +361,7 @@ bool AsmAnalyzer::operator()(Switch const& _switch) if (!expectExpression(*_switch.expression)) success = false; - set<tuple<LiteralKind, string>> cases; + set<tuple<LiteralKind, YulString>> cases; for (auto const& _case: _switch.cases) { if (_case.value) @@ -477,7 +477,7 @@ bool AsmAnalyzer::expectDeposit(int _deposit, int _oldHeight, SourceLocation con m_errorReporter.typeError( _location, "Expected expression to return one item to the stack, but did return " + - boost::lexical_cast<string>(m_stackHeight - _oldHeight) + + to_string(m_stackHeight - _oldHeight) + " items." ); return false; @@ -503,7 +503,7 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t { m_errorReporter.declarationError( _variable.location, - "Variable " + _variable.name + " used before it was declared." + "Variable " + _variable.name.str() + " used before it was declared." ); success = false; } @@ -512,7 +512,7 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t else if (m_resolver) { bool insideFunction = m_currentScope->insideFunction(); - variableSize = m_resolver(_variable, julia::IdentifierContext::LValue, insideFunction); + variableSize = m_resolver(_variable, yul::IdentifierContext::LValue, insideFunction); } if (variableSize == size_t(-1)) { @@ -550,7 +550,7 @@ Scope& AsmAnalyzer::scope(Block const* _block) } void AsmAnalyzer::expectValidType(string const& type, SourceLocation const& _location) { - if (m_flavour != AsmFlavour::IULIA) + if (m_flavour != AsmFlavour::Yul) return; if (!builtinTypes.count(type)) @@ -565,8 +565,10 @@ void AsmAnalyzer::warnOnInstructions(solidity::Instruction _instr, SourceLocatio // We assume that returndatacopy, returndatasize and staticcall are either all available // or all not available. solAssert(m_evmVersion.supportsReturndata() == m_evmVersion.hasStaticCall(), ""); + // Similarly we assume bitwise shifting and create2 go together. + solAssert(m_evmVersion.hasBitwiseShifting() == m_evmVersion.hasCreate2(), ""); - if (_instr == solidity::Instruction::CREATE2) + if (_instr == solidity::Instruction::EXTCODEHASH) m_errorReporter.warning( _location, "The \"" + @@ -593,7 +595,8 @@ void AsmAnalyzer::warnOnInstructions(solidity::Instruction _instr, SourceLocatio else if (( _instr == solidity::Instruction::SHL || _instr == solidity::Instruction::SHR || - _instr == solidity::Instruction::SAR + _instr == solidity::Instruction::SAR || + _instr == solidity::Instruction::CREATE2 ) && !m_evmVersion.hasBitwiseShifting()) m_errorReporter.warning( _location, diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h index 8d2a71f0..a8673efa 100644 --- a/libsolidity/inlineasm/AsmAnalysis.h +++ b/libsolidity/inlineasm/AsmAnalysis.h @@ -25,7 +25,7 @@ #include <libsolidity/inlineasm/AsmScope.h> -#include <libjulia/backends/evm/AbstractAssembly.h> +#include <libyul/backends/evm/AbstractAssembly.h> #include <libsolidity/inlineasm/AsmDataForward.h> @@ -59,7 +59,7 @@ public: EVMVersion _evmVersion, boost::optional<Error::Type> _errorTypeForLoose, AsmFlavour _flavour = AsmFlavour::Loose, - julia::ExternalIdentifierAccess::Resolver const& _resolver = julia::ExternalIdentifierAccess::Resolver() + yul::ExternalIdentifierAccess::Resolver const& _resolver = yul::ExternalIdentifierAccess::Resolver() ): m_resolver(_resolver), m_info(_analysisInfo), @@ -106,7 +106,7 @@ private: void checkLooseFeature(SourceLocation const& _location, std::string const& _description); int m_stackHeight = 0; - julia::ExternalIdentifierAccess::Resolver m_resolver; + yul::ExternalIdentifierAccess::Resolver m_resolver; Scope* m_currentScope = nullptr; /// Variables that are active at the current point in assembly (as opposed to /// "part of the scope but not yet declared") diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index dded9f76..3a62b232 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -32,8 +32,8 @@ #include <libevmasm/SourceLocation.h> #include <libevmasm/Instruction.h> -#include <libjulia/backends/evm/AbstractAssembly.h> -#include <libjulia/backends/evm/EVMCodeTransform.h> +#include <libyul/backends/evm/AbstractAssembly.h> +#include <libyul/backends/evm/EVMCodeTransform.h> #include <libdevcore/CommonIO.h> @@ -49,7 +49,7 @@ using namespace dev; using namespace dev::solidity; using namespace dev::solidity::assembly; -class EthAssemblyAdapter: public julia::AbstractAssembly +class EthAssemblyAdapter: public yul::AbstractAssembly { public: explicit EthAssemblyAdapter(eth::Assembly& _assembly): @@ -145,12 +145,12 @@ void assembly::CodeGenerator::assemble( Block const& _parsedData, AsmAnalysisInfo& _analysisInfo, eth::Assembly& _assembly, - julia::ExternalIdentifierAccess const& _identifierAccess, + yul::ExternalIdentifierAccess const& _identifierAccess, bool _useNamedLabelsForFunctions ) { EthAssemblyAdapter assemblyAdapter(_assembly); - julia::CodeTransform( + yul::CodeTransform( assemblyAdapter, _analysisInfo, false, diff --git a/libsolidity/inlineasm/AsmCodeGen.h b/libsolidity/inlineasm/AsmCodeGen.h index a7d7ead1..bbc31397 100644 --- a/libsolidity/inlineasm/AsmCodeGen.h +++ b/libsolidity/inlineasm/AsmCodeGen.h @@ -41,12 +41,12 @@ struct Block; class CodeGenerator { public: - /// Performs code generation and appends generated to to _assembly. + /// Performs code generation and appends generated to _assembly. static void assemble( Block const& _parsedData, AsmAnalysisInfo& _analysisInfo, eth::Assembly& _assembly, - julia::ExternalIdentifierAccess const& _identifierAccess = julia::ExternalIdentifierAccess(), + yul::ExternalIdentifierAccess const& _identifierAccess = yul::ExternalIdentifierAccess(), bool _useNamedLabelsForFunctions = false ); }; diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h index 2982d5e0..a8d5e327 100644 --- a/libsolidity/inlineasm/AsmData.h +++ b/libsolidity/inlineasm/AsmData.h @@ -27,7 +27,13 @@ #include <libevmasm/Instruction.h> #include <libevmasm/SourceLocation.h> +#include <libyul/YulString.h> + #include <boost/variant.hpp> +#include <boost/noncopyable.hpp> + +#include <map> +#include <memory> namespace dev { @@ -36,20 +42,21 @@ namespace solidity namespace assembly { -using Type = std::string; +using YulString = dev::yul::YulString; +using Type = YulString; -struct TypedName { SourceLocation location; std::string name; Type type; }; +struct TypedName { SourceLocation location; YulString name; Type type; }; using TypedNameList = std::vector<TypedName>; /// Direct EVM instruction (except PUSHi and JUMPDEST) struct Instruction { SourceLocation location; solidity::Instruction instruction; }; /// Literal number or string (up to 32 bytes) enum class LiteralKind { Number, Boolean, String }; -struct Literal { SourceLocation location; LiteralKind kind; std::string value; Type type; }; +struct Literal { SourceLocation location; LiteralKind kind; YulString value; Type type; }; /// External / internal identifier or label reference -struct Identifier { SourceLocation location; std::string name; }; +struct Identifier { SourceLocation location; YulString name; }; /// Jump label ("name:") -struct Label { SourceLocation location; std::string name; }; +struct Label { SourceLocation location; YulString name; }; /// Assignment from stack (":= x", moves stack top into x, potentially multiple slots) struct StackAssignment { SourceLocation location; Identifier variableName; }; /// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand @@ -69,7 +76,7 @@ struct VariableDeclaration { SourceLocation location; TypedNameList variables; s /// Block that creates a scope (frees declared stack variables) struct Block { SourceLocation location; std::vector<Statement> statements; }; /// Function definition ("function f(a, b) -> (d, e) { ... }") -struct FunctionDefinition { SourceLocation location; std::string name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; +struct FunctionDefinition { SourceLocation location; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; /// Conditional execution without "else" part. struct If { SourceLocation location; std::shared_ptr<Expression> condition; Block body; }; /// Switch case or default case diff --git a/libsolidity/inlineasm/AsmDataForward.h b/libsolidity/inlineasm/AsmDataForward.h index 3a9600fe..69cf8f1d 100644 --- a/libsolidity/inlineasm/AsmDataForward.h +++ b/libsolidity/inlineasm/AsmDataForward.h @@ -17,7 +17,7 @@ /** * @author Christian <c@ethdev.com> * @date 2016 - * Forward declaration of classes for inline assembly / JULIA AST + * Forward declaration of classes for inline assembly / Yul AST */ #pragma once @@ -57,7 +57,7 @@ enum class AsmFlavour { Loose, // no types, EVM instructions as function, jumps and direct stack manipulations Strict, // no types, EVM instructions as functions, but no jumps and no direct stack manipulations - IULIA // same as Strict mode with types + Yul // same as Strict mode with types }; } diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index d3b0808b..1f399edc 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -26,7 +26,7 @@ #include <boost/algorithm/string.hpp> -#include <ctype.h> +#include <cctype> #include <algorithm> using namespace std; @@ -97,7 +97,7 @@ assembly::Statement Parser::parseStatement() fatalParserError("Only one default case allowed."); else if (m_scanner->currentToken() == Token::Case) fatalParserError("Case not allowed after default case."); - if (_switch.cases.size() == 0) + if (_switch.cases.empty()) fatalParserError("Switch statement without any cases."); _switch.location.end = _switch.cases.back().body.location.end; return _switch; @@ -112,8 +112,8 @@ assembly::Statement Parser::parseStatement() advance(); expectToken(Token::Colon); assignment.variableName.location = location(); - assignment.variableName.name = currentLiteral(); - if (instructions().count(assignment.variableName.name)) + assignment.variableName.name = YulString(currentLiteral()); + if (instructions().count(assignment.variableName.name.str())) fatalParserError("Identifier expected, got instruction name."); assignment.location.end = endPosition(); expectToken(Token::Identifier); @@ -150,7 +150,7 @@ assembly::Statement Parser::parseStatement() expectToken(Token::Comma); elementary = parseElementaryOperation(); if (elementary.type() != typeid(assembly::Identifier)) - fatalParserError("Variable name expected in multiple assignemnt."); + fatalParserError("Variable name expected in multiple assignment."); assignment.variableNames.emplace_back(boost::get<assembly::Identifier>(elementary)); } while (currentToken() == Token::Comma); @@ -173,7 +173,7 @@ assembly::Statement Parser::parseStatement() if (currentToken() == Token::Assign && peekNextToken() != Token::Colon) { assembly::Assignment assignment = createWithLocation<assembly::Assignment>(identifier.location); - if (m_flavour != AsmFlavour::IULIA && instructions().count(identifier.name)) + if (m_flavour != AsmFlavour::Yul && instructions().count(identifier.name.str())) fatalParserError("Cannot use instruction names for identifier names."); advance(); assignment.variableNames.emplace_back(identifier); @@ -279,7 +279,7 @@ assembly::Expression Parser::parseExpression() "Expected '(' (instruction \"" + instructionNames().at(instr.instruction) + "\" expects " + - boost::lexical_cast<string>(args) + + to_string(args) + " arguments)" )); } @@ -318,11 +318,6 @@ std::map<string, dev::solidity::Instruction> const& Parser::instructions() transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); }); s_instructions[name] = instruction.second; } - - // add alias for suicide - s_instructions["suicide"] = solidity::Instruction::SELFDESTRUCT; - // add alis for sha3 - s_instructions["sha3"] = solidity::Instruction::KECCAK256; } return s_instructions; } @@ -362,13 +357,13 @@ Parser::ElementaryOperation Parser::parseElementaryOperation() else literal = currentLiteral(); // first search the set of instructions. - if (m_flavour != AsmFlavour::IULIA && instructions().count(literal)) + if (m_flavour != AsmFlavour::Yul && instructions().count(literal)) { dev::solidity::Instruction const& instr = instructions().at(literal); ret = Instruction{location(), instr}; } else - ret = Identifier{location(), literal}; + ret = Identifier{location(), YulString{literal}}; advance(); break; } @@ -399,15 +394,15 @@ Parser::ElementaryOperation Parser::parseElementaryOperation() Literal literal{ location(), kind, - currentLiteral(), - "" + YulString{currentLiteral()}, + {} }; advance(); - if (m_flavour == AsmFlavour::IULIA) + if (m_flavour == AsmFlavour::Yul) { expectToken(Token::Colon); literal.location.end = endPosition(); - literal.type = expectAsmIdentifier(); + literal.type = YulString{expectAsmIdentifier()}; } else if (kind == LiteralKind::Boolean) fatalParserError("True and false are not valid literals."); @@ -416,7 +411,7 @@ Parser::ElementaryOperation Parser::parseElementaryOperation() } default: fatalParserError( - m_flavour == AsmFlavour::IULIA ? + m_flavour == AsmFlavour::Yul ? "Literal or identifier expected." : "Literal, identifier or instruction expected." ); @@ -454,7 +449,7 @@ assembly::FunctionDefinition Parser::parseFunctionDefinition() RecursionGuard recursionGuard(*this); FunctionDefinition funDef = createWithLocation<FunctionDefinition>(); expectToken(Token::Function); - funDef.name = expectAsmIdentifier(); + funDef.name = YulString{expectAsmIdentifier()}; expectToken(Token::LParen); while (currentToken() != Token::RParen) { @@ -486,7 +481,7 @@ assembly::Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) RecursionGuard recursionGuard(*this); if (_initialOp.type() == typeid(Instruction)) { - solAssert(m_flavour != AsmFlavour::IULIA, "Instructions are invalid in JULIA"); + solAssert(m_flavour != AsmFlavour::Yul, "Instructions are invalid in Yul"); Instruction& instruction = boost::get<Instruction>(_initialOp); FunctionalInstruction ret; ret.instruction = instruction.instruction; @@ -507,7 +502,7 @@ assembly::Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) "Expected expression (instruction \"" + instructionNames().at(instr) + "\" expects " + - boost::lexical_cast<string>(args) + + to_string(args) + " arguments)" )); @@ -519,7 +514,7 @@ assembly::Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) "Expected ',' (instruction \"" + instructionNames().at(instr) + "\" expects " + - boost::lexical_cast<string>(args) + + to_string(args) + " arguments)" )); else @@ -532,7 +527,7 @@ assembly::Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) "Expected ')' (instruction \"" + instructionNames().at(instr) + "\" expects " + - boost::lexical_cast<string>(args) + + to_string(args) + " arguments)" )); expectToken(Token::RParen); @@ -557,7 +552,7 @@ assembly::Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) } else fatalParserError( - m_flavour == AsmFlavour::IULIA ? + m_flavour == AsmFlavour::Yul ? "Function name expected." : "Assembly instruction or function name required in front of \"(\")" ); @@ -569,12 +564,12 @@ TypedName Parser::parseTypedName() { RecursionGuard recursionGuard(*this); TypedName typedName = createWithLocation<TypedName>(); - typedName.name = expectAsmIdentifier(); - if (m_flavour == AsmFlavour::IULIA) + typedName.name = YulString{expectAsmIdentifier()}; + if (m_flavour == AsmFlavour::Yul) { expectToken(Token::Colon); typedName.location.end = endPosition(); - typedName.type = expectAsmIdentifier(); + typedName.type = YulString{expectAsmIdentifier()}; } return typedName; } @@ -582,7 +577,7 @@ TypedName Parser::parseTypedName() string Parser::expectAsmIdentifier() { string name = currentLiteral(); - if (m_flavour == AsmFlavour::IULIA) + if (m_flavour == AsmFlavour::Yul) { switch (currentToken()) { @@ -606,7 +601,9 @@ bool Parser::isValidNumberLiteral(string const& _literal) { try { - u256(_literal); + // Try to convert _literal to u256. + auto tmp = u256(_literal); + (void) tmp; } catch (...) { diff --git a/libsolidity/inlineasm/AsmPrinter.cpp b/libsolidity/inlineasm/AsmPrinter.cpp index bacd7a94..ae0bd1eb 100644 --- a/libsolidity/inlineasm/AsmPrinter.cpp +++ b/libsolidity/inlineasm/AsmPrinter.cpp @@ -24,6 +24,8 @@ #include <libsolidity/inlineasm/AsmData.h> #include <libsolidity/interface/Exceptions.h> +#include <libdevcore/CommonData.h> + #include <boost/algorithm/string.hpp> #include <boost/algorithm/string/replace.hpp> #include <boost/range/adaptor/transformed.hpp> @@ -40,7 +42,8 @@ using namespace dev::solidity::assembly; string AsmPrinter::operator()(assembly::Instruction const& _instruction) { - solAssert(!m_julia, ""); + solAssert(!m_yul, ""); + solAssert(isValidInstruction(_instruction.instruction), "Invalid instruction"); return boost::to_lower_copy(instructionInfo(_instruction.instruction).name); } @@ -49,15 +52,17 @@ string AsmPrinter::operator()(assembly::Literal const& _literal) switch (_literal.kind) { case LiteralKind::Number: - return _literal.value + appendTypeName(_literal.type); + solAssert(isValidDecimal(_literal.value.str()) || isValidHex(_literal.value.str()), "Invalid number literal"); + return _literal.value.str() + appendTypeName(_literal.type); case LiteralKind::Boolean: - return ((_literal.value == "true") ? "true" : "false") + appendTypeName(_literal.type); + solAssert(_literal.value.str() == "true" || _literal.value.str() == "false", "Invalid bool literal."); + return ((_literal.value.str() == "true") ? "true" : "false") + appendTypeName(_literal.type); case LiteralKind::String: break; } string out; - for (char c: _literal.value) + for (char c: _literal.value.str()) if (c == '\\') out += "\\\\"; else if (c == '"') @@ -87,18 +92,20 @@ string AsmPrinter::operator()(assembly::Literal const& _literal) string AsmPrinter::operator()(assembly::Identifier const& _identifier) { - return _identifier.name; + solAssert(!_identifier.name.empty(), "Invalid identifier."); + return _identifier.name.str(); } string AsmPrinter::operator()(assembly::FunctionalInstruction const& _functionalInstruction) { - solAssert(!m_julia, ""); + solAssert(!m_yul, ""); + solAssert(isValidInstruction(_functionalInstruction.instruction), "Invalid instruction"); return boost::to_lower_copy(instructionInfo(_functionalInstruction.instruction).name) + "(" + boost::algorithm::join( _functionalInstruction.arguments | boost::adaptors::transformed(boost::apply_visitor(*this)), - ", " ) + + ", ") + ")"; } @@ -109,13 +116,15 @@ string AsmPrinter::operator()(ExpressionStatement const& _statement) string AsmPrinter::operator()(assembly::Label const& _label) { - solAssert(!m_julia, ""); - return _label.name + ":"; + solAssert(!m_yul, ""); + solAssert(!_label.name.empty(), "Invalid label."); + return _label.name.str() + ":"; } string AsmPrinter::operator()(assembly::StackAssignment const& _assignment) { - solAssert(!m_julia, ""); + solAssert(!m_yul, ""); + solAssert(!_assignment.variableName.name.empty(), "Invalid variable name."); return "=: " + (*this)(_assignment.variableName); } @@ -133,7 +142,7 @@ string AsmPrinter::operator()(assembly::VariableDeclaration const& _variableDecl string out = "let "; out += boost::algorithm::join( _variableDeclaration.variables | boost::adaptors::transformed( - [this](TypedName variable) { return variable.name + appendTypeName(variable.type); } + [this](TypedName argument) { return formatTypedName(argument); } ), ", " ); @@ -147,10 +156,11 @@ string AsmPrinter::operator()(assembly::VariableDeclaration const& _variableDecl string AsmPrinter::operator()(assembly::FunctionDefinition const& _functionDefinition) { - string out = "function " + _functionDefinition.name + "("; + solAssert(!_functionDefinition.name.empty(), "Invalid function name."); + string out = "function " + _functionDefinition.name.str() + "("; out += boost::algorithm::join( _functionDefinition.parameters | boost::adaptors::transformed( - [this](TypedName argument) { return argument.name + appendTypeName(argument.type); } + [this](TypedName argument) { return formatTypedName(argument); } ), ", " ); @@ -160,7 +170,7 @@ string AsmPrinter::operator()(assembly::FunctionDefinition const& _functionDefin out += " -> "; out += boost::algorithm::join( _functionDefinition.returnVariables | boost::adaptors::transformed( - [this](TypedName argument) { return argument.name + appendTypeName(argument.type); } + [this](TypedName argument) { return formatTypedName(argument); } ), ", " ); @@ -181,11 +191,13 @@ string AsmPrinter::operator()(assembly::FunctionCall const& _functionCall) string AsmPrinter::operator()(If const& _if) { + solAssert(_if.condition, "Invalid if condition."); return "if " + boost::apply_visitor(*this, *_if.condition) + "\n" + (*this)(_if.body); } string AsmPrinter::operator()(Switch const& _switch) { + solAssert(_switch.expression, "Invalid expression pointer."); string out = "switch " + boost::apply_visitor(*this, *_switch.expression); for (auto const& _case: _switch.cases) { @@ -200,6 +212,7 @@ string AsmPrinter::operator()(Switch const& _switch) string AsmPrinter::operator()(assembly::ForLoop const& _forLoop) { + solAssert(_forLoop.condition, "Invalid for loop condition."); string out = "for "; out += (*this)(_forLoop.pre); out += "\n"; @@ -223,9 +236,15 @@ string AsmPrinter::operator()(Block const& _block) return "{\n " + body + "\n}"; } -string AsmPrinter::appendTypeName(std::string const& _type) const +string AsmPrinter::formatTypedName(TypedName _variable) const +{ + solAssert(!_variable.name.empty(), "Invalid variable name."); + return _variable.name.str() + appendTypeName(_variable.type); +} + +string AsmPrinter::appendTypeName(YulString _type) const { - if (m_julia) - return ":" + _type; + if (m_yul) + return ":" + _type.str(); return ""; } diff --git a/libsolidity/inlineasm/AsmPrinter.h b/libsolidity/inlineasm/AsmPrinter.h index 5bd87aba..72048975 100644 --- a/libsolidity/inlineasm/AsmPrinter.h +++ b/libsolidity/inlineasm/AsmPrinter.h @@ -24,6 +24,8 @@ #include <libsolidity/inlineasm/AsmDataForward.h> +#include <libyul/YulString.h> + #include <boost/variant.hpp> namespace dev @@ -36,7 +38,7 @@ namespace assembly class AsmPrinter: public boost::static_visitor<std::string> { public: - explicit AsmPrinter(bool _julia = false): m_julia(_julia) {} + explicit AsmPrinter(bool _yul = false): m_yul(_yul) {} std::string operator()(assembly::Instruction const& _instruction); std::string operator()(assembly::Literal const& _literal); @@ -55,9 +57,10 @@ public: std::string operator()(assembly::Block const& _block); private: - std::string appendTypeName(std::string const& _type) const; + std::string formatTypedName(TypedName _variable) const; + std::string appendTypeName(yul::YulString _type) const; - bool m_julia = false; + bool m_yul = false; }; } diff --git a/libsolidity/inlineasm/AsmScope.cpp b/libsolidity/inlineasm/AsmScope.cpp index 64d5bd9a..10893b96 100644 --- a/libsolidity/inlineasm/AsmScope.cpp +++ b/libsolidity/inlineasm/AsmScope.cpp @@ -21,10 +21,10 @@ #include <libsolidity/inlineasm/AsmScope.h> using namespace std; +using namespace dev; using namespace dev::solidity::assembly; - -bool Scope::registerLabel(string const& _name) +bool Scope::registerLabel(yul::YulString _name) { if (exists(_name)) return false; @@ -32,7 +32,7 @@ bool Scope::registerLabel(string const& _name) return true; } -bool Scope::registerVariable(string const& _name, JuliaType const& _type) +bool Scope::registerVariable(yul::YulString _name, YulType const& _type) { if (exists(_name)) return false; @@ -42,7 +42,7 @@ bool Scope::registerVariable(string const& _name, JuliaType const& _type) return true; } -bool Scope::registerFunction(string const& _name, std::vector<JuliaType> const& _arguments, std::vector<JuliaType> const& _returns) +bool Scope::registerFunction(yul::YulString _name, std::vector<YulType> const& _arguments, std::vector<YulType> const& _returns) { if (exists(_name)) return false; @@ -50,7 +50,7 @@ bool Scope::registerFunction(string const& _name, std::vector<JuliaType> const& return true; } -Scope::Identifier* Scope::lookup(string const& _name) +Scope::Identifier* Scope::lookup(yul::YulString _name) { bool crossedFunctionBoundary = false; for (Scope* s = this; s; s = s->superScope) @@ -70,7 +70,7 @@ Scope::Identifier* Scope::lookup(string const& _name) return nullptr; } -bool Scope::exists(string const& _name) const +bool Scope::exists(yul::YulString _name) const { if (identifiers.count(_name)) return true; diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h index 447d6490..65848018 100644 --- a/libsolidity/inlineasm/AsmScope.h +++ b/libsolidity/inlineasm/AsmScope.h @@ -22,6 +22,10 @@ #include <libsolidity/interface/Exceptions.h> +#include <libyul/YulString.h> + +#include <libdevcore/Visitor.h> + #include <boost/variant.hpp> #include <boost/optional.hpp> @@ -35,54 +39,29 @@ namespace solidity namespace assembly { -template <class...> -struct GenericVisitor{}; - -template <class Visitable, class... Others> -struct GenericVisitor<Visitable, Others...>: public GenericVisitor<Others...> -{ - using GenericVisitor<Others...>::operator (); - explicit GenericVisitor( - std::function<void(Visitable&)> _visitor, - std::function<void(Others&)>... _otherVisitors - ): - GenericVisitor<Others...>(_otherVisitors...), - m_visitor(_visitor) - {} - - void operator()(Visitable& _v) const { m_visitor(_v); } - - std::function<void(Visitable&)> m_visitor; -}; -template <> -struct GenericVisitor<>: public boost::static_visitor<> { - void operator()() const {} -}; - - struct Scope { - using JuliaType = std::string; + using YulType = yul::YulString; using LabelID = size_t; - struct Variable { JuliaType type; }; + struct Variable { YulType type; }; struct Label { }; struct Function { - std::vector<JuliaType> arguments; - std::vector<JuliaType> returns; + std::vector<YulType> arguments; + std::vector<YulType> returns; }; using Identifier = boost::variant<Variable, Label, Function>; using Visitor = GenericVisitor<Variable const, Label const, Function const>; using NonconstVisitor = GenericVisitor<Variable, Label, Function>; - bool registerVariable(std::string const& _name, JuliaType const& _type); - bool registerLabel(std::string const& _name); + bool registerVariable(yul::YulString _name, YulType const& _type); + bool registerLabel(yul::YulString _name); bool registerFunction( - std::string const& _name, - std::vector<JuliaType> const& _arguments, - std::vector<JuliaType> const& _returns + yul::YulString _name, + std::vector<YulType> const& _arguments, + std::vector<YulType> const& _returns ); /// Looks up the identifier in this or super scopes and returns a valid pointer if found @@ -90,12 +69,12 @@ struct Scope /// will any lookups across assembly boundaries. /// The pointer will be invalidated if the scope is modified. /// @param _crossedFunction if true, we already crossed a function boundary during recursive lookup - Identifier* lookup(std::string const& _name); + Identifier* lookup(yul::YulString _name); /// Looks up the identifier in this and super scopes (will not find variables across function /// boundaries and generally stops at assembly boundaries) and calls the visitor, returns /// false if not found. template <class V> - bool lookup(std::string const& _name, V const& _visitor) + bool lookup(yul::YulString _name, V const& _visitor) { if (Identifier* id = lookup(_name)) { @@ -107,7 +86,7 @@ struct Scope } /// @returns true if the name exists in this scope or in super scopes (also searches /// across function and assembly boundaries). - bool exists(std::string const& _name) const; + bool exists(yul::YulString _name) const; /// @returns the number of variables directly registered inside the scope. size_t numberOfVariables() const; @@ -118,7 +97,7 @@ struct Scope /// If true, variables from the super scope are not visible here (other identifiers are), /// but they are still taken into account to prevent shadowing. bool functionScope = false; - std::map<std::string, Identifier> identifiers; + std::map<yul::YulString, Identifier> identifiers; }; } diff --git a/libsolidity/inlineasm/AsmScopeFiller.cpp b/libsolidity/inlineasm/AsmScopeFiller.cpp index 86f3809c..d1f98083 100644 --- a/libsolidity/inlineasm/AsmScopeFiller.cpp +++ b/libsolidity/inlineasm/AsmScopeFiller.cpp @@ -57,7 +57,7 @@ bool ScopeFiller::operator()(Label const& _item) //@TODO secondary location m_errorReporter.declarationError( _item.location, - "Label name " + _item.name + " already taken in this scope." + "Label name " + _item.name.str() + " already taken in this scope." ); return false; } @@ -75,18 +75,18 @@ bool ScopeFiller::operator()(assembly::VariableDeclaration const& _varDecl) bool ScopeFiller::operator()(assembly::FunctionDefinition const& _funDef) { bool success = true; - vector<Scope::JuliaType> arguments; + vector<Scope::YulType> arguments; for (auto const& _argument: _funDef.parameters) - arguments.push_back(_argument.type); - vector<Scope::JuliaType> returns; + arguments.emplace_back(_argument.type.str()); + vector<Scope::YulType> returns; for (auto const& _return: _funDef.returnVariables) - returns.push_back(_return.type); + returns.emplace_back(_return.type.str()); if (!m_currentScope->registerFunction(_funDef.name, arguments, returns)) { //@TODO secondary location m_errorReporter.declarationError( _funDef.location, - "Function name " + _funDef.name + " already taken in this scope." + "Function name " + _funDef.name.str() + " already taken in this scope." ); success = false; } @@ -164,7 +164,7 @@ bool ScopeFiller::registerVariable(TypedName const& _name, SourceLocation const& //@TODO secondary location m_errorReporter.declarationError( _location, - "Variable name " + _name.name + " already taken in this scope." + "Variable name " + _name.name.str() + " already taken in this scope." ); return false; } |