From f04adde6641b09c8744fb1576eda87657b4d9a2d Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 25 Mar 2021 17:00:05 +0100 Subject: [PATCH] Allow hex string literals in Yul. --- Changelog.md | 1 + docs/grammar/Solidity.g4 | 2 +- docs/grammar/SolidityLexer.g4 | 3 ++- docs/yul.rst | 5 ++++- libyul/AsmParser.cpp | 5 ++--- .../syntaxTests/inlineAssembly/hex_assignment.sol | 1 - .../syntaxTests/inlineAssembly/hex_expression.sol | 1 - .../syntaxTests/inlineAssembly/hex_switch_case.sol | 1 - .../literals/hex_string_duplicate_underscore_yul.sol | 9 +++++++++ .../literals/hex_string_invalid_characters_yul.sol | 9 +++++++++ .../syntaxTests/string/hex_as_identifier.sol | 5 +++++ test/libyul/yulInterpreterTests/hex_literals.yul | 12 ++++++++++++ test/libyul/yulSyntaxTests/hex_assignment.yul | 1 - test/libyul/yulSyntaxTests/hex_assignment_long.yul | 5 +++++ test/libyul/yulSyntaxTests/hex_expression.yul | 1 - .../libyul/yulSyntaxTests/hex_string_literal_odd.yul | 7 +++++++ test/libyul/yulSyntaxTests/hex_switch_case.yul | 1 - test/libyul/yulSyntaxTests/hex_switch_case_long.yul | 7 +++++++ 18 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 test/libsolidity/syntaxTests/literals/hex_string_duplicate_underscore_yul.sol create mode 100644 test/libsolidity/syntaxTests/literals/hex_string_invalid_characters_yul.sol create mode 100644 test/libsolidity/syntaxTests/string/hex_as_identifier.sol create mode 100644 test/libyul/yulInterpreterTests/hex_literals.yul create mode 100644 test/libyul/yulSyntaxTests/hex_assignment_long.yul create mode 100644 test/libyul/yulSyntaxTests/hex_string_literal_odd.yul create mode 100644 test/libyul/yulSyntaxTests/hex_switch_case_long.yul diff --git a/Changelog.md b/Changelog.md index a59bf8959..4cf75596c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.8.4 (unreleased) Language Features: + * Assembly / Yul: Allow hex string literals. * Possibility to use ``bytes.concat`` with variable number of ``bytes`` and ``bytesNN`` arguments which behaves as a restricted version of `abi.encodePacked` with a more descriptive name. * Support custom errors via the ``error`` keyword and introduce the ``revert`` statement. diff --git a/docs/grammar/Solidity.g4 b/docs/grammar/Solidity.g4 index 69da6b405..7962cea77 100644 --- a/docs/grammar/Solidity.g4 +++ b/docs/grammar/Solidity.g4 @@ -564,5 +564,5 @@ yulPath: YulIdentifier (YulPeriod YulIdentifier)*; */ yulFunctionCall: (YulIdentifier | YulEVMBuiltin) YulLParen (yulExpression (YulComma yulExpression)*)? YulRParen; yulBoolean: YulTrue | YulFalse; -yulLiteral: YulDecimalNumber | YulStringLiteral | YulHexNumber | yulBoolean; +yulLiteral: YulDecimalNumber | YulStringLiteral | YulHexNumber | yulBoolean | YulHexStringLiteral; yulExpression: yulPath | yulFunctionCall | yulLiteral; diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index 6b5209c3e..0d16dcfa2 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -263,6 +263,7 @@ YulLeave: 'leave'; YulLet: 'let'; YulSwitch: 'switch'; YulTrue: 'true'; +YulHex: 'hex'; /** * Builtin functions in the EVM Yul dialect. @@ -314,7 +315,7 @@ YulDecimalNumber: '0' | ([1-9] [0-9]*); YulStringLiteral: '"' DoubleQuotedStringCharacter* '"' | '\'' SingleQuotedStringCharacter* '\''; - +YulHexStringLiteral: HexString; YulWS: [ \t\r\n\u000C]+ -> skip ; YulCOMMENT: '/*' .*? '*/' -> channel(HIDDEN) ; diff --git a/docs/yul.rst b/docs/yul.rst index f63acf6f2..dbca676c9 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -174,7 +174,10 @@ whitespace, i.e. there is no terminating ``;`` or newline required. Literals -------- -You can use integer constants in decimal or hexadecimal notation. +As literals, you can use integer constants in decimal or hexadecimal notation +or strings as ASCII (`"abc"`) or HEX strings (`hex"616263"`) of up to +32 bytes length. + When compiling for the EVM, this will be translated into an appropriate ``PUSHi`` instruction. In the following example, ``3`` and ``2`` are added resulting in 5 and then the diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 25b94157c..408fadf7a 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -285,6 +285,7 @@ variant Parser::parseLiteralOrIdentifier() return identifier; } case Token::StringLiteral: + case Token::HexStringLiteral: case Token::Number: case Token::TrueLiteral: case Token::FalseLiteral: @@ -293,6 +294,7 @@ variant Parser::parseLiteralOrIdentifier() switch (currentToken()) { case Token::StringLiteral: + case Token::HexStringLiteral: kind = LiteralKind::String; break; case Token::Number: @@ -324,9 +326,6 @@ variant Parser::parseLiteralOrIdentifier() return literal; } - case Token::HexStringLiteral: - fatalParserError(3772_error, "Hex literals are not valid in this context."); - break; case Token::Illegal: fatalParserError(1465_error, "Illegal token: " + to_string(m_scanner->currentError())); break; diff --git a/test/libsolidity/syntaxTests/inlineAssembly/hex_assignment.sol b/test/libsolidity/syntaxTests/inlineAssembly/hex_assignment.sol index b51dd8604..d8fdb0f9f 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/hex_assignment.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/hex_assignment.sol @@ -6,4 +6,3 @@ contract C { } } // ---- -// ParserError 3772: (72-81): Hex literals are not valid in this context. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/hex_expression.sol b/test/libsolidity/syntaxTests/inlineAssembly/hex_expression.sol index 2f4f69174..36a9a519d 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/hex_expression.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/hex_expression.sol @@ -6,4 +6,3 @@ contract C { } } // ---- -// ParserError 3772: (67-76): Hex literals are not valid in this context. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/hex_switch_case.sol b/test/libsolidity/syntaxTests/inlineAssembly/hex_switch_case.sol index de64567d7..038e8c4ff 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/hex_switch_case.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/hex_switch_case.sol @@ -8,4 +8,3 @@ contract C { } } // ---- -// ParserError 3772: (92-99): Hex literals are not valid in this context. diff --git a/test/libsolidity/syntaxTests/literals/hex_string_duplicate_underscore_yul.sol b/test/libsolidity/syntaxTests/literals/hex_string_duplicate_underscore_yul.sol new file mode 100644 index 000000000..0ed89d729 --- /dev/null +++ b/test/libsolidity/syntaxTests/literals/hex_string_duplicate_underscore_yul.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + assembly { + let x := hex"12__34"; + } + } +} +// ---- +// ParserError 1465: (84-92): Illegal token: Invalid use of number separator '_'. diff --git a/test/libsolidity/syntaxTests/literals/hex_string_invalid_characters_yul.sol b/test/libsolidity/syntaxTests/literals/hex_string_invalid_characters_yul.sol new file mode 100644 index 000000000..9e623854b --- /dev/null +++ b/test/libsolidity/syntaxTests/literals/hex_string_invalid_characters_yul.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + assembly { + let x := hex"abxy"; + } + } +} +// ---- +// ParserError 1465: (84-90): Illegal token: Expected even number of hex-nibbles. diff --git a/test/libsolidity/syntaxTests/string/hex_as_identifier.sol b/test/libsolidity/syntaxTests/string/hex_as_identifier.sol new file mode 100644 index 000000000..063b52b89 --- /dev/null +++ b/test/libsolidity/syntaxTests/string/hex_as_identifier.sol @@ -0,0 +1,5 @@ +function g() pure { + assembly { let hex := 1 } +} +// ---- +// ParserError 2314: (39-42): Expected identifier but got 'ILLEGAL' diff --git a/test/libyul/yulInterpreterTests/hex_literals.yul b/test/libyul/yulInterpreterTests/hex_literals.yul new file mode 100644 index 000000000..60e59b219 --- /dev/null +++ b/test/libyul/yulInterpreterTests/hex_literals.yul @@ -0,0 +1,12 @@ +{ + let x := hex"112233445566778899aabbccddeeff6677889900" + let y := hex"1234_abcd" + sstore(0, x) + sstore(1, y) +} +// ---- +// Trace: +// Memory dump: +// Storage dump: +// 0000000000000000000000000000000000000000000000000000000000000000: 112233445566778899aabbccddeeff6677889900000000000000000000000000 +// 0000000000000000000000000000000000000000000000000000000000000001: 1234abcd00000000000000000000000000000000000000000000000000000000 diff --git a/test/libyul/yulSyntaxTests/hex_assignment.yul b/test/libyul/yulSyntaxTests/hex_assignment.yul index 213163916..cd37bf616 100644 --- a/test/libyul/yulSyntaxTests/hex_assignment.yul +++ b/test/libyul/yulSyntaxTests/hex_assignment.yul @@ -2,4 +2,3 @@ let x := hex"0011" } // ---- -// ParserError 3772: (15-24): Hex literals are not valid in this context. diff --git a/test/libyul/yulSyntaxTests/hex_assignment_long.yul b/test/libyul/yulSyntaxTests/hex_assignment_long.yul new file mode 100644 index 000000000..eaedcd3b1 --- /dev/null +++ b/test/libyul/yulSyntaxTests/hex_assignment_long.yul @@ -0,0 +1,5 @@ +{ + let x := hex"00110011001100110011001100110011001100110011001100110011001100110011001100110011" +} +// ---- +// TypeError 3069: (15-100): String literal too long (40 > 32) diff --git a/test/libyul/yulSyntaxTests/hex_expression.yul b/test/libyul/yulSyntaxTests/hex_expression.yul index 191fdf085..785681148 100644 --- a/test/libyul/yulSyntaxTests/hex_expression.yul +++ b/test/libyul/yulSyntaxTests/hex_expression.yul @@ -2,4 +2,3 @@ pop(hex"2233") } // ---- -// ParserError 3772: (10-19): Hex literals are not valid in this context. diff --git a/test/libyul/yulSyntaxTests/hex_string_literal_odd.yul b/test/libyul/yulSyntaxTests/hex_string_literal_odd.yul new file mode 100644 index 000000000..e21bf6c59 --- /dev/null +++ b/test/libyul/yulSyntaxTests/hex_string_literal_odd.yul @@ -0,0 +1,7 @@ +{ + let name := hex"abc" +} +// ==== +// dialect: evm +// ---- +// ParserError 1465: (18-24): Illegal token: Expected even number of hex-nibbles. diff --git a/test/libyul/yulSyntaxTests/hex_switch_case.yul b/test/libyul/yulSyntaxTests/hex_switch_case.yul index 87ba6a4a9..e0d00539a 100644 --- a/test/libyul/yulSyntaxTests/hex_switch_case.yul +++ b/test/libyul/yulSyntaxTests/hex_switch_case.yul @@ -4,4 +4,3 @@ case hex"1122" {} } // ---- -// ParserError 3772: (33-40): Hex literals are not valid in this context. diff --git a/test/libyul/yulSyntaxTests/hex_switch_case_long.yul b/test/libyul/yulSyntaxTests/hex_switch_case_long.yul new file mode 100644 index 000000000..abdbc6ec1 --- /dev/null +++ b/test/libyul/yulSyntaxTests/hex_switch_case_long.yul @@ -0,0 +1,7 @@ +{ + switch codesize() + case hex"00" {} + case hex"112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900" {} +} +// ---- +// TypeError 3069: (53-178): String literal too long (60 > 32)