Skip to content

Commit 0470345

Browse files
committed
Merge branch 'develop' of github.com:tfire/solidity into fix/remove-namespace-ast-annotations
2 parents 519e1c9 + bebdccc commit 0470345

File tree

119 files changed

+1742
-251
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+1742
-251
lines changed

Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
### 0.8.13 (unreleased)
22

33
Language Features:
4+
* General: Allow annotating inline assembly as memory-safe to allow optimizations and stack limit evasion that rely on respecting Solidity's memory model.
45

56

67
Compiler Features:
78
* JSON-AST: Added selector field for errors and events.
89

910
Bugfixes:
11+
* Yul IR Code Generation: Optimize embedded creation code with correct settings. This fixes potential mismatches between the constructor code of a contract compiled in isolation and the bytecode in ``type(C).creationCode``, resp. the bytecode used for ``new C(...)``.
1012

1113

1214
### 0.8.12 (2022-02-16)

cmake/EthUtils.cmake

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,11 @@ function(detect_stray_source_files FILELIST DIRECTORY)
4848
message(SEND_ERROR "The following source files are present but are not compiled: ${sources}")
4949
endif()
5050
endfunction(detect_stray_source_files)
51+
52+
# CreateExportedFunctionsForEMSDK(OUTPUT_VARIABLE Symbol1 Symbol2 ... SymbolN)
53+
function(CreateExportedFunctionsForEMSDK OUTPUT_VARIABLE)
54+
list(TRANSFORM ARGN PREPEND "\"_")
55+
list(TRANSFORM ARGN APPEND "\"")
56+
list(JOIN ARGN "," ARGN)
57+
set(${OUTPUT_VARIABLE} "[${ARGN}]" PARENT_SCOPE)
58+
endfunction()

docs/assembly.rst

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,11 @@ of their block is reached.
228228
Conventions in Solidity
229229
-----------------------
230230

231+
.. _assembly-typed-variables:
232+
233+
Values of Typed Variables
234+
=========================
235+
231236
In contrast to EVM assembly, Solidity has types which are narrower than 256 bits,
232237
e.g. ``uint24``. For efficiency, most arithmetic operations ignore the fact that
233238
types can be shorter than 256
@@ -237,6 +242,11 @@ This means that if you access such a variable
237242
from within inline assembly, you might have to manually clean the higher-order bits
238243
first.
239244

245+
.. _assembly-memory-management:
246+
247+
Memory Management
248+
=================
249+
240250
Solidity manages memory in the following way. There is a "free memory pointer"
241251
at position ``0x40`` in memory. If you want to allocate memory, use the memory
242252
starting from where this pointer points at and update it.
@@ -268,3 +278,99 @@ first slot of the array and followed by the array elements.
268278
Statically-sized memory arrays do not have a length field, but it might be added later
269279
to allow better convertibility between statically- and dynamically-sized arrays, so
270280
do not rely on this.
281+
282+
Memory Safety
283+
=============
284+
285+
Without the use of inline assembly, the compiler can rely on memory to remain in a well-defined
286+
state at all times. This is especially relevant for :ref:`the new code generation pipeline via Yul IR <ir-breaking-changes>`:
287+
this code generation path can move local variables from stack to memory to avoid stack-too-deep errors and
288+
perform additional memory optimizations, if it can rely on certain assumptions about memory use.
289+
290+
While we recommend to always respect Solidity's memory model, inline assembly allows you to use memory
291+
in an incompatible way. Therefore, moving stack variables to memory and additional memory optimizations are,
292+
by default, disabled in the presence of any inline assembly block that contains a memory operation or assigns
293+
to solidity variables in memory.
294+
295+
However, you can specifically annotate an assembly block to indicate that it in fact respects Solidity's memory
296+
model as follows:
297+
298+
.. code-block:: solidity
299+
300+
assembly ("memory-safe") {
301+
...
302+
}
303+
304+
In particular, a memory-safe assembly block may only access the following memory ranges:
305+
306+
- Memory allocated by yourself using a mechanism like the ``allocate`` function described above.
307+
- Memory allocated by Solidity, e.g. memory within the bounds of a memory array you reference.
308+
- The scratch space between memory offset 0 and 64 mentioned above.
309+
- Temporary memory that is located *after* the value of the free memory pointer at the beginning of the assembly block,
310+
i.e. memory that is "allocated" at the free memory pointer without updating the free memory pointer.
311+
312+
Furthermore, if the assembly block assigns to Solidity variables in memory, you need to assure that accesses to
313+
the Solidity variables only access these memory ranges.
314+
315+
Since this is mainly about the optimizer, these restrictions still need to be followed, even if the assembly block
316+
reverts or terminates. As an example, the following assembly snippet is not memory safe:
317+
318+
.. code-block:: solidity
319+
320+
assembly {
321+
returndatacopy(0, 0, returndatasize())
322+
revert(0, returndatasize())
323+
}
324+
325+
But the following is:
326+
327+
.. code-block:: solidity
328+
329+
assembly ("memory-safe") {
330+
let p := mload(0x40)
331+
returndatacopy(p, 0, returndatasize())
332+
revert(p, returndatasize())
333+
}
334+
335+
Note that you do not need to update the free memory pointer if there is no following allocation,
336+
but you can only use memory starting from the current offset given by the free memory pointer.
337+
338+
If the memory operations use a length of zero, it is also fine to just use any offset (not only if it falls into the scratch space):
339+
340+
.. code-block:: solidity
341+
342+
assembly ("memory-safe") {
343+
revert(0, 0)
344+
}
345+
346+
Note that not only memory operations in inline assembly itself can be memory-unsafe, but also assignments to
347+
solidity variables of reference type in memory. For example the following is not memory-safe:
348+
349+
.. code-block:: solidity
350+
351+
bytes memory x;
352+
assembly {
353+
x := 0x40
354+
}
355+
x[0x20] = 0x42;
356+
357+
Inline assembly that neither involves any operations that access memory nor assigns to any solidity variables
358+
in memory is automatically considered memory-safe and does not need to be annotated.
359+
360+
.. warning::
361+
It is your responsibility to make sure that the assembly actually satisfies the memory model. If you annotate
362+
an assembly block as memory-safe, but violate one of the memory assumptions, this **will** lead to incorrect and
363+
undefined behaviour that cannot easily be discovered by testing.
364+
365+
In case you are developing a library that is meant to be compatible across multiple versions
366+
of solidity, you can use a special comment to annotate an assembly block as memory-safe:
367+
368+
.. code-block:: solidity
369+
370+
/// @solidity memory-safe-assembly
371+
assembly {
372+
...
373+
}
374+
375+
Note that we will disallow the annotation via comment in a future breaking release, so if you are not concerned with
376+
backwards-compatibility with older compiler versions, prefer using the dialect string.

docs/grammar/SolidityLexer.g4

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,12 @@ mode AssemblyBlockMode;
251251
AssemblyDialect: '"evmasm"';
252252
AssemblyLBrace: '{' -> popMode, pushMode(YulMode);
253253
254+
AssemblyFlagString: '"' DoubleQuotedStringCharacter+ '"';
255+
256+
AssemblyBlockLParen: '(';
257+
AssemblyBlockRParen: ')';
258+
AssemblyBlockComma: ',';
259+
254260
AssemblyBlockWS: [ \t\r\n\u000C]+ -> skip ;
255261
AssemblyBlockCOMMENT: '/*' .*? '*/' -> channel(HIDDEN) ;
256262
AssemblyBlockLINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN) ;

docs/grammar/SolidityParser.g4

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,13 @@ revertStatement: Revert expression callArgumentList Semicolon;
476476
* The contents of an inline assembly block use a separate scanner/lexer, i.e. the set of keywords and
477477
* allowed identifiers is different inside an inline assembly block.
478478
*/
479-
assemblyStatement: Assembly AssemblyDialect? AssemblyLBrace yulStatement* YulRBrace;
479+
assemblyStatement: Assembly AssemblyDialect? assemblyFlags? AssemblyLBrace yulStatement* YulRBrace;
480+
481+
/**
482+
* Assembly flags.
483+
* Comma-separated list of double-quoted strings as flags.
484+
*/
485+
assemblyFlags: AssemblyBlockLParen AssemblyFlagString (AssemblyBlockComma AssemblyFlagString)* AssemblyBlockRParen;
480486

481487
//@doc:inline
482488
variableDeclarationList: variableDeclarations+=variableDeclaration (Comma variableDeclarations+=variableDeclaration)*;

docs/index.rst

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ Solidity is an object-oriented, high-level language for implementing smart
55
contracts. Smart contracts are programs which govern the behaviour of accounts
66
within the Ethereum state.
77

8-
Solidity is a `curly-bracket language <https://en.wikipedia.org/wiki/List_of_programming_languages_by_type#Curly-bracket_languages>`_.
9-
It is influenced by C++, Python and JavaScript, and is designed to target the Ethereum Virtual Machine (EVM).
10-
You can find more details about which languages Solidity has been inspired by in
11-
the :doc:`language influences <language-influences>` section.
8+
Solidity is a `curly-bracket language <https://en.wikipedia.org/wiki/List_of_programming_languages_by_type#Curly-bracket_languages>`_ designed to target the Ethereum Virtual Machine (EVM).
9+
It is influenced by C++, Python and JavaScript. You can find more details about which languages Solidity has been inspired by in the :doc:`language influences <language-influences>` section.
1210

1311
Solidity is statically typed, supports inheritance, libraries and complex
1412
user-defined types among other features.
@@ -90,24 +88,25 @@ our `Gitter channel <https://gitter.im/ethereum/solidity/>`_.
9088
Translations
9189
------------
9290

93-
Community volunteers help translate this documentation into several languages.
94-
They have varying degrees of completeness and up-to-dateness. The English
91+
Community contributors help translate this documentation into several languages.
92+
Note that they have varying degrees of completeness and up-to-dateness. The English
9593
version stands as a reference.
9694

95+
You can switch between languages by clicking on the flyout menu in the bottom-left corner
96+
and selecting the preferred language.
97+
98+
* `French <https://docs.soliditylang.org/fr/latest/>`_
99+
* `Indonesian <https://github.com/solidity-docs/id-indonesian>`_
100+
* `Persian <https://github.com/solidity-docs/fa-persian>`_
101+
* `Japanese <https://github.com/solidity-docs/ja-japanese>`_
102+
* `Korean <https://github.com/solidity-docs/ko-korean>`_
103+
* `Chinese <https://github.com/solidity-docs/zh-cn-chinese/>`_
104+
97105
.. note::
98106

99107
We recently set up a new GitHub organization and translation workflow to help streamline the
100108
community efforts. Please refer to the `translation guide <https://github.com/solidity-docs/translation-guide>`_
101-
for information on how to contribute to the community translations moving forward.
102-
103-
* `French <https://solidity-fr.readthedocs.io>`_ (in progress)
104-
* `Italian <https://github.com/damianoazzolini/solidity>`_ (in progress)
105-
* `Japanese <https://solidity-jp.readthedocs.io>`_
106-
* `Korean <https://solidity-kr.readthedocs.io>`_ (in progress)
107-
* `Russian <https://github.com/ethereum/wiki/wiki/%5BRussian%5D-%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE-%D0%BF%D0%BE-Solidity>`_ (rather outdated)
108-
* `Simplified Chinese <https://learnblockchain.cn/docs/solidity/>`_ (in progress)
109-
* `Spanish <https://solidity-es.readthedocs.io>`_
110-
* `Turkish <https://github.com/denizozzgur/Solidity_TR/blob/master/README.md>`_ (partial)
109+
for information on how to start a new language or contribute to the community translations.
111110

112111
Contents
113112
========

docs/ir-breaking-changes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11

22
.. index: ir breaking changes
33
4+
.. _ir-breaking-changes:
5+
46
*********************************
57
Solidity IR-based Codegen Changes
68
*********************************

docs/using-the-compiler.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -410,12 +410,13 @@ Input Description
410410
"source1.sol": ["contract1"],
411411
"source2.sol": ["contract2", "contract3"]
412412
},
413-
// Choose whether division and modulo operations should be replaced by
414-
// multiplication with slack variables. Default is `true`.
415-
// Using `false` here is recommended if you are using the CHC engine
413+
// Choose how division and modulo operations should be encoded.
414+
// When using `false` they are replaced by multiplication with slack
415+
// variables. This is the default.
416+
// Using `true` here is recommended if you are using the CHC engine
416417
// and not using Spacer as the Horn solver (using Eldarica, for example).
417418
// See the Formal Verification section for a more detailed explanation of this option.
418-
"divModWithSlacks": true,
419+
"divModNoSlacks": false,
419420
// Choose which model checker engine to use: all (default), bmc, chc, none.
420421
"engine": "chc",
421422
// Choose which types of invariants should be reported to the user: contract, reentrancy.

docs/yul.rst

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,11 @@ regular strings in native encoding. For code,
11241124
11251125
Above, ``Block`` refers to ``Block`` in the Yul code grammar explained in the previous chapter.
11261126

1127+
.. note::
1128+
1129+
An object with a name that ends in ``_deployed`` is treated as deployed code by the Yul optimizer.
1130+
The only consequence of this is a different gas cost heuristic in the optimizer.
1131+
11271132
.. note::
11281133

11291134
Data objects or sub-objects whose names contain a ``.`` can be defined
@@ -1172,17 +1177,17 @@ An example Yul Object is shown below:
11721177
11731178
// now return the runtime object (the currently
11741179
// executing code is the constructor code)
1175-
size := datasize("runtime")
1180+
size := datasize("Contract1_deployed")
11761181
offset := allocate(size)
11771182
// This will turn into a memory->memory copy for Ewasm and
11781183
// a codecopy for EVM
1179-
datacopy(offset, dataoffset("runtime"), size)
1184+
datacopy(offset, dataoffset("Contract1_deployed"), size)
11801185
return(offset, size)
11811186
}
11821187
11831188
data "Table2" hex"4123"
11841189
1185-
object "runtime" {
1190+
object "Contract1_deployed" {
11861191
code {
11871192
function allocate(size) -> ptr {
11881193
ptr := mload(0x40)
@@ -1204,7 +1209,7 @@ An example Yul Object is shown below:
12041209
// code here ...
12051210
}
12061211
1207-
object "runtime" {
1212+
object "Contract2_deployed" {
12081213
code {
12091214
// code here ...
12101215
}

libevmasm/Assembly.cpp

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -397,26 +397,6 @@ AssemblyItem Assembly::newImmutableAssignment(string const& _identifier)
397397
return AssemblyItem{AssignImmutable, h};
398398
}
399399

400-
Assembly& Assembly::optimise(bool _enable, EVMVersion _evmVersion, bool _isCreation, size_t _runs)
401-
{
402-
OptimiserSettings settings;
403-
settings.isCreation = _isCreation;
404-
settings.runInliner = true;
405-
settings.runJumpdestRemover = true;
406-
settings.runPeephole = true;
407-
if (_enable)
408-
{
409-
settings.runDeduplicate = true;
410-
settings.runCSE = true;
411-
settings.runConstantOptimiser = true;
412-
}
413-
settings.evmVersion = _evmVersion;
414-
settings.expectedExecutionsPerDeployment = _runs;
415-
optimise(settings);
416-
return *this;
417-
}
418-
419-
420400
Assembly& Assembly::optimise(OptimiserSettings const& _settings)
421401
{
422402
optimiseInternal(_settings, {});
@@ -435,9 +415,8 @@ map<u256, u256> const& Assembly::optimiseInternal(
435415
for (size_t subId = 0; subId < m_subs.size(); ++subId)
436416
{
437417
OptimiserSettings settings = _settings;
438-
// Disable creation mode for sub-assemblies.
439-
settings.isCreation = false;
440-
map<u256, u256> const& subTagReplacements = m_subs[subId]->optimiseInternal(
418+
Assembly& sub = *m_subs[subId];
419+
map<u256, u256> const& subTagReplacements = sub.optimiseInternal(
441420
settings,
442421
JumpdestRemover::referencedTags(m_items, subId)
443422
);
@@ -456,7 +435,7 @@ map<u256, u256> const& Assembly::optimiseInternal(
456435
m_items,
457436
_tagsReferencedFromOutside,
458437
_settings.expectedExecutionsPerDeployment,
459-
_settings.isCreation,
438+
isCreation(),
460439
_settings.evmVersion
461440
}.optimise();
462441

@@ -557,8 +536,8 @@ map<u256, u256> const& Assembly::optimiseInternal(
557536

558537
if (_settings.runConstantOptimiser)
559538
ConstantOptimisationMethod::optimiseConstants(
560-
_settings.isCreation,
561-
_settings.isCreation ? 1 : _settings.expectedExecutionsPerDeployment,
539+
isCreation(),
540+
isCreation() ? 1 : _settings.expectedExecutionsPerDeployment,
562541
_settings.evmVersion,
563542
*this
564543
);

0 commit comments

Comments
 (0)